diff --git a/contributors.yml b/contributors.yml
index 57082791773..2931be59d05 100644
--- a/contributors.yml
+++ b/contributors.yml
@@ -713,3 +713,4 @@
- zayenz
- zhe
- zwhitchcox
+- zwily
diff --git a/templates/classic-remix-compiler/cloudflare-workers/.gitignore b/templates/classic-remix-compiler/cloudflare-workers/.gitignore
index a6978e55559..d30462277aa 100644
--- a/templates/classic-remix-compiler/cloudflare-workers/.gitignore
+++ b/templates/classic-remix-compiler/cloudflare-workers/.gitignore
@@ -5,3 +5,4 @@ node_modules
/build
/public/build
.env
+.dev.vars
\ No newline at end of file
diff --git a/templates/classic-remix-compiler/cloudflare-workers/app/root.tsx b/templates/classic-remix-compiler/cloudflare-workers/app/root.tsx
index 68397b09d47..cdad1a5039b 100644
--- a/templates/classic-remix-compiler/cloudflare-workers/app/root.tsx
+++ b/templates/classic-remix-compiler/cloudflare-workers/app/root.tsx
@@ -1,5 +1,3 @@
-import type { LinksFunction } from "@remix-run/cloudflare";
-import { cssBundleHref } from "@remix-run/css-bundle";
import {
Links,
LiveReload,
@@ -8,12 +6,25 @@ import {
Scripts,
ScrollRestoration,
} from "@remix-run/react";
+import type { LinksFunction } from "@remix-run/cloudflare";
+
+import styles from "./tailwind.css";
export const links: LinksFunction = () => [
- ...(cssBundleHref ? [{ rel: "stylesheet", href: cssBundleHref }] : []),
+ { rel: "stylesheet", href: styles },
+ { rel: "preconnect", href: "https://fonts.googleapis.com" },
+ {
+ rel: "preconnect",
+ href: "https://fonts.gstatic.com",
+ crossOrigin: "anonymous",
+ },
+ {
+ rel: "stylesheet",
+ href: "https://fonts.googleapis.com/css2?family=Inter:ital,opsz,wght@0,14..32,100..900;1,14..32,100..900&display=swap",
+ },
];
-export default function App() {
+export function Layout({ children }: { children: React.ReactNode }) {
return (
@@ -23,7 +34,7 @@ export default function App() {
-
+ {children}
@@ -31,3 +42,7 @@ export default function App() {
);
}
+
+export default function App() {
+ return ;
+}
diff --git a/templates/classic-remix-compiler/cloudflare-workers/app/routes/_index.tsx b/templates/classic-remix-compiler/cloudflare-workers/app/routes/_index.tsx
index 4aa6089f125..97083ec2074 100644
--- a/templates/classic-remix-compiler/cloudflare-workers/app/routes/_index.tsx
+++ b/templates/classic-remix-compiler/cloudflare-workers/app/routes/_index.tsx
@@ -9,33 +9,130 @@ export const meta: MetaFunction = () => {
export default function Index() {
return (
-
-
Welcome to Remix
-
+
+
+
+
+ Welcome to Remix
+
+
+
+
+
+
+
+
);
}
+
+const resources = [
+ {
+ href: "https://remix.run/start/quickstart",
+ text: "Quick Start (5 min)",
+ icon: (
+
+ ),
+ },
+ {
+ href: "https://remix.run/start/tutorial",
+ text: "Tutorial (30 min)",
+ icon: (
+
+ ),
+ },
+ {
+ href: "https://remix.run/docs",
+ text: "Remix Docs",
+ icon: (
+
+ ),
+ },
+ {
+ href: "https://rmx.as/discord",
+ text: "Join Discord",
+ icon: (
+
+ ),
+ },
+];
diff --git a/templates/classic-remix-compiler/cloudflare-workers/app/tailwind.css b/templates/classic-remix-compiler/cloudflare-workers/app/tailwind.css
new file mode 100644
index 00000000000..303fe158fcf
--- /dev/null
+++ b/templates/classic-remix-compiler/cloudflare-workers/app/tailwind.css
@@ -0,0 +1,12 @@
+@tailwind base;
+@tailwind components;
+@tailwind utilities;
+
+html,
+body {
+ @apply bg-white dark:bg-gray-950;
+
+ @media (prefers-color-scheme: dark) {
+ color-scheme: dark;
+ }
+}
diff --git a/templates/classic-remix-compiler/cloudflare-workers/load-context.ts b/templates/classic-remix-compiler/cloudflare-workers/load-context.ts
new file mode 100644
index 00000000000..d11eedbcb63
--- /dev/null
+++ b/templates/classic-remix-compiler/cloudflare-workers/load-context.ts
@@ -0,0 +1,26 @@
+import { type PlatformProxy } from "wrangler";
+
+type GetLoadContextArgs = {
+ request: Request;
+ context: {
+ cloudflare: Omit<
+ PlatformProxy
,
+ "dispose" | "caches"
+ > & {
+ caches:
+ | PlatformProxy["caches"]
+ | CacheStorage;
+ };
+ };
+};
+
+declare module "@remix-run/cloudflare" {
+ // eslint-disable-next-line @typescript-eslint/no-empty-interface
+ interface AppLoadContext extends ReturnType {
+ // This will merge the result of `getLoadContext` into the `AppLoadContext`
+ }
+}
+
+export function getLoadContext({ context }: GetLoadContextArgs) {
+ return context;
+}
diff --git a/templates/classic-remix-compiler/cloudflare-workers/package.json b/templates/classic-remix-compiler/cloudflare-workers/package.json
index 87f765d4f8f..6b3748c8d91 100644
--- a/templates/classic-remix-compiler/cloudflare-workers/package.json
+++ b/templates/classic-remix-compiler/cloudflare-workers/package.json
@@ -4,14 +4,14 @@
"type": "module",
"scripts": {
"build": "remix build",
- "deploy": "wrangler deploy",
+ "deploy": "npm run build && wrangler deploy",
"dev": "remix dev --manual -c \"npm start\"",
"lint": "eslint --ignore-path .gitignore --cache --cache-location ./node_modules/.cache/eslint .",
"start": "wrangler dev ./build/index.js",
- "typecheck": "tsc"
+ "typecheck": "tsc",
+ "typegen": "wrangler types"
},
"dependencies": {
- "@cloudflare/kv-asset-handler": "^0.1.3",
"@remix-run/cloudflare": "*",
"@remix-run/css-bundle": "*",
"@remix-run/react": "*",
@@ -20,7 +20,7 @@
"react-dom": "^18.2.0"
},
"devDependencies": {
- "@cloudflare/workers-types": "^4.20230518.0",
+ "@cloudflare/workers-types": "^4.20240925.0",
"@remix-run/dev": "*",
"@types/react": "^18.2.20",
"@types/react-dom": "^18.2.7",
@@ -32,8 +32,9 @@
"eslint-plugin-jsx-a11y": "^6.7.1",
"eslint-plugin-react": "^7.33.2",
"eslint-plugin-react-hooks": "^4.6.0",
+ "tailwindcss": "^3.4.4",
"typescript": "^5.1.6",
- "wrangler": "^3.24.0"
+ "wrangler": "^3.80.1"
},
"engines": {
"node": ">=18.0.0"
diff --git a/templates/classic-remix-compiler/cloudflare-workers/public/logo-dark.png b/templates/classic-remix-compiler/cloudflare-workers/public/logo-dark.png
new file mode 100644
index 00000000000..b24c7aee3a8
Binary files /dev/null and b/templates/classic-remix-compiler/cloudflare-workers/public/logo-dark.png differ
diff --git a/templates/classic-remix-compiler/cloudflare-workers/public/logo-light.png b/templates/classic-remix-compiler/cloudflare-workers/public/logo-light.png
new file mode 100644
index 00000000000..4490ae79307
Binary files /dev/null and b/templates/classic-remix-compiler/cloudflare-workers/public/logo-light.png differ
diff --git a/templates/classic-remix-compiler/cloudflare-workers/remix.config.js b/templates/classic-remix-compiler/cloudflare-workers/remix.config.js
index fbf8e7ec39f..9ad0213a486 100644
--- a/templates/classic-remix-compiler/cloudflare-workers/remix.config.js
+++ b/templates/classic-remix-compiler/cloudflare-workers/remix.config.js
@@ -4,8 +4,8 @@ export default {
server: "./server.ts",
serverConditions: ["workerd", "worker", "browser"],
serverDependenciesToBundle: [
- // bundle everything except the virtual module for the static content manifest provided by wrangler
- /^(?!.*\b__STATIC_CONTENT_MANIFEST\b).*$/,
+ // bundle everything except the external cloudflare:workers package
+ /^(?!.*\bcloudflare:workers\b).*$/,
],
serverMainFields: ["browser", "module", "main"],
serverMinify: true,
diff --git a/templates/classic-remix-compiler/cloudflare-workers/remix.env.d.ts b/templates/classic-remix-compiler/cloudflare-workers/remix.env.d.ts
index b5be9ba3bbe..425870ae632 100644
--- a/templates/classic-remix-compiler/cloudflare-workers/remix.env.d.ts
+++ b/templates/classic-remix-compiler/cloudflare-workers/remix.env.d.ts
@@ -1,8 +1,3 @@
///
///
///
-
-declare module "__STATIC_CONTENT_MANIFEST" {
- const manifest: string;
- export default manifest;
-}
diff --git a/templates/classic-remix-compiler/cloudflare-workers/server.ts b/templates/classic-remix-compiler/cloudflare-workers/server.ts
index 4b6e39ef295..bee19ccb283 100644
--- a/templates/classic-remix-compiler/cloudflare-workers/server.ts
+++ b/templates/classic-remix-compiler/cloudflare-workers/server.ts
@@ -1,11 +1,7 @@
-import { getAssetFromKV } from "@cloudflare/kv-asset-handler";
-import type { AppLoadContext } from "@remix-run/cloudflare";
import { createRequestHandler, logDevReady } from "@remix-run/cloudflare";
import * as build from "@remix-run/dev/server-build";
-// eslint-disable-next-line import/no-unresolved
-import __STATIC_CONTENT_MANIFEST from "__STATIC_CONTENT_MANIFEST";
+import { getLoadContext } from "./load-context";
-const MANIFEST = JSON.parse(__STATIC_CONTENT_MANIFEST);
const handleRemixRequest = createRequestHandler(build, process.env.NODE_ENV);
if (process.env.NODE_ENV === "development") {
@@ -13,44 +9,30 @@ if (process.env.NODE_ENV === "development") {
}
export default {
- async fetch(
- request: Request,
- env: {
- __STATIC_CONTENT: Fetcher;
- },
- ctx: ExecutionContext
- ): Promise {
+ async fetch(request, env, ctx): Promise {
try {
- const url = new URL(request.url);
- const ttl = url.pathname.startsWith("/build/")
- ? 60 * 60 * 24 * 365 // 1 year
- : 60 * 5; // 5 minutes
- return await getAssetFromKV(
- {
- request,
- waitUntil: ctx.waitUntil.bind(ctx),
- } as FetchEvent,
- {
- ASSET_NAMESPACE: env.__STATIC_CONTENT,
- ASSET_MANIFEST: MANIFEST,
- cacheControl: {
- browserTTL: ttl,
- edgeTTL: ttl,
+ const loadContext = getLoadContext({
+ request,
+ context: {
+ cloudflare: {
+ // This object matches the return value from Wrangler's
+ // `getPlatformProxy` used during development via Remix's
+ // `cloudflareDevProxyVitePlugin`:
+ // https://developers.cloudflare.com/workers/wrangler/api/#getplatformproxy
+ cf: request.cf,
+ ctx: {
+ waitUntil: ctx.waitUntil.bind(ctx),
+ passThroughOnException: ctx.passThroughOnException.bind(ctx),
+ },
+ caches,
+ env,
},
- }
- );
- } catch (error) {
- // No-op
- }
-
- try {
- const loadContext: AppLoadContext = {
- env,
- };
+ },
+ });
return await handleRemixRequest(request, loadContext);
} catch (error) {
console.log(error);
return new Response("An unexpected error occurred", { status: 500 });
}
},
-};
+} satisfies ExportedHandler;
diff --git a/templates/classic-remix-compiler/cloudflare-workers/tailwind.config.ts b/templates/classic-remix-compiler/cloudflare-workers/tailwind.config.ts
new file mode 100644
index 00000000000..14d0f00ce6a
--- /dev/null
+++ b/templates/classic-remix-compiler/cloudflare-workers/tailwind.config.ts
@@ -0,0 +1,22 @@
+import type { Config } from "tailwindcss";
+
+export default {
+ content: ["./app/**/{**,.client,.server}/**/*.{js,jsx,ts,tsx}"],
+ theme: {
+ extend: {
+ fontFamily: {
+ sans: [
+ '"Inter"',
+ "ui-sans-serif",
+ "system-ui",
+ "sans-serif",
+ '"Apple Color Emoji"',
+ '"Segoe UI Emoji"',
+ '"Segoe UI Symbol"',
+ '"Noto Color Emoji"',
+ ],
+ },
+ },
+ },
+ plugins: [],
+} satisfies Config;
diff --git a/templates/classic-remix-compiler/cloudflare-workers/tsconfig.json b/templates/classic-remix-compiler/cloudflare-workers/tsconfig.json
index 7edc18b084a..0fdf9f1f339 100644
--- a/templates/classic-remix-compiler/cloudflare-workers/tsconfig.json
+++ b/templates/classic-remix-compiler/cloudflare-workers/tsconfig.json
@@ -1,7 +1,13 @@
{
- "include": ["remix.env.d.ts", "**/*.ts", "**/*.tsx"],
+ "include": [
+ "worker-configuration.d.ts",
+ "remix.env.d.ts",
+ "**/*.ts",
+ "**/*.tsx"
+ ],
"compilerOptions": {
"lib": ["DOM", "DOM.Iterable", "ES2022"],
+ "types": ["@remix-run/cloudflare", "@cloudflare/workers-types"],
"isolatedModules": true,
"esModuleInterop": true,
"jsx": "react-jsx",
diff --git a/templates/classic-remix-compiler/cloudflare-workers/worker-configuration.d.ts b/templates/classic-remix-compiler/cloudflare-workers/worker-configuration.d.ts
new file mode 100644
index 00000000000..2a6ba0cb08c
--- /dev/null
+++ b/templates/classic-remix-compiler/cloudflare-workers/worker-configuration.d.ts
@@ -0,0 +1,3 @@
+// Generated by Wrangler by running `wrangler types`
+
+interface Env {}
diff --git a/templates/classic-remix-compiler/cloudflare-workers/wrangler.toml b/templates/classic-remix-compiler/cloudflare-workers/wrangler.toml
index e52f6c2e546..3dba78a2865 100644
--- a/templates/classic-remix-compiler/cloudflare-workers/wrangler.toml
+++ b/templates/classic-remix-compiler/cloudflare-workers/wrangler.toml
@@ -1,12 +1,15 @@
+#:schema node_modules/wrangler/config-schema.json
name = "remix-cloudflare-workers"
workers_dev = true
main = "./build/index.js"
# https://developers.cloudflare.com/workers/platform/compatibility-dates
-compatibility_date = "2023-04-20"
+compatibility_date = "2024-09-26"
-[site]
- bucket = "./public"
+[assets]
+directory = "./public"
-[build]
- command = "npm run build"
+[observability]
+# Set this to true to enable logging. (Extra costs may apply)
+# https://developers.cloudflare.com/workers/observability/logs/workers-logs
+enabled = false