v0.1.0 · Cloudflare-ready

Build with Preact.
Deploy everywhere.

pracht is a Preact framework with explicit routing, per-route render modes, and thin adapters for Cloudflare, Vercel, and Node.js.

src/routes.ts

routes.ts
import { defineApp, group, route, timeRevalidate } from "@pracht/core";

export const app = defineApp({
  shells: {
    public: "./shells/public.tsx",
    app:    "./shells/app.tsx",
  },
  middleware: { auth: "./middleware/auth.ts" },
  routes: [
    group({ shell: "public" }, [
      route("/",        "./routes/home.tsx",    { render: "ssg" }),
      route("/pricing", "./routes/pricing.tsx", {
        render: "isg", revalidate: timeRevalidate(3600),
      }),
    ]),
    group({ shell: "app", middleware: ["auth"] }, [
      route("/dashboard", "./routes/dashboard.tsx", { render: "ssr" }),
      route("/settings",  "./routes/settings.tsx",  { render: "spa" }),
    ]),
  ],
});

Why pracht

Everything you need, nothing you don't

A focused framework that gives you the primitives to build fast, maintainable Preact applications — without magic.

🗺

Explicit Route Manifest

Define routes in code, not filesystem conventions. Assign shells, middleware, and render modes per group or route — auditable and type-checked.

Per-Route Render Modes

SSG, SSR, ISG, and SPA — pick the right strategy for each page. Mix static marketing pages with dynamic dashboards in a single app.

🔷

Preact-First

Built on Preact for a tiny runtime. Full hooks support, JSX, and the complete Preact ecosystem. Fast by default.

🌐

Edge-Ready Adapters

Deploy to Cloudflare Workers, Vercel Edge Functions, or Node.js. Thin adapter layers with no vendor lock-in.

⚙️

Vite-Native

Full Vite pipeline for client and SSR builds. Bring your own plugins — Tailwind, MDX, image tools all work without special integration.

🔒

End-to-End Types

Loader return types flow automatically to components. No manual typing, no casting — just inference from server to client.

Rendering

One app, four rendering strategies

Configure render mode per route. Mix and match in the same app without extra wiring or separate deployments.

SSG

Static Generation

HTML at build time. Serve from CDN with zero server cost. Perfect for marketing pages, blogs, and docs.

SSR

Server Rendering

Fresh HTML on every request. Full access to cookies, headers, and auth state. Ideal for personalized pages.

ISG

Incremental Static

Static HTML that regenerates on a schedule. Serve instantly, update in the background. Great for catalogs and pricing.

SPA

Client-Only

No SSR — render entirely in the browser. Best for auth-gated dashboards where SEO doesn't matter.

Data Loading

Loaders stay on the server

Loader functions run server-side only — during the build for SSG, on each request for SSR. Secrets, database connections, and API keys never reach the client bundle.

After hydration, client navigation fetches only the loader data as JSON — the component tree updates without a full page reload.

Data loading guide →
routes/dashboard.tsx
import type { LoaderArgs, RouteComponentProps } from "@pracht/core";

export async function loader({ request, context }: LoaderArgs) {
  const user = await getUser(request);
  return { user, projects: await context.db.projects.all() };
}

export function head({ data }) {
  return { title: `${data.user.name} — Dashboard` };
}

export function Component({ data }: RouteComponentProps<typeof loader>) {
  // data is typed: { user: User; projects: Project[] }
  return <h1>Welcome, {data.user.name}</h1>;
}

Get Started

Ready to build?

Install pracht and the Vite plugin, wire up your adapter, and ship to Cloudflare Workers or Vercel in minutes.

$npm create pracht@latest my-app