├── .eslintrc.json ├── public ├── favicon.ico └── vercel.svg ├── next.config.js ├── utility └── createEmotionCache.ts ├── next-env.d.ts ├── styles ├── theme │ └── lightThemeOptions.ts ├── globals.css └── Home.module.css ├── pages ├── api │ └── hello.ts ├── _app.tsx ├── index.tsx └── _document.tsx ├── .gitignore ├── tsconfig.json ├── package.json └── README.md /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "next/core-web-vitals" 3 | } 4 | -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zdavidson/muxt-ts/HEAD/public/favicon.ico -------------------------------------------------------------------------------- /next.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('next').NextConfig} */ 2 | module.exports = { 3 | reactStrictMode: true, 4 | } 5 | -------------------------------------------------------------------------------- /utility/createEmotionCache.ts: -------------------------------------------------------------------------------- 1 | import createCache from '@emotion/cache'; 2 | 3 | const createEmotionCache = () => { 4 | return createCache({ key: 'css', prepend: true }); 5 | }; 6 | 7 | export default createEmotionCache; 8 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /styles/theme/lightThemeOptions.ts: -------------------------------------------------------------------------------- 1 | import { ThemeOptions } from '@mui/material/styles'; 2 | 3 | const lightThemeOptions: ThemeOptions = { 4 | palette: { 5 | mode: 'light', 6 | }, 7 | }; 8 | 9 | export default lightThemeOptions; 10 | -------------------------------------------------------------------------------- /styles/globals.css: -------------------------------------------------------------------------------- 1 | html, 2 | body { 3 | padding: 0; 4 | margin: 0; 5 | font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen, 6 | Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif; 7 | } 8 | 9 | a { 10 | color: inherit; 11 | text-decoration: none; 12 | } 13 | 14 | * { 15 | box-sizing: border-box; 16 | } 17 | -------------------------------------------------------------------------------- /pages/api/hello.ts: -------------------------------------------------------------------------------- 1 | // Next.js API route support: https://nextjs.org/docs/api-routes/introduction 2 | import type { NextApiRequest, NextApiResponse } from 'next' 3 | 4 | type Data = { 5 | name: string 6 | } 7 | 8 | export default function handler( 9 | req: NextApiRequest, 10 | res: NextApiResponse 11 | ) { 12 | res.status(200).json({ name: 'John Doe' }) 13 | } 14 | -------------------------------------------------------------------------------- /.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 | 8 | # testing 9 | /coverage 10 | 11 | # next.js 12 | /.next/ 13 | /out/ 14 | 15 | # production 16 | /build 17 | 18 | # misc 19 | .DS_Store 20 | *.pem 21 | 22 | # debug 23 | npm-debug.log* 24 | yarn-debug.log* 25 | yarn-error.log* 26 | 27 | # local env files 28 | .env.local 29 | .env.development.local 30 | .env.test.local 31 | .env.production.local 32 | 33 | # vercel 34 | .vercel 35 | 36 | # typescript 37 | *.tsbuildinfo 38 | -------------------------------------------------------------------------------- /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 | }, 18 | "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"], 19 | "exclude": ["node_modules"] 20 | } 21 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "scripts": { 4 | "dev": "next dev", 5 | "build": "next build", 6 | "start": "next start", 7 | "lint": "next lint" 8 | }, 9 | "dependencies": { 10 | "@emotion/cache": "^11.7.1", 11 | "@emotion/react": "^11.9.0", 12 | "@emotion/server": "^11.4.0", 13 | "@emotion/styled": "^11.6.0", 14 | "@fontsource/roboto": "^4.5.1", 15 | "@mui/icons-material": "^5.6.2", 16 | "@mui/material": "^5.7.0", 17 | "next": "^14.0.0", 18 | "react": "^18.2.0", 19 | "react-dom": "^18.2.0" 20 | }, 21 | "devDependencies": { 22 | "@types/node": "^18.0.3", 23 | "@types/react": "^18.0.9", 24 | "eslint": "^8.15.0", 25 | "eslint-config-next": "^12.1.6", 26 | "typescript": "^4.6.4" 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | This is a [Next.js](https://nextjs.org/), [MUI v5](https://mui.com/) and [Typescript](https://github.com/microsoft/TypeScript) starter. You can use this to start your Next.js + MUI + Typescript development faster and easier. 2 | 3 | ## Getting Started 4 | 5 | 1. First, Clone the project. 6 | 2. (Optional) If you want, You can also change the project name to whatever your like and also add the project name in the `package.json`. 7 | 3. Run this command in the project directory to install dependencies: 8 | 9 | ```bash 10 | npm i 11 | # or 12 | yarn 13 | ``` 14 | 15 | 4. You can run dev server with the following command: 16 | 17 | ```bash 18 | npm run dev 19 | # or 20 | yarn dev 21 | ``` 22 | 23 | 5. Open [http://localhost:3000](http://localhost:3000) with your browser to see the result. 24 | -------------------------------------------------------------------------------- /public/vercel.svg: -------------------------------------------------------------------------------- 1 | 3 | 4 | -------------------------------------------------------------------------------- /pages/_app.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import type { AppProps } from 'next/app'; 3 | import { CacheProvider, EmotionCache } from '@emotion/react'; 4 | import { ThemeProvider, CssBaseline, createTheme } from '@mui/material'; 5 | 6 | import '@fontsource/roboto/300.css'; 7 | import '@fontsource/roboto/400.css'; 8 | import '@fontsource/roboto/500.css'; 9 | import '@fontsource/roboto/700.css'; 10 | 11 | import createEmotionCache from '../utility/createEmotionCache'; 12 | import lightThemeOptions from '../styles/theme/lightThemeOptions'; 13 | import '../styles/globals.css'; 14 | interface MyAppProps extends AppProps { 15 | emotionCache?: EmotionCache; 16 | } 17 | 18 | const clientSideEmotionCache = createEmotionCache(); 19 | 20 | const lightTheme = createTheme(lightThemeOptions); 21 | 22 | const MyApp: React.FunctionComponent = (props) => { 23 | const { Component, emotionCache = clientSideEmotionCache, pageProps } = props; 24 | 25 | return ( 26 | 27 | 28 | 29 | 30 | 31 | 32 | ); 33 | }; 34 | 35 | export default MyApp; 36 | -------------------------------------------------------------------------------- /styles/Home.module.css: -------------------------------------------------------------------------------- 1 | .container { 2 | padding: 0 2rem; 3 | } 4 | 5 | .main { 6 | min-height: 100vh; 7 | padding: 4rem 0; 8 | flex: 1; 9 | display: flex; 10 | flex-direction: column; 11 | justify-content: center; 12 | align-items: center; 13 | } 14 | 15 | .footer { 16 | display: flex; 17 | flex: 1; 18 | padding: 2rem 0; 19 | border-top: 1px solid #eaeaea; 20 | justify-content: center; 21 | align-items: center; 22 | } 23 | 24 | .footer a { 25 | display: flex; 26 | justify-content: center; 27 | align-items: center; 28 | flex-grow: 1; 29 | } 30 | 31 | .title a { 32 | color: #0070f3; 33 | text-decoration: none; 34 | } 35 | 36 | .title a:hover, 37 | .title a:focus, 38 | .title a:active { 39 | text-decoration: underline; 40 | } 41 | 42 | .title { 43 | margin: 0; 44 | line-height: 1.15; 45 | font-size: 4rem; 46 | } 47 | 48 | .title, 49 | .description { 50 | text-align: center; 51 | } 52 | 53 | .description { 54 | margin: 4rem 0; 55 | line-height: 1.5; 56 | font-size: 1.5rem; 57 | } 58 | 59 | .code { 60 | background: #fafafa; 61 | border-radius: 5px; 62 | padding: 0.75rem; 63 | font-size: 1.1rem; 64 | font-family: Menlo, Monaco, Lucida Console, Liberation Mono, DejaVu Sans Mono, 65 | Bitstream Vera Sans Mono, Courier New, monospace; 66 | } 67 | 68 | .grid { 69 | display: flex; 70 | align-items: center; 71 | justify-content: center; 72 | flex-wrap: wrap; 73 | max-width: 800px; 74 | } 75 | 76 | .card { 77 | margin: 1rem; 78 | padding: 1.5rem; 79 | text-align: left; 80 | color: inherit; 81 | text-decoration: none; 82 | border: 1px solid #eaeaea; 83 | border-radius: 10px; 84 | transition: color 0.15s ease, border-color 0.15s ease; 85 | max-width: 300px; 86 | } 87 | 88 | .card:hover, 89 | .card:focus, 90 | .card:active { 91 | color: #0070f3; 92 | border-color: #0070f3; 93 | } 94 | 95 | .card h2 { 96 | margin: 0 0 1rem 0; 97 | font-size: 1.5rem; 98 | } 99 | 100 | .card p { 101 | margin: 0; 102 | font-size: 1.25rem; 103 | line-height: 1.5; 104 | } 105 | 106 | .logo { 107 | height: 1em; 108 | margin-left: 0.5rem; 109 | } 110 | 111 | @media (max-width: 600px) { 112 | .grid { 113 | width: 100%; 114 | flex-direction: column; 115 | } 116 | } 117 | -------------------------------------------------------------------------------- /pages/index.tsx: -------------------------------------------------------------------------------- 1 | import type { NextPage } from 'next' 2 | import Head from 'next/head' 3 | import Image from 'next/image' 4 | import styles from '../styles/Home.module.css' 5 | 6 | const Home: NextPage = () => { 7 | return ( 8 |
9 | 10 | Create Next App 11 | 12 | 13 | 14 | 15 |
16 |

17 | Welcome to Next.js! 18 |

19 | 20 |

21 | Get started by editing{' '} 22 | pages/index.tsx 23 |

24 | 25 | 54 |
55 | 56 | 68 |
69 | ) 70 | } 71 | 72 | export default Home 73 | -------------------------------------------------------------------------------- /pages/_document.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import Document, { Html, Head, Main, NextScript } from 'next/document'; 3 | import createEmotionServer from '@emotion/server/create-instance'; 4 | 5 | import createEmotionCache from '../utility/createEmotionCache'; 6 | 7 | export default class MyDocument extends Document { 8 | render() { 9 | return ( 10 | 11 | 12 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | ); 23 | } 24 | } 25 | 26 | // `getInitialProps` belongs to `_document` (instead of `_app`), 27 | // it's compatible with static-site generation (SSG). 28 | MyDocument.getInitialProps = async (ctx) => { 29 | // Resolution order 30 | // 31 | // On the server: 32 | // 1. app.getInitialProps 33 | // 2. page.getInitialProps 34 | // 3. document.getInitialProps 35 | // 4. app.render 36 | // 5. page.render 37 | // 6. document.render 38 | // 39 | // On the server with error: 40 | // 1. document.getInitialProps 41 | // 2. app.render 42 | // 3. page.render 43 | // 4. document.render 44 | // 45 | // On the client 46 | // 1. app.getInitialProps 47 | // 2. page.getInitialProps 48 | // 3. app.render 49 | // 4. page.render 50 | 51 | const originalRenderPage = ctx.renderPage; 52 | 53 | // You can consider sharing the same emotion cache between all the SSR requests to speed up performance. 54 | // However, be aware that it can have global side effects. 55 | const cache = createEmotionCache(); 56 | const { extractCriticalToChunks } = createEmotionServer(cache); 57 | 58 | /* eslint-disable */ 59 | ctx.renderPage = () => 60 | originalRenderPage({ 61 | enhanceApp: (App: any) => (props) => 62 | , 63 | }); 64 | /* eslint-enable */ 65 | 66 | const initialProps = await Document.getInitialProps(ctx); 67 | // This is important. It prevents emotion to render invalid HTML. 68 | // See https://github.com/mui-org/material-ui/issues/26561#issuecomment-855286153 69 | const emotionStyles = extractCriticalToChunks(initialProps.html); 70 | const emotionStyleTags = emotionStyles.styles.map((style) => ( 71 |