Skip to content

KosmoJS

A Vite template evolved into a full‑stack meta‑framework Multiple source folders. Directory-based routing. Cascading middleware. Nested layouts. End-to-end validation. Fetch clients. OpenAPI spec. Koa, Hono, SolidJS, React, Vue and more.

Params Validation

Rather than learn and maintain separate schema definition languages, you can express validation rules directly in TypeScript.
KosmoJS automatically generates high-performance runtime validators from your types.
Use TRefine to specify JSON Schema constraints.
Details ➜
api/users/[id]/{activity}/index.ts
ts
import { defineRoute } from "_/front/api";

export default defineRoute<
  "users/[id]/{activity}",
  [
    // validate id as number
    number,
    // activity, if given, should be one of
    TRefine<string, "posts" | "comments" | "likes">,
  ]
>(({ GET }) => [
  GET((ctx) => {
    // ctx.validated.params is typed and validated at runtime
    const { id, activity } = ctx.validated.params
  })
]);

Payload Validation

Validation targets provides control over what gets validated.
Body targets: json / form / raw.
Metadata targets: query, headers, cookies.
Use TRefine to specify JSON Schema constraints.
Details ➜
api/users/index.ts
ts
import { defineRoute } from "_/admin/api";

type Payload = {
  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;
}

export default defineRoute<"users">(({ POST }) => [
  POST<{
    json: Payload, 
  }>((ctx) => {
    // ctx.validated.json is typed and validated at runtime
  })
]);

Response Validation

Just as you validate incoming request data, you can validate outgoing response data by providing a tuple with status code, content type and expected schema.
Also an union of tuples can be used to specify multiple variants.
Enabled by default on dev, disabled in production.
Details ➜
api/pages/[id]/index.ts
ts
import { defineRoute } from "_/admin/api";

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<"pages/[id]">(({ GET }) => [
  GET<{
    response: [200, "json", Page], 
  }>(async (ctx) => {
    // response should match defined schema
  })
]);

Composable Middleware

Global middleware added to api/use.ts will run on every route. Routes can use slot option to override global middleware.
Custom slots like logger should be added to api/env.d.ts file.
Details ➜
ts
import { use } from "_/admin/api";

export default [
  use(
    (ctx, next) => {
      // global logger
      return next();
    },
    { slot: "logger", }, 
  ),
];
ts
import { defineRoute } from "_/front/api";

export default defineRoute<"example">(({ use, GET }) => [
  use(
    async (ctx, next) => {
      // custom logger
      return next();
    },
    { slot: "logger", }, 
  ),

  GET(async (ctx) => {
    // ...
  }),
]);
ts
export declare module "@kosmojs/api" {
  interface UseSlots {
    logger: string; 
  }
}

Cascading Middleware

Create a use.ts file in any folder, and its default exported middleware automatically wraps all routes in that folder and its subfolders - no imports or manual wiring required.
Details ➜
api/users/use.ts
ts
import { use } from "_/front/api";

export default [
  use(async (ctx, next) => {
    // any route inside users/ folder and its subfolders
    // will wire this middleware automatically
    return next();
  })
];

🎯 What is KosmoJS? ​

KosmoJS is a meta-framework that integrates TypeScript, Vite, Koa/Hono, 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. Just thoughtful structure around tools you already know.

πŸ“˜ Learn more


πŸ’‘ Why Source Folders? ​

Applications often include multiple distinct concerns - each with different routing, auth, and config:

πŸ”Ή Public marketing site at /
πŸ”Ή Customer application at /app
πŸ”Ή Admin dashboard at /admin

Each lives in its own source folder with independent api/ and pages/ directories, sharing types and validation logic across a single project. The directory structure enforces boundaries that code review can't.

πŸ“˜ Getting started Β· Directory-based routing


πŸ›‘οΈ One Source of Truth ​

KosmoJS converts your TypeScript types into runtime validators, typed fetch clients, client-side validation, and OpenAPI schemas - all from the same definitions. No duplication, no drift.

πŸ“˜ Type safety Β· Validation Β· Fetch clients


βš™οΈ API Development ​

Build APIs inside Vite's dev server with hot-reload. Slot-based middleware gives you fine-grained control - override globals per-route or per-subtree, compose request handling precisely. What you build locally is what deploys.

πŸ“˜ Dev workflow Β· Middleware


πŸš€ Production Ready ​

pnpm build produces a bundled API server, optimized frontend assets, and an optional SSR bundle. Deploy to Node.js, Deno, Bun, containers, serverless, or edge.

πŸ“˜ Production build


🧠 Philosophy ​

Structure without constraints.

Opinionated about organization, unopinionated about implementation. You choose your frontend framework, state management, styling, database - everything else. The structure scales; your choices remain free.

πŸ“˜ About KosmoJS Β· Features


Released under the MIT License.