npx create-plainweb
import { zfd } from "zod-form-data";
import { type Handler } from "plainweb";
import { database } from "app/config/database";
import { contacts } from "app/schema";
import { createContact } from "app/services/contacts";
import { Form } from "app/components/form";
export const POST: Handler = async ({ req }) => {
const parsed = zfd
.formData({ email: zfd.text().refine((e) => e.includes("@")) })
.safeParse(req.body);
if (!parsed.success) {
return <Form email={parsed.data.email} error="Invalid email" />;
}
await createContact(database, parsed.data.email);
return <div>Thanks for subscribing!</div>;
}
export const GET: Handler = async () => {
return <Form />;
}
Every design decision prioritizes your ability to ship fast.
Compose and render JSX on the server. Fully type-safe.
Sprinkle HTMX and Alpine.js on top. No frontend build process.
Stream responses using <Suspense/> without client-side JavaScript.
The file system determines the URL paths. No more naming routes twice.
A single process to deploy and manage.
Type-safe SQL query builder that gets out of your way.
Run persistent tasks in the background, concurrently or in-parallel.
Test services, components, routes, emails and tasks with ease.
Receive ~2 updates a month, no spam, unsubscribe anytime.