Skip to content

Everything KosmoJS provides, at a glance.

Multiple Source Folders

Organize distinct concerns - public site, customer app, admin dashboard - as independent source folders within a single Vite project. Each gets its own set of frameworks, base URL, development workflow and build pipeline.

Read more ›

Directory-Based Routing

Your folder structure defines your routes - for both API and client pages.

api/users/[id]/index.ts    ➜ /api/users/:id
pages/users/[id]/index.tsx ➜ /users/:id

Dynamic parameters: [id] required · {id} optional · {...path} splat. No separate routing config to maintain - restructure files and routes update automatically.

Mixed segments are also supported for backend routes (and some frontend integrations):

products/[category].html/index.ts   ➜ products/electronics.html
files/[name].[ext]/index.ts         ➜ files/document.pdf, /files/logo.png

Read more ›

Power Syntax for Params

When standard named parameters aren't enough, use raw path-to-regexp v8 patterns directly in your folder names:

book{-:id}-info           ➜ /book-info or /book-123-info
locale{-:lang{-:country}} ➜ /locale, /locale-en, /locale-en-US
api/{v:version}/users     ➜ /api/users or /api/v2/users

Any param name containing non-alphanumeric characters is treated as a raw pattern - giving you precise control over URL structure without sacrificing the directory-based routing model.

Read more ›

End-to-End Type Safety

Write TypeScript types once - KosmoJS generates runtime validators automatically. The same definition drives compile-time checking, runtime validation, type-safe fetch clients, and OpenAPI specs.

ts
export default defineRoute(({ POST }) => [
  POST<{
    json: {
      email: VRefine<string, { format: "email" }>;
      age: VRefine<number, { minimum: 18 }>;
    },
    response: [200, "json", User],
  }>(async (ctx) => {
    const { email, age } = ctx.validated.json;
    // payload validated before reaching here
    // response validated before sending
  }),
]);

Read more ›

Generated Fetch Clients + OpenAPI

For every API route, KosmoJS generates a fully-typed fetch client and an OpenAPI 3.1 spec - both derived from the same type definitions.

ts
import fetchClients from "_/fetch";

const user = await fetchClients["users/[id]"].GET([123]);
// fully typed, validates payload client-side before the request is sent

Fetch Clients › · OpenAPI ➜

Isomorphic Fetch

The same fetch client runs on the server and the client.

When a call fires during SSR, the request goes to the API route in-process, skipping the network while still running the full validation and handler chain.

The result is serialized into the page and reused on hydration, so the request is not repeated on the client.

ts
// runs on the server during SSR, on the client during navigation -
// same call, same types, no network hop on the server
export const loader = ({ params }) => fetchClients["users/[id]"].GET([params.id]);

Read more ›

Built-in Streaming SSR

Render pages as a stream instead of a single string - the shell flushes to the browser early, improving Time-to-First-Byte for large pages or long data-fetching chains.

Each framework streams through its own native renderer, returning a web-standard ReadableStream that works the same on Node, Bun, and Deno; KosmoJS adds no rendering layer of its own.

Streaming is opt-in - every route defaults to string rendering. Set renderMode: "stream" to stream all routes, or map glob patterns for per-route selection:

kosmo.config.ts
ts
ssrGenerator({
  renderMode: {
    "docs/**": "stream",
  },
})

Available for React, SolidJS, and Vue; MDX renders to a string.

Read more ›

Composable Middleware (Slots)

Global middleware defined in api/use.ts can be overridden per-route or per-subtree using named slots - without removing or bypassing parent middleware entirely.

ts
// global default in api/use.ts
use(async (ctx, next) => { /* ... */ }, { slot: "logger" })

// override for a specific route
use(async (ctx, next) => { /* custom logger */ }, { slot: "logger" })

Slots give you surgical control over middleware composition: replace only what needs replacing, inherit everything else. Custom slot names are supported by extending the UseSlots interface.

Read more ›

Cascading Middleware

Place a use.ts file in any folder and its middleware automatically wraps all routes in that folder and its subfolders - no imports or wiring needed.

api/admin/use.ts       → wraps all routes under /api/admin
api/admin/users/use.ts → wraps only routes under /api/admin/users

Parent middleware always runs before child middleware. Combine with slots to override globals for entire route subtrees.

Read more ›

Nested Layouts

Frontend pages support nested layout components that wrap child routes - compose shared UI (nav, sidebars, auth shells) at any level of the route hierarchy.

pages/
  app/
    layout.tsx        ← wraps all /app/* pages
    dashboard/
      layout.tsx      ← wraps all /app/dashboard/* pages
      index.tsx
      settings/
        index.tsx

Read more ›

Multiple Frameworks

  • Backend: Koa or Hono - same routing architecture, same type safety.
  • Frontend: React, Vue, SolidJS, Svelte, MDX - same routing/layout/SSR.

Different source folders can use different framework combinations. When you add a source folder, KosmoJS generates a ready-to-go setup for your chosen stack - router config, entry points, TypeScript settings, and all the wiring between them. Switch frameworks per folder without learning a new set of conventions.

Read more ›

Built on Proven Tools

No proprietary runtime, no custom bundler, no framework lock-in. Every layer is a tool you can use, debug, and replace independently.


Released under the MIT License.