Web
Build web applications with Bini.js — the default platform target.
Web Overview
Web is the default platform target in Bini.js. It's a standard Vite + React SPA with file-based routing, pre-rendering support, and a Hono API layer. Your application runs in the browser and can be deployed to any hosting platform.
SPA
Single-page application with client-side routing
API Layer
Hono-powered API routes in src/app/api/
Pre-rendering
Static HTML with bini-ssg
Windows
Create a web application on Windows using the CLI. Web is the default platform, so you don't need to specify it.
Interactive Mode
Run the CLI and select web when prompted:
Prompt: Which platform would you like to target?
web / windows / macos / linux / android / ios
Select web and press Enter
With --platform Flag
Default (No Flag)
macOS
Create a web application on macOS using the CLI. Web is the default platform, so you don't need to specify it.
Interactive Mode
Run the CLI and select web when prompted:
Prompt: Which platform would you like to target?
web / windows / macos / linux / android / ios
Select web and press Enter
With --platform Flag
Default (No Flag)
Linux
Create a web application on Linux using the CLI. Web is the default platform, so you don't need to specify it.
Interactive Mode
Run the CLI and select web when prompted:
Prompt: Which platform would you like to target?
web / windows / macos / linux / android / ios
Select web and press Enter
With --platform Flag
Default (No Flag)
Development Server
Start the development server with HMR (Hot Module Replacement):
The dev server provides:
- Fast refresh with HMR
- File-based routing with live updates
- API routes served at
/api/* - Environment variables from
.envfiles - Error overlay with
bini-overlay
Production Server
Build and serve your application in production mode:
bini-server is a zero-dependency production server that includes:
- Static file serving with ETag/304 caching
- API routes from
src/app/api/ - SPA fallback for client-side routing
- Graceful shutdown
- Configurable timeouts and body limits
Pre-rendering
Every route is pre-rendered to static HTML during npm run build. There is no separate export command or export mode — bini-ssg drives pre-rendering as part of the same build.
How It Works
npm run build type-checks (TypeScript projects) and then runs vite build. The bini-ssg plugin drives pre-rendering as part of that same build:
- Static routes (e.g.,
/,/about) are rendered to real server-rendered HTML - Dynamic routes (e.g.,
/blog/:slug) get a shell page with hydration - React 19
renderToPipeableStreamis used for server rendering - StaticRouter from React Router provides the routing context
Your render() Function
The render() function is exported from src/main.tsx:
Build Command
The output is real server-rendered markup, not a client-only shell. The client then hydrates it with hydrateRoot on load.
Output Structure
Hydration and Shell Pages
For dynamic routes, bini-ssg injects a marker script:
Your client entry checks this flag:
Deployment
bini-deploy is bundled into every scaffold and exposed as npm run deploy.
Deploy Command
For web, npm run deploy prompts for a hosting target and generates the appropriate configuration:
| Platform | Runtime | File Generated |
|---|---|---|
| Node.js | Node.js | — (bini-server reads src/app/api/ directly) |
| Netlify | Edge Functions (Deno) | netlify/edge-functions/api.ts + netlify.toml |
| Vercel | Edge Runtime | api/index.ts + vercel.json |
| Cloudflare | Workers | worker.ts + wrangler.toml |
| Deno | Deno | server/index.ts |
Deployment Options
- SPA + API Server: Build with
npm run build, deploy withnpm start(requires Node.js) - Pre-rendered Static: Build with
npm run build, deploy thedist/folder to any static hosting - Edge/Serverless: Use
npm run deployto generate platform-specific entry files
Node.js Deployment
For Node.js hosts (Railway, Render, Fly.io, a VPS):
bini-server reads handlers directly from src/app/api/, so deploy the whole project — not just dist/. Use pm2 on a bare VPS.
GitHub Pages / Subpaths
Set base: '/my-repo/' in vite.config.ts, then npm run build for a fully pre-rendered, subpath-aware dist/.