TanStack Start Clean Architecture

September 28, 2025 ยท View on GitHub

A modern boilerplate for building full-stack React applications with TanStack Start, implementing Clean Architecture principles for maintainable, testable, and scalable code.

๐Ÿš€ Tech Stack

Frontend

  • React 19.1.1 with TypeScript
  • TanStack Start 1.132.19 - Full-stack React framework
  • TanStack Router 1.132.19 - Type-safe file-based routing
  • Tailwind CSS 4.1.13 - Utility-first CSS framework
  • shadcn/ui - High-quality accessible component library
  • Radix UI - Primitive components for complex UI
  • Lucide React - Beautiful icon library

Backend & Database

  • TanStack Start Server Functions - Full-stack capabilities
  • Prisma - Modern database toolkit and ORM
  • SQLite - Lightweight database

Development Tools

  • Vite 7.1.7 - Lightning-fast build tool
  • TypeScript 5.9.2 - Type safety and enhanced DX
  • ESLint - Code linting with comprehensive presets
  • Prettier - Code formatting
  • Vitest - Fast unit testing framework

๐Ÿ“‹ Prerequisites

  • Node.js (version 18 or higher)
  • pnpm or yarn or pnpm

๐Ÿ› ๏ธ Installation

  1. Clone the repository:

    git clone git@github.com:felipestanzani/tanstack-start-ca.git
    cd tanstack-start-ca
    
  2. Install dependencies:

    pnpm install
    
  3. Set up environment variables:

    Create a .env file in the root directory with the following content:

    # Database
    DATABASE_URL="file:./dev.db"
    
  4. Set up the database:

    Generate the Prisma client from the schema:

    pnpm db:generate
    

    Create the SQLite database and apply the schema:

    pnpm db:push
    

๐Ÿš€ Development

Start the development server:

pnpm dev

The application will be available at http://localhost:3000

Available Scripts

Development

  • pnpm dev - Start development server
  • pnpm build - Build for production
  • pnpm preview - Preview production build

Code Quality

  • pnpm lint - Run ESLint
  • pnpm format - Format code with Prettier

Testing

  • pnpm test - Run tests with Vitest
  • pnpm test:run - Run tests once
  • pnpm test:watch - Run tests in watch mode
  • pnpm test:coverage - Run tests with coverage

Database

  • pnpm db:generate - Generate Prisma client
  • pnpm db:push - Push schema changes to database
  • pnpm db:migrate - Create and apply migrations
  • pnpm db:studio - Open Prisma Studio for database management

๐Ÿ—๏ธ Clean Architecture Structure

This project follows Clean Architecture principles with clear separation of concerns and dependency inversion. For detailed architecture documentation, see CLEAN_ARCHITECTURE.md.

tanstack-start-clean-architecture/
โ”œโ”€โ”€ prisma/                         # Database schema and migrations
โ”‚   โ””โ”€โ”€ schema.prisma
โ”œโ”€โ”€ src/
โ”‚   โ”œโ”€โ”€ core/                       # Core Business Logic (Domain + Application Layers)
โ”‚   โ”‚   โ”œโ”€โ”€ domain/                 # ๐ŸŸฆ Domain Layer (Innermost)
โ”‚   โ”‚   โ”‚   โ”œโ”€โ”€ entities/           # Business entities with domain logic
โ”‚   โ”‚   โ”‚   โ”‚   โ”œโ”€โ”€ base.entity.ts  # Base entity with common properties
โ”‚   โ”‚   โ”‚   โ”‚   โ”œโ”€โ”€ counter.entity.ts # Counter business entity
โ”‚   โ”‚   โ”‚   โ”‚   โ””โ”€โ”€ index.ts        # Domain entities barrel export
โ”‚   โ”‚   โ”‚   โ”œโ”€โ”€ events/             # Domain events
โ”‚   โ”‚   โ”‚   โ”‚   โ””โ”€โ”€ index.ts
โ”‚   โ”‚   โ”‚   โ”œโ”€โ”€ repositories/       # Repository interfaces (contracts)
โ”‚   โ”‚   โ”‚   โ”‚   โ”œโ”€โ”€ counter.repository.ts
โ”‚   โ”‚   โ”‚   โ”‚   โ””โ”€โ”€ index.ts
โ”‚   โ”‚   โ”‚   โ””โ”€โ”€ value-objects/      # Domain value objects
โ”‚   โ”‚   โ”‚       โ””โ”€โ”€ index.ts
โ”‚   โ”‚   โ””โ”€โ”€ application/            # ๐ŸŸจ Application Layer
โ”‚   โ”‚       โ”œโ”€โ”€ dtos/               # Data Transfer Objects
โ”‚   โ”‚       โ”‚   โ””โ”€โ”€ index.ts
โ”‚   โ”‚       โ”œโ”€โ”€ services/           # Application services
โ”‚   โ”‚       โ”‚   โ””โ”€โ”€ index.ts
โ”‚   โ”‚       โ””โ”€โ”€ use-cases/          # Use cases (business operations)
โ”‚   โ”‚           โ”œโ”€โ”€ counter/
โ”‚   โ”‚           โ”‚   โ”œโ”€โ”€ get-counter.use-case.ts
โ”‚   โ”‚           โ”‚   โ”œโ”€โ”€ increment-counter.use-case.ts
โ”‚   โ”‚           โ”‚   โ””โ”€โ”€ index.ts
โ”‚   โ”‚           โ””โ”€โ”€ index.ts
โ”‚   โ”œโ”€โ”€ infrastructure/             # ๐ŸŸฉ Infrastructure Layer
โ”‚   โ”‚   โ”œโ”€โ”€ di/                     # Dependency Injection
โ”‚   โ”‚   โ”‚   โ”œโ”€โ”€ container.ts        # DI container
โ”‚   โ”‚   โ”‚   โ””โ”€โ”€ index.ts
โ”‚   โ”‚   โ””โ”€โ”€ repositories/           # Repository implementations
โ”‚   โ”‚       โ”œโ”€โ”€ prisma-counter.repository.ts
โ”‚   โ”‚       โ””โ”€โ”€ index.ts
โ”‚   โ”œโ”€โ”€ presentation/               # ๐ŸŸช Presentation Layer
โ”‚   โ”‚   โ””โ”€โ”€ controllers/            # HTTP request handlers
โ”‚   โ”‚       โ”œโ”€โ”€ counter.controller.ts
โ”‚   โ”‚       โ””โ”€โ”€ index.ts
โ”‚   โ”œโ”€โ”€ components/                 # React UI components
โ”‚   โ”‚   โ”œโ”€โ”€ theme-provider.tsx
โ”‚   โ”‚   โ””โ”€โ”€ ui/                     # shadcn/ui components
โ”‚   โ”‚       โ””โ”€โ”€ button.tsx
โ”‚   โ”œโ”€โ”€ lib/                        # Utility functions
โ”‚   โ”‚   โ””โ”€โ”€ utils.ts
โ”‚   โ”œโ”€โ”€ routes/                     # File-based routing (TanStack Router)
โ”‚   โ”‚   โ”œโ”€โ”€ __root.tsx              # Root layout
โ”‚   โ”‚   โ””โ”€โ”€ index.tsx               # Home page
โ”‚   โ”œโ”€โ”€ styles/                     # Global styles
โ”‚   โ”‚   โ””โ”€โ”€ app.css
โ”‚   โ”œโ”€โ”€ tests/                      # Test files organized by layer
โ”‚   โ”‚   โ”œโ”€โ”€ application/
โ”‚   โ”‚   โ”‚   โ””โ”€โ”€ use-cases/
โ”‚   โ”‚   โ”‚       โ””โ”€โ”€ get-counter.use-case.test.ts
โ”‚   โ”‚   โ”œโ”€โ”€ domain/
โ”‚   โ”‚   โ”‚   โ””โ”€โ”€ entities/
โ”‚   โ”‚   โ”‚       โ””โ”€โ”€ counter.entity.test.ts
โ”‚   โ”‚   โ””โ”€โ”€ setup.ts
โ”‚   โ”œโ”€โ”€ router.tsx                  # Router configuration
โ”‚   โ””โ”€โ”€ routeTree.gen.ts            # Generated route tree
โ”œโ”€โ”€ components.json                 # shadcn/ui configuration
โ”œโ”€โ”€ package.json
โ”œโ”€โ”€ tsconfig.json                   # TypeScript configuration
โ”œโ”€โ”€ vite.config.ts                  # Vite configuration
โ”œโ”€โ”€ eslint.config.mjs               # ESLint configuration
โ”œโ”€โ”€ CLEAN_ARCHITECTURE.md           # Detailed architecture documentation
โ””โ”€โ”€ README.md

๐Ÿงฑ Architecture Layers

๐ŸŸฆ Domain Layer (src/core/domain/)

The innermost layer containing pure business logic:

  • Entities: Core business objects with domain rules (e.g., Counter)
  • Repository Interfaces: Contracts for data access
  • Domain Events: Business events within the domain
  • Value Objects: Immutable domain concepts

๐ŸŸจ Application Layer (src/core/application/)

Orchestrates business operations:

  • Use Cases: Application-specific business rules
  • DTOs: Data transfer objects for layer communication
  • Services: Application services coordinating domain objects

๐ŸŸฉ Infrastructure Layer (src/infrastructure/)

Handles external concerns:

  • Repository Implementations: Concrete data access implementations
  • Dependency Injection: DI container for managing dependencies
  • External Services: Third-party integrations

๐ŸŸช Presentation Layer (src/presentation/)

User interface and API endpoints:

  • Controllers: HTTP request/response handlers using TanStack Start
  • Routes: Application routing with TanStack Router
  • Components: React UI components

๐Ÿงช Testing Strategy

The project includes comprehensive testing organized by architecture layer:

src/tests/
โ”œโ”€โ”€ application/        # Application layer tests
โ”œโ”€โ”€ domain/            # Domain layer tests
โ”œโ”€โ”€ infrastructure/    # Infrastructure layer tests
โ””โ”€โ”€ presentation/      # Presentation layer tests

Test Types

  • Unit Tests: Testing individual components and business logic
  • Integration Tests: Testing layer interactions
  • End-to-End Tests: Testing complete user workflows

๐Ÿ—„๏ธ Database

This project uses SQLite with Prisma for data persistence.

Database Schema

The application uses a simple Counter table with the following structure:

model Counter {
  id        String   @id
  value     Int      @default(0)
  createdAt DateTime @default(now())
  updatedAt DateTime @updatedAt
}

Repository Implementation

The counter persistence uses database storage (PrismaCounterRepository):

  • Implements the CounterRepository interface
  • Uses SQLite for data persistence
  • Supports the default counter with automatic creation
  • Handles upsert operations for counter updates
  • Maintains full compatibility with existing use cases

Note: The Prisma client is generated to the standard location (node_modules/@prisma/client) for better ES module compatibility with Vite/TanStack Start.

โšก State Management with TanStack Query

This project uses TanStack Query for all client-server state synchronization and UI data fetching. Benefits include:

  • Automatic caching and background updates
  • Optimistic UI for instant feedback on mutations
  • Error handling and retry logic out of the box
  • DevTools for query/mutation debugging

Query Setup

Custom Hooks

  • useCounter() โ€” Fetches the current counter value
  • useIncrementCounter() โ€” Increments the counter (with optimistic update)

See src/hooks/use-counter.ts for implementation details.

Example Usage (Home Page)

The home page demonstrates:

  • Live counter value with auto-refresh
  • Increment button with instant UI feedback
  • Loading and error states
  • Optimistic updates for a snappy user experience

๐Ÿ†• Counter Feature Demo

  • Increment the counter with instant feedback
  • UI disables button during loading/mutation
  • Error messages and retry options for failed requests
  • Powered by TanStack Query hooks and server functions

๐ŸŽฏ Features

This boilerplate includes:

  • โœ… Clean Architecture implementation
  • โœ… Type-safe routing with TanStack Router
  • โœ… Server-side rendering with TanStack Start
  • โœ… Database integration with Prisma + SQLite
  • โœ… UI components with shadcn/ui
  • โœ… Testing setup with Vitest
  • โœ… Code quality with ESLint and Prettier
  • โœ… Dependency injection container
  • โœ… Example counter feature demonstrating architecture
  • โœ… State management with TanStack Query (caching, mutations, optimistic updates)
  • โœ… React Query DevTools for development
  • โœ… Increment counter with optimistic UI

๐Ÿ“š Learn More

๐Ÿค Contributing

Contributions are welcome! Please read our contributing guidelines and submit pull requests for any improvements.

๐Ÿ“„ License

This project is licensed under the MIT License - see the LICENSE file for details.

๐Ÿ™ Acknowledgments

  • Clean Architecture principles by Robert C. Martin
  • TanStack team for amazing React tools
  • shadcn for the beautiful UI components
  • The open-source community for inspiration and tools