Zero to a working route in under five minutes.
Create a Project
npm create kosmo demoA short interactive setup walks you through the choices that matter: the frontend framework and the backend you want to build with. Everything else starts with sensible defaults.
Pick whatever feels familiar - nothing here is set in stone, and any folder you add later can make entirely different choices.
It is also possible to bootstrap in the current folder, just use . as name:
npm create kosmo .After bootstrap, cd into freshly created project (unless the project was bootstrapped in the current folder):
cd ./demoInstall Dependencies
npm installWhat you have at this point is deliberately minimal: a package.json and your source folder's config with a few empty stub files. Follow next steps to turn this skeleton into a working app.
Start the dev server
The dev server completes the setup: it seeds the remaining project files and wires everything together. From then on it watches your routes and recomputes as you work:
npm run devYour app is now running at http://localhost:4556.
Create a route
Create the file api/users/[id]/index.ts - KosmoJS detects it and seeds starter code automatically.
Replace the seeded content with something real:
// Hono: api/users/[id]/index.ts
import { defineRoute } from "_/api";
export default defineRoute<"users/[id]">(({ GET }) => [
GET(async (ctx) => {
const { id } = ctx.req.param();
return ctx.json({ id, name: "Jane Smith", email: "jane@example.com" });
}),
]);Visit http://localhost:4556/api/users/123. You should see JSON.
Create a page
With the dev server still running, create pages/users/[id]/index.tsx (or .vue / .svelte / .mdx). KosmoJS seeds a placeholder component - replace it with a page that fetches from your API route. React, SolidJS, and Vue fetch in the component here; Svelte and MDX read through a loader export instead (resolved before render), so they need no loading state:
// React: pages/users/[id]/index.tsx
import { useState, useEffect } from "react";
import { useParams } from "react-router";
import fetchClients from "_/fetch";
const { GET } = fetchClients["users/[id]"];
export default function UserPage() {
const { id } = useParams();
const [user, setUser] = useState(null);
useEffect(() => { GET([id]).then(setUser); }, [id]);
return user
? <div><h1>{user.name}</h1><p>{user.email}</p></div>
: <div>Loading...</div>;
}Visit http://localhost:4556/users/123. Your page renders with data from the API.
The fetch client is fully typed - user.name and user.email autocomplete in your editor, and invalid parameters are caught before the request leaves the browser.
What just happened
Your folder structure became your routes:
api/users/[id]/index.ts -> /api/users/:id
pages/users/[id]/index.tsx -> /users/:id[id] is a required parameter. {id} makes it optional. {...path} matches any depth. The parallel structure between api/ and pages/ is intentional - API endpoints and their corresponding pages are always easy to find.
The fetch client is derived automatically from your API route definition. Change the API types, and the client updates with them - no manual sync.
That's the foundation. From here:
- Tutorial - validation, middleware, fetch clients, pages, SSR
- Project Structure - what lives where, and what
@/~/_/mean - Configuration - every
kosmo.config.tsoption - CLI - every command and flag, interactive and non-interactive
- Routing - parameters, mixed segments, power syntax
- Framework Support - what each framework does and doesn't support
- Features - everything KosmoJS provides, at a glance