A Vite plugin to make Cloudflare Bindings work locally when using TanStack Start.
npm i -D vite-plugin-tss-cloudflare-proxy
yarn add -D vite-plugin-tss-cloudflare-proxy
pnpm add -D vite-plugin-tss-cloudflare-proxy
bun add -D vite-plugin-tss-cloudflare-proxy
Or, using JSR:
npx jsr add @ponjimon/vite-plugin-tss-cloudflare-proxy
yarn dlx jsr add @ponjimon/vite-plugin-tss-cloudflare-proxy
pnpm dlx jsr add @ponjimon/vite-plugin-tss-cloudflare-proxy
bunx jsr add @ponjimon/vite-plugin-tss-cloudflare-proxy
import cloudflareDevProxyVitePlugin from '@ponjimon/vite-plugin-tss-cloudflare-proxy'
import { defineConfig } from '@tanstack/start/config'
export default defineConfig({
vite: {
plugins: () => [
cloudflareDevProxyVitePlugin(),
],
},
})
Next, create a env.d.ts
file in app/env.d.ts
with the following content:
/// <reference types="@cloudflare/workers-types" />
import type { H3EventContext } from 'vinxi/http'
import type { PlatformProxy } from 'wrangler'
interface EnvVars {
// Add your bindings here
// KV: KVNamespace
}
declare global {
interface Env extends EnvVars {}
}
declare module 'vinxi/http' {
interface H3EventContext {
cf: CfProperties
cloudflare: Omit<PlatformProxy<Env>, 'dispose'>
}
}
declare global {
interface Request {
context: H3EventContext
}
}
Next, you will have to update the API entry handler (app/api.ts
):
--- app/api.ts
+++ app/api.ts
@@ -1,3 +1,11 @@
-import { createStartAPIHandler, defaultAPIFileRouteHandler } from '@tanstack/start/api'
+import { defaultAPIFileRouteHandler } from '@tanstack/start/api'
+import { eventHandler, toWebRequest } from 'vinxi/http'
-export default createStartAPIHandler(defaultAPIFileRouteHandler)
+const apiHandler = eventHandler(async (event) => {
+ const request = toWebRequest(event)
+ request.context = event.context
+ const res = await defaultAPIFileRouteHandler({ request })
+ return res
+})
+
+export default apiHandler
Now you will have access to the Cloudflare bindings locally but also on the edge, for example:
import { createAPIFileRoute } from '@tanstack/start/api'
export const Route = createAPIFileRoute('/api/completion')({
GET: async ({ request }) => {
const res = await request.context.cloudflare.env.AI.run('@cf/meta/llama-3.1-8b-instruct', {
messages: [{ role: 'user', content: 'Hello, World!' }],
})
if ('response' in res) {
return new Response(res.response)
}
return new Response('No response')
},
})
Important
This plugin is still experimental and may not work for all use cases.
It is specifically tailored to work with the @tanstack/start
framework.
Currently, it will only work with API Routes. Server Functions are not supported yet.
The base for this plugin was taken from Remix
And a special thanks to opennextjs-cloudflare for overcoming this issue.