A modern, production-ready full-stack React application template combining TanStack Router with Hono for server-side rendering. This setup delivers fast, SEO-friendly applications with excellent developer experience.
AI Ready: this repo includes checked-in framework-specific docs in
docs/ai/and repo-local skills in.agents/skills/so an LLM can follow the project's actual patterns when helping build the app.
# Clone the template
npx degit bskimball/tanstack-hono my-app
# Navigate to your project
cd my-app
# Run the interactive setup script
bash scripts/setup.shThe setup script will:
- Update project name in package.json
- Create .env file from .env.example
- Install dependencies (optional)
- Initialize git repository (optional)
# Clone the template
npx degit bskimball/tanstack-hono my-app
# Navigate to your project
cd my-app
# Copy environment file
cp .env.example .env
# Install dependencies
npm install
# Start development server
npm run devOpen http://localhost:3000 to see your app running!
Health Check: http://localhost:3000/api/health
- πΊ TanStack Router: Type-safe, file-based routing with powerful data loading
- β‘ Hono SSR: Ultra-fast server-side rendering with minimal overhead
- π₯ Vite+: Lightning-fast development with Hot Module Replacement, powered by Rolldown
- π TypeScript: Full type safety across client and server, checked by tsgo/tsgolint
- π¨ Tailwind CSS v4: Modern utility-first CSS framework
- π§Ή Oxlint & Oxfmt: Fast linting and formatting via Vite+ (replaces ESLint & Prettier)
- π§ͺ Vitest: Fast unit testing with great DX
src/
βββ components/
β βββ Header.tsx # Site header component
β βββ HeroSection.tsx # Landing page hero
βββ hooks/
β βββ useDebounce.ts # Reusable debounce hook
βββ lib/
β βββ api.ts # Shared Hono RPC client
βββ routes/ # File-based routing (TanStack Router)
β βββ __root.tsx # Root layout component
β βββ index.tsx # Home page route
β βββ about.tsx # About page route
β βββ error.tsx # Error boundary route
β βββ -api.ts # Server-only API route helpers
β βββ -test.ts # Test route utilities (ignored by router)
βββ tests/
β βββ Header.test.tsx
β βββ HeroSection.test.tsx
β βββ root-route.test.tsx
βββ entry-client.tsx # Client-side hydration entry
βββ entry-server.tsx # Hono server with SSR setup
βββ router.tsx # Router configuration
βββ routeTree.gen.ts # Auto-generated route tree (do not edit)
βββ reportWebVitals.ts # Web Vitals reporting
βββ styles.css # Global styles
vp dev # Start development server
vp run build # Build for production (client + server)
vp test # Run tests
vp check # Lint, format, and type-check
vp check --fix # Auto-fix lint and formatting issues
npm start # Start production server (after build)- Request: Browser requests a URL
- Server: Hono matches route and runs TanStack Router SSR
- Render: React components render to an HTML string by default
- Response: Full HTML sent to browser with embedded data
- Hydration: Client-side React takes over for SPA navigation
This template ships with non-streaming SSR by default via renderRouterToString in
src/entry-server.tsx.
That keeps the default setup simple, but TanStack Router also supports streaming SSR when you want to flush the initial shell early and stream deferred data or suspenseful query work as it resolves.
See docs/ai/streaming.md for:
- When to keep non-streaming SSR
- How to switch
src/entry-server.tsxto streaming - How to use the existing Hono RPC client in deferred loaders and queries
- A
defer(...)+Awaitexample - A
Suspenseexample - An SSR query streaming example using
@tanstack/react-router-ssr-query
Routes are automatically generated from files in src/routes/:
// src/routes/about.tsx
import { createFileRoute } from "@tanstack/react-router";
export const Route = createFileRoute("/about")({
component: AboutPage,
});
function AboutPage() {
return <div>About us!</div>;
}import { Link } from "@tanstack/react-router";
function Navigation() {
return <Link to="/about">About</Link>;
}import type { InferResponseType } from "hono/client";
import { createFileRoute } from "@tanstack/react-router";
import { api } from "../lib/api";
const getHealthRoute = api.health.$get;
type Health = InferResponseType<typeof getHealthRoute>;
async function getHealth(): Promise<Health> {
const response = await api.health.$get();
if (!response.ok) {
throw new Error("Failed to load health check");
}
return response.json();
}
export const Route = createFileRoute("/status")({
loader: async () => {
return {
health: await getHealth(),
};
},
component: StatusPage,
});
function StatusPage() {
const { health } = Route.useLoaderData();
return <pre>{JSON.stringify(health, null, 2)}</pre>;
}For client-side data, you can reuse the same Hono-backed helpers with TanStack Query instead of maintaining a separate fetch path:
import { queryOptions, useQuery } from "@tanstack/react-query";
export const healthQuery = queryOptions({
queryKey: ["health"],
queryFn: getHealth,
staleTime: 30_000,
});
function HealthBadge() {
const { data, isPending } = useQuery(healthQuery);
if (isPending) return <p>Checking API...</p>;
return <p>API status: {data.status}</p>;
}See docs/ai/routing-and-data.md and docs/ai/server-api.md for the full Hono
RPC patterns used in this template.
The root layout (src/routes/__root.tsx) wraps all pages:
import { Outlet, createRootRoute } from "@tanstack/react-router";
import { Header } from "../components/Header";
export const Route = createRootRoute({
component: RootLayout,
});
function RootLayout() {
return (
<>
<Header />
<main>
<Outlet />
</main>
</>
);
}SSR Advantages:
- SEO: Fully rendered HTML for search engines
- LCP: Faster Largest Contentful Paint
- Progressive Enhancement: Works without JavaScript
- Social Sharing: Rich preview cards with meta tags
Hono Benefits:
- Small Bundle: Minimal server overhead
- Edge Ready: Deploy to Cloudflare Workers, etc.
- Fast Startup: Quick cold start times
# Build and run production
docker-compose up app
# Development with hot reload
docker-compose --profile dev up devdocker build -t tanstack-hono .
docker run -p 3000:3000 tanstack-hononpm run build
npm start- Docker: Use included Dockerfile and docker-compose.yml
- Vercel/Netlify: Serverless functions
- Railway/Render: Container deployments
- Cloudflare Workers: Edge runtime
- VPS: With PM2 + Nginx
See ARCHITECTURE.md for detailed deployment strategies.
- AGENTS.md - Guide for AI agents working with this codebase
- CLAUDE.md - Claude-specific context and patterns
- docs/ai/README.md - Index of framework-specific working docs for this repo
- ARCHITECTURE.md - Deep dive into system design
- CONTRIBUTING.md - Contribution guidelines
- docs/ai/streaming.md - How to enable TanStack Router streaming SSR
This template includes checked-in guidance for LLMs and coding agents, so they have repo-specific context for building features instead of relying only on generic framework knowledge.
.cursorrulesfor Cursor IDEAGENTS.mdfor general AI agent guidelinesCLAUDE.mdfor Claude-specific contextdocs/ai/for task-focused docs covering commands, architecture, routing, Hono APIs, styling, testing, deployment, and streaming SSR.agents/skills/for repo-local skills covering Hono, TanStack Router, TanStack Query, Vite, Vite+, Vitest, and React research
An LLM that reads those files should have the project-specific instructions it needs to help implement and maintain the app effectively.
- TanStack Router - Type-safe routing
- Hono - Ultrafast web framework
- SSR Guide - TanStack Router SSR
- Vite SSR - Vite server-side rendering
MIT License - see LICENSE file for details
Contributions are welcome! Please read CONTRIBUTING.md for guidelines.