├── .vscode └── settings.json ├── README.md ├── app ├── entry.client.tsx ├── entry.server.tsx ├── root.tsx └── routes │ ├── index.tsx │ └── second.tsx ├── build.ts ├── deno.json ├── dev.ts ├── import_map.client.dev.json ├── import_map.client.json ├── import_map.server.dev.json ├── import_map.server.json ├── package.json ├── prod.ts └── remix.gen.ts /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "deno.enable": true, 3 | "deno.lint": true, 4 | "deno.unstable": false, 5 | "deno.importMap": "./import_map.server.dev.json" 6 | } 7 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # remix-deno-example 2 | 3 | Example showing how to use: https://github.com/jacob-ebey/remix-deno 4 | 5 | ## Usage 6 | 7 | **Development mode:** 8 | 9 | ```bash 10 | deno task dev 11 | ``` 12 | 13 | This will automatically re-generate your `remix.gen.ts` file for production. 14 | 15 | **Build:** 16 | 17 | If you haven't or can't run dev mode for some reason, you can prepare your site for production with: 18 | 19 | ```bash 20 | deno task build 21 | ``` 22 | 23 | **Production mode:** 24 | 25 | ```bash 26 | deno task start 27 | ``` 28 | 29 | ## Notes 30 | 31 | You **should** commit `remix.gen.ts` to your repo. 32 | -------------------------------------------------------------------------------- /app/entry.client.tsx: -------------------------------------------------------------------------------- 1 | /** @jsx React.createElement */ 2 | import * as React from "react"; 3 | import * as ReactDOM from "react-dom/client"; 4 | import { RemixBrowser } from "remix/react"; 5 | 6 | ReactDOM.hydrateRoot(document, ); 7 | -------------------------------------------------------------------------------- /app/entry.server.tsx: -------------------------------------------------------------------------------- 1 | /** @jsx React.createElement */ 2 | import * as React from "react"; 3 | import * as ReactDOM from "react-dom/server"; 4 | import { RemixServer } from "remix/react"; 5 | import type { EntryContext } from "remix/server"; 6 | import isbot from "isbot"; 7 | 8 | export default async function handleDocumentRequest( 9 | request: Request, 10 | responseStatusCode: number, 11 | responseHeaders: Headers, 12 | remixContext: EntryContext 13 | ) { 14 | const body = await ReactDOM.renderToReadableStream( 15 | , 16 | { 17 | onError(error) { 18 | console.error(error); 19 | responseStatusCode = 500; 20 | }, 21 | } 22 | ); 23 | 24 | const userAgent = request.headers.get("User-Agent"); 25 | if (userAgent && isbot(userAgent)) { 26 | await body.allReady; 27 | } 28 | 29 | const headers = new Headers(responseHeaders); 30 | headers.set("Content-Type", "text/html"); 31 | 32 | return new Response(body, { 33 | headers, 34 | status: responseStatusCode, 35 | }); 36 | } 37 | -------------------------------------------------------------------------------- /app/root.tsx: -------------------------------------------------------------------------------- 1 | /** @jsx React.createElement */ 2 | import * as React from "react"; 3 | import { Links, Meta, Outlet, Scripts, ScrollRestoration } from "remix/react"; 4 | import type { MetaFunction } from "remix/server"; 5 | 6 | export const meta: MetaFunction = () => ({ 7 | charset: "utf-8", 8 | title: "New Remix App", 9 | viewport: "width=device-width,initial-scale=1", 10 | }); 11 | 12 | export default function App() { 13 | return ( 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | ); 26 | } 27 | -------------------------------------------------------------------------------- /app/routes/index.tsx: -------------------------------------------------------------------------------- 1 | /** @jsx React.createElement */ 2 | import * as React from "react"; 3 | import { Link, useLoaderData } from "remix/react"; 4 | import type { LoaderFunction } from "remix/server"; 5 | import { json } from "remix/server"; 6 | 7 | export const loader: LoaderFunction = () => { 8 | return json({ 9 | message: "Hello, World!", 10 | }); 11 | }; 12 | 13 | export default function Index() { 14 | const { message } = useLoaderData(); 15 | return ( 16 |
17 |

{message}

18 |

19 | Second 20 |

21 |
22 | ); 23 | } 24 | -------------------------------------------------------------------------------- /app/routes/second.tsx: -------------------------------------------------------------------------------- 1 | /** @jsx React.createElement */ 2 | import * as React from "react"; 3 | import { Link, useLoaderData } from "remix/react"; 4 | import type { LoaderFunction } from "remix/server"; 5 | import { json } from "remix/server"; 6 | 7 | export const loader: LoaderFunction = () => { 8 | return json({ 9 | message: "Second", 10 | }); 11 | }; 12 | 13 | export default function Index() { 14 | const { message } = useLoaderData(); 15 | return ( 16 |
17 |

{message}

18 |

19 | Home 20 |

21 |
22 | ); 23 | } 24 | -------------------------------------------------------------------------------- /build.ts: -------------------------------------------------------------------------------- 1 | import { 2 | loadConfig, 3 | writeRemixGen, 4 | } from "remix-deno"; 5 | 6 | const config = await loadConfig({ mode: "production" }); 7 | await writeRemixGen(config); 8 | -------------------------------------------------------------------------------- /deno.json: -------------------------------------------------------------------------------- 1 | { 2 | "importMap": "import_map.server.json", 3 | "tasks": { 4 | "build": "deno run -A --no-check ./build.ts", 5 | "dev": "deno run -A --no-check --watch=app/ --import-map=import_map.server.dev.json ./dev.ts", 6 | "start": "deno run -A --import-map=import_map.server.json ./prod.ts" 7 | }, 8 | "compilerOptions": { 9 | "lib": ["dom", "dom.iterable", "dom.asynciterable", "deno.ns"] 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /dev.ts: -------------------------------------------------------------------------------- 1 | import { serveDev } from "remix-deno"; 2 | 3 | await serveDev((mod) => import(mod)); 4 | -------------------------------------------------------------------------------- /import_map.client.dev.json: -------------------------------------------------------------------------------- 1 | { 2 | "imports": { 3 | "isbot": "https://esm.sh/isbot@3.5.0?pin=v86&dev", 4 | "mime": "https://esm.sh/mime@3.0.0?pin=v86&dev", 5 | "react": "https://esm.sh/react@18.2.0?pin=v86&dev", 6 | "react-dom/client": "https://esm.sh/react-dom@18.2.0/client?pin=v86&deps=react@18.2.0&dev", 7 | "react-dom/server": "https://esm.sh/react-dom@18.2.0/server?pin=v86&deps=react@18.2.0&dev", 8 | "react-dom": "https://esm.sh/react-dom@18.2.0?pin=v86&deps=react@18.2.0&dev", 9 | "remix/react": "https://esm.sh/@remix-run/react@1.6.0?pin=v86&deps=react@18.2.0&dev", 10 | "remix/server": "https://esm.sh/@remix-run/deno@1.6.0/index.ts?pin=v86&deps=react@18.2.0&dev", 11 | "@remix-run/server-runtime": "https://esm.sh/@remix-run/server-runtime@1.6.0?pin=v86&target=deno&deps=react@18.2.0&dev" 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /import_map.client.json: -------------------------------------------------------------------------------- 1 | { 2 | "imports": { 3 | "isbot": "https://esm.sh/isbot@3.5.0?pin=v86", 4 | "mime": "https://esm.sh/mime@3.0.0?pin=v86", 5 | "react": "https://esm.sh/react@18.2.0?pin=v86", 6 | "react-dom/client": "https://esm.sh/react-dom@18.2.0/client?pin=v86&deps=react@18.2.0", 7 | "react-dom/server": "https://esm.sh/react-dom@18.2.0/server?pin=v86&deps=react@18.2.0", 8 | "react-dom": "https://esm.sh/react-dom@18.2.0?pin=v86&deps=react@18.2.0", 9 | "remix/react": "https://esm.sh/@remix-run/react@1.6.0?pin=v86&deps=react@18.2.0", 10 | "remix/server": "https://esm.sh/@remix-run/deno@1.6.0/index.ts?pin=v86&deps=react@18.2.0", 11 | "@remix-run/server-runtime": "https://esm.sh/@remix-run/server-runtime@1.6.0?pin=v86&target=deno&deps=react@18.2.0" 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /import_map.server.dev.json: -------------------------------------------------------------------------------- 1 | { 2 | "imports": { 3 | "isbot": "https://esm.sh/isbot@3.5.0?pin=v86&target=deno&dev", 4 | "mime": "https://esm.sh/mime@3.0.0?pin=v86&target=deno&dev", 5 | "react": "https://esm.sh/react@18.2.0?pin=v86&target=deno&dev", 6 | "react-dom/client": "https://esm.sh/react-dom@18.2.0/client?pin=v86&target=deno&deps=react@18.2.0&dev", 7 | "react-dom/server": "https://esm.sh/react-dom@18.2.0/server?pin=v86&target=deno&deps=react@18.2.0&dev", 8 | "react-dom": "https://esm.sh/react-dom@18.2.0?pin=v86&target=deno&deps=react@18.2.0&dev", 9 | "remix-deno": "https://deno.land/x/remix_deno@v0.0.13/mod.ts", 10 | "remix/react": "https://esm.sh/@remix-run/react@1.6.0?pin=v86&target=deno&deps=react@18.2.0&dev", 11 | "remix/server": "https://esm.sh/@remix-run/deno@1.6.0/index.ts?pin=v86&target=deno&deps=react@18.2.0&dev", 12 | "@remix-run/server-runtime": "https://esm.sh/@remix-run/server-runtime@1.6.0?pin=v86&target=deno&deps=react@18.2.0&dev" 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /import_map.server.json: -------------------------------------------------------------------------------- 1 | { 2 | "imports": { 3 | "isbot": "https://esm.sh/isbot@3.5.0?pin=v86&target=deno", 4 | "mime": "https://esm.sh/mime@3.0.0?pin=v86&target=deno", 5 | "react": "https://esm.sh/react@18.2.0?pin=v86&target=deno", 6 | "react-dom/client": "https://esm.sh/react-dom@18.2.0/client?pin=v86&target=deno&deps=react@18.2.0", 7 | "react-dom/server": "https://esm.sh/react-dom@18.2.0/server?pin=v86&target=deno&deps=react@18.2.0", 8 | "react-dom": "https://esm.sh/react-dom@18.2.0?pin=v86&target=deno&deps=react@18.2.0", 9 | "remix-deno": "https://deno.land/x/remix_deno@v0.0.13/mod.ts", 10 | "remix/react": "https://esm.sh/@remix-run/react@1.6.0?pin=v86&target=deno&deps=react@18.2.0", 11 | "remix/server": "https://esm.sh/@remix-run/deno@1.6.0/index.ts?pin=v86&target=deno&deps=react@18.2.0", 12 | "@remix-run/server-runtime": "https://esm.sh/@remix-run/server-runtime@1.6.0?pin=v86&target=deno&deps=react@18.2.0" 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "sideEffects": false 3 | } 4 | -------------------------------------------------------------------------------- /prod.ts: -------------------------------------------------------------------------------- 1 | import { serveProd } from "remix-deno"; 2 | import * as remixGen from "./remix.gen.ts"; 3 | 4 | await serveProd(remixGen); 5 | -------------------------------------------------------------------------------- /remix.gen.ts: -------------------------------------------------------------------------------- 1 | import * as entryModule from "./app/entry.server.tsx"; 2 | import * as route0 from "./app/routes/index.tsx" 3 | import * as route1 from "./app/routes/second.tsx" 4 | import * as route2 from "./app/root.tsx" 5 | export const entry = { module: entryModule }; 6 | export const routes = { 7 | ["routes/index"]: { 8 | caseSensitive: undefined, 9 | id: "routes/index", 10 | index: true, 11 | parentId: "root", 12 | path: undefined, 13 | module: route0, 14 | }, 15 | ["routes/second"]: { 16 | caseSensitive: undefined, 17 | id: "routes/second", 18 | index: undefined, 19 | parentId: "root", 20 | path: "second", 21 | module: route1, 22 | }, 23 | ["root"]: { 24 | caseSensitive: undefined, 25 | id: "root", 26 | index: undefined, 27 | parentId: undefined, 28 | path: "", 29 | module: route2, 30 | } 31 | }; 32 | --------------------------------------------------------------------------------