├── next.config.js ├── now.json ├── .gitignore ├── pages ├── About.js ├── Post.js └── index.js ├── components ├── Layout.js └── Header.js ├── package.json ├── server.js └── README.md /next.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | target: 'serverless' 3 | } 4 | -------------------------------------------------------------------------------- /now.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 2, 3 | "builds": [{ "src": "package.json", "use": "@now/next" }] 4 | } 5 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .idea/ 2 | *.log 3 | npm-debug.log 4 | yarn-error.log 5 | .DS_Store 6 | build/ 7 | node_modules/ 8 | dist/ 9 | .cache 10 | .next/ 11 | -------------------------------------------------------------------------------- /pages/About.js: -------------------------------------------------------------------------------- 1 | import Layout from "../components/Layout"; 2 | 3 | export default function About() { 4 | return ( 5 | 6 |

This is the about page

7 |
8 | ) 9 | }; 10 | -------------------------------------------------------------------------------- /components/Layout.js: -------------------------------------------------------------------------------- 1 | import Header from './Header' 2 | 3 | const layoutStyle = { 4 | margin: 20, 5 | padding: 20, 6 | border: '1px solid #DDD' 7 | }; 8 | 9 | const Layout = props => ( 10 |
11 |
12 | {props.children} 13 |
14 | ); 15 | 16 | export default Layout 17 | -------------------------------------------------------------------------------- /components/Header.js: -------------------------------------------------------------------------------- 1 | import Link from 'next/link'; 2 | 3 | const linkStyle = { 4 | marginRight: 15 5 | }; 6 | 7 | const Header = () => ( 8 |
9 | 10 | Home 11 | 12 | 13 | About 14 | 15 | 16 |
17 | ); 18 | 19 | export default Header; 20 | -------------------------------------------------------------------------------- /pages/Post.js: -------------------------------------------------------------------------------- 1 | import { withRouter } from 'next/router'; 2 | import Layout from '../components/Layout'; 3 | 4 | const Content = withRouter( props => ( 5 |
6 |

{ props.router.query.title }

7 |

This is the blog post content

8 |
9 | ) ); 10 | 11 | 12 | const Page = () => ( 13 | 14 | 15 | 16 | ); 17 | export default Page; 18 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "next-js-app", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "dev": "next", 8 | "build": "next build", 9 | "start": "next start -p $PORT", 10 | "now-build": "next build" 11 | }, 12 | "keywords": [], 13 | "author": "", 14 | "license": "ISC", 15 | "devDependencies": { 16 | "next": "^12.1.0", 17 | "react": "^16.8.6", 18 | "react-dom": "^16.8.6" 19 | }, 20 | "dependencies": { 21 | "express": "^4.17.1", 22 | "isomorphic-unfetch": "^3.0.0" 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /pages/index.js: -------------------------------------------------------------------------------- 1 | import Layout from '../components/Layout.js' 2 | import Link from 'next/link' 3 | import fetch from 'isomorphic-unfetch' 4 | 5 | const Index = (props) => ( 6 | 7 |

Batman TV Shows

8 | 17 | 42 |
43 | ); 44 | 45 | Index.getInitialProps = async function() { 46 | const res = await fetch('https://api.tvmaze.com/search/shows?q=batman'); 47 | const data = await res.json(); 48 | 49 | console.log(`Show data fetched. Count: ${data.length}`); 50 | 51 | return { 52 | shows: data.map(entry => entry.show) 53 | } 54 | }; 55 | 56 | 57 | 58 | export default Index 59 | -------------------------------------------------------------------------------- /server.js: -------------------------------------------------------------------------------- 1 | const express = require('express'); 2 | const next = require('next'); 3 | 4 | const port = parseInt(process.env.PORT, 10) || 3000; 5 | const dev = process.env.NODE_ENV !== 'production'; 6 | const app = next({ dev }); 7 | const handle = app.getRequestHandler(); 8 | 9 | app 10 | .prepare() 11 | .then(() => { 12 | const server = express(); 13 | 14 | // Express server handlers 15 | server.get('/p/:id', (req, res) => { 16 | const actualPage = '/post'; 17 | const queryParams = { title: req.params.id }; 18 | app.render(req, res, actualPage, queryParams); 19 | }); 20 | 21 | server.get('/post/:slug', (req, res) => { 22 | const queryParams = { slug: req.params.slug, apiRoute: 'post' }; 23 | app.render(req, res, '/post', queryParams); 24 | }); 25 | 26 | server.get('/page/:slug', (req, res) => { 27 | const queryParams = { slug: req.params.slug, apiRoute: 'page' }; 28 | app.render(req, res, '/post', queryParams); 29 | }); 30 | 31 | server.get('/category/:slug', (req, res) => { 32 | const queryParams = { slug: req.params.slug }; 33 | app.render(req, res, '/category', queryParams); 34 | }); 35 | 36 | // Fallback handler 37 | server.get('*', (req, res) => { 38 | return handle(req, res) 39 | }); 40 | 41 | // Listen on the default port (3000) 42 | server.listen(dev, err => { 43 | if (err) throw err; 44 | console.log('> Ready on http://localhost:3000') 45 | }) 46 | }) 47 | .catch(error => { 48 | console.error(error.stack); 49 | process.exit(1) 50 | }); 51 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Next JS Application 2 | 3 | # Full Series Tutorial 4 | https://codeytek.com/course/next-js-tutorials-for-beginners/ 5 | 6 | ## Description :clipboard: 7 | > A Next JS Application Demo. 8 | 9 | ## Installation :wrench: 10 | 11 | 1. Clone this repo by running `git clone https://github.com/imranhsayed/next-js-app` 12 | 2. `cd next-js-app` 13 | 3. `npm install` 14 | 4. `npm run dev` 15 | 16 | ## Useful Links: :link: 17 | 18 | 1. [Next JS Docs](https://nextjs.org/learn/basics/getting-started/setup) 19 | 20 | ## Instructions :point_right: 21 | 22 | ## Branches Information :point_right: 23 | 24 | 1. [simple-nextjs-app](https://github.com/imranhsayed/next-js-app/tree/simple-nextjs-app) Simple next js app 25 | 2. [express-with-next)](https://github.com/imranhsayed/next-js-app/tree/express-with-next)) Simple next js app with custom express server 26 | 3. [express-with-next-ssr)](https://github.com/imranhsayed/next-js-app/tree/express-with-next-ssr)) Custom end point by creating express server, and displaying clean URL for single post ( `'/post/slug' instead of '/post?id=22'` ) 27 | 3. [shared-component-navigation](https://github.com/imranhsayed/next-js-app/tree/shared-component-navigation) Example to show navigation and Creating Layout Component that can be shared between multiple component. 28 | 4. [dynamic-page-query-string](https://github.com/imranhsayed/next-js-app/tree/dynamic-page-query-string) Example to create dynamic post pages by extracting query string from url using `withRouter` 29 | 5. [route-masking](https://github.com/imranhsayed/next-js-app/tree/route-masking) Example to show a different URL on the browser than the actual URL that your app sees by adding "as" props to the link. 30 | 31 | ## [Custom Express Configuration with next js](https://github.com/imranhsayed/next-js-app/tree/express-with-next) 32 | 33 | ```ruby 34 | const express = require( 'express' ); 35 | const next = require( 'next' ); 36 | 37 | const port = 3000; 38 | const dev = process.env.NODE_ENV !== 'production'; 39 | const app = next( { dev } ); 40 | const handle = app.getRequestHandler(); 41 | 42 | /** 43 | * app (next js ) will prepare our server with express, and then, 44 | * wrap express application inside next 45 | * 46 | */ 47 | app.prepare() 48 | .then( () => { 49 | const server = express(); 50 | 51 | /** 52 | * This will override the default '/about' next js route and when user goes to '/about' 53 | * it will serve index.js because route '/' which we are rendering in app.render() belongs to index.js 54 | */ 55 | server.get( '/about', ( req, res ) => { 56 | return app.render( req, res, '/' ); 57 | } ); 58 | 59 | /** 60 | * Wrapping express app inside next will allow us to create routes by using 61 | * express js function inside of the next js build 62 | * 63 | * '*' means all routes which are not explicit , use this route for them. 64 | */ 65 | server.get( '*', ( req, res ) => { 66 | return handle( req, res ); 67 | } ); 68 | 69 | server.listen( port, ( err ) => { 70 | if ( err ) { 71 | throw err; 72 | } 73 | console.warn( `Ready on http://localhost:${port}` ); 74 | } ); 75 | } ); 76 | ``` 77 | 78 | ## Common Commands :computer: 79 | 80 | 1. `dev` Starts local development server at [http://localhost:3000](http://localhost:3000) 81 | 2. `build` Runs build 82 | 3. `start` Runs next js server 83 | 84 | ## Built With :zap: 85 | 86 | 1. Node 87 | 2. Express 88 | 3. React 89 | 4. Next JS 90 | 5. Webpack 91 | 6. Babel 92 | 93 | # Useful Blogs 94 | 95 | 1. [Headless WordPress with Next JS](https://medium.com/kata-engineering/headless-wordpress-next-js-what-we-learned-c10abdf80f6a) 96 | 97 | # Useful Links 98 | 99 | 1. [GraphQL API Plugin for WordPress](https://github.com/wp-graphql/wp-graphql) 100 | 101 | ## Author :bust_in_silhouette: 102 | 103 | * **[Imran Sayed](https://codeytek.com)** 104 | 105 | ## License 106 | 107 | [![License](http://img.shields.io/:license-mit-blue.svg?style=flat-square)](http://badges.mit-license.org) 108 | 109 | - **[MIT license](http://opensource.org/licenses/mit-license.php)** 110 | --------------------------------------------------------------------------------