Multiple Source Folders
Organize distinct concerns - public site, customer app, admin dashboard - all connected in one Vite project.
Structured Vite Template. Build type-safe full-stack apps. Multiple source folders. Directory-based nested routing. Runtime end-to-end validation. Generated fetch clients, OpenAPI spec. Multiple frameworks (SolidJS, React, Vue).
id to be a number import { defineRoute } from "_/admin/api/users/[id]";
export default defineRoute<[
number // validate id as number
]>(({ GET }) => [
GET((ctx) => {
// ctx.typedParams.id is typed and validated at runtime
const { id } = ctx.typedParams
})
]);import { defineRoute } from "_/admin/api/users/[id]";
export default defineRoute<[
// validate id as positive integer
TRefine<number, { minimum: 1, multipleOf: 1 }>
]>(({ GET }) => [
GET((ctx) => {
// ctx.typedParams.id is typed and validated at runtime
const { id } = ctx.typedParams
})
]);id to be a positive integer.TRefine to specify JSON Schema constraints. TRefine can be used to specify JSON Schema constraints. import { defineRoute } from "_/admin/api/users";
export default defineRoute(({ POST }) => [
POST<{
email: TRefine<string, { format: "email" }>;
password: TRefine<string, { pattern: "^(?=.*[a-zA-Z0-9])$" }>;
name: TRefine<string, { minLength: 5; maxLength: 50 }>;
dateOfBirth: TRefine<string, { format: "date" }>;
agreeToTerms: boolean;
marketingOptIn?: boolean;
}>((ctx) => {
// ctx.payload is typed and validated at runtime
})
]);import { defineRoute } from "_/front/api/blog/[...page]";
type Page = {
id: TRefine<string, { format: "uuid" }>;
title: TRefine<string, { minLength: 1; maxLength: 255 }>;
content: string;
tags: string[];
status: "draft" | "published" | "scheduled";
}
export default defineRoute(({ GET }) => [
GET<
never, // no payload validation
Page // validate response to be a valid Page
>(async (ctx) => {
// ctx.body should match the schema defined above,
// otherwise validation fails and an error response is returned
})
]);ctx.body should match defined schema for validation to pass. never for the first argument. slot option to allow routes to override this middleware later. Use the on option to run middleware only for specific HTTP methods. import { use } from "@kosmojs/api";
import bodyparser from "@kosmojs/api/bodyparser";
export default [
use(
bodyparser.json(),
{
slot: "bodyparser",
on: ["POST", "PUT", "PATCH"],
},
),
];import bodyparser from "@kosmojs/api/bodyparser";
import { defineRoute } from "_/admin/api/files/upload";
export default defineRoute(({ use, POST }) => [
use(
bodyparser.form(), // use form bodyparser
{
slot: "bodyparser",
on: ["POST"],
},
),
POST((ctx) => {
// ctx.payload now contains parsed form data
})
]);slot option in routes to override global middleware with the same slot name. Eg., for file upload routes, use a form body parser instead of the default JSON parser. KosmoJS. KosmoJS is a structured Vite template that keeps your full-stack concerns aligned.
Rather than inventing yet another framework, KosmoJS integrates proven tools - TypeScript, Vite, Koa, and your frontend framework - into a clear organizational pattern. Separation of concerns isn't something you have to remember - it's built into the structure.
No proprietary abstractions. No new paradigms to learn. Just thoughtful structure around tools you already know.
π Learn more
Multiple source folders for distinct concerns - each with its own API and pages directories, eg.:
πΉ Public marketing site at /
πΉ Customer application at /app
πΉ Admin dashboard at /admin
All in one monorepo-like project, each with independent routing and configuration, yet sharing types and validation logic.
API / Pages separation keeps server and client code from mixing. Your directory structure enforces boundaries that code review can't.
π Getting started Β· Directory-based routing
At its core, KosmoJS structures full-stack Vite development around a Koa application.
πΉ Vite handles your frontend builds and organizational structure.
πΉ Koa powers your API runtime with runtype validation and middleware composition.
πΉ KosmoJS is the structured template that brings them together.
KosmoJS converts your types into runtime validation routines, ensuring type safety beyond compile time - no duplication, no drift.
Define parameter types, payload structures, and response shapes once. KosmoJS generates:
Everything stays aligned because everything derives from the same source of truth.
π Type safety overview Β· Validation Β· Payload validation
Every API route gets a fully-typed fetch client with built-in validation. Your frontend knows exactly what parameters each endpoint expects, what payload structure it accepts, and what response shape it returns.
Invalid data is caught client-side, before network requests. Your API never processes malformed requests.
π Fetch clients intro Β· Getting started Β· Client-side validation
Build APIs directly inside Vite's dev server with hot-reload support.
Slot-based middleware gives you fine-grained control - override global middleware per endpoint, compose request handling precisely, maintain consistent patterns across routes.
Development and production use the same structure - what you build locally is what deploys.
π Dev workflow Β· Middleware patterns
pnpm build produces deployment-ready output:
Deploy to any Node.js environment: traditional servers, containers, serverless platforms, or edge runtimes.
Structure without constraints.
KosmoJS is opinionated about organization but unopinionated about implementation. Clear boundaries between API and pages. Obvious locations for shared types and utilities. Separation of concerns built into the filesystem.
You choose your frontend framework, state management, styling approach, database, and everything else.
The structure scales; your choices remain free.
π About KosmoJS Β· Features