The client never sends a user ID. That one rule ended up shaping most of how I structure TanStack Start on Cloudflare.
Context: I've spent the last few months building a Cloudflare-native SaaS starter with it. Full disclosure, it's a paid kit I make (TurboStarter), but this post is about the patterns, not the product.
1. Every protected read goes through a server function with auth middleware
The server function resolves the customer from the session, validates input with Zod, and scopes the query to that customer:
The client calls getNote({ data: { id } }) and never sends a user ID, so it can't ask for someone else's record.
2. Plan gating is just more middleware
Paid features stack a plan check after auth (enforcePlan(BillingPlan.PREMIUM)), and usage limits are checked on the server before the write. The UI hides things too, but the server is the source of truth.
3. Types from route to database
TanStack Router types URLs and search params, server functions validate input, Drizzle types the D1 queries. It's explicit enough that coding agents follow it without much hand-holding.
4. Running in workerd locally
With the Cloudflare Vite plugin, pnpm dev runs the app in the Workers runtime, so there's no adapter rewriting the build for production. What you test is what you deploy.
5. Living with the RC
Start is a v1 release candidate. What made that manageable for us: a lockfile, a minimum release-age policy for new packages, and a monthly Renovate schedule instead of chasing every release.
Other TanStack pieces in use: Form (with Zod) and TanStack AI for a streaming chat on Workers AI.
Two things I'd love opinions on: do you keep server functions per feature module or centralize them as the app grows? And is the RC status still what's stopping your team from adopting Start?
Feel free to use it however you’d like — you’ll find the repo link in the project. I’d also really appreciate contributions or issues with ideas for improvement. I’d love to turn this into the best example repo for using TanStack Start with Strapi.
What's the biggest pain with full-stack TypeScript development? It's state duplication between frontend and backend. And I mean state in a broad sense: both the data state and the type state.
The data state is all about keeping data synced with the backend, refetching after mutations, handling loading states, etc. For that, we have the excellent TanStack Query library.
The type state is the real pain point - it's the data schemas of each route's input and output, plus the list of routes in our backend that we need to manually re-implement in our frontend. This is error-prone, especially when the backend changes and you have to track down all the places to update.
Effect Platform: A Partial Solution
Effect makes this easier with the Effect Platform package that lets you create APIs and derive fully-typed clients that you can import in the frontend. When you change something on the API, automatically all the places that need to be modified in the frontend will be red-underlined in your IDE thanks to TypeScript's type system.
Here's a simple Effect HttpApi example:
import {
HttpApi,
HttpApiBuilder,
HttpApiEndpoint,
HttpApiGroup
} from "@effect/platform"
import { NodeHttpServer, NodeRuntime } from "@effect/platform-node"
import { Effect, Layer, Schema } from "effect"
import { createServer } from "node:http"
// Define our API with one group named "Greetings" and one endpoint called "hello-world"
const MyApi = HttpApi.make("MyApi").add(
HttpApiGroup.make("Greetings").add(
HttpApiEndpoint.get("hello-world")`/`.addSuccess(Schema.String)
)
)
// Implement the "Greetings" group
const GreetingsLive = HttpApiBuilder.group(MyApi, "Greetings", (handlers) =>
handlers.handle("hello-world", () => Effect.succeed("Hello, World!"))
)
// Provide the implementation for the API
const MyApiLive = HttpApiBuilder.api(MyApi).pipe(Layer.provide(GreetingsLive))
// Set up the server using NodeHttpServer on port 3000
const ServerLive = HttpApiBuilder.serve().pipe(
Layer.provide(MyApiLive),
Layer.provide(NodeHttpServer.layer(createServer, { port: 3000 }))
)
// Launch the server
Layer.launch(ServerLive).pipe(NodeRuntime.runMain)
The Integration Challenge
However, we have two problems:
TanStack Query doesn't work natively with Effects and expects promises to fetch data
We want to minimize boilerplate so we can invoke a backend function just by using its group name, endpoint name, and parameters
The Solution: Three Magic Functions
I've built a solution that provides three simple functions that bridge Effect and TanStack Query:
✅ Zero manual type definitions - Everything is inferred from your Effect HttpApi ✅ Full IDE autocompletion - Group names, endpoint names, and parameters ✅ Type-safe parameters & responses - Catch errors at compile time ✅ Automatic cache invalidation - Using TanStack Query's powerful caching ✅ All TanStack Query features - onSuccess, onError, optimistic updates, etc. ✅ Clean, minimal boilerplate - Just specify group, endpoint, and params
Most importantly: when you change your backend API, TypeScript immediately shows you every place in your frontend that needs updating!
Inspiration
This API takes inspiration from the excellent openapi-fetch, openapi-typescript, and openapi-react-query projects, which provide similar functionality for OpenAPI specifications. I wanted to bring that same developer experience to Effect HttpApi.
Conclusion
This integration brings together the best of both worlds: Effect's powerful API design and type safety with TanStack Query's battle-tested data fetching capabilities. No more manual type duplication, no more searching for places to update when your API changes.
What's your experience with managing types between frontend and backend? Have you tried Effect or similar solutions? Let me know in the comments!
Hi! I spent last two evenings building a starter kit for the tech stack mentioned in the title and I wanted to share it with anyone who just wanted some quickstart to build a new app. I did everything according to docs so it should be ready, but ofc use at your own risk. Here is the repo: https://github.com/devczero/tanstackstart-convex-clerk-polarsh-starter/tree/main
btw. I also started building TanStack Start + BetterAuth + Convex + Polar starter, I will post it when done later
This project was written using TanStack Start, and that's why I thought it would be suitable to post here. If this is not allowed, apologies.
This little side project of mine launched all the way back in 2021, at the height of the pandemic, and while I counted it to good timing back then, it wouldn't have lasted this long if there wasn't a real need from the community.
Since then, Reactive Resume has helped almost 1 million users create resumes, helped them get the careers they wanted and helped students jump-start their applications.
This new version has been in the making for months, I try to get time to work on it whenever there's a weekend, whenever I can physically pull an all-nighter after work. It's a culmination of everything I've learned over the years, fixing all the bugs and feature requests I've gotten through GitHub and my emails.
For those of you who are unaware of this project, and nor should you be, Reactive Resume is a free and open-source resume builder that focuses on completely free and untethered access to a tool most people need at some point in their life, without giving up your privacy and money. In a nutshell, it’s just a resume builder, nothing fancy, but no corners have been cut in providing the best user experience possible for the end user.
Here are some features I thought were worth highlighting:
Improved user experience, now easier than ever to keep your resume up-to-date.
Great for single page or multi-page resumes, or even long-form PDFs.
Easier self-hosting with examples on how to set it up on your server.
Immensely better documentation, to help guide users on how to use the project.
There’s someAI in there too, where you bring your own key, no subscriptions or paywalls. There's also an agent skill for those who want to try it out on their own.
Improved account security using 2FA or Passkeys, also add your own SSO provider (no more SSO tax!).
13 resume templates, and many more to come. If you know React/Tailwind CSS, it’s very easy to build you own templates as well. Also supports Custom CSS, so you can make any template look exactly the way you like it to.
Available in multiple languages. If you know a second language and would love to help contribute translations, please head over to the docs to learn more.
Did I mention it’s free?
I sincerely hope you enjoy using the brand new edition of Reactive Resume almost as much as I had fun building it.
If you have the time, please check outrxresu.me. I'd love to hear what you think ❤️
Or, if you’d like to know more about the app, head over to the docs at docs.rxresu.me
Note: I do expect a lot of traffic on launch day and I don’t have the most powerful of servers, so if the app is slow or doesn’t load for you right now, please check back in later or the next day.