Vite
Build modern full-stack applications with Igniter.js and Vite, the lightning-fast build tool for modern web development.
Vite is a next-generation frontend build tool that provides an instant dev server and lightning-fast hot module replacement. When combined with Igniter.js, you can build full-stack applications with a type-safe API backend and a modern React/Vue/Svelte frontend—all in a single codebase with excellent developer experience.
This guide focuses on integrating Igniter.js as an API backend within a Vite project. You'll learn how to set up API routes that work seamlessly with Vite's dev server and production builds, while maintaining full type safety between your frontend and backend.
Full-Stack Development
Vite + Igniter.js enables full-stack development with frontend frameworks like React, Vue, or Svelte while maintaining a type-safe API layer.
Quick Start
For a complete full-stack setup, we recommend using TanStack Start (Vite-powered React framework):
npx @igniter-js/cli@latest initpnpm dlx @igniter-js/cli@latest inityarn dlx @igniter-js/cli@latest initbunx @igniter-js/cli@latest initYour app runs at http://localhost:3000, API at http://localhost:3000/api/v1, and docs at http://localhost:3000/api/v1/docs 🚀
Direct Command
If you prefer to skip the interactive prompts, you can specify your project name and framework directly:
npx @igniter-js/cli@latest init my-vite-app --framework tanstack-startpnpm dlx @igniter-js/cli@latest init my-vite-app --framework tanstack-startyarn dlx @igniter-js/cli@latest init my-vite-app --framework tanstack-startbunx @igniter-js/cli@latest init my-vite-app --framework tanstack-startThis command will create a TanStack Start project with all Igniter.js features pre-configured.
Manual Setup with Vite
Complete Vite Setup Guide
Prerequisites
Before you begin, ensure you have:
- Node.js 22.0+
- Vite 5.0+
- A Vite project (React, Vue, Svelte, etc.)
Install Dependencies
Add Igniter.js to your Vite project:
npm install @igniter-js/core zodpnpm add @igniter-js/core zodyarn add @igniter-js/core zodbun add @igniter-js/core zodConfigure Vite for API Routes
Update your vite.config.ts to proxy API requests during development:
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
export default defineConfig({
plugins: [react()],
server: {
proxy: {
// Proxy API requests to your backend
'/api': {
target: 'http://localhost:3001',
changeOrigin: true,
},
},
},
})This configuration proxies /api/* requests to your Igniter.js server during development.
Define Application Context
Create the context for your API. Create src/igniter.context.ts:
/**
* Application Context Type
* Defines what dependencies are available to all API handlers
*/
export interface AppContext {
// Add your dependencies here, e.g.:
// db: PrismaClient
// auth: AuthService
}
/**
* Context Factory
* Creates the context instance passed to handlers
*/
export function createIgniterAppContext(): AppContext {
return {
// Initialize dependencies here
}
}Initialize Igniter.js
Create the main Igniter instance. Create src/igniter.ts:
import { Igniter } from '@igniter-js/core'
import { createIgniterAppContext } from './igniter.context'
export const igniter = Igniter
.context(createIgniterAppContext())
.config({
baseURL: import.meta.env.VITE_API_URL || 'http://localhost:3001',
basePATH: import.meta.env.VITE_API_BASE_PATH || '/api/v1',
})
.docs({
info: {
title: 'My Vite App API',
version: '1.0.0',
description: 'Full-stack app with Vite and Igniter.js',
}
})
.create()Note: Vite uses import.meta.env for environment variables, not process.env.
Create Your First Controller
Controllers group related endpoints. Create src/features/example/controllers/example.controller.ts:
import { igniter } from '@/igniter'
export const exampleController = igniter.controller({
name: 'Example',
path: '/example',
actions: {
hello: igniter.query({
path: '/hello',
handler: async ({ response }) => {
return response.success({
message: 'Hello from Igniter.js with Vite!',
timestamp: new Date().toISOString()
})
},
}),
},
})Create barrel export at src/features/example/index.ts:
export * from './controllers/example.controller'Create Application Router
The router assembles all controllers. Create src/igniter.router.ts:
import { igniter } from './igniter'
import { exampleController } from './features/example'
export const AppRouter = igniter.router({
controllers: {
example: exampleController
}
})
export type AppRouterType = typeof AppRouterCreate Separate API Server
For Vite projects, run the API as a separate Node.js server. Create server/index.ts:
import express from 'express'
import { expressAdapter } from '@igniter-js/core/adapters'
import { AppRouter } from '../src/igniter.router'
const app = express()
const PORT = process.env.API_PORT || 3001
const API_BASE_PATH = '/api/v1'
// Mount Igniter.js router
app.use(API_BASE_PATH, expressAdapter(AppRouter.handler))
app.listen(PORT, () => {
console.log(`🚀 API Server running at http://localhost:${PORT}`)
})Add to package.json:
{
"scripts": {
"dev": "concurrently \"vite\" \"tsx watch server/index.ts\"",
"dev:api": "tsx watch server/index.ts",
"dev:frontend": "vite"
}
}Install concurrently:
npm install -D concurrently tsxUsing in React Components
Type-Safe Client
Create a type-safe client. Create src/igniter.client.ts:
import { createIgniterClient } from '@igniter-js/core/client'
import type { AppRouterType } from './igniter.router'
export const api = createIgniterClient<AppRouterType>({
baseURL: import.meta.env.VITE_API_URL || 'http://localhost:3001',
basePATH: import.meta.env.VITE_API_BASE_PATH || '/api/v1',
router: () => import('./igniter.schema').then(m => m.AppRouterSchema),
})
export type ApiClient = typeof apiUsing Client Components
Use React hooks for automatic loading/error states:
'use client'
import { api } from '@/igniter.client'
export function Example() {
const { data, isLoading, error } = api.example.hello.useQuery()
if (isLoading) return <div>Loading...</div>
if (error) return <div>Error: {error.message}</div>
return <div>Message: {data.message}</div>
}Generating Schema and Docs
Since TanStack Start is a full-stack framework, you'll need to generate the client schema whenever you modify your API.
When to Generate Schema
Critical: You MUST run schema generation BEFORE using the client in your frontend. The client depends on the generated schema to function correctly.
Run this command whenever you modify your API structure (add/remove/modify controllers or actions) OR before using the client for the first time.
Generate Schema
Run this command whenever you make changes to your API structure:
npx @igniter-js/cli@latest generate schemapnpm dlx @igniter-js/cli@latest generate schemayarn dlx @igniter-js/cli@latest generate schemabunx @igniter-js/cli@latest generate schemaThis creates:
src/igniter.schema.ts- Type-safe schema for client-side usagesrc/docs/openapi.json- OpenAPI 3.0 specification
Generate OpenAPI Documentation
To generate or update the OpenAPI specification and interactive documentation:
npx @igniter-js/cli@latest generate docspnpm dlx @igniter-js/cli@latest generate docsyarn dlx @igniter-js/cli@latest generate docsbunx @igniter-js/cli@latest generate docsEnvironment Variables
Create .env for Vite environment variables:
VITE_API_URL=http://localhost:3001
VITE_API_BASE_PATH=/api/v1Access in code using import.meta.env.VITE_*:
const apiUrl = import.meta.env.VITE_API_URLProduction Build
Build Both Frontend and API
Update package.json:
{
"scripts": {
"build": "tsc && vite build",
"build:api": "tsc --project tsconfig.server.json",
"preview": "vite preview"
}
}Create tsconfig.server.json for the API:
{
"extends": "./tsconfig.json",
"compilerOptions": {
"outDir": "./dist/server",
"module": "commonjs",
"target": "ES2020"
},
"include": ["server/**/*", "src/igniter*.ts", "src/features/**/*"]
}Alternative: TanStack Start
For the best full-stack Vite experience, use TanStack Start which includes:
- Built-in API routes (no separate server needed)
- File-based routing
- SSR and streaming
- Type-safe data loading
See the TanStack Start guide for details.