Skip to content

Instantly share code, notes, and snippets.

@vdelacou
Last active February 22, 2022 04:09
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save vdelacou/c5f3fd74c5e836706c0adaeb0d383bd0 to your computer and use it in GitHub Desktop.
Save vdelacou/c5f3fd74c5e836706c0adaeb0d383bd0 to your computer and use it in GitHub Desktop.
Create NEXT app Typescript with typescript eslint jest and TailwindCSS
{
"env": {
"browser": true,
"es2021": true,
"node": true
},
"extends": [
"airbnb",
"airbnb/hooks",
"plugin:@typescript-eslint/recommended",
"plugin:react/recommended",
"plugin:etc/recommended",
"plugin:jsx-a11y/recommended",
"plugin:import/typescript",
"plugin:@next/next/recommended"
],
"parser": "@typescript-eslint/parser",
"parserOptions": {
"ecmaFeatures": {
"jsx": true
},
"ecmaVersion": 12,
"sourceType": "module",
"project": "./tsconfig.json"
},
"plugins": [
"@typescript-eslint",
"react",
"etc",
"jsx-a11y",
"import"
],
"rules": {
"no-use-before-define": "off",
"@typescript-eslint/no-use-before-define": [
"error"
],
"react/react-in-jsx-scope": "off",
"react/jsx-filename-extension": [
"warn",
{
"extensions": [
".tsx",
".js"
]
}
],
"import/extensions": [
"error",
"ignorePackages",
{
"ts": "never",
"tsx": "never"
}
],
"no-shadow": "off",
"@typescript-eslint/no-shadow": [
"error"
],
"@typescript-eslint/explicit-function-return-type": [
"error",
{
"allowExpressions": true
}
],
"max-len": [
"warn",
{
"code": 180
}
],
"react-hooks/rules-of-hooks": "error",
"react-hooks/exhaustive-deps": "warn",
"react/function-component-definition": [
"error",
{
"namedComponents": "arrow-function"
}
],
"import/prefer-default-export": "off",
"comma-dangle": [
"error",
"never"
],
"import/no-extraneous-dependencies": [
"error",
{
"devDependencies": [
"**/*.test.ts",
"**/*.test.tsx",
"**/*.config.**"
]
}
],
"no-multiple-empty-lines": "error",
"sort-keys": "error",
"etc/prefer-interface": "error"
},
"settings": {
"import/resolver": {
"typescript": {}
}
}
}
import {
GetStaticPaths, GetStaticPathsResult, GetStaticProps, GetStaticPropsResult, NextPage
} from 'next';
import { NextSeo } from 'next-seo';
import { ParsedUrlQuery } from 'querystring';
import React, { PropsWithChildren } from 'react';
import contentData from '../content/pages.json';
interface PageProps {
title: string;
content: string;
}
interface PathProps extends ParsedUrlQuery {
slug: string[]
}
export const Page: NextPage<PageProps> = ({ title, content }: PropsWithChildren<PageProps>) => (
<>
<NextSeo title={title} />
<h1>{title}</h1>
<div
// eslint-disable-next-line react/no-danger
dangerouslySetInnerHTML={{ __html: content }}
/>
</>
);
export default Page;
export const getStaticPaths: GetStaticPaths<PathProps> = async (): Promise<GetStaticPathsResult<PathProps>> => {
const paths = contentData.pages.map((value) => {
const slug = value.path.split('/').slice(1);
return { params: { slug } };
});
return { fallback: false, paths };
};
export const getStaticProps: GetStaticProps<PageProps, PathProps> = async ({ params }): Promise<GetStaticPropsResult<PageProps>> => {
const currentPath = `/${params.slug.join('/')}`;
const page: PageProps = contentData.pages.find((value) => value.path === currentPath);
return { props: page };
};

Create project

npx create-next-app --example with-typescript --use-npm your-app

cd your-app

npx npm-check-updates -u

Configure vscode

mkdir .vscode
curl -o .vscode/extensions.json https://gist.githubusercontent.com/vdelacou/c5f3fd74c5e836706c0adaeb0d383bd0/raw/extensions.json
curl -o .vscode/settings.json https://gist.githubusercontent.com/vdelacou/c5f3fd74c5e836706c0adaeb0d383bd0/raw/settings.json

Install and init eslint

npx install-peerdeps --dev eslint-config-airbnb
npm install --save-dev @typescript-eslint/eslint-plugin @typescript-eslint/parser eslint-import-resolver-typescript eslint-plugin-etc

Add next js linter

npm install --save-dev @next/eslint-plugin-next
npx json -I -f package.json -e 'this.scripts={...this.scripts , "lint": "next lint" }'

Add the Rules for .eslintrc.json

curl -o .eslintrc.json https://gist.githubusercontent.com/vdelacou/c5f3fd74c5e836706c0adaeb0d383bd0/raw/.eslintrc.json

Clean example

rm -rvf components interfaces pages utils
mkdir src
mkdir src/pages
mkdir src/pages/api
mkdir src/styles

Install tailwind CSS

npm install autoprefixer postcss tailwindcss

curl -o tailwind.config.js https://gist.githubusercontent.com/vdelacou/c5f3fd74c5e836706c0adaeb0d383bd0/raw/tailwind.config.js

curl -o postcss.config.js https://gist.githubusercontent.com/vdelacou/c5f3fd74c5e836706c0adaeb0d383bd0/raw/postcss.config.js

curl -o src/styles/main.css https://gist.githubusercontent.com/vdelacou/c5f3fd74c5e836706c0adaeb0d383bd0/raw/main.css

Add example

npm install next-seo --save

curl -o src/pages/[..slug].tsx https://gist.githubusercontent.com/vdelacou/c5f3fd74c5e836706c0adaeb0d383bd0/raw/[..slug].tsx

curl -o src/pages/api/hello.ts https://gist.githubusercontent.com/vdelacou/c5f3fd74c5e836706c0adaeb0d383bd0/raw/hello.ts

mkdir src/content

curl -o src/content/pages.json https://gist.githubusercontent.com/vdelacou/c5f3fd74c5e836706c0adaeb0d383bd0/raw/pages.json

Add sitemap.xml generation

npm install next-sitemap --save-dev

npx json -I -f package.json -e 'this.scripts={...this.scripts , "postbuild": "next-sitemap" }'

curl -o next-sitemap.js https://gist.githubusercontent.com/vdelacou/c5f3fd74c5e836706c0adaeb0d383bd0/raw/next-sitemap.js

{
"head": {
"title": "Create Next App",
"description": "Next App typescript tailwind jest"
},
"main": {
"header": {
"title": "Click on",
"button": "Test Button"
},
"subHeader": {
"title": "Change Language"
}
},
"footer": {
"title": "Powered By",
"image": {
"alt": "Vercel Logo"
}
}
}
{
"recommendations": [
"dbaeumer.vscode-eslint",
"eamodio.gitlens",
"bradlc.vscode-tailwindcss",
"heybourn.headwind",
"mikestead.dotenv",
"csstools.postcss",
"blanu.vscode-styled-jsx"
]
}
{
"head": {
"title": "Créer une Next App",
"description": "Next App typescript tailwind jest"
},
"main": {
"header": {
"title": "Cliquer sur le",
"button": "Button de test"
},
"subHeader": {
"title": "Changer de Langue"
}
},
"footer": {
"title": "Poussé par",
"image": {
"alt": "Vercel Logo"
}
}
}
import { NextApiRequest, NextApiResponse } from 'next';
const handler = (req: NextApiRequest, res: NextApiResponse): void => {
res.status(200).json({ name: 'John Doe' });
};
export default handler;
@tailwind base;
@tailwind components;
@tailwind utilities;
module.exports = {
i18n: {
defaultLocale: 'en',
locales: ['en', 'fr'],
serializeConfig: false,
saveMissing: true,
missingKeyHandler: (ng, ns, key) => {
// eslint-disable-next-line no-console
console.warn(`Warning Missing Key: ${key}`);
return key;
},
},
};
module.exports = {
siteUrl: process.env.SITE_URL || 'http://localhost:3000',
generateRobotsTxt: true,
};
/* eslint-disable @typescript-eslint/no-var-requires */
const { i18n } = require('./next-i18next.config.js');
module.exports = {
i18n,
};
{
"pages": [
{
"title": "Home Page",
"path": "/foo",
"content": "<p>Home content...</p>"
},
{
"title": "Bar Page",
"path": "/bar",
"content": "<p><strong>Bar</strong> content...</p>"
},
{
"title": "Baz Page",
"path": "/baz",
"content": "<p><strong>Baz</strong> content...</p>"
}
]
}
module.exports = {
plugins: {
tailwindcss: {},
autoprefixer: {},
},
};
{
"typescript.tsdk": "node_modules\\typescript\\lib",
"files.autoSave": "afterDelay",
"editor.formatOnSave": true,
"editor.codeActionsOnSave": {
"source.organizeImports": true,
"source.addMissingImports": true,
"source.fixAll.eslint": true
},
"search.exclude": {
"**/node_modules": true,
"**/.vscode": true,
"**/build": true,
"**/dist": true
},
"git.autofetch": true,
"typescript.implementationsCodeLens.enabled": true,
"editor.trimAutoWhitespace": true,
"files.encoding": "utf8",
"files.trimFinalNewlines": true,
"files.trimTrailingWhitespace": true,
"css.validate": false,
"editor.quickSuggestions": {
"strings": true
},
"editor.detectIndentation": false,
"editor.tabSize": 2
}
module.exports = {
mode: 'jit',
content: ['./src/**/*.{ts,tsx}'],
theme: {
extend: {},
},
variants: {
extend: {},
},
plugins: [],
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment