Litoho is an experimental full-stack framework built around Lit, file-based routing, SSR, and a small package-first architecture.
This README reflects the 0.1.4 milestone: the first usable monorepo snapshot with a working CLI, page routing, server rendering, client-only pages, typed API routes, playground apps, and CLI-first examples.
Litoho is aiming for a simple mental model:
- use Lit for UI
- use folder-based routing for pages and APIs
- use
"use client"and"use server"directives to describe page mode - use one Node server for SSR pages, APIs, and Vite in development
- keep the framework split into focused packages instead of one large runtime
- Lit-based full-stack app model
- File-based page routing from
app/pages - File-based API routing from
app/api - Nested layouts with
_layout.ts - Special pages with
_not-found.tsand_error.ts - SSR page rendering through
@litoho/server - Client-only page mode through top-level
"use client" - Server-intent page mode through top-level
"use server" - Typed query parsing for API routes
public/asset serving for files likelogo.png,robots.txt, andsitemap.xml- Route manifest generation
- CLI scaffolding for pages, APIs, layouts, and resources
- A lightweight reactive core with
signal(),memo(),watch(),batch(), andstore()
packages/
app/ App contracts, manifest loading, client boot
cli/ litoho CLI
core/ Reactive primitives and shared frontend runtime helpers
router/ Route matching and resolution
ui/ Lit UI primitives
server/ SSR server runtime and Node app integration
testing/ Framework test baseline
playgrounds/
demo-app/
demo-hydration/
demo-state/
demo-middleware/
examples/
basic-routing/
state-patterns/
crud-resource/
middleware-lab/
browser-app/
ui-showcase/
planning/
PLANNING.mdThe examples/ folder is a CLI-first showcase for the current Litoho feature set.
examples/basic-routingNested routes, route params, layouts, SSR pages,_not-found, and_errorexamples/state-patterns"use client"pages,signal()/memo()state, and typed query APIsexamples/crud-resourceResource scaffolding, collection/detail pages, typed API query parsing, and SSR dashboard pagesexamples/middleware-labMiddleware stacks, auth/security helpers, request inspection, error handling, and protected APIsexamples/browser-appBrowser-oriented middleware preset, docs-style nested layouts, and client interactionsexamples/ui-showcaseLive showcase for@litoho/ui, including buttons, inputs, dialog, tabs, dropdown-menu, toast, and select
See examples/README.md for the CLI commands used to scaffold them.
@litoho/coreReactive state primitives and shared frontend building blocks.@litoho/appPage/layout module contracts, manifest loading, hydration helpers, and browser boot.@litoho/routerRoute matching utilities for static and dynamic segments.@litoho/uiLit-first UI primitives like buttons, badges, cards, inputs, dialog, tabs, dropdown-menu, toast, and select. Supports selective imports like@litoho/ui/badge, preset-based CLI registration likelitoho ui add form, discovery vialitoho ui list/litoho ui info dialog, local vendor copies withlitoho ui add overlay --copy, and maintenance flows vialitoho ui diff/litoho ui upgrade, including metadata-aware statuses such asoutdatedandmodified.@litoho/serverHono-based server runtime, SSR document rendering, typed API helpers, and Node integration.litohoProject scaffolding, route manifest generation, dev/build/start commands, and doctor checks.@litoho/testingTest coverage for manifests, router behavior, SSR, and state primitives.
Litoho uses folder-based pages.
Allowed files in app/pages:
_index.ts_layout.ts_not-found.ts_error.ts
Examples:
app/pages/_index.ts
app/pages/docs/_layout.ts
app/pages/docs/getting-started/_index.ts
app/pages/products/[id]/_index.tsPage mode is directive-based:
"use client";Use "use client"; for interactive pages that should mount on the browser without SSR page HTML.
"use server";Use "use server"; when you want to mark a page as server-rendered explicitly. If no directive is present, the route behaves as a server page by default.
API routes live in app/api.
Examples:
app/api/health.ts
app/api/products.ts
app/api/products/[id].ts
app/api/_middleware.tsYou can define typed query parsing with defineApiRoute() from @litoho/server.
- Install dependencies:
pnpm install- Build the framework packages:
pnpm build- Run tests:
pnpm --filter @litoho/testing test- Start a playground app:
cd playgrounds/demo-state
pnpm devThe default local URL is http://localhost:3000.
From the repo root:
npx litoho new my-app
cd my-app
npm install
npm run devGenerated apps include:
app/pagesapp/apipublicsrc/main.tsserver.tsvite.config.ts
Files inside public/ are served directly by the Node app, so URLs like /logo.png, /robots.txt, and /sitemap.xml work without custom routing.
New apps also include public/favicon.svg and the root layout links it with document.links, so changing the browser icon is usually just replacing that file. If you prefer an ICO file, place public/favicon.ico and point the icon link to /favicon.ico.
Release helpers are available from the repo root:
pnpm run release:preflight
pnpm run identity:preview
pnpm run release:pack
pnpm run release:publishThe full release guide is in docs/PUBLISHING.md. The MVP release gate is tracked in docs/MVP.md.
Main commands available in 0.1.4:
litoho new <name>
litoho dev [--hmr-port <port>] [--hmr-host <host>] [--hmr-protocol <ws|wss>] [--root <dir>]
litoho build [--root <dir>]
litoho start [--root <dir>]
litoho doctor [--root <dir>]
litoho generate routes [--root <dir>]Generate helpers:
litoho g p docs/getting-started
litoho g p products --params id
litoho g a users --params id
litoho g a products --params id --query q:number,draft:boolean,tag:strings
litoho g l docs
litoho g r products"use client";
import { html } from "lit";
import type { LitoPageModule } from "@litoho/app";
import { memo, signal, watch } from "@litoho/core";
const count = signal(0);
const doubled = memo(() => count.value * 2);
watch(() => {
console.log("count:", count.value, "doubled:", doubled.value);
}, [count, doubled]);
const page: LitoPageModule = {
document: {
title: "Counter"
},
render: () => html`
<main>
<h1>${count.value}</h1>
<p>Doubled: ${doubled.value}</p>
<button @click=${() => (count.value += 1)}>Increment</button>
</main>
`
};
export default page;import { defineApiRoute } from "@litoho/server";
export default defineApiRoute({
query: {
q: "number"
},
get({ params, queryData }) {
return Response.json({
ok: true,
params,
query: queryData
});
}
});0.1.4 is still an early framework snapshot. The core developer flow works, but the project is still evolving and some conventions may tighten as Litoho moves toward a more stable release.
Things that are already solid enough to explore:
- building apps with Lit pages
- mixing SSR and client-only pages
- generating routes and scaffolds with the CLI
- using typed APIs and nested layouts
- experimenting with the Litoho state primitives
- The repo uses
pnpmworkspaces. - Root build uses TypeScript project references.
- Playgrounds are the best place to validate framework behavior before changing public contracts.
litoho doctorhelps catch invalid page file conventions.
The working roadmap lives in planning/PLANNING.md.
MIT License. See LICENSE.