├── 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 |
9 | {props.shows.map(show => (
10 | -
11 |
12 | {show.name}
13 |
14 |
15 | ))}
16 |
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 | [](http://badges.mit-license.org)
108 |
109 | - **[MIT license](http://opensource.org/licenses/mit-license.php)**
110 |
--------------------------------------------------------------------------------