Back to blog

Modern Frontend Architecture with Vite, React & TanStack

Published March 31, 2025
Updated September 1, 2025
4 min read

Learn how to build a modern, scalable frontend architecture using Vite, React, and TanStack tools (Query, Router, Form, and Table). In this guide, I’ll share my go-to setup, folder structure, best practices, and code snippets for fast, maintainable web apps.

Introduction 👋

Vite changed the game for frontend tooling with its lightning-fast dev server and modern build system. Pair that with React and the powerful TanStack suite (Query, Router, Form, Table), and you’ve got a frontend stack that’s fast, scalable, and enjoyable to work with. In this post, I’ll walk you through the architectural patterns I use in production projects and expand on lessons learned since the initial version of this article.

Why Vite, React & TanStack? 🚀

The combination of Vite, React, and TanStack has become one of the strongest contenders for building production-ready applications. Let’s recap and expand why:

  • Vite: Instant hot module replacement, optimized builds, and TypeScript support. Compared to Webpack or CRA, Vite drastically reduces friction in development and deployment.
  • React: Still the leader in component-driven architecture. Its ecosystem is unmatched, and with React 18’s concurrent rendering features, performance and responsiveness have only improved.
  • TanStack Query: It abstracts away much of the complexity of managing asynchronous state. Instead of manually juggling loading, error, and cache states, you get a battle-tested pattern.
  • TanStack Router: Provides type safety and a more modern developer experience compared to React Router. The strongly typed route params reduce runtime errors and align with TypeScript-first workflows.
  • TanStack Form: A hidden gem. It keeps validation scalable, especially when paired with Zod for schema enforcement.

When combined, these tools let you write less boilerplate and focus more on business logic.

Folder Structure 📁

A maintainable project starts with a solid structure:


src/
├── components/
├── features/
│   └── vehicles/
│       ├── api.ts
│       ├── VehicleList.tsx
│       └── useVehicles.ts
├── routes/
│   ├── index.tsx
│   ├── vehicles.tsx
│   └── drivers.tsx
├── lib/
│   └── tanstack/
│       ├── queryClient.ts
│       ├── router.tsx
│       └── form.ts
├── types/
└── main.tsx

This layout keeps business logic and UI closely tied to each feature. Features are isolated, but still consistent across the app. It avoids the trap of “god folders” where everything mixes together.

Tip: Treat each feature like its own mini-application.

Routing with TanStack Router 🗺️

Routing is no longer just about navigation; it’s about type safety, nested layouts, and predictable state.

import { createRouter } from '@tanstack/react-router';

const router = createRouter({
  routeConfig: [
    {
      path: '/',
      component: HomePage,
    },
    {
      path: '/vehicles',
      component: VehicleList,
    },
  ],
});

With TanStack Router:

  • Route params are type-safe.
  • Nested layouts feel natural.
  • You get better integration with data loaders and context providers.

This avoids subtle bugs caused by mis-typed params or missing props.

Data Fetching with TanStack Query 🌐

Data fetching should be declarative, not imperative. Here’s a typical example:

import { useQuery } from '@tanstack/react-query';
import { getVehicles } from './api';

export const useVehicles = () => useQuery({
  queryKey: ['vehicles'],
  queryFn: getVehicles,
});

Why it works so well:

  • Caching ensures minimal redundant requests.
  • Background syncing keeps stale data fresh.
  • The devtools provide real-time insight into your queries.

This elevates your app’s resilience while keeping code simple.

Forms with TanStack Form + Zod 📝

Forms are notorious for complexity, but schema-driven validation simplifies them:

const schema = z.object({
  name: z.string().min(2),
});

const form = useForm({ schema });

return (
  <form onSubmit={form.handleSubmit()}>
    <input {...form.register('name')} />
    <button type="submit">Save</button>
  </form>
);

Why it matters:

  • You get declarative validation.
  • No need for manual error handling spaghetti.
  • Easily scales as forms grow.

In practice, pairing this with UI libraries like ShadCN UI or TailwindCSS results in clean, user-friendly forms.

Extra Tips for Clean Architecture ✨

Over the past months, I’ve refined some additional practices:

  • Use TypeScript everywhere: Catch errors at compile time, not runtime.
  • Centralize API logic: Avoid scattering API calls. Use a single layer per feature.
  • Avoid prop drilling: Use context or TanStack Store for state sharing.
  • Adopt atomic components: Pair them with Tailwind or ShadCN for consistency.
  • Automate testing early: Unit and integration tests prevent regressions.

These habits keep projects maintainable, even as teams grow.

What Changed Since Early 2025 📅

Since originally writing this post in March 2025, a few trends and updates have stood out:

  1. TanStack Router adoption is accelerating. More projects are moving away from React Router, especially TypeScript-heavy codebases.
  2. Server-first thinking is stronger. Many apps combine this frontend stack with serverless backends (AWS Lambda, SST, etc.), and the contract-driven development pairs perfectly with TypeScript.
  3. Design systems are gaining traction. Libraries like ShadCN UI, Material 3, and Tailwind CSS utilities have made styling more consistent across projects.
  4. Monorepos with Turborepo/SST are becoming standard. Developers increasingly want unified workflows across web, mobile, and backend.

This stack is no longer just an experiment—it’s production-grade and here to stay.

Conclusion ✅

This Vite + React + TanStack stack has drastically improved my productivity and code quality. Whether you’re building an admin dashboard, logistics app, or SaaS UI, this setup keeps things fast, typed, and easy to scale. Since early 2025, its adoption has only grown, and the tooling continues to evolve at a rapid pace.

If you’re planning a new project today, this architecture provides a future-proof foundation. Start small, keep features isolated, lean on TypeScript, and let the TanStack ecosystem handle the heavy lifting. You’ll spend less time fighting tooling and more time building meaningful features.