PostCSS backend framework

butcss turns CSS into servers

Write routes, SQL, and responses in CSS syntax. Compile to Express with SQLite built in and run in seconds.

Installpnpm installpnpm build
Selectors for routesSQLite firstRequest helpersConditional responses
server.css
@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)));
}
Request to response
GET /users

CSS selectors map to Express routes with SQL baked into the same block.

200 OK
[
  { "id": 1, "name": "Ava" },
  { "id": 2, "name": "Rio" }
]
Overview

Backend logic built from CSS primitives.

Keep routes, data, and control flow in one readable stylesheet and compile it into a production-ready Express server.

01

Routes as selectors

Describe endpoints with [path="/users"]:GET and ship without boilerplate.

02

SQL in plain sight

Use sql() with SQLite to query and mutate data right where it is needed.

03

Request data helpers

Pull params, query, body, and headers with explicit helper functions.

04

Conditional responses

Use if() to branch responses and return JSON with dynamic status codes.

05

Server config at top

Set ports and database locations inside @server and keep setup close.

06

CSS-first workflow

Write logic the same way you style: with selectors and clear blocks.

Flow

From stylesheet to server in three moves.

Design routes, compile, run. Keep the stack small and fast to iterate.

1

Write CSS

Define @server, @database, and route blocks with selectors.

2

Compile

butcss parses the file and compiles an Express app.

3

Run

Point the CLI at your CSS and serve instantly.

Example

A CRUD-ready stylesheet, readable at a glance.

Each block handles routing, data, and responses in one place.

crud.css
@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" }));
}

What you get

  • //Routing, queries, and responses live together.
  • //Helpers cover params, query, body, and headers.
  • //if() handles branching without new files or controllers.
  • //SQLite makes local dev and demos quick to spin up.
Examples live in ./examples and run as-is.
Quickstart

Run the demo in minutes.

Install, build, and point the CLI at a CSS file.

Install

pnpm install
pnpm build

Run

node dist/cli.js ./examples/crud.css

CLI usage

css-server <file>
Ready to build

Ship a server without leaving your stylesheet.

butcss keeps backend logic readable, composable, and fast to iterate.