Last active
May 2, 2026 21:01
-
-
Save mstaicu/503289174d375ca434641059698581fc to your computer and use it in GitHub Desktop.
Remix Run v3
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // package.json | |
| { | |
| "type": "module", | |
| "scripts": { | |
| "build": "esbuild app/pages/register.client.ts app/pages/login.client.ts --bundle --format=esm --outdir=public/assets --entry-names=[name] --minify --sourcemap && esbuild server.ts --bundle --platform=node --format=esm --outfile=dist/server.js --packages=external", | |
| "dev": "esbuild app/pages/register.client.ts app/pages/login.client.ts --bundle --format=esm --outdir=public/assets --entry-names=[name] --sourcemap --watch & NODE_ENV=development tsx watch server.ts", | |
| "start": "node dist/server.js", | |
| "typecheck": "tsc --noEmit" | |
| }, | |
| "dependencies": { | |
| "remix": "^3.0.0-beta.0" | |
| }, | |
| "devDependencies": { | |
| "@types/node": "^25.6.0", | |
| "esbuild": "^0.28.0", | |
| "tsx": "^4.21.0", | |
| "typescript": "^6.0.3" | |
| } | |
| } | |
| // server.js | |
| import http from "node:http"; | |
| import { createRouter } from "remix/fetch-router"; | |
| import { get, route } from "remix/fetch-router/routes"; | |
| import { html } from "remix/html-template"; | |
| import { createRequestListener } from "remix/node-fetch-server"; | |
| import { createHtmlResponse } from "remix/response/html"; | |
| const CONTENT_BASE_URL = | |
| process.env.CONTENT_BASE_URL ?? "https://example.com/content"; | |
| const routes = route({ | |
| home: get("/"), | |
| about: get("/about"), | |
| }); | |
| const router = createRouter(); | |
| router.get(routes.home, () => renderPage("home")); | |
| router.get(routes.about, () => renderPage("about")); | |
| async function renderPage(slug) { | |
| const page = await fetchPage(slug); | |
| if (!page) { | |
| return new Response("Not found", { status: 404 }); | |
| } | |
| return createHtmlResponse( | |
| html`<!doctype html> | |
| <html lang="en"> | |
| <head> | |
| <meta charset="utf-8" /> | |
| <meta name="viewport" content="width=device-width, initial-scale=1" /> | |
| <title>${page.title}</title> | |
| <meta name="description" content="${page.description}" /> | |
| <style> | |
| body { | |
| margin: 0; | |
| font-family: ui-sans-serif, system-ui, sans-serif; | |
| color: #151515; | |
| background: #ffffff; | |
| } | |
| header, | |
| main { | |
| width: min(100% - 32px, 960px); | |
| margin-inline: auto; | |
| } | |
| header { | |
| display: flex; | |
| justify-content: space-between; | |
| align-items: center; | |
| padding-block: 24px; | |
| border-bottom: 1px solid #e5e5e5; | |
| } | |
| nav { | |
| display: flex; | |
| gap: 16px; | |
| } | |
| a { | |
| color: inherit; | |
| text-decoration: none; | |
| font-weight: 600; | |
| } | |
| main { | |
| padding-block: 72px; | |
| } | |
| h1 { | |
| max-width: 760px; | |
| margin: 0; | |
| font-size: 56px; | |
| line-height: 1; | |
| } | |
| p { | |
| max-width: 680px; | |
| font-size: 19px; | |
| line-height: 1.65; | |
| color: #444; | |
| } | |
| section { | |
| margin-top: 48px; | |
| } | |
| h2 { | |
| margin-bottom: 8px; | |
| font-size: 28px; | |
| } | |
| </style> | |
| </head> | |
| <body> | |
| <header> | |
| <a href="/">Aperitif</a> | |
| <nav> | |
| <a href="/">Home</a> | |
| <a href="/about">About</a> | |
| </nav> | |
| </header> | |
| <main> | |
| <h1>${page.title}</h1> | |
| <p>${page.description}</p> | |
| ${page.sections | |
| .map( | |
| (section) => html` | |
| <section> | |
| <h2>${section.heading}</h2> | |
| <p>${section.body}</p> | |
| </section> | |
| `, | |
| ) | |
| .join("")} | |
| </main> | |
| </body> | |
| </html>`, | |
| { | |
| headers: { | |
| "Cache-Control": "public, max-age=60, stale-while-revalidate=300", | |
| }, | |
| }, | |
| ); | |
| } | |
| async function fetchPage(slug) { | |
| const response = await fetch(`${CONTENT_BASE_URL}/pages/${slug}.json`, { | |
| headers: { Accept: "application/json" }, | |
| }); | |
| if (response.status === 404) return null; | |
| if (!response.ok) throw new Error(`CONTENT_FETCH_FAILED_${response.status}`); | |
| return response.json(); | |
| } | |
| const server = http.createServer( | |
| createRequestListener((request) => router.fetch(request)), | |
| ); | |
| const port = Number.parseInt(process.env.PORT ?? "3000", 10); | |
| server.listen(port, () => { | |
| console.log(`marketing site listening on http://localhost:${port}`); | |
| }); |
Author
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Next next next level