├── src ├── hooks │ └── .gitkeep ├── configs │ └── .gitkeep ├── services │ └── .gitkeep ├── components │ └── Main │ │ ├── index.tsx │ │ ├── Main.tsx │ │ ├── Main.stories.tsx │ │ └── Main.spec.tsx ├── types │ ├── .editorconfig │ ├── styled-components.d.ts │ └── jest-styled-components.d.ts ├── app │ ├── page.tsx │ ├── head.tsx │ ├── styles.ts │ ├── layout.tsx │ └── lib │ │ └── registry.tsx └── common │ └── styles │ ├── global.ts │ └── theme.ts ├── public ├── robots.txt └── favicon.ico ├── .prettierrc ├── .github └── architecture.png ├── .husky └── pre-commit ├── .storybook ├── preview.js └── main.js ├── .vscode └── settings.json ├── next.config.js ├── .eslintignore ├── next-env.d.ts ├── .jest └── setup.js ├── .gitignore ├── tsconfig.json ├── jest.config.js ├── .eslintrc.json ├── package.json └── README.md /src/hooks/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/configs/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/services/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/robots.txt: -------------------------------------------------------------------------------- 1 | User-Agent: * 2 | Allow: / 3 | 4 | -------------------------------------------------------------------------------- /src/components/Main/index.tsx: -------------------------------------------------------------------------------- 1 | export * from './Main'; 2 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "semi": true, 3 | "singleQuote": true 4 | } 5 | -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imperadorxs/nextjs-13-boilerplate/HEAD/public/favicon.ico -------------------------------------------------------------------------------- /.github/architecture.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imperadorxs/nextjs-13-boilerplate/HEAD/.github/architecture.png -------------------------------------------------------------------------------- /.husky/pre-commit: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | . "$(dirname -- "$0")/_/husky.sh" 3 | 4 | npx --no-install lint-staged 5 | -------------------------------------------------------------------------------- /.storybook/preview.js: -------------------------------------------------------------------------------- 1 | 2 | export const decorators = [ 3 | (Story) => ( 4 | <> 5 | 6 | 7 | ) 8 | ] 9 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "typescript.tsdk": "node_modules/typescript/lib", 3 | "typescript.enablePromptUseWorkspaceTsdk": true 4 | } -------------------------------------------------------------------------------- /src/components/Main/Main.tsx: -------------------------------------------------------------------------------- 1 | export function Main() { 2 | return ( 3 |
4 |

nextjs template

5 |
6 | ); 7 | } 8 | -------------------------------------------------------------------------------- /next.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('next').NextConfig} */ 2 | const nextConfig = { 3 | experimental: { 4 | appDir: true, 5 | } 6 | } 7 | 8 | module.exports = nextConfig 9 | -------------------------------------------------------------------------------- /src/types/.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | indent_style = space 5 | indent_size = 2 6 | end_of_line = lf 7 | charset = utf-8 8 | trim_trailing_whitespace = true 9 | insert_final_newline = true 10 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | **/*.js 2 | node_modules 3 | build 4 | /src/react-app-env.d.ts 5 | /src/reportWebVitals.ts 6 | /src/components/Archievements 7 | /src/sections/Achievements 8 | *.js 9 | .next 10 | **/*.mdx 11 | **/*.png 12 | -------------------------------------------------------------------------------- /next-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | /// 3 | 4 | // NOTE: This file should not be edited 5 | // see https://nextjs.org/docs/basic-features/typescript for more information. 6 | -------------------------------------------------------------------------------- /src/app/page.tsx: -------------------------------------------------------------------------------- 1 | 'use client'; 2 | 3 | import * as S from './styles'; 4 | 5 | export default function Home() { 6 | return ( 7 | 8 |

Next 13 boilerplate

9 |
10 | ); 11 | } 12 | -------------------------------------------------------------------------------- /src/components/Main/Main.stories.tsx: -------------------------------------------------------------------------------- 1 | import { Story, Meta } from '@storybook/react/types-6-0'; 2 | import { Main } from './index'; 3 | 4 | export default { 5 | title: 'Main', 6 | component: Main, 7 | } as Meta; 8 | 9 | export const Default: Story = (args) =>
; 10 | -------------------------------------------------------------------------------- /.jest/setup.js: -------------------------------------------------------------------------------- 1 | // Optional: configure or set up a testing framework before each test. 2 | // If you delete this file, remove `setupFilesAfterEnv` from `jest.config.js` 3 | 4 | // Used for __tests__/testing-library.js 5 | // Learn more: https://github.com/testing-library/jest-dom 6 | import '@testing-library/jest-dom/extend-expect' 7 | -------------------------------------------------------------------------------- /src/types/styled-components.d.ts: -------------------------------------------------------------------------------- 1 | import 'styled-components'; 2 | import { theme } from '../common/styles/theme'; 3 | 4 | type Theme = typeof theme; 5 | 6 | declare module 'styled-components' { 7 | // eslint-disable-next-line @typescript-eslint/no-empty-interface 8 | export interface DefaultTheme extends Theme {} 9 | } 10 | -------------------------------------------------------------------------------- /src/app/head.tsx: -------------------------------------------------------------------------------- 1 | export default function Head() { 2 | return ( 3 | <> 4 | Create Next App 5 | 6 | 7 | 8 | 9 | ); 10 | } 11 | -------------------------------------------------------------------------------- /src/app/styles.ts: -------------------------------------------------------------------------------- 1 | import styled, { css } from 'styled-components'; 2 | 3 | export const Wrapper = styled.div` 4 | ${({ theme }) => css` 5 | height: 100vh; 6 | width: 100vw; 7 | display: grid; 8 | place-items: center; 9 | 10 | h1 { 11 | font-size: 5rem; 12 | font-weight: 400; 13 | } 14 | background-color: ${theme.colors.black}; 15 | `} 16 | `; 17 | -------------------------------------------------------------------------------- /src/components/Main/Main.spec.tsx: -------------------------------------------------------------------------------- 1 | import { render, screen } from '@testing-library/react'; 2 | 3 | import { Main } from './index'; 4 | 5 | describe('
', () => { 6 | it('should render the heading', () => { 7 | const { container } = render(
); 8 | 9 | expect( 10 | screen.getByRole('heading', { name: /nextjs template/i }) 11 | ).toBeInTheDocument(); 12 | }); 13 | }); 14 | -------------------------------------------------------------------------------- /.storybook/main.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | "stories": [ 3 | "../src/**/*.stories.mdx", 4 | "../src/**/*.stories.@(js|jsx|ts|tsx)" 5 | ], 6 | "addons": [ 7 | "@storybook/addon-links", 8 | "@storybook/addon-essentials", 9 | "@storybook/addon-interactions" 10 | ], 11 | webpackFinal: (config) => { 12 | config.resolve.modules.push(`${process.cwd()}/src`) 13 | return config 14 | }, 15 | "framework": "@storybook/react" 16 | } 17 | -------------------------------------------------------------------------------- /src/common/styles/global.ts: -------------------------------------------------------------------------------- 1 | import { createGlobalStyle, css } from 'styled-components'; 2 | 3 | export const GlobalStyles = createGlobalStyle` 4 | * { 5 | margin: 0; 6 | padding: 0; 7 | box-sizing: border-box; 8 | } 9 | 10 | ${({ theme }) => css` 11 | html { 12 | font-size: 62.5%; // 1rem to equal 10px 13 | } 14 | 15 | html, 16 | body { 17 | height: 100%; 18 | background-color: #333; 19 | color: #ccc; 20 | } 21 | `} 22 | 23 | 24 | `; 25 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | .env 8 | # pwa 9 | public/sw.js 10 | public/workbox-*.js 11 | 12 | # testing 13 | /coverage 14 | 15 | # next.js 16 | /.next/ 17 | /out/ 18 | 19 | # production 20 | /build 21 | 22 | # misc 23 | .DS_Store 24 | *.pem 25 | 26 | # debug 27 | npm-debug.log* 28 | yarn-debug.log* 29 | yarn-error.log* 30 | .pnpm-debug.log* 31 | 32 | # local env files 33 | .env*.local 34 | 35 | # vercel 36 | .vercel 37 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", 4 | "lib": ["dom", "dom.iterable", "esnext"], 5 | "allowJs": true, 6 | "skipLibCheck": true, 7 | "strict": true, 8 | "forceConsistentCasingInFileNames": true, 9 | "noEmit": true, 10 | "esModuleInterop": true, 11 | "module": "esnext", 12 | "moduleResolution": "node", 13 | "resolveJsonModule": true, 14 | "isolatedModules": true, 15 | "jsx": "preserve", 16 | "incremental": true, 17 | "plugins": [ 18 | { 19 | "name": "next" 20 | } 21 | ], 22 | "baseUrl": ".", 23 | "paths": { 24 | "@/*": ["./src/*"] 25 | } 26 | }, 27 | "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"], 28 | "exclude": ["node_modules"] 29 | } 30 | -------------------------------------------------------------------------------- /jest.config.js: -------------------------------------------------------------------------------- 1 | const nextJest = require('next/jest') 2 | 3 | const createJestConfig = nextJest({ 4 | // Provide the path to your Next.js app to load next.config.js and .env files in your test environment 5 | dir: './', 6 | }) 7 | 8 | // Add any custom config to be passed to Jest 9 | const customJestConfig = { 10 | setupFilesAfterEnv: ['/.jest/setup.js'], 11 | modulePaths: ['/src/', '/.jest'], 12 | moduleNameMapper: { 13 | '^styled-components': 14 | '/node_modules/styled-components/dist/styled-components.browser.cjs.js' 15 | }, 16 | testEnvironment: 'jest-environment-jsdom', 17 | } 18 | 19 | // createJestConfig is exported this way to ensure that next/jest can load the Next.js config which is async 20 | module.exports = createJestConfig(customJestConfig) 21 | -------------------------------------------------------------------------------- /src/app/layout.tsx: -------------------------------------------------------------------------------- 1 | 'use client'; 2 | 3 | import StyledComponentsRegistry from './lib/registry'; 4 | import { ThemeProvider } from 'styled-components'; 5 | 6 | import { GlobalStyles } from '@/common/styles/global'; 7 | import { theme } from '@/common/styles/theme'; 8 | 9 | export default function RootLayout({ 10 | children, 11 | }: { 12 | children: React.ReactNode; 13 | }) { 14 | return ( 15 | 16 | {/* 17 | will contain the components returned by the nearest parent 18 | head.tsx. Find out more at https://beta.nextjs.org/docs/api-reference/file-conventions/head 19 | */} 20 | 21 | 22 | 23 | <> 24 | 25 | {children} 26 | 27 | 28 | 29 | 30 | ); 31 | } 32 | -------------------------------------------------------------------------------- /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "browser": true, 4 | "es2021": true, 5 | "jest": true, 6 | "node": true 7 | }, 8 | "settings": { 9 | "react": { 10 | "version": "detect" 11 | } 12 | }, 13 | "extends": [ 14 | "eslint:recommended", 15 | "plugin:react/recommended", 16 | "plugin:@typescript-eslint/recommended", 17 | "plugin:prettier/recommended" 18 | ], 19 | "parser": "@typescript-eslint/parser", 20 | "parserOptions": { 21 | "ecmaFeatures": { 22 | "jsx": true 23 | }, 24 | "ecmaVersion": "latest", 25 | "sourceType": "module" 26 | }, 27 | "plugins": [ 28 | "react", 29 | "@typescript-eslint", 30 | "react-hooks", 31 | "prettier" 32 | ], 33 | "rules": { 34 | "react-hooks/rules-of-hooks": "error", 35 | "react-hooks/exhaustive-deps": "warn", 36 | "react/prop-types": "off", 37 | "react/react-in-jsx-scope": "off", 38 | "prettier/prettier": "error" 39 | } 40 | } -------------------------------------------------------------------------------- /src/types/jest-styled-components.d.ts: -------------------------------------------------------------------------------- 1 | // Types provided from the official repo: 2 | // https://github.com/styled-components/jest-styled-components/blob/master/typings/index.d.ts 3 | 4 | /* eslint-disable @typescript-eslint/no-explicit-any */ 5 | /* eslint-disable @typescript-eslint/ban-types */ 6 | import { Plugin, NewPlugin } from 'pretty-format'; 7 | 8 | declare global { 9 | namespace jest { 10 | interface AsymmetricMatcher { 11 | $$typeof: symbol; 12 | sample?: string | RegExp | object | Array | Function; 13 | } 14 | 15 | type Value = string | number | RegExp | AsymmetricMatcher | undefined; 16 | 17 | interface Options { 18 | media?: string; 19 | modifier?: string; 20 | supports?: string; 21 | } 22 | 23 | // eslint-disable-next-line @typescript-eslint/no-unused-vars 24 | interface Matchers { 25 | toHaveStyleRule(property: string, value?: Value, options?: Options): R; 26 | } 27 | } 28 | } 29 | 30 | export declare const styleSheetSerializer: Exclude; 31 | -------------------------------------------------------------------------------- /src/app/lib/registry.tsx: -------------------------------------------------------------------------------- 1 | /* eslint-disable @typescript-eslint/ban-ts-comment */ 2 | 'use client'; 3 | import React, { useState } from 'react'; 4 | import { useServerInsertedHTML } from 'next/navigation'; 5 | import { ServerStyleSheet, StyleSheetManager } from 'styled-components'; 6 | 7 | export default function StyledComponentsRegistry({ 8 | children, 9 | }: { 10 | children: React.ReactNode; 11 | }) { 12 | // Only create stylesheet once with lazy initial state 13 | // x-ref: https://reactjs.org/docs/hooks-reference.html#lazy-initial-state 14 | const [styledComponentsStyleSheet] = useState(() => new ServerStyleSheet()); 15 | 16 | useServerInsertedHTML(() => { 17 | const styles = styledComponentsStyleSheet.getStyleElement(); 18 | //@ts-ignore 19 | styledComponentsStyleSheet.instance.clearTag(); 20 | return <>{styles}; 21 | }); 22 | 23 | if (typeof window !== 'undefined') return <>{children}; 24 | 25 | return ( 26 | 27 | {children} 28 | 29 | ); 30 | } 31 | -------------------------------------------------------------------------------- /src/common/styles/theme.ts: -------------------------------------------------------------------------------- 1 | export const theme = { 2 | grid: { 3 | container: '130rem', 4 | gutter: '3.2rem', 5 | }, 6 | border: { 7 | radius: '0.4rem', 8 | }, 9 | font: { 10 | family: 11 | "Poppins, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif", 12 | light: 300, 13 | normal: 400, 14 | bold: 600, 15 | sizes: { 16 | xsmall: '1.2rem', 17 | small: '1.4rem', 18 | medium: '1.6rem', 19 | large: '1.8rem', 20 | xlarge: '2.0rem', 21 | xxlarge: '2.8rem', 22 | }, 23 | }, 24 | colors: { 25 | primary: '#F231A5', 26 | secondary: '#3CD3C1', 27 | mainBg: '#06092B', 28 | white: '#FAFAFA', 29 | black: '#030517', 30 | lightGray: '#EAEAEA', 31 | gray: '#8F8F8F', 32 | darkGray: '#2E2F42', 33 | }, 34 | spacings: { 35 | xxsmall: '0.8rem', 36 | xsmall: '1.6rem', 37 | small: '2.4rem', 38 | medium: '3.2rem', 39 | large: '4.0rem', 40 | xlarge: '4.8rem', 41 | xxlarge: '5.6rem', 42 | }, 43 | layers: { 44 | base: 10, 45 | menu: 20, 46 | overlay: 30, 47 | modal: 40, 48 | alwaysOnTop: 50, 49 | }, 50 | }; 51 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "nextjs-13-boilerplate", 3 | "version": "0.1.0", 4 | "private": true, 5 | "scripts": { 6 | "dev": "next dev", 7 | "build": "next build", 8 | "start": "next start", 9 | "prepare": "husky install", 10 | "lint": "next lint", 11 | "test": "jest", 12 | "test:watch": "yarn test --watch", 13 | "storybook": "start-storybook -s ./public -p 6006", 14 | "build-storybook": "build-storybook -s ./public" 15 | }, 16 | "lint-staged": { 17 | "src/**/*": [ 18 | "yarn test --findRelatedTests --passWithNoTests --bail" 19 | ] 20 | }, 21 | "dependencies": { 22 | "@next/font": "13.1.6", 23 | "next": "13.1.6", 24 | "react": "18.2.0", 25 | "react-dom": "18.2.0", 26 | "styled-components": "^5.3.6" 27 | }, 28 | "devDependencies": { 29 | "@babel/core": "^7.17.10", 30 | "@babel/preset-typescript": "^7.16.7", 31 | "@storybook/addon-actions": "^6.4.22", 32 | "@storybook/addon-essentials": "^6.4.22", 33 | "@storybook/addon-interactions": "^6.4.22", 34 | "@storybook/addon-links": "^6.4.22", 35 | "@storybook/react": "^6.4.22", 36 | "@storybook/testing-library": "^0.0.11", 37 | "@testing-library/jest-dom": "5.16.4", 38 | "@testing-library/react": "13.2.0", 39 | "@testing-library/user-event": "14.2.0", 40 | "@types/jest": "^29.4.0", 41 | "@types/node": "18.14.0", 42 | "@types/react": "18.0.28", 43 | "@types/react-dom": "18.0.11", 44 | "@types/styled-components": "^5.1.25", 45 | "@types/testing-library__jest-dom": "5.14.5", 46 | "@typescript-eslint/eslint-plugin": "^5.23.0", 47 | "@typescript-eslint/parser": "^5.23.0", 48 | "babel-loader": "^8.2.5", 49 | "babel-plugin-inline-react-svg": "^2.0.1", 50 | "babel-plugin-styled-components": "^2.0.7", 51 | "eslint": "8.34.0", 52 | "eslint-config-next": "13.1.6", 53 | "eslint-config-prettier": "^8.5.0", 54 | "eslint-plugin-prettier": "^4.0.0", 55 | "eslint-plugin-react": "^7.29.4", 56 | "eslint-plugin-react-hooks": "^4.5.0", 57 | "eslint-plugin-storybook": "^0.5.11", 58 | "husky": "^8.0.1", 59 | "jest": "28.1.0", 60 | "jest-environment-jsdom": "28.1.0", 61 | "jest-styled-components": "^7.0.8", 62 | "lint-staged": "^12.4.1", 63 | "prettier": "^2.6.2", 64 | "typescript": "4.9.5" 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

2 |
3 | logo 4 |
5 |

6 | 7 |

8 | GitHub language count 9 | 10 | Repository size 11 | 12 | 13 | GitHub last commit 14 | 15 | 16 | 17 | Repository issues 18 | 19 | 20 | License 21 | 22 | 23 | Stargazers 24 | 25 |

26 | 27 | # Next.js 13 with Typescript reference architecture 28 | 29 | ## Getting Started 30 | 31 | Start your project with this template. 32 | 33 | ```bash 34 | yarn create next-app -e https://github.com/imperadorxs/nextjs-13-boilerplate 35 | ``` 36 | 37 | ### How to run 38 | 39 | `npm install` 40 | `npm dev` 41 |
42 | `yarn` 43 | `yarn dev` 44 | 45 | ### How to build 46 | 47 | `npm run build` 48 |
49 | `yarn build` 50 | 51 | ### How to tests 52 | 53 | `npm test` 54 |
55 | `yarn test` 56 | 57 | # File structure 58 | 59 | **This is your source code tree:** 60 | 61 | ``` 62 | src 63 | |-- common 64 | |-- assets 65 | |-- helpers 66 | |-- mocks 67 | |-- styles 68 | |-- utils 69 | |-- components 70 | |-- config 71 | |-- hooks 72 | |-- app 73 | |-- lib 74 | |-- registry 75 | |-- head.tsx 76 | |-- layout.tsx 77 | |-- page.tsx 78 | |-- services 79 | ... 80 | ``` 81 | 82 | **This is your component structure:** 83 | 84 | ``` 85 | ... 86 | components 87 | |-- YourComponent 88 | |-- YourComponent.tsx 89 | |-- YourComponent.spec.ts 90 | |-- YourComponent.stories.tsx 91 | |-- interfaces.ts 92 | |-- styles.ts 93 | |-- index.tsx 94 | ... 95 | ``` 96 | 97 | **These are the folders and their functions:** 98 | 99 | `./common` 100 | 101 | Here are all the project assets that will be used by the application such as global styles, images, fonts, mocks, reusable functions, among others 102 | 103 | `./components` 104 | 105 | Components are presentational only elements, grouping UI items 106 | 107 | `./configs` 108 | 109 | Configs are our application's global settings files 110 | 111 | `./hooks` 112 | 113 | Hooks are functions that allow you to “plug in” to React's state and lifecycle features from functional components 114 | 115 | `./app` 116 | 117 | App is a new pages folder are mapped in routes and have all the containers needed to implement a functionality 118 | 119 | `./services` 120 | 121 | Contains all the files responsible for consuming external services, such as the axios configuration file for consuming RestFul APIs. 122 | 123 | ### More utils commands 124 | 125 | Find and fix Javascrit and TypeScript problems according to pre-defined rules 126 | `npm run lint` 127 | `yarn lint` 128 | 129 | # Advantages of using this react project template 130 | 131 | The project is already configured with: 132 | 133 | - React 134 | - Typescript 135 | - Jest 136 | - Eslint 137 | - Prettier 138 | - Styled 139 | - Husky 140 | - Storybook 141 | 142 | ### Main dependecies 143 | 144 | - [nextjs](https://nextjs.org/blog/next-13/) 145 | - [react](https://reactjs.org/) 146 | - [styled-components](https://styled-components.com/) 147 | 148 | ### Main dev dependecies 149 | 150 | - [testing-library](https://testing-library.com/) 151 | - [eslint](https://eslint.org/) 152 | - [husky](https://www.npmjs.com/package/husky) 153 | - [lint-staged](https://www.npmjs.com/package/lint-staged) 154 | - [prettier](https://prettier.io/) 155 | - [typescript](https://www.typescriptlang.org/) 156 | - [web-vitals](https://web.dev/vitals/) 157 | --------------------------------------------------------------------------------