diff --git a/docs/start/config.json b/docs/start/config.json
index 2d5ef6554cb..0f404784862 100644
--- a/docs/start/config.json
+++ b/docs/start/config.json
@@ -296,6 +296,10 @@
{
"label": "Basic + Static rendering",
"to": "framework/react/examples/start-basic-static"
+ },
+ {
+ "label": "Cloudflare Vite Plugin",
+ "to": "framework/react/examples/start-basic-cloudflare"
}
]
},
@@ -321,6 +325,10 @@
{
"label": "Basic + Static rendering",
"to": "framework/solid/examples/start-basic-static"
+ },
+ {
+ "label": "Cloudflare Vite Plugin",
+ "to": "framework/solid/examples/start-basic-cloudflare"
}
]
}
diff --git a/examples/solid/start-basic-cloudflare/.gitignore b/examples/solid/start-basic-cloudflare/.gitignore
new file mode 100644
index 00000000000..32f79ff6cd2
--- /dev/null
+++ b/examples/solid/start-basic-cloudflare/.gitignore
@@ -0,0 +1,6 @@
+node_modules
+.DS_Store
+.cache
+.env
+dist
+.wrangler
diff --git a/examples/solid/start-basic-cloudflare/.prettierignore b/examples/solid/start-basic-cloudflare/.prettierignore
new file mode 100644
index 00000000000..f36f42b7c8b
--- /dev/null
+++ b/examples/solid/start-basic-cloudflare/.prettierignore
@@ -0,0 +1,4 @@
+**/public
+pnpm-lock.yaml
+routeTree.gen.ts
+worker-configuration.d.ts
diff --git a/examples/solid/start-basic-cloudflare/.vscode/settings.json b/examples/solid/start-basic-cloudflare/.vscode/settings.json
new file mode 100644
index 00000000000..00b5278e580
--- /dev/null
+++ b/examples/solid/start-basic-cloudflare/.vscode/settings.json
@@ -0,0 +1,11 @@
+{
+ "files.watcherExclude": {
+ "**/routeTree.gen.ts": true
+ },
+ "search.exclude": {
+ "**/routeTree.gen.ts": true
+ },
+ "files.readonlyInclude": {
+ "**/routeTree.gen.ts": true
+ }
+}
diff --git a/examples/solid/start-basic-cloudflare/README.md b/examples/solid/start-basic-cloudflare/README.md
new file mode 100644
index 00000000000..be34d008fcd
--- /dev/null
+++ b/examples/solid/start-basic-cloudflare/README.md
@@ -0,0 +1,43 @@
+# Start Basic Cloudflare
+
+## Getting Started
+
+### Install the dependencies
+
+```bash
+pnpm i
+```
+
+### Start the development server
+
+```bash
+pnpm dev
+```
+
+### Build for Production
+
+```bash
+pnpm build
+```
+
+### Preview the production build
+
+```bash
+pnpm preview
+```
+
+### Deploy to Cloudflare
+
+```sh
+pnpm run deploy
+```
+
+## Accessing bindings
+
+You can access Cloudflare bindings in server functions by using importable `env`:
+
+```ts
+import { env } from 'cloudflare:workers'
+```
+
+See `src/routes/index.tsx` for an example.
diff --git a/examples/solid/start-basic-cloudflare/package.json b/examples/solid/start-basic-cloudflare/package.json
new file mode 100644
index 00000000000..d897598c5a5
--- /dev/null
+++ b/examples/solid/start-basic-cloudflare/package.json
@@ -0,0 +1,32 @@
+{
+ "name": "tanstack-solid-start-example-basic-cloudflare",
+ "private": true,
+ "sideEffects": false,
+ "type": "module",
+ "scripts": {
+ "dev": "vite dev",
+ "build": "vite build && tsc --noEmit",
+ "preview": "vite preview",
+ "deploy": "npm run build && wrangler deploy",
+ "cf-typegen": "wrangler types",
+ "postinstall": "npm run cf-typegen"
+ },
+ "dependencies": {
+ "@tanstack/solid-router": "^1.133.20",
+ "@tanstack/solid-router-devtools": "^1.133.20",
+ "@tanstack/solid-start": "^1.133.20",
+ "solid-js": "^1.9.5"
+ },
+ "devDependencies": {
+ "@cloudflare/vite-plugin": "^1.13.7",
+ "@types/node": "^22.5.4",
+ "vite-plugin-solid": "^2.11.9",
+ "autoprefixer": "^10.4.20",
+ "postcss": "^8.5.1",
+ "tailwindcss": "^3.4.17",
+ "typescript": "^5.7.2",
+ "vite": "^7.1.7",
+ "vite-tsconfig-paths": "^5.1.4",
+ "wrangler": "^4.40.2"
+ }
+}
diff --git a/examples/solid/start-basic-cloudflare/postcss.config.mjs b/examples/solid/start-basic-cloudflare/postcss.config.mjs
new file mode 100644
index 00000000000..2e7af2b7f1a
--- /dev/null
+++ b/examples/solid/start-basic-cloudflare/postcss.config.mjs
@@ -0,0 +1,6 @@
+export default {
+ plugins: {
+ tailwindcss: {},
+ autoprefixer: {},
+ },
+}
diff --git a/examples/solid/start-basic-cloudflare/public/android-chrome-192x192.png b/examples/solid/start-basic-cloudflare/public/android-chrome-192x192.png
new file mode 100644
index 00000000000..09c8324f8c6
Binary files /dev/null and b/examples/solid/start-basic-cloudflare/public/android-chrome-192x192.png differ
diff --git a/examples/solid/start-basic-cloudflare/public/android-chrome-512x512.png b/examples/solid/start-basic-cloudflare/public/android-chrome-512x512.png
new file mode 100644
index 00000000000..11d626ea3d0
Binary files /dev/null and b/examples/solid/start-basic-cloudflare/public/android-chrome-512x512.png differ
diff --git a/examples/solid/start-basic-cloudflare/public/apple-touch-icon.png b/examples/solid/start-basic-cloudflare/public/apple-touch-icon.png
new file mode 100644
index 00000000000..5a9423cc02c
Binary files /dev/null and b/examples/solid/start-basic-cloudflare/public/apple-touch-icon.png differ
diff --git a/examples/solid/start-basic-cloudflare/public/favicon-16x16.png b/examples/solid/start-basic-cloudflare/public/favicon-16x16.png
new file mode 100644
index 00000000000..e3389b00443
Binary files /dev/null and b/examples/solid/start-basic-cloudflare/public/favicon-16x16.png differ
diff --git a/examples/solid/start-basic-cloudflare/public/favicon-32x32.png b/examples/solid/start-basic-cloudflare/public/favicon-32x32.png
new file mode 100644
index 00000000000..900c77d444c
Binary files /dev/null and b/examples/solid/start-basic-cloudflare/public/favicon-32x32.png differ
diff --git a/examples/solid/start-basic-cloudflare/public/favicon.ico b/examples/solid/start-basic-cloudflare/public/favicon.ico
new file mode 100644
index 00000000000..1a1751676f7
Binary files /dev/null and b/examples/solid/start-basic-cloudflare/public/favicon.ico differ
diff --git a/examples/solid/start-basic-cloudflare/public/favicon.png b/examples/solid/start-basic-cloudflare/public/favicon.png
new file mode 100644
index 00000000000..1e77bc06091
Binary files /dev/null and b/examples/solid/start-basic-cloudflare/public/favicon.png differ
diff --git a/examples/solid/start-basic-cloudflare/public/site.webmanifest b/examples/solid/start-basic-cloudflare/public/site.webmanifest
new file mode 100644
index 00000000000..fa99de77db6
--- /dev/null
+++ b/examples/solid/start-basic-cloudflare/public/site.webmanifest
@@ -0,0 +1,19 @@
+{
+ "name": "",
+ "short_name": "",
+ "icons": [
+ {
+ "src": "/android-chrome-192x192.png",
+ "sizes": "192x192",
+ "type": "image/png"
+ },
+ {
+ "src": "/android-chrome-512x512.png",
+ "sizes": "512x512",
+ "type": "image/png"
+ }
+ ],
+ "theme_color": "#ffffff",
+ "background_color": "#ffffff",
+ "display": "standalone"
+}
diff --git a/examples/solid/start-basic-cloudflare/src/components/DefaultCatchBoundary.tsx b/examples/solid/start-basic-cloudflare/src/components/DefaultCatchBoundary.tsx
new file mode 100644
index 00000000000..0dff3919fd6
--- /dev/null
+++ b/examples/solid/start-basic-cloudflare/src/components/DefaultCatchBoundary.tsx
@@ -0,0 +1,53 @@
+import {
+ ErrorComponent,
+ Link,
+ rootRouteId,
+ useMatch,
+ useRouter,
+} from '@tanstack/solid-router'
+import type { ErrorComponentProps } from '@tanstack/solid-router'
+
+export function DefaultCatchBoundary({ error }: ErrorComponentProps) {
+ const router = useRouter()
+ const isRoot = useMatch({
+ strict: false,
+ select: (state) => state.id === rootRouteId,
+ })
+
+ console.error('DefaultCatchBoundary Error:', error)
+
+ return (
+
+
+
+
+ {isRoot() ? (
+
+ Home
+
+ ) : (
+ {
+ e.preventDefault()
+ window.history.back()
+ }}
+ >
+ Go Back
+
+ )}
+
+
+ )
+}
diff --git a/examples/solid/start-basic-cloudflare/src/components/NotFound.tsx b/examples/solid/start-basic-cloudflare/src/components/NotFound.tsx
new file mode 100644
index 00000000000..ca4c1960fa1
--- /dev/null
+++ b/examples/solid/start-basic-cloudflare/src/components/NotFound.tsx
@@ -0,0 +1,25 @@
+import { Link } from '@tanstack/solid-router'
+
+export function NotFound({ children }: { children?: any }) {
+ return (
+
+
+ {children ||
The page you are looking for does not exist.
}
+
+
+
+
+ Start Over
+
+
+
+ )
+}
diff --git a/examples/solid/start-basic-cloudflare/src/components/PostError.tsx b/examples/solid/start-basic-cloudflare/src/components/PostError.tsx
new file mode 100644
index 00000000000..eb91230d764
--- /dev/null
+++ b/examples/solid/start-basic-cloudflare/src/components/PostError.tsx
@@ -0,0 +1,6 @@
+import { ErrorComponent } from '@tanstack/solid-router'
+import type { ErrorComponentProps } from '@tanstack/solid-router'
+
+export function PostErrorComponent({ error }: ErrorComponentProps) {
+ return
+}
diff --git a/examples/solid/start-basic-cloudflare/src/components/UserError.tsx b/examples/solid/start-basic-cloudflare/src/components/UserError.tsx
new file mode 100644
index 00000000000..529c544ce57
--- /dev/null
+++ b/examples/solid/start-basic-cloudflare/src/components/UserError.tsx
@@ -0,0 +1,6 @@
+import { ErrorComponent } from '@tanstack/solid-router'
+import type { ErrorComponentProps } from '@tanstack/solid-router'
+
+export function UserErrorComponent({ error }: ErrorComponentProps) {
+ return
+}
diff --git a/examples/solid/start-basic-cloudflare/src/routeTree.gen.ts b/examples/solid/start-basic-cloudflare/src/routeTree.gen.ts
new file mode 100644
index 00000000000..194a2a07052
--- /dev/null
+++ b/examples/solid/start-basic-cloudflare/src/routeTree.gen.ts
@@ -0,0 +1,447 @@
+/* eslint-disable */
+
+// @ts-nocheck
+
+// noinspection JSUnusedGlobalSymbols
+
+// This file was automatically generated by TanStack Router.
+// You should NOT make any changes in this file as it will be overwritten.
+// Additionally, you should also exclude this file from your linter and/or formatter to prevent it from being checked or modified.
+
+import { Route as rootRouteImport } from './routes/__root'
+import { Route as UsersRouteImport } from './routes/users'
+import { Route as RedirectRouteImport } from './routes/redirect'
+import { Route as PostsRouteImport } from './routes/posts'
+import { Route as DeferredRouteImport } from './routes/deferred'
+import { Route as CustomScriptDotjsRouteImport } from './routes/customScript[.]js'
+import { Route as PathlessLayoutRouteImport } from './routes/_pathlessLayout'
+import { Route as IndexRouteImport } from './routes/index'
+import { Route as UsersIndexRouteImport } from './routes/users.index'
+import { Route as PostsIndexRouteImport } from './routes/posts.index'
+import { Route as UsersUserIdRouteImport } from './routes/users.$userId'
+import { Route as PostsPostIdRouteImport } from './routes/posts.$postId'
+import { Route as ApiUsersRouteImport } from './routes/api/users'
+import { Route as PathlessLayoutNestedLayoutRouteImport } from './routes/_pathlessLayout/_nested-layout'
+import { Route as PostsPostIdDeepRouteImport } from './routes/posts_.$postId.deep'
+import { Route as ApiUsersUserIdRouteImport } from './routes/api/users.$userId'
+import { Route as PathlessLayoutNestedLayoutRouteBRouteImport } from './routes/_pathlessLayout/_nested-layout/route-b'
+import { Route as PathlessLayoutNestedLayoutRouteARouteImport } from './routes/_pathlessLayout/_nested-layout/route-a'
+
+const UsersRoute = UsersRouteImport.update({
+ id: '/users',
+ path: '/users',
+ getParentRoute: () => rootRouteImport,
+} as any)
+const RedirectRoute = RedirectRouteImport.update({
+ id: '/redirect',
+ path: '/redirect',
+ getParentRoute: () => rootRouteImport,
+} as any)
+const PostsRoute = PostsRouteImport.update({
+ id: '/posts',
+ path: '/posts',
+ getParentRoute: () => rootRouteImport,
+} as any)
+const DeferredRoute = DeferredRouteImport.update({
+ id: '/deferred',
+ path: '/deferred',
+ getParentRoute: () => rootRouteImport,
+} as any)
+const CustomScriptDotjsRoute = CustomScriptDotjsRouteImport.update({
+ id: '/customScript.js',
+ path: '/customScript.js',
+ getParentRoute: () => rootRouteImport,
+} as any)
+const PathlessLayoutRoute = PathlessLayoutRouteImport.update({
+ id: '/_pathlessLayout',
+ getParentRoute: () => rootRouteImport,
+} as any)
+const IndexRoute = IndexRouteImport.update({
+ id: '/',
+ path: '/',
+ getParentRoute: () => rootRouteImport,
+} as any)
+const UsersIndexRoute = UsersIndexRouteImport.update({
+ id: '/',
+ path: '/',
+ getParentRoute: () => UsersRoute,
+} as any)
+const PostsIndexRoute = PostsIndexRouteImport.update({
+ id: '/',
+ path: '/',
+ getParentRoute: () => PostsRoute,
+} as any)
+const UsersUserIdRoute = UsersUserIdRouteImport.update({
+ id: '/$userId',
+ path: '/$userId',
+ getParentRoute: () => UsersRoute,
+} as any)
+const PostsPostIdRoute = PostsPostIdRouteImport.update({
+ id: '/$postId',
+ path: '/$postId',
+ getParentRoute: () => PostsRoute,
+} as any)
+const ApiUsersRoute = ApiUsersRouteImport.update({
+ id: '/api/users',
+ path: '/api/users',
+ getParentRoute: () => rootRouteImport,
+} as any)
+const PathlessLayoutNestedLayoutRoute =
+ PathlessLayoutNestedLayoutRouteImport.update({
+ id: '/_nested-layout',
+ getParentRoute: () => PathlessLayoutRoute,
+ } as any)
+const PostsPostIdDeepRoute = PostsPostIdDeepRouteImport.update({
+ id: '/posts_/$postId/deep',
+ path: '/posts/$postId/deep',
+ getParentRoute: () => rootRouteImport,
+} as any)
+const ApiUsersUserIdRoute = ApiUsersUserIdRouteImport.update({
+ id: '/$userId',
+ path: '/$userId',
+ getParentRoute: () => ApiUsersRoute,
+} as any)
+const PathlessLayoutNestedLayoutRouteBRoute =
+ PathlessLayoutNestedLayoutRouteBRouteImport.update({
+ id: '/route-b',
+ path: '/route-b',
+ getParentRoute: () => PathlessLayoutNestedLayoutRoute,
+ } as any)
+const PathlessLayoutNestedLayoutRouteARoute =
+ PathlessLayoutNestedLayoutRouteARouteImport.update({
+ id: '/route-a',
+ path: '/route-a',
+ getParentRoute: () => PathlessLayoutNestedLayoutRoute,
+ } as any)
+
+export interface FileRoutesByFullPath {
+ '/': typeof IndexRoute
+ '/customScript.js': typeof CustomScriptDotjsRoute
+ '/deferred': typeof DeferredRoute
+ '/posts': typeof PostsRouteWithChildren
+ '/redirect': typeof RedirectRoute
+ '/users': typeof UsersRouteWithChildren
+ '/api/users': typeof ApiUsersRouteWithChildren
+ '/posts/$postId': typeof PostsPostIdRoute
+ '/users/$userId': typeof UsersUserIdRoute
+ '/posts/': typeof PostsIndexRoute
+ '/users/': typeof UsersIndexRoute
+ '/route-a': typeof PathlessLayoutNestedLayoutRouteARoute
+ '/route-b': typeof PathlessLayoutNestedLayoutRouteBRoute
+ '/api/users/$userId': typeof ApiUsersUserIdRoute
+ '/posts/$postId/deep': typeof PostsPostIdDeepRoute
+}
+export interface FileRoutesByTo {
+ '/': typeof IndexRoute
+ '/customScript.js': typeof CustomScriptDotjsRoute
+ '/deferred': typeof DeferredRoute
+ '/redirect': typeof RedirectRoute
+ '/api/users': typeof ApiUsersRouteWithChildren
+ '/posts/$postId': typeof PostsPostIdRoute
+ '/users/$userId': typeof UsersUserIdRoute
+ '/posts': typeof PostsIndexRoute
+ '/users': typeof UsersIndexRoute
+ '/route-a': typeof PathlessLayoutNestedLayoutRouteARoute
+ '/route-b': typeof PathlessLayoutNestedLayoutRouteBRoute
+ '/api/users/$userId': typeof ApiUsersUserIdRoute
+ '/posts/$postId/deep': typeof PostsPostIdDeepRoute
+}
+export interface FileRoutesById {
+ __root__: typeof rootRouteImport
+ '/': typeof IndexRoute
+ '/_pathlessLayout': typeof PathlessLayoutRouteWithChildren
+ '/customScript.js': typeof CustomScriptDotjsRoute
+ '/deferred': typeof DeferredRoute
+ '/posts': typeof PostsRouteWithChildren
+ '/redirect': typeof RedirectRoute
+ '/users': typeof UsersRouteWithChildren
+ '/_pathlessLayout/_nested-layout': typeof PathlessLayoutNestedLayoutRouteWithChildren
+ '/api/users': typeof ApiUsersRouteWithChildren
+ '/posts/$postId': typeof PostsPostIdRoute
+ '/users/$userId': typeof UsersUserIdRoute
+ '/posts/': typeof PostsIndexRoute
+ '/users/': typeof UsersIndexRoute
+ '/_pathlessLayout/_nested-layout/route-a': typeof PathlessLayoutNestedLayoutRouteARoute
+ '/_pathlessLayout/_nested-layout/route-b': typeof PathlessLayoutNestedLayoutRouteBRoute
+ '/api/users/$userId': typeof ApiUsersUserIdRoute
+ '/posts_/$postId/deep': typeof PostsPostIdDeepRoute
+}
+export interface FileRouteTypes {
+ fileRoutesByFullPath: FileRoutesByFullPath
+ fullPaths:
+ | '/'
+ | '/customScript.js'
+ | '/deferred'
+ | '/posts'
+ | '/redirect'
+ | '/users'
+ | '/api/users'
+ | '/posts/$postId'
+ | '/users/$userId'
+ | '/posts/'
+ | '/users/'
+ | '/route-a'
+ | '/route-b'
+ | '/api/users/$userId'
+ | '/posts/$postId/deep'
+ fileRoutesByTo: FileRoutesByTo
+ to:
+ | '/'
+ | '/customScript.js'
+ | '/deferred'
+ | '/redirect'
+ | '/api/users'
+ | '/posts/$postId'
+ | '/users/$userId'
+ | '/posts'
+ | '/users'
+ | '/route-a'
+ | '/route-b'
+ | '/api/users/$userId'
+ | '/posts/$postId/deep'
+ id:
+ | '__root__'
+ | '/'
+ | '/_pathlessLayout'
+ | '/customScript.js'
+ | '/deferred'
+ | '/posts'
+ | '/redirect'
+ | '/users'
+ | '/_pathlessLayout/_nested-layout'
+ | '/api/users'
+ | '/posts/$postId'
+ | '/users/$userId'
+ | '/posts/'
+ | '/users/'
+ | '/_pathlessLayout/_nested-layout/route-a'
+ | '/_pathlessLayout/_nested-layout/route-b'
+ | '/api/users/$userId'
+ | '/posts_/$postId/deep'
+ fileRoutesById: FileRoutesById
+}
+export interface RootRouteChildren {
+ IndexRoute: typeof IndexRoute
+ PathlessLayoutRoute: typeof PathlessLayoutRouteWithChildren
+ CustomScriptDotjsRoute: typeof CustomScriptDotjsRoute
+ DeferredRoute: typeof DeferredRoute
+ PostsRoute: typeof PostsRouteWithChildren
+ RedirectRoute: typeof RedirectRoute
+ UsersRoute: typeof UsersRouteWithChildren
+ ApiUsersRoute: typeof ApiUsersRouteWithChildren
+ PostsPostIdDeepRoute: typeof PostsPostIdDeepRoute
+}
+
+declare module '@tanstack/solid-router' {
+ interface FileRoutesByPath {
+ '/users': {
+ id: '/users'
+ path: '/users'
+ fullPath: '/users'
+ preLoaderRoute: typeof UsersRouteImport
+ parentRoute: typeof rootRouteImport
+ }
+ '/redirect': {
+ id: '/redirect'
+ path: '/redirect'
+ fullPath: '/redirect'
+ preLoaderRoute: typeof RedirectRouteImport
+ parentRoute: typeof rootRouteImport
+ }
+ '/posts': {
+ id: '/posts'
+ path: '/posts'
+ fullPath: '/posts'
+ preLoaderRoute: typeof PostsRouteImport
+ parentRoute: typeof rootRouteImport
+ }
+ '/deferred': {
+ id: '/deferred'
+ path: '/deferred'
+ fullPath: '/deferred'
+ preLoaderRoute: typeof DeferredRouteImport
+ parentRoute: typeof rootRouteImport
+ }
+ '/customScript.js': {
+ id: '/customScript.js'
+ path: '/customScript.js'
+ fullPath: '/customScript.js'
+ preLoaderRoute: typeof CustomScriptDotjsRouteImport
+ parentRoute: typeof rootRouteImport
+ }
+ '/_pathlessLayout': {
+ id: '/_pathlessLayout'
+ path: ''
+ fullPath: ''
+ preLoaderRoute: typeof PathlessLayoutRouteImport
+ parentRoute: typeof rootRouteImport
+ }
+ '/': {
+ id: '/'
+ path: '/'
+ fullPath: '/'
+ preLoaderRoute: typeof IndexRouteImport
+ parentRoute: typeof rootRouteImport
+ }
+ '/users/': {
+ id: '/users/'
+ path: '/'
+ fullPath: '/users/'
+ preLoaderRoute: typeof UsersIndexRouteImport
+ parentRoute: typeof UsersRoute
+ }
+ '/posts/': {
+ id: '/posts/'
+ path: '/'
+ fullPath: '/posts/'
+ preLoaderRoute: typeof PostsIndexRouteImport
+ parentRoute: typeof PostsRoute
+ }
+ '/users/$userId': {
+ id: '/users/$userId'
+ path: '/$userId'
+ fullPath: '/users/$userId'
+ preLoaderRoute: typeof UsersUserIdRouteImport
+ parentRoute: typeof UsersRoute
+ }
+ '/posts/$postId': {
+ id: '/posts/$postId'
+ path: '/$postId'
+ fullPath: '/posts/$postId'
+ preLoaderRoute: typeof PostsPostIdRouteImport
+ parentRoute: typeof PostsRoute
+ }
+ '/api/users': {
+ id: '/api/users'
+ path: '/api/users'
+ fullPath: '/api/users'
+ preLoaderRoute: typeof ApiUsersRouteImport
+ parentRoute: typeof rootRouteImport
+ }
+ '/_pathlessLayout/_nested-layout': {
+ id: '/_pathlessLayout/_nested-layout'
+ path: ''
+ fullPath: ''
+ preLoaderRoute: typeof PathlessLayoutNestedLayoutRouteImport
+ parentRoute: typeof PathlessLayoutRoute
+ }
+ '/posts_/$postId/deep': {
+ id: '/posts_/$postId/deep'
+ path: '/posts/$postId/deep'
+ fullPath: '/posts/$postId/deep'
+ preLoaderRoute: typeof PostsPostIdDeepRouteImport
+ parentRoute: typeof rootRouteImport
+ }
+ '/api/users/$userId': {
+ id: '/api/users/$userId'
+ path: '/$userId'
+ fullPath: '/api/users/$userId'
+ preLoaderRoute: typeof ApiUsersUserIdRouteImport
+ parentRoute: typeof ApiUsersRoute
+ }
+ '/_pathlessLayout/_nested-layout/route-b': {
+ id: '/_pathlessLayout/_nested-layout/route-b'
+ path: '/route-b'
+ fullPath: '/route-b'
+ preLoaderRoute: typeof PathlessLayoutNestedLayoutRouteBRouteImport
+ parentRoute: typeof PathlessLayoutNestedLayoutRoute
+ }
+ '/_pathlessLayout/_nested-layout/route-a': {
+ id: '/_pathlessLayout/_nested-layout/route-a'
+ path: '/route-a'
+ fullPath: '/route-a'
+ preLoaderRoute: typeof PathlessLayoutNestedLayoutRouteARouteImport
+ parentRoute: typeof PathlessLayoutNestedLayoutRoute
+ }
+ }
+}
+
+interface PathlessLayoutNestedLayoutRouteChildren {
+ PathlessLayoutNestedLayoutRouteARoute: typeof PathlessLayoutNestedLayoutRouteARoute
+ PathlessLayoutNestedLayoutRouteBRoute: typeof PathlessLayoutNestedLayoutRouteBRoute
+}
+
+const PathlessLayoutNestedLayoutRouteChildren: PathlessLayoutNestedLayoutRouteChildren =
+ {
+ PathlessLayoutNestedLayoutRouteARoute:
+ PathlessLayoutNestedLayoutRouteARoute,
+ PathlessLayoutNestedLayoutRouteBRoute:
+ PathlessLayoutNestedLayoutRouteBRoute,
+ }
+
+const PathlessLayoutNestedLayoutRouteWithChildren =
+ PathlessLayoutNestedLayoutRoute._addFileChildren(
+ PathlessLayoutNestedLayoutRouteChildren,
+ )
+
+interface PathlessLayoutRouteChildren {
+ PathlessLayoutNestedLayoutRoute: typeof PathlessLayoutNestedLayoutRouteWithChildren
+}
+
+const PathlessLayoutRouteChildren: PathlessLayoutRouteChildren = {
+ PathlessLayoutNestedLayoutRoute: PathlessLayoutNestedLayoutRouteWithChildren,
+}
+
+const PathlessLayoutRouteWithChildren = PathlessLayoutRoute._addFileChildren(
+ PathlessLayoutRouteChildren,
+)
+
+interface PostsRouteChildren {
+ PostsPostIdRoute: typeof PostsPostIdRoute
+ PostsIndexRoute: typeof PostsIndexRoute
+}
+
+const PostsRouteChildren: PostsRouteChildren = {
+ PostsPostIdRoute: PostsPostIdRoute,
+ PostsIndexRoute: PostsIndexRoute,
+}
+
+const PostsRouteWithChildren = PostsRoute._addFileChildren(PostsRouteChildren)
+
+interface UsersRouteChildren {
+ UsersUserIdRoute: typeof UsersUserIdRoute
+ UsersIndexRoute: typeof UsersIndexRoute
+}
+
+const UsersRouteChildren: UsersRouteChildren = {
+ UsersUserIdRoute: UsersUserIdRoute,
+ UsersIndexRoute: UsersIndexRoute,
+}
+
+const UsersRouteWithChildren = UsersRoute._addFileChildren(UsersRouteChildren)
+
+interface ApiUsersRouteChildren {
+ ApiUsersUserIdRoute: typeof ApiUsersUserIdRoute
+}
+
+const ApiUsersRouteChildren: ApiUsersRouteChildren = {
+ ApiUsersUserIdRoute: ApiUsersUserIdRoute,
+}
+
+const ApiUsersRouteWithChildren = ApiUsersRoute._addFileChildren(
+ ApiUsersRouteChildren,
+)
+
+const rootRouteChildren: RootRouteChildren = {
+ IndexRoute: IndexRoute,
+ PathlessLayoutRoute: PathlessLayoutRouteWithChildren,
+ CustomScriptDotjsRoute: CustomScriptDotjsRoute,
+ DeferredRoute: DeferredRoute,
+ PostsRoute: PostsRouteWithChildren,
+ RedirectRoute: RedirectRoute,
+ UsersRoute: UsersRouteWithChildren,
+ ApiUsersRoute: ApiUsersRouteWithChildren,
+ PostsPostIdDeepRoute: PostsPostIdDeepRoute,
+}
+export const routeTree = rootRouteImport
+ ._addFileChildren(rootRouteChildren)
+ ._addFileTypes()
+
+import type { getRouter } from './router.tsx'
+import type { createStart } from '@tanstack/solid-start'
+declare module '@tanstack/solid-start' {
+ interface Register {
+ ssr: true
+ router: Awaited>
+ }
+}
diff --git a/examples/solid/start-basic-cloudflare/src/router.tsx b/examples/solid/start-basic-cloudflare/src/router.tsx
new file mode 100644
index 00000000000..5da353c1ce2
--- /dev/null
+++ b/examples/solid/start-basic-cloudflare/src/router.tsx
@@ -0,0 +1,16 @@
+import { createRouter } from '@tanstack/solid-router'
+import { routeTree } from './routeTree.gen'
+import { DefaultCatchBoundary } from './components/DefaultCatchBoundary'
+import { NotFound } from './components/NotFound'
+
+export function getRouter() {
+ const router = createRouter({
+ routeTree,
+ defaultPreload: 'intent',
+ defaultErrorComponent: DefaultCatchBoundary,
+ defaultNotFoundComponent: () => ,
+ scrollRestoration: true,
+ })
+
+ return router
+}
diff --git a/examples/solid/start-basic-cloudflare/src/routes/__root.tsx b/examples/solid/start-basic-cloudflare/src/routes/__root.tsx
new file mode 100644
index 00000000000..a8b324f1b3a
--- /dev/null
+++ b/examples/solid/start-basic-cloudflare/src/routes/__root.tsx
@@ -0,0 +1,133 @@
+///
+import {
+ HeadContent,
+ Link,
+ Scripts,
+ createRootRoute,
+} from '@tanstack/solid-router'
+import { TanStackRouterDevtools } from '@tanstack/solid-router-devtools'
+import { HydrationScript } from 'solid-js/web'
+import type * as Solid from 'solid-js'
+import { DefaultCatchBoundary } from '~/components/DefaultCatchBoundary'
+import { NotFound } from '~/components/NotFound'
+import appCss from '~/styles/app.css?url'
+import { seo } from '~/utils/seo'
+
+export const Route = createRootRoute({
+ head: () => ({
+ meta: [
+ {
+ charset: 'utf-8',
+ },
+ {
+ name: 'viewport',
+ content: 'width=device-width, initial-scale=1',
+ },
+ ...seo({
+ title:
+ 'TanStack Start | Type-Safe, Client-First, Full-Stack React Framework',
+ description: `TanStack Start is a type-safe, client-first, full-stack React framework. `,
+ }),
+ ],
+ links: [
+ { rel: 'stylesheet', href: appCss },
+ {
+ rel: 'apple-touch-icon',
+ sizes: '180x180',
+ href: '/apple-touch-icon.png',
+ },
+ {
+ rel: 'icon',
+ type: 'image/png',
+ sizes: '32x32',
+ href: '/favicon-32x32.png',
+ },
+ {
+ rel: 'icon',
+ type: 'image/png',
+ sizes: '16x16',
+ href: '/favicon-16x16.png',
+ },
+ { rel: 'manifest', href: '/site.webmanifest', color: '#fffff' },
+ { rel: 'icon', href: '/favicon.ico' },
+ ],
+ scripts: [
+ {
+ src: '/customScript.js',
+ type: 'text/javascript',
+ },
+ ],
+ }),
+ errorComponent: DefaultCatchBoundary,
+ notFoundComponent: () => ,
+ shellComponent: RootDocument,
+})
+
+function RootDocument({ children }: { children: Solid.JSX.Element }) {
+ return (
+
+
+
+
+
+
+
+
+ Home
+ {' '}
+
+ Posts
+ {' '}
+
+ Users
+ {' '}
+
+ Pathless Layout
+ {' '}
+
+ Deferred
+ {' '}
+
+ This Route Does Not Exist
+
+
+
+ {children}
+
+
+
+
+ )
+}
diff --git a/examples/solid/start-basic-cloudflare/src/routes/_pathlessLayout.tsx b/examples/solid/start-basic-cloudflare/src/routes/_pathlessLayout.tsx
new file mode 100644
index 00000000000..af197bc038c
--- /dev/null
+++ b/examples/solid/start-basic-cloudflare/src/routes/_pathlessLayout.tsx
@@ -0,0 +1,16 @@
+import { Outlet, createFileRoute } from '@tanstack/solid-router'
+
+export const Route = createFileRoute('/_pathlessLayout')({
+ component: LayoutComponent,
+})
+
+function LayoutComponent() {
+ return (
+
+ )
+}
diff --git a/examples/solid/start-basic-cloudflare/src/routes/_pathlessLayout/_nested-layout.tsx b/examples/solid/start-basic-cloudflare/src/routes/_pathlessLayout/_nested-layout.tsx
new file mode 100644
index 00000000000..24e4b2545bf
--- /dev/null
+++ b/examples/solid/start-basic-cloudflare/src/routes/_pathlessLayout/_nested-layout.tsx
@@ -0,0 +1,34 @@
+import { Link, Outlet, createFileRoute } from '@tanstack/solid-router'
+
+export const Route = createFileRoute('/_pathlessLayout/_nested-layout')({
+ component: LayoutComponent,
+})
+
+function LayoutComponent() {
+ return (
+
+
I'm a nested layout
+
+
+ Go to route A
+
+
+ Go to route B
+
+
+
+
+
+
+ )
+}
diff --git a/examples/solid/start-basic-cloudflare/src/routes/_pathlessLayout/_nested-layout/route-a.tsx b/examples/solid/start-basic-cloudflare/src/routes/_pathlessLayout/_nested-layout/route-a.tsx
new file mode 100644
index 00000000000..a22902a271f
--- /dev/null
+++ b/examples/solid/start-basic-cloudflare/src/routes/_pathlessLayout/_nested-layout/route-a.tsx
@@ -0,0 +1,11 @@
+import { createFileRoute } from '@tanstack/solid-router'
+
+export const Route = createFileRoute('/_pathlessLayout/_nested-layout/route-a')(
+ {
+ component: LayoutAComponent,
+ },
+)
+
+function LayoutAComponent() {
+ return I'm A!
+}
diff --git a/examples/solid/start-basic-cloudflare/src/routes/_pathlessLayout/_nested-layout/route-b.tsx b/examples/solid/start-basic-cloudflare/src/routes/_pathlessLayout/_nested-layout/route-b.tsx
new file mode 100644
index 00000000000..36231d21539
--- /dev/null
+++ b/examples/solid/start-basic-cloudflare/src/routes/_pathlessLayout/_nested-layout/route-b.tsx
@@ -0,0 +1,11 @@
+import { createFileRoute } from '@tanstack/solid-router'
+
+export const Route = createFileRoute('/_pathlessLayout/_nested-layout/route-b')(
+ {
+ component: LayoutBComponent,
+ },
+)
+
+function LayoutBComponent() {
+ return I'm B!
+}
diff --git a/examples/solid/start-basic-cloudflare/src/routes/api/users.$userId.ts b/examples/solid/start-basic-cloudflare/src/routes/api/users.$userId.ts
new file mode 100644
index 00000000000..8f31b7a8900
--- /dev/null
+++ b/examples/solid/start-basic-cloudflare/src/routes/api/users.$userId.ts
@@ -0,0 +1,33 @@
+import { createFileRoute } from '@tanstack/solid-router'
+import { json } from '@tanstack/solid-start'
+import type { User } from '~/utils/users'
+
+export const Route = createFileRoute('/api/users/$userId')({
+ server: {
+ handlers: {
+ GET: async ({ params, request }) => {
+ console.info(`Fetching users by id=${params.userId}... @`, request.url)
+ try {
+ const res = await fetch(
+ 'https://jsonplaceholder.typicode.com/users/' + params.userId,
+ )
+ if (!res.ok) {
+ throw new Error('Failed to fetch user')
+ }
+
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion
+ const user = (await res.json()) as User
+
+ return json({
+ id: user.id,
+ name: user.name,
+ email: user.email,
+ })
+ } catch (e) {
+ console.error(e)
+ return json({ error: 'User not found' }, { status: 404 })
+ }
+ },
+ },
+ },
+})
diff --git a/examples/solid/start-basic-cloudflare/src/routes/api/users.ts b/examples/solid/start-basic-cloudflare/src/routes/api/users.ts
new file mode 100644
index 00000000000..a9d6505508b
--- /dev/null
+++ b/examples/solid/start-basic-cloudflare/src/routes/api/users.ts
@@ -0,0 +1,64 @@
+import { createFileRoute } from '@tanstack/solid-router'
+import { getRequestHeaders } from '@tanstack/solid-start/server'
+import { createMiddleware, json } from '@tanstack/solid-start'
+import type { User } from '~/utils/users'
+
+const userLoggerMiddleware = createMiddleware().server(async ({ next }) => {
+ console.info('In: /users')
+ console.info('Request Headers:', getRequestHeaders())
+ const result = await next()
+ result.response.headers.set('x-users', 'true')
+ console.info('Out: /users')
+ return result
+})
+
+const testParentMiddleware = createMiddleware().server(async ({ next }) => {
+ console.info('In: testParentMiddleware')
+ const result = await next()
+ result.response.headers.set('x-test-parent', 'true')
+ console.info('Out: testParentMiddleware')
+ return result
+})
+
+const testMiddleware = createMiddleware()
+ .middleware([testParentMiddleware])
+ .server(async ({ next }) => {
+ console.info('In: testMiddleware')
+ const result = await next()
+ result.response.headers.set('x-test', 'true')
+
+ // if (Math.random() > 0.5) {
+ // throw new Response(null, {
+ // status: 302,
+ // headers: { Location: 'https://www.google.com' },
+ // })
+ // }
+
+ console.info('Out: testMiddleware')
+ return result
+ })
+
+export const Route = createFileRoute('/api/users')({
+ server: {
+ middleware: [testMiddleware, userLoggerMiddleware],
+ handlers: {
+ GET: async ({ request }) => {
+ console.info('GET /api/users @', request.url)
+ console.info('Fetching users... @', request.url)
+ const res = await fetch('https://jsonplaceholder.typicode.com/users')
+ if (!res.ok) {
+ throw new Error('Failed to fetch users')
+ }
+
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion
+ const data = (await res.json()) as Array
+
+ const list = data.slice(0, 10)
+
+ return json(
+ list.map((u) => ({ id: u.id, name: u.name, email: u.email })),
+ )
+ },
+ },
+ },
+})
diff --git a/examples/solid/start-basic-cloudflare/src/routes/customScript[.]js.ts b/examples/solid/start-basic-cloudflare/src/routes/customScript[.]js.ts
new file mode 100644
index 00000000000..35b756189ec
--- /dev/null
+++ b/examples/solid/start-basic-cloudflare/src/routes/customScript[.]js.ts
@@ -0,0 +1,15 @@
+import { createFileRoute } from '@tanstack/solid-router'
+
+export const Route = createFileRoute('/customScript.js')({
+ server: {
+ handlers: {
+ GET: () => {
+ return new Response('console.log("Hello from customScript.js!")', {
+ headers: {
+ 'Content-Type': 'application/javascript',
+ },
+ })
+ },
+ },
+ },
+})
diff --git a/examples/solid/start-basic-cloudflare/src/routes/deferred.tsx b/examples/solid/start-basic-cloudflare/src/routes/deferred.tsx
new file mode 100644
index 00000000000..97c018ab033
--- /dev/null
+++ b/examples/solid/start-basic-cloudflare/src/routes/deferred.tsx
@@ -0,0 +1,62 @@
+import { Await, createFileRoute } from '@tanstack/solid-router'
+import { createServerFn } from '@tanstack/solid-start'
+import { Suspense, createSignal } from 'solid-js'
+
+const personServerFn = createServerFn({ method: 'GET' })
+ .inputValidator((d: string) => d)
+ .handler(({ data: name }) => {
+ return { name, randomNumber: Math.floor(Math.random() * 100) }
+ })
+
+const slowServerFn = createServerFn({ method: 'GET' })
+ .inputValidator((d: string) => d)
+ .handler(async ({ data: name }) => {
+ await new Promise((r) => setTimeout(r, 1000))
+ return { name, randomNumber: Math.floor(Math.random() * 100) }
+ })
+
+export const Route = createFileRoute('/deferred')({
+ loader: async () => {
+ return {
+ deferredStuff: new Promise((r) =>
+ setTimeout(() => r('Hello deferred!'), 2000),
+ ),
+ deferredPerson: slowServerFn({ data: 'Tanner Linsley' }),
+ person: await personServerFn({ data: 'John Doe' }),
+ }
+ },
+ component: Deferred,
+})
+
+function Deferred() {
+ const [count, setCount] = createSignal(0)
+ const loaderData = Route.useLoaderData()
+
+ return (
+
+
+ {loaderData().person.name} - {loaderData().person.randomNumber}
+
+
Loading person... }>
+ (
+
+ {data.name} - {data.randomNumber}
+
+ )}
+ />
+
+ Loading stuff...}>
+ {data}
}
+ />
+
+ Count: {count()}
+
+
+
+
+ )
+}
diff --git a/examples/solid/start-basic-cloudflare/src/routes/index.tsx b/examples/solid/start-basic-cloudflare/src/routes/index.tsx
new file mode 100644
index 00000000000..3a610529b01
--- /dev/null
+++ b/examples/solid/start-basic-cloudflare/src/routes/index.tsx
@@ -0,0 +1,27 @@
+import { createFileRoute } from '@tanstack/solid-router'
+import { createServerFn } from '@tanstack/solid-start'
+import { env } from 'cloudflare:workers'
+
+export const Route = createFileRoute('/')({
+ loader: () => getData(),
+ component: Home,
+})
+
+const getData = createServerFn().handler(() => {
+ return {
+ message: `Running in ${navigator.userAgent}`,
+ myVar: env.MY_VAR,
+ }
+})
+
+function Home() {
+ const data = Route.useLoaderData()
+
+ return (
+
+
Welcome Home!!!
+
{data().message}
+
{data().myVar}
+
+ )
+}
diff --git a/examples/solid/start-basic-cloudflare/src/routes/posts.$postId.tsx b/examples/solid/start-basic-cloudflare/src/routes/posts.$postId.tsx
new file mode 100644
index 00000000000..a5bd2751440
--- /dev/null
+++ b/examples/solid/start-basic-cloudflare/src/routes/posts.$postId.tsx
@@ -0,0 +1,34 @@
+import { Link, createFileRoute } from '@tanstack/solid-router'
+import { fetchPost } from '../utils/posts'
+import { NotFound } from '~/components/NotFound'
+import { PostErrorComponent } from '~/components/PostError'
+
+export const Route = createFileRoute('/posts/$postId')({
+ loader: ({ params: { postId } }) => fetchPost({ data: postId }),
+ errorComponent: PostErrorComponent,
+ component: PostComponent,
+ notFoundComponent: () => {
+ return Post not found
+ },
+})
+
+function PostComponent() {
+ const post = Route.useLoaderData()
+
+ return (
+
+
{post().title}
+
{post().body}
+
+ Deep View
+
+
+ )
+}
diff --git a/examples/solid/start-basic-cloudflare/src/routes/posts.index.tsx b/examples/solid/start-basic-cloudflare/src/routes/posts.index.tsx
new file mode 100644
index 00000000000..33d0386c195
--- /dev/null
+++ b/examples/solid/start-basic-cloudflare/src/routes/posts.index.tsx
@@ -0,0 +1,9 @@
+import { createFileRoute } from '@tanstack/solid-router'
+
+export const Route = createFileRoute('/posts/')({
+ component: PostsIndexComponent,
+})
+
+function PostsIndexComponent() {
+ return Select a post.
+}
diff --git a/examples/solid/start-basic-cloudflare/src/routes/posts.tsx b/examples/solid/start-basic-cloudflare/src/routes/posts.tsx
new file mode 100644
index 00000000000..0ecf61e5b30
--- /dev/null
+++ b/examples/solid/start-basic-cloudflare/src/routes/posts.tsx
@@ -0,0 +1,38 @@
+import { Link, Outlet, createFileRoute } from '@tanstack/solid-router'
+import { fetchPosts } from '../utils/posts'
+
+export const Route = createFileRoute('/posts')({
+ loader: async () => fetchPosts(),
+ component: PostsComponent,
+})
+
+function PostsComponent() {
+ const posts = Route.useLoaderData()
+
+ return (
+
+ )
+}
diff --git a/examples/solid/start-basic-cloudflare/src/routes/posts_.$postId.deep.tsx b/examples/solid/start-basic-cloudflare/src/routes/posts_.$postId.deep.tsx
new file mode 100644
index 00000000000..7c52bc19eb9
--- /dev/null
+++ b/examples/solid/start-basic-cloudflare/src/routes/posts_.$postId.deep.tsx
@@ -0,0 +1,26 @@
+import { Link, createFileRoute } from '@tanstack/solid-router'
+import { fetchPost } from '../utils/posts'
+import { PostErrorComponent } from '~/components/PostError'
+
+export const Route = createFileRoute('/posts_/$postId/deep')({
+ loader: async ({ params: { postId } }) =>
+ fetchPost({
+ data: postId,
+ }),
+ errorComponent: PostErrorComponent,
+ component: PostDeepComponent,
+})
+
+function PostDeepComponent() {
+ const post = Route.useLoaderData()
+
+ return (
+
+
+ ← All Posts
+
+
{post().title}
+
{post().body}
+
+ )
+}
diff --git a/examples/solid/start-basic-cloudflare/src/routes/redirect.tsx b/examples/solid/start-basic-cloudflare/src/routes/redirect.tsx
new file mode 100644
index 00000000000..6c88c9ecd9b
--- /dev/null
+++ b/examples/solid/start-basic-cloudflare/src/routes/redirect.tsx
@@ -0,0 +1,9 @@
+import { createFileRoute, redirect } from '@tanstack/solid-router'
+
+export const Route = createFileRoute('/redirect')({
+ beforeLoad: () => {
+ throw redirect({
+ to: '/posts',
+ })
+ },
+})
diff --git a/examples/solid/start-basic-cloudflare/src/routes/users.$userId.tsx b/examples/solid/start-basic-cloudflare/src/routes/users.$userId.tsx
new file mode 100644
index 00000000000..ffd624dcce7
--- /dev/null
+++ b/examples/solid/start-basic-cloudflare/src/routes/users.$userId.tsx
@@ -0,0 +1,45 @@
+import { createFileRoute } from '@tanstack/solid-router'
+import { NotFound } from 'src/components/NotFound'
+import { UserErrorComponent } from 'src/components/UserError'
+import type { User } from '../utils/users'
+
+export const Route = createFileRoute('/users/$userId')({
+ loader: async ({ params: { userId } }) => {
+ try {
+ const res = await fetch('/api/users/' + userId)
+ if (!res.ok) {
+ throw new Error('Unexpected status code')
+ }
+
+ const data = await res.json()
+
+ return data as User
+ } catch {
+ throw new Error('Failed to fetch user')
+ }
+ },
+ errorComponent: UserErrorComponent,
+ component: UserComponent,
+ notFoundComponent: () => {
+ return User not found
+ },
+})
+
+function UserComponent() {
+ const user = Route.useLoaderData()
+
+ return (
+
+
{user().name}
+
{user().email}
+
+
+ )
+}
diff --git a/examples/solid/start-basic-cloudflare/src/routes/users.index.tsx b/examples/solid/start-basic-cloudflare/src/routes/users.index.tsx
new file mode 100644
index 00000000000..118daab096b
--- /dev/null
+++ b/examples/solid/start-basic-cloudflare/src/routes/users.index.tsx
@@ -0,0 +1,16 @@
+import { createFileRoute } from '@tanstack/solid-router'
+
+export const Route = createFileRoute('/users/')({
+ component: UsersIndexComponent,
+})
+
+function UsersIndexComponent() {
+ return (
+
+ )
+}
diff --git a/examples/solid/start-basic-cloudflare/src/routes/users.tsx b/examples/solid/start-basic-cloudflare/src/routes/users.tsx
new file mode 100644
index 00000000000..00e075256d0
--- /dev/null
+++ b/examples/solid/start-basic-cloudflare/src/routes/users.tsx
@@ -0,0 +1,49 @@
+import { Link, Outlet, createFileRoute } from '@tanstack/solid-router'
+import type { User } from '../utils/users'
+
+export const Route = createFileRoute('/users')({
+ loader: async () => {
+ const res = await fetch('/api/users')
+
+ if (!res.ok) {
+ throw new Error('Unexpected status code')
+ }
+
+ const data = await res.json()
+
+ return data as Array
+ },
+ component: UsersComponent,
+})
+
+function UsersComponent() {
+ const users = Route.useLoaderData()
+
+ return (
+
+
+ {[
+ ...users(),
+ { id: 'i-do-not-exist', name: 'Non-existent User', email: '' },
+ ].map((user) => {
+ return (
+ -
+
+
{user.name}
+
+
+ )
+ })}
+
+
+
+
+ )
+}
diff --git a/examples/solid/start-basic-cloudflare/src/styles/app.css b/examples/solid/start-basic-cloudflare/src/styles/app.css
new file mode 100644
index 00000000000..c53c8706654
--- /dev/null
+++ b/examples/solid/start-basic-cloudflare/src/styles/app.css
@@ -0,0 +1,22 @@
+@tailwind base;
+@tailwind components;
+@tailwind utilities;
+
+@layer base {
+ html {
+ color-scheme: light dark;
+ }
+
+ * {
+ @apply border-gray-200 dark:border-gray-800;
+ }
+
+ html,
+ body {
+ @apply text-gray-900 bg-gray-50 dark:bg-gray-950 dark:text-gray-200;
+ }
+
+ .using-mouse * {
+ outline: none !important;
+ }
+}
diff --git a/examples/solid/start-basic-cloudflare/src/utils/loggingMiddleware.tsx b/examples/solid/start-basic-cloudflare/src/utils/loggingMiddleware.tsx
new file mode 100644
index 00000000000..fae87c59659
--- /dev/null
+++ b/examples/solid/start-basic-cloudflare/src/utils/loggingMiddleware.tsx
@@ -0,0 +1,41 @@
+import { createMiddleware } from '@tanstack/solid-start'
+
+const preLogMiddleware = createMiddleware({ type: 'function' })
+ .client(async (ctx) => {
+ const clientTime = new Date()
+
+ return ctx.next({
+ context: {
+ clientTime,
+ },
+ sendContext: {
+ clientTime,
+ },
+ })
+ })
+ .server(async (ctx) => {
+ const serverTime = new Date()
+
+ return ctx.next({
+ sendContext: {
+ serverTime,
+ durationToServer:
+ serverTime.getTime() - ctx.context.clientTime.getTime(),
+ },
+ })
+ })
+
+export const logMiddleware = createMiddleware({ type: 'function' })
+ .middleware([preLogMiddleware])
+ .client(async (ctx) => {
+ const res = await ctx.next()
+
+ const now = new Date()
+ console.log('Client Req/Res:', {
+ duration: now.getTime() - res.context.clientTime.getTime(),
+ durationToServer: res.context.durationToServer,
+ durationFromServer: now.getTime() - res.context.serverTime.getTime(),
+ })
+
+ return res
+ })
diff --git a/examples/solid/start-basic-cloudflare/src/utils/posts.tsx b/examples/solid/start-basic-cloudflare/src/utils/posts.tsx
new file mode 100644
index 00000000000..609b78965e5
--- /dev/null
+++ b/examples/solid/start-basic-cloudflare/src/utils/posts.tsx
@@ -0,0 +1,40 @@
+import { notFound } from '@tanstack/solid-router'
+import { createServerFn } from '@tanstack/solid-start'
+
+export type PostType = {
+ id: number
+ title: string
+ body: string
+}
+
+export const fetchPost = createServerFn({ method: 'POST' })
+ .inputValidator((d: string) => d)
+ .handler(async ({ data }) => {
+ console.info(`Fetching post with id ${data}...`)
+ const res = await fetch(
+ `https://jsonplaceholder.typicode.com/posts/${data}`,
+ )
+ if (!res.ok) {
+ if (res.status === 404) {
+ throw notFound()
+ }
+
+ throw new Error('Failed to fetch post')
+ }
+
+ const post = await res.json()
+
+ return post as PostType
+ })
+
+export const fetchPosts = createServerFn().handler(async () => {
+ console.info('Fetching posts...')
+ const res = await fetch('https://jsonplaceholder.typicode.com/posts')
+ if (!res.ok) {
+ throw new Error('Failed to fetch posts')
+ }
+
+ const posts = await res.json()
+
+ return (posts as Array).slice(0, 10)
+})
diff --git a/examples/solid/start-basic-cloudflare/src/utils/seo.ts b/examples/solid/start-basic-cloudflare/src/utils/seo.ts
new file mode 100644
index 00000000000..d18ad84b74e
--- /dev/null
+++ b/examples/solid/start-basic-cloudflare/src/utils/seo.ts
@@ -0,0 +1,33 @@
+export const seo = ({
+ title,
+ description,
+ keywords,
+ image,
+}: {
+ title: string
+ description?: string
+ image?: string
+ keywords?: string
+}) => {
+ const tags = [
+ { title },
+ { name: 'description', content: description },
+ { name: 'keywords', content: keywords },
+ { name: 'twitter:title', content: title },
+ { name: 'twitter:description', content: description },
+ { name: 'twitter:creator', content: '@tannerlinsley' },
+ { name: 'twitter:site', content: '@tannerlinsley' },
+ { name: 'og:type', content: 'website' },
+ { name: 'og:title', content: title },
+ { name: 'og:description', content: description },
+ ...(image
+ ? [
+ { name: 'twitter:image', content: image },
+ { name: 'twitter:card', content: 'summary_large_image' },
+ { name: 'og:image', content: image },
+ ]
+ : []),
+ ]
+
+ return tags
+}
diff --git a/examples/solid/start-basic-cloudflare/src/utils/users.tsx b/examples/solid/start-basic-cloudflare/src/utils/users.tsx
new file mode 100644
index 00000000000..7ba645b3831
--- /dev/null
+++ b/examples/solid/start-basic-cloudflare/src/utils/users.tsx
@@ -0,0 +1,5 @@
+export type User = {
+ id: number
+ name: string
+ email: string
+}
diff --git a/examples/solid/start-basic-cloudflare/tailwind.config.mjs b/examples/solid/start-basic-cloudflare/tailwind.config.mjs
new file mode 100644
index 00000000000..e49f4eb776e
--- /dev/null
+++ b/examples/solid/start-basic-cloudflare/tailwind.config.mjs
@@ -0,0 +1,4 @@
+/** @type {import('tailwindcss').Config} */
+export default {
+ content: ['./src/**/*.{js,jsx,ts,tsx}'],
+}
diff --git a/examples/solid/start-basic-cloudflare/tsconfig.json b/examples/solid/start-basic-cloudflare/tsconfig.json
new file mode 100644
index 00000000000..a40235b863f
--- /dev/null
+++ b/examples/solid/start-basic-cloudflare/tsconfig.json
@@ -0,0 +1,23 @@
+{
+ "include": ["**/*.ts", "**/*.tsx"],
+ "compilerOptions": {
+ "strict": true,
+ "esModuleInterop": true,
+ "jsx": "preserve",
+ "jsxImportSource": "solid-js",
+ "module": "ESNext",
+ "moduleResolution": "Bundler",
+ "lib": ["DOM", "DOM.Iterable", "ES2022"],
+ "isolatedModules": true,
+ "resolveJsonModule": true,
+ "skipLibCheck": true,
+ "target": "ES2022",
+ "allowJs": true,
+ "forceConsistentCasingInFileNames": true,
+ "baseUrl": ".",
+ "paths": {
+ "~/*": ["./src/*"]
+ },
+ "noEmit": true
+ }
+}
diff --git a/examples/solid/start-basic-cloudflare/vite.config.ts b/examples/solid/start-basic-cloudflare/vite.config.ts
new file mode 100644
index 00000000000..b7459c3511c
--- /dev/null
+++ b/examples/solid/start-basic-cloudflare/vite.config.ts
@@ -0,0 +1,34 @@
+import { defineConfig } from 'vite'
+import tsConfigPaths from 'vite-tsconfig-paths'
+import { cloudflare } from '@cloudflare/vite-plugin'
+import { tanstackStart } from '@tanstack/solid-start/plugin/vite'
+import viteSolid from 'vite-plugin-solid'
+import type { Plugin } from 'vite'
+
+// Plugin to clear resolve.external for Cloudflare compatibility
+function clearSsrExternal(): Plugin {
+ return {
+ name: 'clear-ssr-external',
+ enforce: 'pre',
+ configResolved(config) {
+ // Clear external packages from SSR environment for Cloudflare compatibility
+ const ssrEnv = config.environments.ssr
+ ssrEnv.resolve.external = []
+ },
+ }
+}
+
+export default defineConfig({
+ server: {
+ port: 3000,
+ },
+ plugins: [
+ tsConfigPaths({
+ projects: ['./tsconfig.json'],
+ }),
+ clearSsrExternal(),
+ cloudflare({ viteEnvironment: { name: 'ssr' } }),
+ tanstackStart(),
+ viteSolid({ ssr: true }),
+ ],
+})
diff --git a/examples/solid/start-basic-cloudflare/worker-configuration.d.ts b/examples/solid/start-basic-cloudflare/worker-configuration.d.ts
new file mode 100644
index 00000000000..f4826f698ab
--- /dev/null
+++ b/examples/solid/start-basic-cloudflare/worker-configuration.d.ts
@@ -0,0 +1,8372 @@
+/* eslint-disable */
+// Generated by Wrangler by running `wrangler types` (hash: b11df627d8b3c51b1bf3230a546b0f20)
+// Runtime types generated with workerd@1.20250924.0 2025-09-24 nodejs_compat
+declare namespace Cloudflare {
+ interface Env {
+ MY_VAR: "Hello from Cloudflare";
+ }
+}
+interface Env extends Cloudflare.Env {}
+type StringifyValues> = {
+ [Binding in keyof EnvType]: EnvType[Binding] extends string ? EnvType[Binding] : string;
+};
+declare namespace NodeJS {
+ interface ProcessEnv extends StringifyValues> {}
+}
+
+// Begin runtime types
+/*! *****************************************************************************
+Copyright (c) Cloudflare. All rights reserved.
+Copyright (c) Microsoft Corporation. All rights reserved.
+
+Licensed under the Apache License, Version 2.0 (the "License"); you may not use
+this file except in compliance with the License. You may obtain a copy of the
+License at http://www.apache.org/licenses/LICENSE-2.0
+THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
+WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
+MERCHANTABLITY OR NON-INFRINGEMENT.
+See the Apache Version 2.0 License for specific language governing permissions
+and limitations under the License.
+***************************************************************************** */
+/* eslint-disable */
+// noinspection JSUnusedGlobalSymbols
+declare var onmessage: never;
+/**
+ * An abnormal event (called an exception) which occurs as a result of calling a method or accessing a property of a web API.
+ *
+ * [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMException)
+ */
+declare class DOMException extends Error {
+ constructor(message?: string, name?: string);
+ /* [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMException/message) */
+ readonly message: string;
+ /* [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMException/name) */
+ readonly name: string;
+ /**
+ * @deprecated
+ *
+ * [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMException/code)
+ */
+ readonly code: number;
+ static readonly INDEX_SIZE_ERR: number;
+ static readonly DOMSTRING_SIZE_ERR: number;
+ static readonly HIERARCHY_REQUEST_ERR: number;
+ static readonly WRONG_DOCUMENT_ERR: number;
+ static readonly INVALID_CHARACTER_ERR: number;
+ static readonly NO_DATA_ALLOWED_ERR: number;
+ static readonly NO_MODIFICATION_ALLOWED_ERR: number;
+ static readonly NOT_FOUND_ERR: number;
+ static readonly NOT_SUPPORTED_ERR: number;
+ static readonly INUSE_ATTRIBUTE_ERR: number;
+ static readonly INVALID_STATE_ERR: number;
+ static readonly SYNTAX_ERR: number;
+ static readonly INVALID_MODIFICATION_ERR: number;
+ static readonly NAMESPACE_ERR: number;
+ static readonly INVALID_ACCESS_ERR: number;
+ static readonly VALIDATION_ERR: number;
+ static readonly TYPE_MISMATCH_ERR: number;
+ static readonly SECURITY_ERR: number;
+ static readonly NETWORK_ERR: number;
+ static readonly ABORT_ERR: number;
+ static readonly URL_MISMATCH_ERR: number;
+ static readonly QUOTA_EXCEEDED_ERR: number;
+ static readonly TIMEOUT_ERR: number;
+ static readonly INVALID_NODE_TYPE_ERR: number;
+ static readonly DATA_CLONE_ERR: number;
+ get stack(): any;
+ set stack(value: any);
+}
+type WorkerGlobalScopeEventMap = {
+ fetch: FetchEvent;
+ scheduled: ScheduledEvent;
+ queue: QueueEvent;
+ unhandledrejection: PromiseRejectionEvent;
+ rejectionhandled: PromiseRejectionEvent;
+};
+declare abstract class WorkerGlobalScope extends EventTarget {
+ EventTarget: typeof EventTarget;
+}
+/* [MDN Reference](https://developer.mozilla.org/docs/Web/API/console) */
+interface Console {
+ "assert"(condition?: boolean, ...data: any[]): void;
+ /* [MDN Reference](https://developer.mozilla.org/docs/Web/API/console/clear_static) */
+ clear(): void;
+ /* [MDN Reference](https://developer.mozilla.org/docs/Web/API/console/count_static) */
+ count(label?: string): void;
+ /* [MDN Reference](https://developer.mozilla.org/docs/Web/API/console/countReset_static) */
+ countReset(label?: string): void;
+ /* [MDN Reference](https://developer.mozilla.org/docs/Web/API/console/debug_static) */
+ debug(...data: any[]): void;
+ /* [MDN Reference](https://developer.mozilla.org/docs/Web/API/console/dir_static) */
+ dir(item?: any, options?: any): void;
+ /* [MDN Reference](https://developer.mozilla.org/docs/Web/API/console/dirxml_static) */
+ dirxml(...data: any[]): void;
+ /* [MDN Reference](https://developer.mozilla.org/docs/Web/API/console/error_static) */
+ error(...data: any[]): void;
+ /* [MDN Reference](https://developer.mozilla.org/docs/Web/API/console/group_static) */
+ group(...data: any[]): void;
+ /* [MDN Reference](https://developer.mozilla.org/docs/Web/API/console/groupCollapsed_static) */
+ groupCollapsed(...data: any[]): void;
+ /* [MDN Reference](https://developer.mozilla.org/docs/Web/API/console/groupEnd_static) */
+ groupEnd(): void;
+ /* [MDN Reference](https://developer.mozilla.org/docs/Web/API/console/info_static) */
+ info(...data: any[]): void;
+ /* [MDN Reference](https://developer.mozilla.org/docs/Web/API/console/log_static) */
+ log(...data: any[]): void;
+ /* [MDN Reference](https://developer.mozilla.org/docs/Web/API/console/table_static) */
+ table(tabularData?: any, properties?: string[]): void;
+ /* [MDN Reference](https://developer.mozilla.org/docs/Web/API/console/time_static) */
+ time(label?: string): void;
+ /* [MDN Reference](https://developer.mozilla.org/docs/Web/API/console/timeEnd_static) */
+ timeEnd(label?: string): void;
+ /* [MDN Reference](https://developer.mozilla.org/docs/Web/API/console/timeLog_static) */
+ timeLog(label?: string, ...data: any[]): void;
+ timeStamp(label?: string): void;
+ /* [MDN Reference](https://developer.mozilla.org/docs/Web/API/console/trace_static) */
+ trace(...data: any[]): void;
+ /* [MDN Reference](https://developer.mozilla.org/docs/Web/API/console/warn_static) */
+ warn(...data: any[]): void;
+}
+declare const console: Console;
+type BufferSource = ArrayBufferView | ArrayBuffer;
+type TypedArray = Int8Array | Uint8Array | Uint8ClampedArray | Int16Array | Uint16Array | Int32Array | Uint32Array | Float32Array | Float64Array | BigInt64Array | BigUint64Array;
+declare namespace WebAssembly {
+ class CompileError extends Error {
+ constructor(message?: string);
+ }
+ class RuntimeError extends Error {
+ constructor(message?: string);
+ }
+ type ValueType = "anyfunc" | "externref" | "f32" | "f64" | "i32" | "i64" | "v128";
+ interface GlobalDescriptor {
+ value: ValueType;
+ mutable?: boolean;
+ }
+ class Global {
+ constructor(descriptor: GlobalDescriptor, value?: any);
+ value: any;
+ valueOf(): any;
+ }
+ type ImportValue = ExportValue | number;
+ type ModuleImports = Record;
+ type Imports = Record;
+ type ExportValue = Function | Global | Memory | Table;
+ type Exports = Record;
+ class Instance {
+ constructor(module: Module, imports?: Imports);
+ readonly exports: Exports;
+ }
+ interface MemoryDescriptor {
+ initial: number;
+ maximum?: number;
+ shared?: boolean;
+ }
+ class Memory {
+ constructor(descriptor: MemoryDescriptor);
+ readonly buffer: ArrayBuffer;
+ grow(delta: number): number;
+ }
+ type ImportExportKind = "function" | "global" | "memory" | "table";
+ interface ModuleExportDescriptor {
+ kind: ImportExportKind;
+ name: string;
+ }
+ interface ModuleImportDescriptor {
+ kind: ImportExportKind;
+ module: string;
+ name: string;
+ }
+ abstract class Module {
+ static customSections(module: Module, sectionName: string): ArrayBuffer[];
+ static exports(module: Module): ModuleExportDescriptor[];
+ static imports(module: Module): ModuleImportDescriptor[];
+ }
+ type TableKind = "anyfunc" | "externref";
+ interface TableDescriptor {
+ element: TableKind;
+ initial: number;
+ maximum?: number;
+ }
+ class Table {
+ constructor(descriptor: TableDescriptor, value?: any);
+ readonly length: number;
+ get(index: number): any;
+ grow(delta: number, value?: any): number;
+ set(index: number, value?: any): void;
+ }
+ function instantiate(module: Module, imports?: Imports): Promise;
+ function validate(bytes: BufferSource): boolean;
+}
+/**
+ * This ServiceWorker API interface represents the global execution context of a service worker.
+ * Available only in secure contexts.
+ *
+ * [MDN Reference](https://developer.mozilla.org/docs/Web/API/ServiceWorkerGlobalScope)
+ */
+interface ServiceWorkerGlobalScope extends WorkerGlobalScope {
+ DOMException: typeof DOMException;
+ WorkerGlobalScope: typeof WorkerGlobalScope;
+ btoa(data: string): string;
+ atob(data: string): string;
+ setTimeout(callback: (...args: any[]) => void, msDelay?: number): number;
+ setTimeout(callback: (...args: Args) => void, msDelay?: number, ...args: Args): number;
+ clearTimeout(timeoutId: number | null): void;
+ setInterval(callback: (...args: any[]) => void, msDelay?: number): number;
+ setInterval(callback: (...args: Args) => void, msDelay?: number, ...args: Args): number;
+ clearInterval(timeoutId: number | null): void;
+ queueMicrotask(task: Function): void;
+ structuredClone(value: T, options?: StructuredSerializeOptions): T;
+ reportError(error: any): void;
+ fetch(input: RequestInfo | URL, init?: RequestInit): Promise;
+ self: ServiceWorkerGlobalScope;
+ crypto: Crypto;
+ caches: CacheStorage;
+ scheduler: Scheduler;
+ performance: Performance;
+ Cloudflare: Cloudflare;
+ readonly origin: string;
+ Event: typeof Event;
+ ExtendableEvent: typeof ExtendableEvent;
+ CustomEvent: typeof CustomEvent;
+ PromiseRejectionEvent: typeof PromiseRejectionEvent;
+ FetchEvent: typeof FetchEvent;
+ TailEvent: typeof TailEvent;
+ TraceEvent: typeof TailEvent;
+ ScheduledEvent: typeof ScheduledEvent;
+ MessageEvent: typeof MessageEvent;
+ CloseEvent: typeof CloseEvent;
+ ReadableStreamDefaultReader: typeof ReadableStreamDefaultReader;
+ ReadableStreamBYOBReader: typeof ReadableStreamBYOBReader;
+ ReadableStream: typeof ReadableStream;
+ WritableStream: typeof WritableStream;
+ WritableStreamDefaultWriter: typeof WritableStreamDefaultWriter;
+ TransformStream: typeof TransformStream;
+ ByteLengthQueuingStrategy: typeof ByteLengthQueuingStrategy;
+ CountQueuingStrategy: typeof CountQueuingStrategy;
+ ErrorEvent: typeof ErrorEvent;
+ MessageChannel: typeof MessageChannel;
+ MessagePort: typeof MessagePort;
+ EventSource: typeof EventSource;
+ ReadableStreamBYOBRequest: typeof ReadableStreamBYOBRequest;
+ ReadableStreamDefaultController: typeof ReadableStreamDefaultController;
+ ReadableByteStreamController: typeof ReadableByteStreamController;
+ WritableStreamDefaultController: typeof WritableStreamDefaultController;
+ TransformStreamDefaultController: typeof TransformStreamDefaultController;
+ CompressionStream: typeof CompressionStream;
+ DecompressionStream: typeof DecompressionStream;
+ TextEncoderStream: typeof TextEncoderStream;
+ TextDecoderStream: typeof TextDecoderStream;
+ Headers: typeof Headers;
+ Body: typeof Body;
+ Request: typeof Request;
+ Response: typeof Response;
+ WebSocket: typeof WebSocket;
+ WebSocketPair: typeof WebSocketPair;
+ WebSocketRequestResponsePair: typeof WebSocketRequestResponsePair;
+ AbortController: typeof AbortController;
+ AbortSignal: typeof AbortSignal;
+ TextDecoder: typeof TextDecoder;
+ TextEncoder: typeof TextEncoder;
+ navigator: Navigator;
+ Navigator: typeof Navigator;
+ URL: typeof URL;
+ URLSearchParams: typeof URLSearchParams;
+ URLPattern: typeof URLPattern;
+ Blob: typeof Blob;
+ File: typeof File;
+ FormData: typeof FormData;
+ Crypto: typeof Crypto;
+ SubtleCrypto: typeof SubtleCrypto;
+ CryptoKey: typeof CryptoKey;
+ CacheStorage: typeof CacheStorage;
+ Cache: typeof Cache;
+ FixedLengthStream: typeof FixedLengthStream;
+ IdentityTransformStream: typeof IdentityTransformStream;
+ HTMLRewriter: typeof HTMLRewriter;
+}
+declare function addEventListener(type: Type, handler: EventListenerOrEventListenerObject, options?: EventTargetAddEventListenerOptions | boolean): void;
+declare function removeEventListener(type: Type, handler: EventListenerOrEventListenerObject, options?: EventTargetEventListenerOptions | boolean): void;
+/**
+ * Dispatches a synthetic event event to target and returns true if either event's cancelable attribute value is false or its preventDefault() method was not invoked, and false otherwise.
+ *
+ * [MDN Reference](https://developer.mozilla.org/docs/Web/API/EventTarget/dispatchEvent)
+ */
+declare function dispatchEvent(event: WorkerGlobalScopeEventMap[keyof WorkerGlobalScopeEventMap]): boolean;
+/* [MDN Reference](https://developer.mozilla.org/docs/Web/API/Window/btoa) */
+declare function btoa(data: string): string;
+/* [MDN Reference](https://developer.mozilla.org/docs/Web/API/Window/atob) */
+declare function atob(data: string): string;
+/* [MDN Reference](https://developer.mozilla.org/docs/Web/API/Window/setTimeout) */
+declare function setTimeout(callback: (...args: any[]) => void, msDelay?: number): number;
+/* [MDN Reference](https://developer.mozilla.org/docs/Web/API/Window/setTimeout) */
+declare function setTimeout(callback: (...args: Args) => void, msDelay?: number, ...args: Args): number;
+/* [MDN Reference](https://developer.mozilla.org/docs/Web/API/Window/clearTimeout) */
+declare function clearTimeout(timeoutId: number | null): void;
+/* [MDN Reference](https://developer.mozilla.org/docs/Web/API/Window/setInterval) */
+declare function setInterval(callback: (...args: any[]) => void, msDelay?: number): number;
+/* [MDN Reference](https://developer.mozilla.org/docs/Web/API/Window/setInterval) */
+declare function setInterval(callback: (...args: Args) => void, msDelay?: number, ...args: Args): number;
+/* [MDN Reference](https://developer.mozilla.org/docs/Web/API/Window/clearInterval) */
+declare function clearInterval(timeoutId: number | null): void;
+/* [MDN Reference](https://developer.mozilla.org/docs/Web/API/Window/queueMicrotask) */
+declare function queueMicrotask(task: Function): void;
+/* [MDN Reference](https://developer.mozilla.org/docs/Web/API/Window/structuredClone) */
+declare function structuredClone(value: T, options?: StructuredSerializeOptions): T;
+/* [MDN Reference](https://developer.mozilla.org/docs/Web/API/Window/reportError) */
+declare function reportError(error: any): void;
+/* [MDN Reference](https://developer.mozilla.org/docs/Web/API/Window/fetch) */
+declare function fetch(input: RequestInfo | URL, init?: RequestInit): Promise;
+declare const self: ServiceWorkerGlobalScope;
+/**
+* The Web Crypto API provides a set of low-level functions for common cryptographic tasks.
+* The Workers runtime implements the full surface of this API, but with some differences in
+* the [supported algorithms](https://developers.cloudflare.com/workers/runtime-apis/web-crypto/#supported-algorithms)
+* compared to those implemented in most browsers.
+*
+* [Cloudflare Docs Reference](https://developers.cloudflare.com/workers/runtime-apis/web-crypto/)
+*/
+declare const crypto: Crypto;
+/**
+* The Cache API allows fine grained control of reading and writing from the Cloudflare global network cache.
+*
+* [Cloudflare Docs Reference](https://developers.cloudflare.com/workers/runtime-apis/cache/)
+*/
+declare const caches: CacheStorage;
+declare const scheduler: Scheduler;
+/**
+* The Workers runtime supports a subset of the Performance API, used to measure timing and performance,
+* as well as timing of subrequests and other operations.
+*
+* [Cloudflare Docs Reference](https://developers.cloudflare.com/workers/runtime-apis/performance/)
+*/
+declare const performance: Performance;
+declare const Cloudflare: Cloudflare;
+declare const origin: string;
+declare const navigator: Navigator;
+interface TestController {
+}
+interface ExecutionContext {
+ waitUntil(promise: Promise): void;
+ passThroughOnException(): void;
+ readonly props: Props;
+}
+type ExportedHandlerFetchHandler = (request: Request>, env: Env, ctx: ExecutionContext) => Response | Promise;
+type ExportedHandlerTailHandler = (events: TraceItem[], env: Env, ctx: ExecutionContext) => void | Promise;
+type ExportedHandlerTraceHandler = (traces: TraceItem[], env: Env, ctx: ExecutionContext) => void | Promise;
+type ExportedHandlerTailStreamHandler = (event: TailStream.TailEvent, env: Env, ctx: ExecutionContext) => TailStream.TailEventHandlerType | Promise;
+type ExportedHandlerScheduledHandler = (controller: ScheduledController, env: Env, ctx: ExecutionContext) => void | Promise;
+type ExportedHandlerQueueHandler = (batch: MessageBatch, env: Env, ctx: ExecutionContext) => void | Promise;
+type ExportedHandlerTestHandler = (controller: TestController, env: Env, ctx: ExecutionContext) => void | Promise;
+interface ExportedHandler {
+ fetch?: ExportedHandlerFetchHandler;
+ tail?: ExportedHandlerTailHandler;
+ trace?: ExportedHandlerTraceHandler;
+ tailStream?: ExportedHandlerTailStreamHandler;
+ scheduled?: ExportedHandlerScheduledHandler;
+ test?: ExportedHandlerTestHandler;
+ email?: EmailExportedHandler;
+ queue?: ExportedHandlerQueueHandler;
+}
+interface StructuredSerializeOptions {
+ transfer?: any[];
+}
+/* [MDN Reference](https://developer.mozilla.org/docs/Web/API/PromiseRejectionEvent) */
+declare abstract class PromiseRejectionEvent extends Event {
+ /* [MDN Reference](https://developer.mozilla.org/docs/Web/API/PromiseRejectionEvent/promise) */
+ readonly promise: Promise;
+ /* [MDN Reference](https://developer.mozilla.org/docs/Web/API/PromiseRejectionEvent/reason) */
+ readonly reason: any;
+}
+declare abstract class Navigator {
+ sendBeacon(url: string, body?: (ReadableStream | string | (ArrayBuffer | ArrayBufferView) | Blob | FormData | URLSearchParams | URLSearchParams)): boolean;
+ readonly userAgent: string;
+ readonly hardwareConcurrency: number;
+ readonly language: string;
+ readonly languages: string[];
+}
+interface AlarmInvocationInfo {
+ readonly isRetry: boolean;
+ readonly retryCount: number;
+}
+interface Cloudflare {
+ readonly compatibilityFlags: Record;
+}
+interface DurableObject {
+ fetch(request: Request): Response | Promise;
+ alarm?(alarmInfo?: AlarmInvocationInfo): void | Promise;
+ webSocketMessage?(ws: WebSocket, message: string | ArrayBuffer): void | Promise;
+ webSocketClose?(ws: WebSocket, code: number, reason: string, wasClean: boolean): void | Promise;
+ webSocketError?(ws: WebSocket, error: unknown): void | Promise;
+}
+type DurableObjectStub = Fetcher & {
+ readonly id: DurableObjectId;
+ readonly name?: string;
+};
+interface DurableObjectId {
+ toString(): string;
+ equals(other: DurableObjectId): boolean;
+ readonly name?: string;
+}
+declare abstract class DurableObjectNamespace {
+ newUniqueId(options?: DurableObjectNamespaceNewUniqueIdOptions): DurableObjectId;
+ idFromName(name: string): DurableObjectId;
+ idFromString(id: string): DurableObjectId;
+ get(id: DurableObjectId, options?: DurableObjectNamespaceGetDurableObjectOptions): DurableObjectStub;
+ getByName(name: string, options?: DurableObjectNamespaceGetDurableObjectOptions): DurableObjectStub;
+ jurisdiction(jurisdiction: DurableObjectJurisdiction): DurableObjectNamespace;
+}
+type DurableObjectJurisdiction = "eu" | "fedramp" | "fedramp-high";
+interface DurableObjectNamespaceNewUniqueIdOptions {
+ jurisdiction?: DurableObjectJurisdiction;
+}
+type DurableObjectLocationHint = "wnam" | "enam" | "sam" | "weur" | "eeur" | "apac" | "oc" | "afr" | "me";
+interface DurableObjectNamespaceGetDurableObjectOptions {
+ locationHint?: DurableObjectLocationHint;
+}
+interface DurableObjectClass<_T extends Rpc.DurableObjectBranded | undefined = undefined> {
+}
+interface DurableObjectState {
+ waitUntil(promise: Promise): void;
+ readonly props: Props;
+ readonly id: DurableObjectId;
+ readonly storage: DurableObjectStorage;
+ container?: Container;
+ blockConcurrencyWhile(callback: () => Promise): Promise;
+ acceptWebSocket(ws: WebSocket, tags?: string[]): void;
+ getWebSockets(tag?: string): WebSocket[];
+ setWebSocketAutoResponse(maybeReqResp?: WebSocketRequestResponsePair): void;
+ getWebSocketAutoResponse(): WebSocketRequestResponsePair | null;
+ getWebSocketAutoResponseTimestamp(ws: WebSocket): Date | null;
+ setHibernatableWebSocketEventTimeout(timeoutMs?: number): void;
+ getHibernatableWebSocketEventTimeout(): number | null;
+ getTags(ws: WebSocket): string[];
+ abort(reason?: string): void;
+}
+interface DurableObjectTransaction {
+ get(key: string, options?: DurableObjectGetOptions): Promise;
+ get(keys: string[], options?: DurableObjectGetOptions): Promise