{"id":20314782,"url":"https://github.com/xizon/fullstack-nextjs-app-template","last_synced_at":"2025-04-12T06:19:57.880Z","repository":{"id":63393302,"uuid":"559400712","full_name":"xizon/fullstack-nextjs-app-template","owner":"xizon","description":"A full-stack sample web application based on Next.js that creates a simple whole-website architecture","archived":false,"fork":false,"pushed_at":"2024-12-24T09:56:49.000Z","size":3883,"stargazers_count":158,"open_issues_count":1,"forks_count":69,"subscribers_count":4,"default_branch":"main","last_synced_at":"2024-12-27T19:33:00.642Z","etag":null,"topics":["docker-images","express","expressjs","next","nextjs","nextjs-example","nextjs-starter","nextjs-template","pm2","react","reactjs","server-side-rendering","ssr","typescript"],"latest_commit_sha":null,"homepage":"https://fullstack-nextjs-app-template.vercel.app","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/xizon.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-10-30T01:48:50.000Z","updated_at":"2024-12-25T14:13:28.000Z","dependencies_parsed_at":"2023-01-23T00:46:18.817Z","dependency_job_id":"96bd9849-42f7-4de9-a1b3-66365b83e507","html_url":"https://github.com/xizon/fullstack-nextjs-app-template","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xizon%2Ffullstack-nextjs-app-template","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xizon%2Ffullstack-nextjs-app-template/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xizon%2Ffullstack-nextjs-app-template/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xizon%2Ffullstack-nextjs-app-template/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/xizon","download_url":"https://codeload.github.com/xizon/fullstack-nextjs-app-template/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248525425,"owners_count":21118670,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["docker-images","express","expressjs","next","nextjs","nextjs-example","nextjs-starter","nextjs-template","pm2","react","reactjs","server-side-rendering","ssr","typescript"],"created_at":"2024-11-14T18:16:42.086Z","updated_at":"2025-04-12T06:19:57.858Z","avatar_url":"https://github.com/xizon.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Full-Stack Next.js Application Template\n\n This repository is a full-stack sample web application based on Next.js that creates a simple whole-website architecture, and provides the foundational services, components, and plumbing needed to get a basic web application up and running. \n\n\n\n![quick overview](public/assets/images/screenshot.jpg)\n\n\n## Table of Contents\n\n* [Scheme](#scheme)\n* [File Structures](#file-structures)\n* [Getting Started](#getting-started)\n* [Further Help](#further-help)\n*  - [(💎 Incremental Guide) Migrating from Pages Router to App Router](#---incremental-guide-migrating-from-pages-router-to-app-router)\n*  - [Deploy on Custom Server](#--deploy-on-custom-server)\n*  - [Deploy on Custom Server](#--deploy-on-custom-server)\n*  - [Node.js Port 3000 already in use but it actually isn't?](#--nodejs-port-3000-already-in-use-but-it-actually-isnt)\n*  - [Change the Favicon](#--change-the-favicon)\n*  - [Customize Menu](#--customize-menu)\n*  - [Set port in next.js](#--set-port-in-nextjs)\n*  - [Set basePath for a static exported](#--set-basepath-for-a-static-exported)\n*  - [Site URL (Root Directory) Configurations](#--site-url-root-directory-configurations)\n*  - [Deploy Using Docker (build a single next.js program image)](#--deploy-using-docker-build-a-single-nextjs-program-image)\n*  - [Deploy Using Docker (Build composite image that include other custom images)](#--deploy-using-docker-build-composite-image-that-include-other-custom-images)\n*  - [Deploy Using Docker (Common Load-balancing Solutions of Socket.io Issue)](#--deploy-using-docker-common-load-balancing-solutions-of-socketio-issue)\n*  - [Installation Error or Unable To Run](#--installation-error-or-unable-to-run)\n* [Contributing](#contributing)\n* [Supported development environment](#supported-development-environment)\n* [Changelog](#changelog)\n* [Licensing](#licensing)\n\n\n\n## Scheme\n\nList my progress here:\n\n\n| Function Block |  Supports  |\n| --- | --- |\n| 💎 Pages Router Demo Template | ✅  👉🏼 Enabling it requires renaming the folder [@pages](@pages) to `pages`, and deleting [app](app). |\n| 💎 App Router Demo Template | ✅ 👉🏼 Default |\n| 💎 Exporting Pure HTML Static Files (**.html**) | ✅  👉🏼 run `npm run export` and `npm run export:fix`|\n| HTTP Navigation (SSR \u0026 Async) | ✅ |\n| Multiple API Constructs | ✅ |\n| Parameter Acquisition | ✅ |\n| Pagination | ✅ |\n| Basic Importing Methods for Components | ✅ |\n| Authorization | ✅ |\n| Login | ✅ |\n| Network Requests | ✅ |\n| API Demo | ✅ |\n| CURD Demo | ✅ |\n| JWT Demo | ✅ |\n| File Import | ✅ |\n| SEO Premium | ✅ |\n| Static Pages | ✅ |\n| Incremental Static Regeneration | ✅ |\n| Remote Download | ✅ |\n| Fully Static HTML Files Generation | ✅ |\n| Custom Server | ✅ |\n| Custom Hooks (auth, redux, draggable, keypress etc.) | ✅ |\n| Frontend Page Interacts With Node | ✅ |\n| Alias Support | ✅ |\n| Local PHP Service Association | ✅ |\n| Server Deployment | ✅ |\n| Deploy Using Docker | ✅ |\n| Redux Supplement (for navigation) | ✅ |\n| Redux SSR (for homepage navigation) | ✅ |\n| WebSocket Support via `socket.io` | ✅ |\n| Additional Node.js Services | ✅ |\n| Request Cache Demo | ✅ |\n| Authentication of Microservices | ✅ |\n| Markdown Render Demo | ✅ |\n| Video stream demo (normal, encryption and decryption modes) | ✅ 👉🏼 Check out the Next API directory and [src/components/VideoPlayer](src/components/VideoPlayer) |\n| NestJS Server Demo | ✅ 👉🏼 Go to the folder [backend@nest](backend@nest) |\n| 🍗 Compress and optimize all files in a folder. | ⚠️ *unbundled* 👉🏼 [imgop](https://github.com/xizon/imgop) |\n| 🍗 End-to-end typesafe API (gRPC) | ⚠️ *unbundled* 👉🏼 [gRPC Getting Started](https://github.com/xizon/grpc-getting-started) |\n| 🍗 React UI Components Libraries | ⚠️ *unbundled* 👉🏼 [Funda UI](https://github.com/xizon/funda-ui) |\n| 🍗 Nextjs Doc Template | ⚠️ *unbundled* 👉🏼 [Nextjs Doc Template](https://github.com/xizon/nextjs-doc-template) |\n\n\n\n\n\n## File Structures\n\n\n```sh\nfullstack-nextjs-app-template/\n├── README.md\n├── CHANGELOG.md\n├── LICENSE\n├── next.config.js\n├── server.js\n├── ecosystem.config.js\n├── middleware.ts\n├── tsconfig.json\n├── package-lock.json\n├── package.json \n├── .dockerignore\n├── Dockerfile\n├── docker-compose.yml\n├── out/                # Folder generated by export command which contains the HTML/CSS/JS assets for your application\n├── backend@nest/       # NestJS server\n├── backend/            # Express server\n│   ├── server-php.js \n│   └── ...             # All other files are optional\n├── scripts/            # Node Script Library\n├── public/             # Contains static resources, PHP remote test files, .md files for markdown rendering, etc.\n├── app/                # App Router Demo Template\n├── @pages/             # Pages Router Demo Template (Enabling it requires renaming the folder `@pages` to `pages`, and deleting `app`.)\n│   ├── api/\n│   └── *.tsx\n├── src/\n│   ├── config/\n│   ├── data/\n│   ├── contexts/\n│   ├── interfaces/\n│   ├── components/\n│   ├── styles/\n│   ├── utils/\n│   └── store/\n└──\n```\n\n\n\n\n## Getting Started\n\nMake sure if NODEJS is installed on your computer.\n\n### Install  Dependencies:\n\n```sh\n$ npm install\n```\nIt will create `node_module` folder in this all dependency files will be install with this command.\n\n### Update Next.js:\n\n```sh\n$ npm i next@latest react@latest react-dom@latest eslint-config-next@latest\n```\n\ncheck out [here](https://nextjs.org/docs/pages/building-your-application/upgrading)\n\n\n\n### Run Project in development mode:\n\n\u003e A php service assisted test was launched.\n\n```sh\n$ npm run dev \u0026 npm run action:phpserver  \n```\nWith is command file will be compiled and it will be loaded on local server [http://localhost:3000](http://localhost:3000).\n\n\n### Production Build :\n\n```sh\n$ npm run build \n```\n**Note:** Defer generating all pages on-demand by this command. You can have faster builds by generating all pages on-demand for previews (but not production builds). This is helpful for sites with hundreds/thousands of static pages.\n\n\n```sh\n$ npm run build:static \n```\nThis build mode will generate static data.\n\n\n\n### Start a Next.js production server:\n\n```sh\n$ npm run start\n```\n\n\n\n### Run PHP server independently (Separate start port 4000 service)**\n\nPlease install php on your computer first. Once enabled, you can test the background management features.\n\n**a) for `Express`**\n```sh\n$ npm run action:phpserver\n```\n\n\n**b) for `NestJS` in \"./backend@nest\" **\n```sh\n$ cd backend@nest\n\n# generate an executable file (you can run \"npm run action:phpserver:nest\")\n$ npm run build\n\n# development\n$ npm run start\n\n# watch mode\n$ npm run start:dev\n\n# production mode\n$ npm run start:prod\n```\n\n\nPlease use a PHP server environment with a local port of 4000, check the file at `./backend/server-php.js` (for Express) or `./backend@nest/dist/main.js` (for NestJS)\n\nWith is command file will be compiled and it will be loaded on local server [http://localhost:4000](http://localhost:4000).\n\n\n\n### Deploy node server on hosting server:\n\n**production mode:**\n```sh\n$ npm run build  # this command must be run first\n$ npm run deploy:prod \n```\n\n**development mode:**\n```sh\n$ npm run deploy:dev \n```\n\n*(If it doesn't work because of Node permission, use the following [commands](#deploy-on-custom-server-commands))*\n\n### Stop the existing deployments\n```sh\n$ npm run destroy\n```\n\n\n### Export your Next.js application to static HTML\n\n\nFIrst, you need to enable [Static Exports](https://nextjs.org/docs/pages/building-your-application/deploying/static-exports).\n\n\n\u003e [!WARNING]\n\u003e [ISR](https://nextjs.org/docs/pages/building-your-application/rendering/incremental-static-regeneration) cannot be used with \"output: export\". \n\n\n\n**Step 1. generate static resources:**\n```sh\n$ npm run export\n```\n\n**Step 2. fix name for HTML files:**\n```sh\n$ npm run export:fix\n```\n\n**Step 3. preview the static site**\n\nThen, test the generated static website (the HTML static website is located in the directory `.out/`). Access using the URL [http://localhost:12345](http://localhost:12345)\n\n```sh\n$ npm run export:test\n```\n\n\n\n\n## Further Help\n\n\u003cdetails\u003e\n  \u003csummary\u003e\u003ch4\u003e 👉🏼 (💎 Incremental Guide) Migrating from Pages Router to App Router\u003c/h4\u003e\u003c/summary\u003e\n  \nCheck out [this article](https://clerk.com/blog/migrating-pages-router-to-app-router-an-incremental-guide)\n\n### [0\\. Create the /app directory](#0-create-the-app-directory)\n\nBefore you can get started with the App Router, you will first need to create a **/app** directory as a sibling to your **/pages** directory.\n\n### [1\\. Migrate /pages/\\_document to the App Router](#1-migrate-pages-document-to-the-app-router)\n\nIf you have a [Custom Document](https://nextjs.org/docs/pages/building-your-application/routing/custom-document) at **/pages/\\_document.tsx**, it should look something like this, though likely with some customization:\n\n/pages/\\_document.tsx\n```js\nimport { Html, Head, Main, NextScript } from 'next/document'\n\nexport default function Document() {\n    return (\n    \u003cHtml\u003e\n        \u003cHead /\u003e\n        \u003cbody\u003e\n        \u003cMain /\u003e\n        \u003cNextScript /\u003e\n        \u003c/body\u003e\n    \u003c/Html\u003e\n    )\n}\n```\nWe need to convert this into a [Root Layout](https://nextjs.org/docs/app/building-your-application/routing/pages-and-layouts#root-layout-required), which can be treated as a 1-to-1 corollary to a Custom Document:\n\n1.  Clone **/pages/\\_document.tsx** into **/app/layout.tsx**. We will keep both files since we're doing incremental adoption. (If you use .jsx that is no problem, you can use layout.jsx instead)\n2.  Remove the **next/document** import line entirely\n3.  Replace `\u003cHtml\u003e` and `\u003c/Html\u003e` with the lowercase, HTML equivalent `\u003chtml\u003e` and `\u003c/html\u003e`. For accessibility, it's best to add a language to your opening tag, like `\u003chtml lang=\"en\"\u003e`\n4.  Replace `\u003cHead\u003e` and `\u003c/Head\u003e` with the lowercase, HTML equivalent `\u003chead\u003e` and `\u003c/head\u003e`. If you only have a self-closing `\u003cHead /\u003e`, you can remove it entirely\n5.  Replace `\u003cMain /\u003e` with `{children}`, and update the default function export to accept a `{children}` argument. For Typescript users, `children` is of type `React.ReactNode`\n6.  Remove `\u003cNextScript /\u003e` entirely\n\nWhen complete, **/app/layout.tsx** should look more like this, plus your customizations:\n\n/app/layout.tsx\n```js\nexport default function RootLayout({ children }: { children: React.ReactNode }) {\n    return (\n    \u003chtml lang=\"en\"\u003e\n        \u003cbody\u003e{children}\u003c/body\u003e\n    \u003c/html\u003e\n    )\n}\n```\n**Important: /app/layout.tsx is required** in the **/app** directory. If you do not have a Custom Document, you can copy-paste the above sample directly into **/app/layout.tsx**.\n\n### [2\\. Migrate /pages/\\_app.tsx to the App Router](#2-migrate-pages-app-tsx-to-the-app-router)\n\n**Note:** If you do not have a file at **/pages/\\_app.tsx** you can skip to Step 3.\n\nIf you have a [Custom App](https://nextjs.org/docs/pages/building-your-application/routing/custom-app) at **/pages/\\_app.tsx**, it should look something like this, though likely with some customization:\n\n/pages/\\_app.tsx\n```js\nimport type { AppProps } from 'next/app'\n\nexport default function MyApp({ Component, pageProps }: AppProps) {\n    return \u003cComponent {...pageProps} /\u003e\n}\n```\nThe **/app** directory does not have a 1-to-1 corollary for a Custom App, but it can easily be expressed in the new structure:\n\n1.  Clone **/pages/\\_app.tsx** into **/app/ClientLayout.tsx**. We will keep both files since we're doing incremental adoption. (If you use .jsx that is no problem, you can use ClientLayout.jsx instead)\n2.  Add a new line to the top of the file that reads `\"use client\"` (with the quotes)\n3.  Replace the default export's function signature. Instead of taking `Component` and `pageProps` arguments, it should only take a `children` argument. For Typescript users, `children` is of type `React.ReactNode`.\n4.  Replace `\u003cComponent {...pageProps} /\u003e` with `\u003c\u003e{children}\u003c/\u003e`, or just `{children}` if you have another wrapping element\n5.  If there are any remaining references to `pageProps`, please comment them out for now, and revisit them on a page-by-page basis. Next.js has added a new [metadata API](https://nextjs.org/docs/app/building-your-application/optimizing/metadata) that should normally be used in place of accessing `pageProps` here\n6.  We recommend changing the default export name from `MyApp` to `ClientLayout`. It is not strictly necessary, but it is more conventional\n\nWhen complete, **/app/ClientLayout.tsx** should look more like this, plus your customizations:\n\n/app/ClientLayout.tsx\n```js\n'use client'\n\nexport default function ClientLayout({ children }: { children: React.ReactNode }) {\n    return \u003c\u003e{children}\u003c/\u003e\n}\n```\nNow, this is where things get a little different:\n\n*   In the Pages Router, **/pages/\\_app.tsx** is a \"magic\" layout file that is automatically added to the React tree\n*   In the App Router, the only layout file automatically added to the React tree is the Root Layout from Step 1. So, we will need to manually import and mount our `ClientLayout` inside **/app/layout.tsx**\n\nOpen **/app/layout.tsx**, import ClientLayout, and use it to wrap `{children}`. When complete, your Root Layout should look like this, plus any customizations from Step 1:\n\n/app/layout.tsx\n```js\nimport ClientLayout from './ClientLayout'\n\nexport default function RootLayout({ children }: { children: React.ReactNode }) {\n    return (\n    \u003chtml lang=\"en\"\u003e\n        \u003cbody\u003e\n        \u003cClientLayout\u003e{children}\u003c/ClientLayout\u003e\n        \u003c/body\u003e\n    \u003c/html\u003e\n    )\n}\n```\n### [3\\. Migrate each page to the App Router](#3-migrate-each-page-to-the-app-router)\n\nNow that your layout has been copied into the App Router, it's time to start migrating your pages one-by-one. There will be a few steps for each page:\n\n1.  Create a directory for the page\n2.  Create one file to handle data fetching\n3.  Create one file to render the page\n4.  Remove the Pages Router page\n\nFor the avoidance of doubt: yes, we will be splitting your Pages Router page into two files: one for data fetching and one for rendering.\n\n#### [3.1. Create a directory for the page](#3-1-create-a-directory-for-the-page)\n\nBoth the Pages Router and the App Router are \"filesystem routers,\" but they are organized slightly differently. In the App Router, each page gets its own directory. Here is how to determine the directory name:\n\n*   If your file is named **index.tsx**, create the same parent directory structure\n    \n    *   For **/pages/foo/index.tsx**, create **/app/foo**\n    *   For **/pages/index.tsx**, you already have **/app**\n    \n*   If your file is **not** named **index.tsx**, create a directory with that filename\n    \n    *   For **/pages/bar.tsx**, create **/app/bar**\n    *   For **/pages/baz/\\[slug\\].tsx**, create **/app/baz/\\[slug\\]**\n    *   For **/pages/baz/\\[\\[...slug\\].tsx**, create **/app/baz/\\[\\[...slug\\]\\]**\n    \n\n#### [3.2. Create a file to handle data fetching](#3-2-create-a-file-to-handle-data-fetching)\n\nInside your page directory, create a file called **page.tsx** to handle data fetching. Copy-paste the following snippet as the foundation of this file (**Note:** we will create **ClientPage.tsx** in 3.3.):\n\npage.tsx\n```js\nimport ClientPage from './ClientPage'\n\nexport default async function Page() {\n    return \u003cClientPage /\u003e\n}\n```\nIf your Pages Router file does not have any data fetching, you can continue on to the next step. Otherwise, find your data fetcher below to learn how it can be migrated:\n\n**Migrating getStaticProps to the App Router**\n\nConsider the following is your implementation of `getStaticProps`:\n```js\nexport const getStaticProps: GetStaticProps\u003cPageProps\u003e = async () =\u003e {\n    const res = await fetch('https://api.github.com/repos/vercel/next.js')\n    const repo = await res.json()\n    return { props: { repo } }\n}\n```\nTo migrate this with as little modification as possible, we will:\n\n1.  Copy-paste `getStaticProps` into **page.tsx**\n2.  Call `getStaticProps` from within our `Page` component\n3.  Add `export const dynamic = \"force-static\"` so the page data is fetched once and cached, not refetched on every load \n4.  Pass the result to our (not yet created) `ClientPage` component\n\nHere is the end result:\n\npage.tsx\n```js\nimport ClientPage from './ClientPage'\n\nexport const getStaticProps: GetStaticProps\u003cPageProps\u003e = async () =\u003e {\n    const res = await fetch('https://api.github.com/repos/vercel/next.js')\n    const repo = await res.json()\n    return { props: { repo } }\n}\n\nexport const dynamic = 'force-static'\n\nexport default async function Page() {\n    const { props } = await getStaticProps()\n    return \u003cClientPage {...props} /\u003e\n}\n```\n**Migrating getServerSideProps to the App Router**\n\nConsider the following implementation of `getServerSideProps`:\n```js\nimport { getAuth } from '@clerk/nextjs/server'\n\nexport const getServerSideProps: GetServerSideProps\u003cPageProps\u003e = async ({ req }) =\u003e {\n    const { userId } = getAuth(req)\n\n    const res = await fetch('https://api.example.com/foo', {\n    headers: {\n        Authorization: `Bearer: ${process.env.API_KEY}`,\n    },\n    })\n    const data = await res.json()\n    return { props: { data } }\n}\n```\nTo migrate this with as little modification as possible, we will:\n\n1.  Copy-paste `getServerSideProps` into **page.tsx**\n2.  Add `export const dynamic = \"force-dynamic\"` so the page data is refetched on every load, [reference docs](https://nextjs.org/docs/app/building-your-application/data-fetching/fetching-caching-and-revalidating)\n3.  Replace any usage of `req` with the App Router equivalent\n4.  Our example uses [Clerk for authentication](/solutions/nextjs-authentication), so the end result will replace this line with its App Router-compatible replacement\n5.  Replace `req.headers` with the new [headers() helper](https://nextjs.org/docs/app/api-reference/functions/headers)\n6.  Replace `req.cookies` with the new [cookies() helper](https://nextjs.org/docs/app/api-reference/functions/headers)\n7.  Replace `req.url.searchParams` with the new [searchParams helper](https://nextjs.org/docs/app/api-reference/file-conventions/page#searchparams-optional)\n8.  Replace any Dynamic Route segment usage with the new [params helper](https://nextjs.org/docs/app/api-reference/file-conventions/page#params-optional)\n9.  Call `getServerSideProps` from within our `Page` component\n10.  Pass the result to our (not yet created) `ClientPage` component\n\nHere is the end result:\n\npage.tsx\n```js\nimport { auth } from '@clerk/nextjs'\nimport ClientPage from './ClientPage'\n\nexport const getServerSideProps: GetServerSideProps\u003cPageProps\u003e = async () =\u003e {\n    const { userId } = auth()\n\n    const res = await fetch('https://api.example.com/foo', {\n    headers: {\n        Authorization: `Bearer: ${process.env.API_KEY}`,\n    },\n    })\n    const data = await res.json()\n    return { props: { data } }\n}\n\nexport const dynamic = 'force-dynamic'\n\nexport default async function Page() {\n    const { props } = await getServerSideProps()\n    return \u003cClientPage {...props} /\u003e\n}\n```\n**Migrating getStaticPaths to the App Router**\n\nConsider the following implementation of `getStaticPaths`:\n```js\nexport async function getStaticPaths() {\n    return {\n    paths: [{ params: { id: '1' } }, { params: { id: '2' } }],\n    }\n}\n```\nIn the App Router, this implementation barely changes. It's simply given a new name (`generateStaticParams`) and the output is transformed to something simpler. That means you can use your old implementation directly, and simply transform the output.\n\nHere is the end result – we included an example of how it can be used in tandem with `getStaticProps`:\n\npage.tsx\n```js\nimport ClientPage from './ClientPage'\n\nexport async function getStaticPaths() {\n    return {\n    paths: [{ params: { id: '1' } }, { params: { id: '2' } }],\n    }\n}\n\nexport async function generateStaticParams() {\n    const staticPaths = await getStaticPaths()\n    return staticPaths.paths.map((x) =\u003e x.params)\n}\n\nexport const getStaticProps: GetStaticProps\u003cPageProps\u003e = async ({ params }) =\u003e {\n    const res = await fetch(`https://api.example.com/foo/${params.id}`)\n    const data = await res.json()\n    return { props: { data } }\n}\n\nexport default async function Page({ params }) {\n    const { props } = await getStaticProps({ params })\n    return \u003cClientPage {...props} /\u003e\n}\n```\n#### [3.3. Create a file to render the page](#3-3-create-a-file-to-render-the-page)\n\nNow that data fetching is ready, we need to configure the rendering. To accomplish this:\n\n*   Copy your original Pages Router page into **ClientPage.tsx**\n*   Remove any data fetching code, since it now lives in **page.tsx**\n\nThat's it! We have already configured **page.tsx** to mount this file and pass props, so it should be working.\n\n#### [3.4. Remove the Pages Router page](#3-4-remove-the-pages-router-page)\n\nNow that your page is ready in the App Router, you can delete the old Pages Router variant.\n\n\n[MORE: App Router Incremental Adoption Guide](https://nextjs.org/docs/app/building-your-application/upgrading/app-router-migration)\n\n\u003c/details\u003e\n\n\n\n\u003cdetails\u003e\n  \u003csummary\u003e\u003ch4\u003e 👉🏼 Deploy on Custom Server\u003c/h4\u003e\u003c/summary\u003e\n  \n\n\u003e 📌 Note: Using server.js may cause an error during [HMR] restart (first loading of the client): \n\u003e *WebSocket connection to 'ws://localhost:3000/_next/webpack-hmr' failed:* --\u003e *InvalidArgumentError: invalid upgrade header*\n\u003e You can ignore it.\n\n### 👣 (Step 1) Create a file as the server startup entry\n\nCreate a new file `server.js` (do not use `.ts`) at the same level as your `pages` directory. Take a look at the following example of a custom server:\n\n```js\nconst { createServer } = require('http');\nconst { parse } = require('url');\nconst next = require('next');\n\nlet dev = process.env.NODE_ENV !== 'production';\ndev = false;  // need run `npm run build` first\nconst hostname = 'localhost';\nconst port = 3000;\n// when using middleware `hostname` and `port` must be provided below\nconst app = next({ dev, hostname, port });\nconst handle = app.getRequestHandler();\n\napp.prepare().then(() =\u003e {\n  createServer(async (req, res) =\u003e {\n    try {\n      // Be sure to pass `true` as the second argument to `url.parse`.\n      // This tells it to parse the query portion of the URL.\n      const parsedUrl = parse(req.url, true)\n      const { pathname, query } = parsedUrl\n\n      if (pathname === '/a') {\n        await app.render(req, res, '/a', query)\n      } else if (pathname === '/b') {\n        await app.render(req, res, '/b', query)\n      } else {\n        await handle(req, res, parsedUrl)\n      }\n      \n    } catch (err) {\n      console.error('Error occurred handling', req.url, err)\n      res.statusCode = 500\n      res.end('internal server error')\n    }\n  }).listen(port, (err) =\u003e {\n    if (err) throw err\n    console.log(`\u003e Ready on http://${hostname}:${port}`)\n  })\n})\n```\n\n\n#### Enabling HTTPS on Local Server\n\nModify the file `server.js`, use [https.createServer([options][, requestListener])](https://nodejs.org/api/https.html#httpscreateserveroptions-requestlistener) to wrap the express service, please check out the sample code below:\n\n\n```js\n// Supprt HTTPS\nconst fs = require('fs');\nconst path = require('path');\nconst https = require('https');\nconst cert = fs.readFileSync(path.join(__dirname,'../../path/bundle.crt'));\nconst key = fs.readFileSync(path.join(__dirname,'../../path/ca.key'));\nconst options = {key: key, cert: cert };\n\n\napp.prepare().then(() =\u003e {\n    https.createServer(options, async (req, res) =\u003e {\n        try {\n            ...\n        } catch (err) {\n            console.error('Error occurred handling', req.url, err)\n            res.statusCode = 500\n            res.end('internal server error')\n        }\n    }).listen(port, (err) =\u003e {\n        if (err) throw err\n        console.log(`\u003e Ready on https://${hostname}:${port}`)\n    })\n})\n```\n\naccess with `https://localhost:3000` or `https://{YOUR_IP}:3000`\n\n\n\n### 👣 (Step 2) Configure `package.json` \n\nTo run the custom server you'll need to update the scripts in package.json like so:\n```json\n\"scripts\": {\n  \"dev\": \"node server.js\",\n  \"start\": \"NODE_ENV=production node server.js\"\n}\n```\n\n**(Optional).** Disabling file-system routing\n```js\nmodule.exports = {\n  useFileSystemPublicRoutes: false,\n}\n```\n\n### 👣 (Step 3) Install PM2 environment\n\nStart Next.js application with PM2 as a service (only works if you are using Node v18.17.0 or above.)\n\n#### 3.1) Installing Node and NPM on hosting server **(Optional).**\n\nNode14+ version will be installed here\n\n```sh\n$ curl -sL https://rpm.nodesource.com/setup_14.x | sudo bash -\n$ sudo yum install nodejs\n$ node --version  #v14.16.1\n$ npm --version   #6.14.12\n```\n\n\n#### 3.2) Installing PM2. With NPM\n\n```sh\n$ sudo npm install pm2@latest -g\n```\n\n\u003ca id=\"deploy-on-custom-server-commands\"\u003e\u003c/a\u003e\n\n#### 3.3) Frequently used commands for PM2:\n\n```sh\n#into your `\"fullstack-nextjs-app-template/\"` folder directory.\n$ cd /{your_directory}/fullstack-nextjs-app-template\n\n\n#run app\n$ pm2 start ecosystem.config.js\n\n#other commands\n$ pm2 restart ecosystem.config.js\n$ pm2 stop ecosystem.config.js\n$ pm2 delete ecosystem.config.js\n$ pm2 list\n$ pm2 logs\n```\n\n\n#### 3.4) 🏹 Now once your build complete successfully run below command to run your Next.js with PM2\n\n```sh\n$ pm2 start npm --name \"fullstack-nextjs-app-template\" -- start\n```\n\ndestroy process:\n```sh\n$ pm2 stop \"fullstack-nextjs-app-template\" \u0026 pm2 delete \"fullstack-nextjs-app-template\"\n```\n\n\n#### 3.5) Detect available init system, generate configuration and enable startup system, and you can check the status of the same using\n\n```sh\n$ pm2 startup\n$ systemctl status pm2-root\n$ pm2 start /{your_directory}/fullstack-nextjs-app-template/ecosystem.config.js --restart-delay=3000\n$ pm2 save\n```\n\n\n\n\u003cblockquote\u003e\n\u003ch3\u003e💡 Some solutions to problems that may occur when deploying the application with NPM or PM2 on cloud server:\u003c/h3\u003e\n \n**a）The `build` or `dev` command fails**\n\nWhen on an M1 Mac and switching from a Node.js version without M1 support to one with, e.g. v14 to v16, you may need a different swc dependency which can require re-installing `node_modules` (npm i --force or yarn install --force).\n\n```sh\n$ npm i --force  # This can be ignored if you can build\n$ rm -rf /{your_directory}/fullstack-nextjs-app-template/.next  # Delete the. Next folder\n$ npm run build\n$ pm2 start ecosystem.config.js\n```\n\n*Make sure your server has directory and file permissions to run the project*\n\n\n**b）ERROR: permission denied, access '/usr/lib/node_modules'**\n\n*Solution:*\n```sh\n$ chmod -R a+x node_modules\n```\n\n**c）ERROR:  JavaScript heap out of memory**\n\nThere is a strict standard limit for memory usage in V8 to be a maximum of ~1GB (32-bit) and ~1.7GB (64-bit),  if you do not increase it manually.\n\n*Solution:*\n```sh\nexport NODE_OPTIONS=--max_old_space_size=4096\n```\n\n\n**d) Error: EACCES: permission denied, mkdir '/root/.pm2/xxxx'**\n\n*Solution:*\n\nIn general, just avoid using `NPM` to run PM2 commands.\n\n\n*You could still try the following:*\n\nMake sure you kill any PM2 instance before starting PM2 in no deamon mode (pm2 kill).\n\n```sh\n# re-install PM2 (optional)\n$ sudo npm i -g pm2   \n\n# if pm2 was reinstalled, ts-node must be reinstalled (optional)\n$ sudo npm install -g ts-node@latest  \n\n# clear all pm2 instances\n$ pm2 kill\n\n# then restart it\n$ pm2 start xxxxxx\n```\n\u003c/blockquote\u003e\n\n\n#### 3.5) Use domain to access your Next.js appication.\n\nYou had created a basic Next.js App from here, then you need to deploy a Next.js App on Apache or Nginx web server. Please refer to the network for the tutorial on setting up the proxy.\n\n\n### 👣 (Step 4) Nginx’s Site Configuration\n\nNow that the app is ready to be deployed, we should prepare the Nginx end. In case Nginx is not installed, it can be easily installed with the apt packaging system by running the following two commands:\n\n```sh\n$ sudo apt update\n$ sudo apt install nginx\n```\nor\n```sh\n$ sudo yum install nginx -y\n```\n\nStart Nginx:\n\n```sh\n$ systemctl start nginx\n```\n\nStart at boot:\n\n```sh\n$ systemctl enable nginx\n```\n\n\n\nSet Up a Firewall Using FirewallD on CentOS 8:\n\n```sh\n$ firewall-cmd --permanent --zone=public --add-service=http\n$ firewall-cmd --permanent --zone=public --add-service=https\n$ firewall-cmd --permanent --zone=public --add-port=3000/tcp\n$ firewall-cmd --reload\n$ systemctl restart nginx \n```\n\nWe can check if Nginx is running on the system:\n\n```sh\n$ systemctl status nginx\n```\n\n\nAlright, now that the Nginx service has successfully started running, we can go ahead and modify the configuration file found at `/etc/nginx/conf.d/default.conf`. This is where we will point the domain to fire up the correct Next.js application:\n\n```sh\n$ vi /etc/nginx/conf.d/default.conf\n```\n\nAt the end of the file, add:\n\n```bash\nserver {\n        listen      443 ssl;\n        server_name backend1.example.com;\n\n        ...\n        location / {\n            proxy_set_header Host $http_host;\n            proxy_pass http://{YOUR_IP}:3000;\n        }\n\n}\n```\n\nAfter adding these lines to the file, we need to restart the Nginx service:\n\n```sh\n$ systemctl restart nginx\n```\n\nThere probably won’t be any messages if the service restarted successfully. Otherwise, it will spit out lines of error messages.\n\n\n\n\u003c/details\u003e\n\n\n\u003cdetails\u003e\n  \u003csummary\u003e\u003ch4\u003e 👉🏼 Node.js Port 3000 already in use but it actually isn't?\u003c/h4\u003e\u003c/summary\u003e\n  \n\nrun the following command\n```sh\n$ killall -9 node\n```\n\n\u003c/details\u003e\n\n\n\u003cdetails\u003e\n  \u003csummary\u003e\u003ch4\u003e 👉🏼 Change the Favicon\u003c/h4\u003e\u003c/summary\u003e\n  \n\nTo change your Site Favicon, navigate the file `pages/_document.tsx` and modify the code between `\u003cHead\u003e`\n\n\n\u003c/details\u003e\n\n\n\u003cdetails\u003e\n  \u003csummary\u003e\u003ch4\u003e 👉🏼 Customize Menu\u003c/h4\u003e\u003c/summary\u003e\n  \n\n\nNavigate the file `src/components/Header` and modify it.\n\n\u003c/details\u003e\n\n\n\u003cdetails\u003e\n  \u003csummary\u003e\u003ch4\u003e 👉🏼 Set port in next.js\u003c/h4\u003e\u003c/summary\u003e\n  \n\nIn your package.json file, add -p 8080 to the dev/start scripts to start the server on port 8080:\n```json\n\"scripts\": {\n  \"dev\": \"next -p 8080\",\n  \"start\": \"next start -p 8080\"\n}\n```\n\nAlternatively, if you don't want to hardcode this in the package.json file, you could start the script with ENV variable PORT.\n```sh\n$ PORT=8080 npm run dev\n```\n\n\u003c/details\u003e\n\n\n\u003cdetails\u003e\n  \u003csummary\u003e\u003ch4\u003e 👉🏼 Set basePath for a static exported\u003c/h4\u003e\u003c/summary\u003e\n  \nLocate both `next.config.js` and `scripts/config-rootdir-of-publishing-source.js`.\n\na) **next.config.js**: Change attributes `basePath` and `assetPrefix`\n\nb) **scripts/config-rootdir-of-publishing-source.js**: Change the paths related to the folder directory in `public/`, such as `assets/`\n\nc) run\n```sh\n$ npm run action:rootdir\n```\n\u003c/details\u003e\n\n\n\n\n\u003cdetails\u003e\n  \u003csummary\u003e\u003ch4\u003e 👉🏼 Site URL (Root Directory) Configurations\u003c/h4\u003e\u003c/summary\u003e\n  \n\nChange the root directory of the website so that it can be used when you upload the project to another directory. Modify the key `siteUrl` of the `./src/data/app.json`.\n\nIf the file is in the root directory, you can leave it empty. If in another directory, you can write: \"/blog\". **(no trailing slash)**\n\n\n```json\n{\n    \"siteUrl\": \"http://localhost:3000\",\n    \"copyright\": \"xxxxxxxxxx\"\n}\n```\n\n\n\n\u003c/details\u003e\n\n\n\u003cdetails\u003e\n  \u003csummary\u003e\u003ch4\u003e 👉🏼 Deploy Using Docker (build a single next.js program image)\u003c/h4\u003e\u003c/summary\u003e\n  \n\n\u003e\n\u003e ⚠️ Tips: When running the `getServerSideProps` of Next.js, `Express` and `WebSocket` services of Node.js, the communication would be container to container. So for these requests, routes to localhost (`http://localhost:3000`) would not work. Instead it would need to be something like `http://localhost:7777` instead (when communicating from the frontend service to the backend service). The localhost domain would work as expected on the client side requests.\n\u003e\n\u003e ⚠️ Warning: Multiple micro-service containers cannot be opened on the server side at the same time, otherwise the upstream server will terminate the WebSocket connection.\n\u003e\n\u003e \n\u003e When you run this without docker everything works because all services are on localhost. When run via docker-compose they no longer are.\n\u003e \n\n\n\n### 👣 (Step 1) First download docker (version Intel chip, note. macOs10.14 and below versions use up to version 4.11.0)\n\nhttps://docs.docker.com/desktop/release-notes/#4110\n\n\ninstall docker on ubuntu\n\n```sh\n$ sudo apt-get update\n$ sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin\n$ sudo docker run hello-world\n```\n\n\n### 👣 (Step 2) Create a new file `Dockerfile` in the root directory of the application\n\n\n```sh\n$ cd /Applications/MAMP/htdocs/fullstack-nextjs-app-template\n$ touch Dockerfile\n$ vi Dockerfile\n```\n\nthe following:\n\n[Dockerfile](Dockerfile)\n\n\n…\n\n\n### 👣 (Step 3) To add support for Docker to an existing project, simply copy the Dockerfile to the root of the project and add the following to the `next.config.js` file:\n\nYou can directly set the `dockerDeploymentEnabled` property to `true` in the current `next.config.js`.\n\n\n\u003e [!NOTE]\n\u003e Use Docker container, don't use [Static Exports](https://nextjs.org/docs/pages/building-your-application/deploying/static-exports).\n\n\n```js\n// next.config.js\nmodule.exports = {\n     // ... rest of the configuration.\n       output: 'standalone',\n}\n```\n\n\n\n### 👣 (Step 4) Build your container:\nSyntax: docker build [OPTIONS] PATH | URL | -\n\n! ! ! Note: The last path is a point, don't miss it\n\n```sh\n$ docker build -t fullstack-nextjs-app-template:v1 .\n```\n\n[The first deployment takes a few minutes because it needs other docker libraries, and it only takes tens of seconds after that]\n\n\n\u003e ❌ **If 401 Unauthorized error, first run:**\n\u003e\n\u003e ```sh\n\u003e $ docker pull node:18.20.4-alpine3.20\n\u003e ```\n\u003e \n\n\n### 👣 (Step 5) Run your application. Based on the tags you gave your Dockerfile, you can now run them with the docker run command.\n\nThe -p flag exposes the container's ports to services outside of docker (the first port is the port exposed to the outside). Use of multiple ports: `docker run -p \u003chost_port1\u003e:\u003ccontainer_port1\u003e -p \u003chost_port2\u003e:\u003ccontainer_port2\u003e`\n\nRun your container:\n\n```sh\n$ docker run -p 3000:3000 fullstack-nextjs-app-template:v1\n```\n\n\n\u003e \n\u003e **NOTE**:\n\u003e\n\u003e If **Ctrl+C** does not work to terminate the container, please add the following code in the server file such as Express, and use the following command to temporarily run the container. Access [Specify an init process](https://docs.docker.com/engine/reference/run/#specify-an-init-process)\n\u003e \n\u003e ```js\n\u003e // Stop running node in docker with Ctrl+C sends the SIGINT signal.\n\u003e // Usage: docker run --init -p \u003chost_port\u003e:\u003ccontainer_port\u003e \u003cimage_name:version\u003e\n\u003e const process = require('process');\n\u003e process.on('SIGINT', () =\u003e {\n\u003e     console.info(\"Interrupted\")\n\u003e     process.exit(0);\n\u003e });\n\u003e ```\n\u003e \n\u003e ```bash\n\u003e $ docker run --init -p \u003chost_port\u003e:\u003ccontainer_port\u003e \u003cimage_name:version\u003e\n\u003e ```\n\u003e \n\n\n\n### 👣 (Step 6) Persistence running (exit the command panel is still executed, add a parameter -d)\n\nRun the image with -d to run the container in detached mode, leaving the container running in the background. The -p flag redirects the public port to a private port inside the container.\n\n```sh\n$ docker run -p 3000:3000 -d fullstack-nextjs-app-template:v1\n```\n\n\n\n### 👣 (Step 7) Docker process check\n\n```sh\n$ docker ps\n$ docker stop \u003cPID\u003e\n$ docker kill \u003cPID\u003e\n```\n\n\n\n### 👣 (Step 8) Node.js process check\n\nThe process already exists, to delete, for example, port 3000\n\n```sh\n#Query the process of port 3000\n$ lsof -i tcp:3000\n\n#PID is replaced by the id of the process\n$ kill -9 \u003cPID\u003e\n```\n\n\n\n### 👣 (Step 9) Push image to private server\n\n\u003e Note: change the `192.168.1.140` to yours\n\n\n#### （1）First configure the shared folder\n\nOtherwise, an error will be reported:\n\n\u003e docker: Error response from daemon: Mounts denied: \n\n\n#### （2）Install and run [docker-registry](https://docs.docker.com/registry/)\n \nSometimes it may be inconvenient to use a public repository like Docker Hub, and users can create a local repository for private use. For example, an image built based on a company's internal project.\n\n`docker-registry` is an official tool that can be used to build a private image.\n\n \nIt can be run by obtaining the official **Registry**. By default, the repository will be created in the container's `/var/lib/registry` directory (for Linux or Mac), and now I reset it to a shared directory on my computer.\n \n```bash\ndocker run --name registry -d  -p 5000:5000 --restart=always  -v /Users/changcheng/Desktop/share:/var/lib/registry registry\n```\n \naccess：http://192.168.1.140:5000/v2/\n \n \nIndicates that port `5000` has been successfully proxied by docker.\n \n \n#### （3）Mark the image to point to your registry [IP is replaced with local LAN IP, or other IP]\n \n```bash\n$ docker tag fullstack-nextjs-app-template:v1 192.168.1.140:5000/fullstack-nextjs-app-template-v1\n```\npush it\n\n```bash\n$ docker push 192.168.1.140:5000/fullstack-nextjs-app-template-v1\n```\n \n#### （4）[Configure the Docker daemon](https://docs.docker.com/registry/recipes/mirror/)\n\nIn case of error: \n\n\u003e http: server gave HTTP response to HTTPS client\n\n\nPlease configure `registry-mirrors` image sources and `insecure-registries` private repositories in Docker Desktop\n \nModify `daemon.json` (can be modified directly through the Docker Desktop)\n\n```bash\n$ cat ~/.docker/daemon.json\n```\n\nAdd the following configuration:\n```json\n{\n    \"registry-mirror\":[\n        \"http://hub-mirror.c.163.com\"\n    ],\n    \"insecure-registries\":[\n        \"192.168.1.140:5000\"\n    ]\n}\n```\n\n \nrestart docker\n\n\n#### （5）Pull the image [LAN can also use it]\n\n```bash\n$ docker pull 192.168.1.140:5000/fullstack-nextjs-app-template-v1\n```\n\n\n\n\n### 👣 (Step 10) Export the image (Optional)\n\nView the container that is running in the background (note that you need to run it first to find the id)\n\n```sh\n$ docker ps\n```\n\nTo package the running docker container into an image image, run `docker commit \u003ccontainer_id\u003e \u003cimage_name:version\u003e`\n\n```sh\n$ docker commit 16cb27979742 fullstack-nextjs-app-template:v1\n```\n\nNext, save the newly packaged image as a tar file, run `docker save \u003cimage_name:version\u003e -o \u003cpath_name\u003e`\n\n\n```sh\n$ docker save fullstack-nextjs-app-template:v1 -o ./fullstack-nextjs-app-template-v1.tar\n```\n\n\n### 👣 (Step 11) Package into an application for the arm64 architecture (Optional)\n\nTo package a Next.js app using Docker for ARM architecture, follow these steps:\n\n#### （1）`Dockerfile`\n\n```sh\n...\n\n# A base image for the ARM architecture, such as the arm64 version of Node.js\nFROM node:18.20.4-alpine3.20 AS base\n\n...\n```\n\n\n#### （2）build command\n\n```sh\n$ docker build --platform linux/arm64 -t fullstack-nextjs-app-template-arm64:v1 .\n```\n\nCross-platform:\n\n```sh\n$ docker buildx create --use\n$ docker buildx build --platform linux/arm64 -t fullstack-nextjs-app-template-arm64:v1 .\n```\n\n\n\n\u003e **Notes**\n\u003e   - Docker Buildx enables multi-platform builds. Ensure that Docker is set up to use Buildx by running `docker buildx create --use`.\n\u003e   - Using the `alpine` version of the Node.js base image helps keep the image size small and reduces dependencies, which is beneficial for ARM devices.\n\u003e   - If you're using packages that include native modules (such as `sharp`), make sure they are correctly compiled or installed for the ARM architecture.\n\n\u003c/details\u003e\n\n\n\n\u003cdetails\u003e\n  \u003csummary\u003e\u003ch4\u003e 👉🏼 Deploy Using Docker (Build composite image that include other custom images)\u003c/h4\u003e\u003c/summary\u003e\n  \n\n\n### 👣 (Step 1) Create a file `docker-compose.yml`, the content as follows:\n\n```yml\nservices:\n  web:\n    build: .\n    ports:\n      - \"3000:3000\"\n    depends_on:\n      - my_node_service\n  my_node_service:\n    image: \"my-node-server:v1\"\n    ports:\n      - \"4001:4001\"\n```\n\n\n### 👣 (Step 2) Build another image, like this:\n\n```bash\n# build\n$ docker build -t my-node-server:v1 .\n# test\n$ docker run --init -p 4001:4001 my-node-server:v1\n```\n\n\n### 👣 (Step 3) Build a composite image, run:\n\n```bash\n$ docker-compose up\n```\n\n\n\u003c/details\u003e\n\n\n\u003cdetails\u003e\n  \u003csummary\u003e\u003ch4\u003e 👉🏼 Deploy Using Docker (Common Load-balancing Solutions of Socket.io Issue)\u003c/h4\u003e\u003c/summary\u003e\n  \n\n\n#### 1. Multiple Kubernetes pods\n\n**Solution 1:**\n\nUsing k8s with load balancing, without nginx. Config the sessionAffinity on service:\n\n```yml\nservice.spec.sessionAffinity = \"ClientIP\"\n```\n\n\n**Solution 2:**\n\nAdding transports: ['websocket'] to socketIOClient options in our multi-pod Kubernetes environment:\n\n```yml\nsocketIOClient(someUrl, {transports: ['websocket']});\n```\n\n\n#### 2. Configure WebSockets with Envoy Proxy\n\n\u003e The file path of the WebSocket service is `./backend/server-socket.js`\n\nTLS termination is handled at the Envoy Proxy, ensuring secure communication between the browser and the proxy. Here’s the simple configuration block you need within the HttpConnectionManager section to enable WebSocket support:\n\n[check out here](https://www.envoyproxy.io/docs/envoy/latest/start/sandboxes/websocket)\n\n\n```yml\nupgrade_configs: \n upgrade_type: \"websocket\"\n```\n\n\n**Correct WebSocket configuration (for both HTTP/1.1 and HTTP/2)**\n\nBrowsers do not allow WebSockets to run directly over HTTP/2.\n\n\n```yml\nstatic_resources:\n  listeners:\n    - name: listener_0\n      address:\n        socket_address:\n          address: 0.0.0.0\n          port_value: 8080\n      filter_chains:\n        - filters:\n            - name: envoy.filters.network.http_connection_manager\n              typed_config:\n                \"@type\": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager\n                codec_type: AUTO  # Allow HTTP/1.1 and HTTP/2\n                stat_prefix: ingress_http\n                route_config:\n                  virtual_hosts:\n                    - name: backend\n                      domains: [\"*\"]\n                      routes:\n                        - match:\n                            prefix: \"/\"\n                          route:\n                            cluster: websocket_service\n                            timeout: 0s  # Disable HTTP request timeout to ensure WebSocket long connection\n                            upgrade_configs:\n                              - upgrade_type: \"websocket\"  # Allow WebSocket\n                http_filters:\n                  - name: envoy.filters.http.router\n\n  clusters:\n    - name: websocket_service\n      connect_timeout: 0.25s\n      type: STATIC\n      http2_protocol_options: {}  # Enable HTTP/2\n      load_assignment:\n        cluster_name: websocket_service\n        endpoints:\n          - lb_endpoints:\n              - endpoint:\n                  address:\n                    socket_address:\n                      address: 127.0.0.1  # WebSocket server address\n                      port_value: 5001  # WebSocket Server Port\n```\n\nAnd, Disabling HTTP/2 on the Node.js server:\n\n```js\nconst http = require('http');  // Use HTTP/1.1 instead of HTTP/2\nconst express = require('express');\nconst { Server } = require('socket.io');\n\nconst app = express();\nconst server = http.createServer(app);  // Make sure you use HTTP/1.1\nconst io = new Server(server, {\n    cors: {\n        origin: \"*\",\n        methods: [\"GET\", \"POST\"]\n    }\n});\n\n...\n```\n\n\n\n#### 3. Other platforms\n\nRefer to: [Using multiple nodes](https://socket.io/docs/v4/using-multiple-nodes/)\n\n\n\n\u003c/details\u003e\n\n\n\u003cdetails\u003e\n  \u003csummary\u003e\u003ch4\u003e 👉🏼 Installation Error or Unable To Run\u003c/h4\u003e\u003c/summary\u003e\n  \n\na) Has `node_modules` folder, just do it directly.\n\nIf running `npm run \u003cscript\u003e` fails because Node has been upgraded, use `npx -p node@\u003cversion\u003e \u003cyour_script\u003e` to run:\n\nsuch as\n\n```sh\n$ npx -p node@15.14.0 npm run dev\n$ npx -p node@14.21.3 npm run start\n```\n\n\n\nb) If there is no `node_modules` folder, using `npm install --legacy-peer-deps` is still unsuccessful. After deleting the dependencies of **package.json** and remove file **package-lock.json**, use the following command to reinstall:\n\n```sh\n$ npm install \u003cpackage1\u003e \u003cpackage2\u003e --legacy-peer-deps\n$ npm install --save-dev \u003cpackage1\u003e \u003cpackage2\u003e --legacy-peer-deps\n```\n\n\nc) NPM or NPX cache error\n\nView the location of the local npm cache:\n```sh\n$ npm config get cache\n```\n\nClear cache (npm and npx)\n```sh\n$ npm cache clean --force\n```\n\nor\n\n```sh\n$ rm -rf ~/.npm\n```\n\nCheck cache\n```sh\n$ npm cache verify\n```\n\n\u003c/details\u003e\n\n\n\n## Ecosystem\n\n**Generics (!!Required):**\n- [React](https://reactjs.org/)\n- [nextjs](https://nextjs.org/)\n- [redux](https://redux.js.org/)\n- [axios](https://github.com/axios/axios)\n- [Express](http://expressjs.com/)\n- [next-cookies](https://github.com/matthewmueller/next-cookies)\n- [pm2](https://pm2.keymetrics.io/)\n\n**Video plugins:**\n- [fluent-ffmpeg](https://github.com/fluent-ffmpeg/node-fluent-ffmpeg)\n- [HLS](https://github.com/video-dev/hls.js)\n\n\n**PHP server:**\n- [php-express](https://github.com/fnobi/php-express)\n\n**Markdown parser:**\n- [markdown-it](https://github.com/markdown-it/markdown-it)\n\n\n## Supported development environment\n\n- Next.js 13.0.0 to 15+\n- React 18 to 19\n- TypeScript 4.x.x + \n- Express 4.x.x\n\n\n\n## Changelog\n\n[releases](CHANGELOG.md)\n\n\n\n## Licensing\n\nLicensed under the [MIT](https://opensource.org/licenses/MIT).\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fxizon%2Ffullstack-nextjs-app-template","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fxizon%2Ffullstack-nextjs-app-template","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fxizon%2Ffullstack-nextjs-app-template/lists"}