Vite Frontend

Use Vite's plugin ecosystem (React, Vue, Svelte, Solid, Qwik...) with HMR in dev and a hashed, code-split bundle in production. Same port for API and frontend. Compiles to a single executable.

Overview

@tekir/vitewires Vite's dev server and build pipeline into your tekir app. In development a Vite dev server runs in-process and tekir proxies non-API requests to it — you keep a single port for everything. In production tekir serves the pre-bundled output directly from disk (or from memory inside a compiled binary).

Install

bun add @tekir/vite vite
bun add -d @vitejs/plugin-react @types/react @types/react-dom
bun add react react-dom

vite is a peer dependency, so you control the version. Pick the framework plugin you need (@vitejs/plugin-react, @vitejs/plugin-vue, @sveltejs/vite-plugin-svelte etc.) and add it to vite.config.ts.

Setup

index.ts
import { tekir } from '@tekir/core'

const { router, start } = await tekir({
  config: { app: { port: 3000 } },
  frontend: { type: 'vite' }   // looks for vite.config.ts in cwd
})

router.get('/api/hello', () => ({ message: 'from server' }))

start()
vite.config.ts
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'

export default defineConfig({
  root: 'resources',                       // where your index.html lives
  plugins: [react()],
  build: { outDir: '../dist/client' },
})

Typical project layout:

my-app/
├── index.ts
├── vite.config.ts
├── resources/
│   ├── index.html
│   ├── main.tsx
│   └── App.tsx
├── public/                  # optional, copied into the build as-is
└── package.json

vite.config.ts

tekir auto-discovers vite.config.ts (or .js/.mts/.mjs) in your project root and passes it to both the dev server and the build hook. This way every plugin you add — React, Vue, Tailwind, etc. — works exactly the way Vite documents it. Without this, plugins silently drop and your production bundle ends up using the classic JSX runtime (e.g. you see ReferenceError: React is not defined in the browser).

React, Vue, Svelte, Solid

Any framework Vite supports works. Swap the plugin and adjust your entry file:

// React
import react from '@vitejs/plugin-react'
plugins: [react()]

// Vue
import vue from '@vitejs/plugin-vue'
plugins: [vue()]

// Svelte
import { svelte } from '@sveltejs/vite-plugin-svelte'
plugins: [svelte()]

// Solid
import solid from 'vite-plugin-solid'
plugins: [solid()]

Environment Variables

Vite inlines only variables prefixed with VITE_ into the client bundle (we wire envPrefix: 'VITE_' for you). Anything else stays server-side and never reaches the browser:

.env
# .env (project root)
VITE_API_URL=https://api.example.com   # exposed to the browser
DATABASE_URL=postgres://...            # stays on the server
resources/main.tsx
// resources/main.tsx
console.log(import.meta.env.VITE_API_URL)
// → "https://api.example.com" (inlined at build time)

console.log(import.meta.env.DATABASE_URL)
// → undefined (stripped by Vite's envPrefix filter)

Production Build

# Build the frontend (runs vite build) + start production server
tekir build
tekir serve

build runs the Vite production build (your vite.config.ts plugins, your publicDir, your build.outDir) and writes hashed assets into dist/client/. start serves them with the right MIME types and falls back to index.html for client-side routes.

Single Executable

Vite frontend is fully supported by --compile. tekir runs the Vite build, walks dist/client/, and embeds every asset into the binary as a Bun blob. The compiled binary serves them straight from memory — no node_modules on disk, no Vite, no rollup at runtime.

# One self-contained binary: server + bundled frontend
tekir build --compile
./server

Cross-compile, build-time defines, splitting, plugins and the rest live in the fluent API reference.

Options

Most settings belong in vite.config.ts. The few options on the tekir side override the dev/build wiring:

frontend: {
  type: 'vite',
  root: 'resources',          // override vite.config.ts root
  buildDir: 'dist/client',    // where Vite writes the production bundle
  plugins: [/* additional inline plugins */],
  define: { __APP_VERSION__: '"1.0.0"' },
  resolve: { alias: { '@': '/src' } },
}