├── .gitignore ├── .idea ├── .gitignore ├── misc.xml ├── modules.xml └── nextjs-material-ui.iml ├── README.md ├── package.json ├── pages ├── _app.js ├── _document.js ├── about.js └── index.js └── src ├── Copyright.js ├── Link.js ├── ProTip.js └── theme.js /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/ignore-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | 6 | # misc 7 | .DS_Store 8 | .env.local 9 | .env.development.local 10 | .env.test.local 11 | .env.production.local 12 | 13 | npm-debug.log* 14 | yarn-debug.log* 15 | yarn-error.log* 16 | 17 | # Next.js 18 | /.next 19 | -------------------------------------------------------------------------------- /.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # Default ignored files 2 | /shelf/ 3 | /workspace.xml 4 | # Editor-based HTTP Client requests 5 | /httpRequests/ 6 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /.idea/nextjs-material-ui.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Next.js example 2 | 3 | ## How to use 4 | 5 | Download the example [or clone the repo](https://github.com/mui-org/material-ui): 6 | 7 | ```sh 8 | curl https://codeload.github.com/mui-org/material-ui/tar.gz/master | tar -xz --strip=2 material-ui-master/examples/nextjs 9 | cd nextjs 10 | ``` 11 | 12 | Install it and run: 13 | 14 | ```sh 15 | npm install 16 | npm run dev 17 | ``` 18 | 19 | or: 20 | 21 | [![Edit on CodeSandbox](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/github/mui-org/material-ui/tree/master/examples/nextjs) 22 | 23 | ## The idea behind the example 24 | 25 | [Next.js](https://github.com/zeit/next.js) is a framework for server-rendered React apps. 26 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "nextjs", 3 | "version": "4.0.0", 4 | "private": true, 5 | "dependencies": { 6 | "@material-ui/core": "latest", 7 | "clsx": "latest", 8 | "next": "latest", 9 | "prop-types": "latest", 10 | "react": "latest", 11 | "react-dom": "latest" 12 | }, 13 | "scripts": { 14 | "dev": "next", 15 | "build": "next build", 16 | "start": "next start", 17 | "post-update": "echo \"codesandbox preview only, need an update\" && yarn upgrade --latest" 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /pages/_app.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import PropTypes from 'prop-types'; 3 | import Head from 'next/head'; 4 | import { ThemeProvider } from '@material-ui/core/styles'; 5 | import CssBaseline from '@material-ui/core/CssBaseline'; 6 | import theme from '../src/theme'; 7 | 8 | export default function MyApp(props) { 9 | const { Component, pageProps } = props; 10 | 11 | React.useEffect(() => { 12 | // Remove the server-side injected CSS. 13 | const jssStyles = document.querySelector('#jss-server-side'); 14 | if (jssStyles) { 15 | jssStyles.parentElement.removeChild(jssStyles); 16 | } 17 | }, []); 18 | 19 | return ( 20 | 21 | 22 | My page 23 | 24 | 25 | 26 | {/* CssBaseline kickstart an elegant, consistent, and simple baseline to build upon. */} 27 | 28 | 29 | 30 | 31 | ); 32 | } 33 | 34 | MyApp.propTypes = { 35 | Component: PropTypes.elementType.isRequired, 36 | pageProps: PropTypes.object.isRequired, 37 | }; 38 | -------------------------------------------------------------------------------- /pages/_document.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Document, { Html, Head, Main, NextScript } from 'next/document'; 3 | import { ServerStyleSheets } from '@material-ui/core/styles'; 4 | import theme from '../src/theme'; 5 | 6 | export default class MyDocument extends Document { 7 | render() { 8 | return ( 9 | 10 | 11 | {/* PWA primary color */} 12 | 13 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | ); 24 | } 25 | } 26 | 27 | // `getInitialProps` belongs to `_document` (instead of `_app`), 28 | // it's compatible with server-side generation (SSG). 29 | MyDocument.getInitialProps = async (ctx) => { 30 | // Resolution order 31 | // 32 | // On the server: 33 | // 1. app.getInitialProps 34 | // 2. page.getInitialProps 35 | // 3. document.getInitialProps 36 | // 4. app.render 37 | // 5. page.render 38 | // 6. document.render 39 | // 40 | // On the server with error: 41 | // 1. document.getInitialProps 42 | // 2. app.render 43 | // 3. page.render 44 | // 4. document.render 45 | // 46 | // On the client 47 | // 1. app.getInitialProps 48 | // 2. page.getInitialProps 49 | // 3. app.render 50 | // 4. page.render 51 | 52 | // Render app and page and get the context of the page with collected side effects. 53 | const sheets = new ServerStyleSheets(); 54 | const originalRenderPage = ctx.renderPage; 55 | 56 | ctx.renderPage = () => 57 | originalRenderPage({ 58 | enhanceApp: (App) => (props) => sheets.collect(), 59 | }); 60 | 61 | const initialProps = await Document.getInitialProps(ctx); 62 | 63 | return { 64 | ...initialProps, 65 | // Styles fragment is rendered after the app and page rendering finish. 66 | styles: [...React.Children.toArray(initialProps.styles), sheets.getStyleElement()], 67 | }; 68 | }; 69 | -------------------------------------------------------------------------------- /pages/about.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Container from '@material-ui/core/Container'; 3 | import Typography from '@material-ui/core/Typography'; 4 | import Box from '@material-ui/core/Box'; 5 | import Button from '@material-ui/core/Button'; 6 | import ProTip from '../src/ProTip'; 7 | import Link from '../src/Link'; 8 | import Copyright from '../src/Copyright'; 9 | 10 | export default function About() { 11 | return ( 12 | 13 | 14 | 15 | Next.js example 16 | 17 | 20 | 21 | 22 | 23 | 24 | ); 25 | } 26 | -------------------------------------------------------------------------------- /pages/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Container from '@material-ui/core/Container'; 3 | import Typography from '@material-ui/core/Typography'; 4 | import Box from '@material-ui/core/Box'; 5 | import ProTip from '../src/ProTip'; 6 | import Link from '../src/Link'; 7 | import Copyright from '../src/Copyright'; 8 | 9 | export default function Index() { 10 | return ( 11 | 12 | 13 | 14 | Next.js example 15 | 16 | 17 | Go to the about page 18 | 19 | 20 | 21 | 22 | 23 | ); 24 | } 25 | -------------------------------------------------------------------------------- /src/Copyright.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Typography from '@material-ui/core/Typography'; 3 | import MuiLink from '@material-ui/core/Link'; 4 | 5 | export default function Copyright() { 6 | return ( 7 | 8 | {'Copyright © '} 9 | 10 | Your Website 11 | {' '} 12 | {new Date().getFullYear()} 13 | {'.'} 14 | 15 | ); 16 | } 17 | -------------------------------------------------------------------------------- /src/Link.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable jsx-a11y/anchor-has-content */ 2 | import React from 'react'; 3 | import PropTypes from 'prop-types'; 4 | import clsx from 'clsx'; 5 | import { useRouter } from 'next/router'; 6 | import NextLink from 'next/link'; 7 | import MuiLink from '@material-ui/core/Link'; 8 | 9 | const NextComposed = React.forwardRef(function NextComposed(props, ref) { 10 | const { as, href, ...other } = props; 11 | 12 | return ( 13 | 14 | 15 | 16 | ); 17 | }); 18 | 19 | NextComposed.propTypes = { 20 | as: PropTypes.oneOfType([PropTypes.string, PropTypes.object]), 21 | href: PropTypes.oneOfType([PropTypes.string, PropTypes.object]), 22 | prefetch: PropTypes.bool, 23 | }; 24 | 25 | // A styled version of the Next.js Link component: 26 | // https://nextjs.org/docs/#with-link 27 | function Link(props) { 28 | const { 29 | href, 30 | activeClassName = 'active', 31 | className: classNameProps, 32 | innerRef, 33 | naked, 34 | ...other 35 | } = props; 36 | 37 | const router = useRouter(); 38 | const pathname = typeof href === 'string' ? href : href.pathname; 39 | const className = clsx(classNameProps, { 40 | [activeClassName]: router.pathname === pathname && activeClassName, 41 | }); 42 | 43 | if (naked) { 44 | return ; 45 | } 46 | 47 | return ( 48 | 49 | ); 50 | } 51 | 52 | Link.propTypes = { 53 | activeClassName: PropTypes.string, 54 | as: PropTypes.oneOfType([PropTypes.string, PropTypes.object]), 55 | className: PropTypes.string, 56 | href: PropTypes.oneOfType([PropTypes.string, PropTypes.object]), 57 | innerRef: PropTypes.oneOfType([PropTypes.func, PropTypes.object]), 58 | naked: PropTypes.bool, 59 | onClick: PropTypes.func, 60 | prefetch: PropTypes.bool, 61 | }; 62 | 63 | export default React.forwardRef((props, ref) => ); 64 | -------------------------------------------------------------------------------- /src/ProTip.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { makeStyles } from '@material-ui/core/styles'; 3 | import Link from '@material-ui/core/Link'; 4 | import SvgIcon from '@material-ui/core/SvgIcon'; 5 | import Typography from '@material-ui/core/Typography'; 6 | 7 | function LightBulbIcon(props) { 8 | return ( 9 | 10 | 11 | 12 | ); 13 | } 14 | 15 | const useStyles = makeStyles((theme) => ({ 16 | root: { 17 | margin: theme.spacing(6, 0, 3), 18 | }, 19 | lightBulb: { 20 | verticalAlign: 'middle', 21 | marginRight: theme.spacing(1), 22 | }, 23 | })); 24 | 25 | export default function ProTip() { 26 | const classes = useStyles(); 27 | return ( 28 | 29 | 30 | Pro tip: See more{' '} 31 | templates on the 32 | Material-UI documentation. 33 | 34 | ); 35 | } 36 | -------------------------------------------------------------------------------- /src/theme.js: -------------------------------------------------------------------------------- 1 | import { createMuiTheme } from '@material-ui/core/styles'; 2 | import { red } from '@material-ui/core/colors'; 3 | 4 | // Create a theme instance. 5 | const theme = createMuiTheme({ 6 | palette: { 7 | primary: { 8 | main: '#556cd6', 9 | }, 10 | secondary: { 11 | main: '#19857b', 12 | }, 13 | error: { 14 | main: red.A400, 15 | }, 16 | background: { 17 | default: '#fff', 18 | }, 19 | }, 20 | }); 21 | 22 | export default theme; 23 | --------------------------------------------------------------------------------