{"id":20046190,"url":"https://github.com/spa5k/nextjs_approuter_electron","last_synced_at":"2025-04-06T12:07:36.922Z","repository":{"id":247652867,"uuid":"798240252","full_name":"spa5k/nextjs_approuter_electron","owner":"spa5k","description":"This is a template for building Electron apps with Next.js App router, SSR and Server Components","archived":false,"fork":false,"pushed_at":"2025-01-03T05:00:19.000Z","size":529,"stargazers_count":100,"open_issues_count":1,"forks_count":18,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-03-30T11:06:32.969Z","etag":null,"topics":["approuter","electron","nextjs","nextron"],"latest_commit_sha":null,"homepage":"https://www.saybackend.com/blog/03-electron-nextjs-ssr","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/spa5k.png","metadata":{"files":{"readme":"README.md","changelog":null,"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":"2024-05-09T11:32:35.000Z","updated_at":"2025-03-30T05:06:43.000Z","dependencies_parsed_at":"2025-01-15T15:16:41.472Z","dependency_job_id":"3eb8530d-0f35-4938-999f-22d0c6b95766","html_url":"https://github.com/spa5k/nextjs_approuter_electron","commit_stats":null,"previous_names":["spa5k/nextjs_approuter_electron"],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/spa5k%2Fnextjs_approuter_electron","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/spa5k%2Fnextjs_approuter_electron/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/spa5k%2Fnextjs_approuter_electron/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/spa5k%2Fnextjs_approuter_electron/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/spa5k","download_url":"https://codeload.github.com/spa5k/nextjs_approuter_electron/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247478319,"owners_count":20945266,"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":["approuter","electron","nextjs","nextron"],"created_at":"2024-11-13T11:21:43.377Z","updated_at":"2025-04-06T12:07:36.899Z","avatar_url":"https://github.com/spa5k.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# NextJS App Router with Electron, SSR, Server Components, etc.\n\n![nextjsimage](https://raw.githubusercontent.com/spa5k/nextjs_approuter_electron/main/public/nextjs_electron.png)\n\nThis boilerplate demonstrates a turborepo setup combining Next.js with Electron, allowing you to use the same codebase with SSR (Server-Side Rendering)/ React Server Components(RSC) for Electron applications.\n\n![nextjsimage](https://raw.githubusercontent.com/spa5k/nextjs_approuter_electron/main/public/app.png)\n\n## Project Structure\n\n1. **Next.js App** - `next.config.mjs`\n   - For the Next.js app, configure it by setting the output to \"standalone\":\n     ```diff\n     /** @type {import('next').NextConfig} */\n     module.exports = {\n       transpilePackages: [\"@nextelectron/ui\"],\n     + output: \"standalone\",\n     };\n     ```\n   - This configuration produces a minimal bundle usable in Electron. Additionally, this output can be utilized in a Dockerfile to create a containerized version of your app, which is small in size and can run anywhere, not just Vercel.\n\n2. **Electron App** - `package.json`\n   - The Electron app uses the Next.js app as the renderer, relying on stock Electron without external libraries.\n   - Electron `build` configuration in `package.json`:\n     ```json\n     \"build\": {\n       \"asar\": true,\n       \"executableName\": \"NextJSElectron\",\n       \"appId\": \"com.saybackend.nextjs-electron\",\n       \"asarUnpack\": [\n         \"node_modules/next\",\n         \"node_modules/@img\",\n         \"node_modules/sharp\",\n         \"**\\\\*.{node,dll}\"\n       ],\n       \"files\": [\n         \"build\",\n         {\n           \"from\": \".next/standalone\",\n           \"to\": \"app\",\n           \"filter\": [\n             \"!**/.env\",\n             \"!**/package.json\"\n           ]\n         },\n         {\n           \"from\": \".next/static\",\n           \"to\": \"app/.next/static\"\n         },\n         {\n           \"from\": \"public\",\n           \"to\": \"app/public\"\n         }\n       ],\n       \"win\": {\n         \"target\": [\n           \"nsis\"\n         ]\n       },\n       \"linux\": {\n         \"target\": [\n           \"deb\"\n         ],\n         \"category\": \"Development\"\n       }\n     }\n     ```\n   - The Next.js app output is copied to the Electron app to be used as the renderer during the build process.\n   - Main Electron file (`main.ts`):\n     ```ts\n     import { is } from \"@electron-toolkit/utils\";\n     import { app, BrowserWindow, ipcMain } from \"electron\";\n     import { getPort } from \"get-port-please\";\n     import { startServer } from \"next/dist/server/lib/start-server\";\n     import { join } from \"path\";\n\n     const createWindow = () =\u003e {\n       const mainWindow = new BrowserWindow({\n         width: 900,\n         height: 670,\n         webPreferences: {\n           preload: join(__dirname, \"preload.js\"),\n           nodeIntegration: true,\n         },\n       });\n\n       mainWindow.on(\"ready-to-show\", () =\u003e mainWindow.show());\n\n       const loadURL = async () =\u003e {\n         if (is.dev) {\n           mainWindow.loadURL(\"http://localhost:3000\");\n         } else {\n           try {\n             const port = await startNextJSServer();\n             console.log(\"Next.js server started on port:\", port);\n             mainWindow.loadURL(`http://localhost:${port}`);\n           } catch (error) {\n             console.error(\"Error starting Next.js server:\", error);\n           }\n         }\n       };\n\n       loadURL();\n       return mainWindow;\n     };\n\n     const startNextJSServer = async () =\u003e {\n       try {\n         const nextJSPort = await getPort({ portRange: [30_011, 50_000] });\n         const webDir = join(app.getAppPath(), \"app\");\n\n         await startServer({\n           dir: webDir,\n           isDev: false,\n           hostname: \"localhost\",\n           port: nextJSPort,\n           customServer: true,\n           allowRetry: false,\n           keepAliveTimeout: 5000,\n           minimalMode: true,\n         });\n\n         return nextJSPort;\n       } catch (error) {\n         console.error(\"Error starting Next.js server:\", error);\n         throw error;\n       }\n     };\n\n     app.whenReady().then(() =\u003e {\n       createWindow();\n\n       ipcMain.on(\"ping\", () =\u003e console.log(\"pong\"));\n       app.on(\"activate\", () =\u003e {\n         if (BrowserWindow.getAllWindows().length === 0) createWindow();\n       });\n     });\n\n     app.on(\"window-all-closed\", () =\u003e {\n       if (process.platform !== \"darwin\") app.quit();\n     });\n     ```\n   - Unlike traditional Electron setups where `index.html` is loaded, this setup runs the Next.js app on a different port and loads it, enabling SSR in Electron.\n   - `get-port-please` is used to get a free port, starting the Next.js server on that port. This allows the same codebase to be used for both web and Electron.\n\n## Running the Application\n\nTo run the application, use the following commands:\n\n```bash\nmake next_dev\nmake electron_dev\n```\n\nTo build the Electron app:\n\n```bash\nmake electron_dist\n```\n\n\u003e **Note**: Electron expects the Next.js app's production output to be present and copied to the Electron app. Ensure you have built the Next.js app before running the Electron app.\n\n## Makefile\n\n### Next.js Tasks\n\n- **Development Server**: Starts the development server for Next.js.\n  ```sh\n  make next_dev\n  ```\n\n- **Build**: Builds the Next.js project for production.\n  ```sh\n  make next_build\n  ```\n\n- **Start**: Starts the Next.js project.\n  ```sh\n  make next_start\n  ```\n\n- **Lint**: Lints the Next.js project.\n  ```sh\n  make next_lint\n  ```\n\n### Code Formatting\n\n- **Format Code**: Formats the codebase using `dprint`.\n  ```sh\n  make format\n  ```\n\n### Electron Tasks\n\n- **Postinstall**: Installs app dependencies for Electron.\n  ```sh\n  make postinstall\n  ```\n\n- **Build for Distribution**: Builds Electron for distribution in directory mode.\n  ```sh\n  make electron_dist\n  ```\n\n- **Build for Debian Distribution**: Builds Electron for Debian distribution.\n  ```sh\n  make electron_dist_deb\n  ```\n\n- **Build Using tsup**: Builds Electron using `tsup`.\n  ```sh\n  make electron_build\n  ```\n\n- **Watch Mode**: Watch mode for Electron with `tsup`.\n  ```sh\n  make electron_build_watch\n  ```\n\n- **Development Mode**: Starts development mode for Electron.\n  ```sh\n  make electron_dev\n  ```\n\n### Composite Tasks\n\n- **Build All**: Builds both Next.js and Electron projects.\n  ```sh\n  make build\n  ```\n\n- **Distribute All**: Distributes both Next.js and Electron projects.\n  ```sh\n  make dist\n  ```\n\n- **Development Mode for All**: Starts development mode for both Electron and Next.js.\n  ```sh\n  make dev\n  ```\n\n### Usage\n\nTo use any of the tasks, simply run the corresponding `make` command in your terminal. For example, to start the development server for Next.js, you would run:\n\n```sh\nmake next_dev\n```\n\nFor a list of all available tasks, you can run:\n\n```sh\nmake help\n```\n\nThis will display a summary of all tasks and their descriptions.\n\n## Additional Information\n\n- Ensure all dependencies are installed using `pnpm` before running the tasks.\n- The tasks are defined in the `Makefile` for ease of use and to maintain consistency across development and build processes.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fspa5k%2Fnextjs_approuter_electron","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fspa5k%2Fnextjs_approuter_electron","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fspa5k%2Fnextjs_approuter_electron/lists"}