Routes as selectors
Describe endpoints with [path="/users"]:GET and ship without boilerplate.
Write routes, SQL, and responses in CSS syntax. Compile to Express with SQLite built in and run in seconds.
pnpm installpnpm build@server {
port: env(PORT, 3000);
database: env(DATABASE, ./app.db);
}
[path="/users"]:GET {
@return json(sql("SELECT * FROM users"));
}
[path="/users"]:POST {
--name: body(name);
--email: body(email);
@return json(sql("INSERT INTO users (name, email) VALUES (?, ?)", var(--name), var(--email)));
}CSS selectors map to Express routes with SQL baked into the same block.
[
{ "id": 1, "name": "Ava" },
{ "id": 2, "name": "Rio" }
]Keep routes, data, and control flow in one readable stylesheet and compile it into a production-ready Express server.
Describe endpoints with [path="/users"]:GET and ship without boilerplate.
Use sql() with SQLite to query and mutate data right where it is needed.
Pull params, query, body, and headers with explicit helper functions.
Use if() to branch responses and return JSON with dynamic status codes.
Set ports and database locations inside @server and keep setup close.
Write logic the same way you style: with selectors and clear blocks.
Design routes, compile, run. Keep the stack small and fast to iterate.
Define @server, @database, and route blocks with selectors.
butcss parses the file and compiles an Express app.
Point the CLI at your CSS and serve instantly.
Each block handles routing, data, and responses in one place.
@database {
CREATE TABLE users (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT,
email TEXT
);
}
[path="/users/:id"]:GET {
--id: param(:id);
--user: sql("SELECT * FROM users WHERE id = ?", var(--id));
@return json(if(--user: var(--user); else: { "error": "Not found" }));
}Install, build, and point the CLI at a CSS file.
pnpm install
pnpm buildnode dist/cli.js ./examples/crud.csscss-server <file>butcss keeps backend logic readable, composable, and fast to iterate.