TanStack Start Integration
Full-featured LocaleLens integration with TanStack Start
This demo shows a production-style, end-to-end integration with TanStack Start, including SSR, authentication, protected routes, and server-side translation loading. It demonstrates how LocaleLens works in a real-world full-stack React application.
This repository is not a starter template — it's a reference implementation showing how LocaleLens fits into a full production-style app.
Recommended starting point for advanced integrations
Who this is for
- •Building an SSR app with TanStack Start
- •Handling auth and protected routes
- •Wanting server-side i18n without client-side plumbing
What this demo covers
- •SSR with server-side loaders
- •Authentication with protected routes
- •API keys kept server-side via server functions
- •Cookie-based locale persistence
- •Accept-Language header detection
- •Multiple locales (EN, DE, ES) with runtime switching
Looking for something simpler?
- Next.js demo — minimal pattern, no UI focus
- React demo — barebones proxy example
TanStack Start's server functions create a clear boundary between server and client code. This is perfect for LocaleLens because:
- •API keys stay on the server — The LocaleLens API key never reaches the browser
- •SSR translations — Pages render with translations already loaded (no flash of untranslated content)
- •No client-side i18n plumbing — Translations are resolved before rendering
- •Caching potential — Server-side fetches can be cached at the edge
The demo uses a clear server/client split:
┌─────────────────────────────────────────────────────────────┐
│ SERVER │
├─────────────────────────────────────────────────────────────┤
│ detectLocale() → Read cookie / Accept-Language │
│ getTranslations() → Fetch from LocaleLens API (with key) │
│ loadTranslations() → Combined helper for route loaders │
│ requireAuth() → Check auth before rendering │
└─────────────────────────────────────────────────────────────┘
│
▼ Loader data (locale + translations)
┌─────────────────────────────────────────────────────────────┐
│ CLIENT │
├─────────────────────────────────────────────────────────────┤
│ I18nProvider → Receives translations from loader │
│ useTranslation() → Access t() function │
│ setLocale() → Triggers router invalidation │
└─────────────────────────────────────────────────────────────┘Key insight: The client never fetches translations directly — only resolved strings are passed from server loaders.
Copy this pattern: The detectLocale → loadTranslations → root loader flow can be lifted directly into your own TanStack Start app.
1. Clone and install
git clone https://github.com/localelens/localelens-demo-tanstack-start
cd localelens-demo-tanstack-start
pnpm install2. Configure environment
cp .env.example .envAdd your LocaleLens credentials:
LOCALELENS_PROJECT_ID=your_project_id
LOCALELENS_API_KEY=your_api_key3. Run the demo
pnpm devYou'll get a public landing page, locale switcher, and a protected dashboard with server-rendered translations.
Server Functions
src/lib/localelens.ts contains server-only functions:
// Detect locale from cookie or Accept-Language header
export async function detectLocale(): Promise<Locale> {
const cookieStore = await getWebRequest()
// ... cookie parsing and Accept-Language detection
}
// Fetch translations (server-side only, API key safe)
export async function getTranslations(locale: Locale) {
const response = await fetch(
`${API_URL}/projects/${PROJECT_ID}/translations/${locale}`,
{ headers: { Authorization: `Bearer ${API_KEY}` } }
)
return response.json()
}Root Loader
Translations are loaded once in the root layout:
// src/routes/__root.tsx
export const Route = createRootRoute({
loader: async () => {
const { locale, translations } = await loadTranslations()
return { locale, translations }
},
component: RootComponent,
})Using Translations
import { useTranslation } from '../lib/i18n'
function MyPage() {
const t = useTranslation()
return <h1>{t('my.page.title')}</h1>
}The demo includes a protected dashboard route that requires authentication:
// src/routes/dashboard.tsx
import { createFileRoute } from '@tanstack/react-router'
import { requireAuth } from '../lib/auth'
export const Route = createFileRoute('/dashboard')({
beforeLoad: () => requireAuth(),
component: DashboardPage,
})This demonstrates how LocaleLens integrates with authentication — translations are available on both public and protected routes.