single-file · rewrite-free

One PHP file.
The whole site.

Sifpress folds a PHP JSON API, a full React admin app, its styles and the SPA HTML into one sifpress.php artifact — migrations included. Drop it into any directory of any PHP host: no .htaccess, no try_files, no #/ hash routing, no Node.js on the server.

Requires PHP 8.3+pdo_sqlite + FTS5mbstringfileinfo

sifpress.php one artifact
  • PHP core env · bootstrap · db · router
  • JSON API auth, RBAC, pages, assets, SEO
  • Migrations migrations/*.sql embedded, run on demand
  • SPA HTML admin UI shell + meta injection
  • JS React 19 bundle, inlined
  • CSS Tailwind build, inlined
?p=sifpress/api ?p=sifpress/admin ?p=sifpress/migration one HTTP request per page load
1 production file
0 rewrite rules
1 req per page load, JS+CSS inlined
8.3+ PHP required to run

why sifpress

Everything ships inside the artifact

One build assembles the API, the app, the styles, the HTML and the schema into a single PHP file that behaves identically at any install path.

Single-file artifact

php build.php type-checks, bundles the React app, inlines every script and stylesheet, embeds the SQL migrations and writes one artifact: dist/sifpress.php. Idempotent and repeatable.

Rewrite-free routing

Routes are plain query parameters — ?p=sifpress/admin, ?p=sifpress/api&action=auth.login — that every web server already understands. URLs stay real, shareable and crawler-friendly.

Just works anywhere

The same file works at /, /myapp/ or four levels deep, with no rebuild and no server config. Production never needs Node.js — only PHP.

SQLite + FTS5

WAL-mode database with a pending-migration detector, per-migration BEGIN IMMEDIATE transactions and full-text search. The schema lives in migrations/*.sql.

Admin with RBAC

DB-backed sessions with HttpOnly cookies, roles and permissions, page-level grants, and a Milkdown WYSIWYG markdown editor in a TanStack Router admin UI.

Themes as bundles

Public-facing sifront SPAs are built into two-file .sifront ZIPs, uploaded from the admin, stored in the DB and served through the artifact’s own shell.

Self-updating

Point the app at a latest.json manifest and upgrades become one click: download the release artifact, verify its md5, swap it in.

CLI & backups

setup, migrate, backup, config, cron — WAL-safe VACUUM INTO snapshots, tarred and pruned on a schedule.

routing model

The ?p= protocol

One query parameter does all of the dispatching. Nothing to configure on the server, nothing lost to hash routing, back/forward works out of the box.

The protocol

  • p=sifpress/api server-side JSON API (action required)
  • p=sifpress/admin admin SPA (React)
  • anything else the active sifront (viewer routes like ?p=/article/x)

No .htaccess, no #/ hash routing, no history-mode server rewrites — the SPA maps browser URLs back to internal routes with TanStack Router’s rewrite layer and moves with history.pushState.

Example URLs

  • /sifpress.php active sifront
  • /sifpress.php?p=/article/hello-world sifront route
  • /sifpress.php?p=sifpress/admin admin UI
  • /sifpress.php?p=sifpress/admin/articles admin route
  • /sifpress.php?p=sifpress/api&action=auth.login JSON API

Because p is a real parameter, every link is copyable, bookmarkable and indexable — no server ever has to be told how to serve it.

how it works

One request, one fork

The browser asks for a single PHP file; the artifact decides between JSON and the inlined SPA on its own.

Browser one request — JS + CSS inlined
sifpress.php one file in your document root
?p=sifpress/api action=…
PHP JSON API auth · pages · assets · migration
anything else ?p=sifpress/admin · ?p=/…
React SPA admin UI or active sifront

The production server needs only one PHP file — no rewrite rules, no separate assets, no Node.js.

front system

Meet the sifronts

The public face of a Sifpress site is a sifront — a self-contained React theme built into a two-file .sifront archive, stored in the database and served by the artifact itself. Swap it without touching the PHP.

sifronts/<name> React theme · pnpm package
php buildfront.php dev or release build
<name>.sifront meta.json + bundle.js
upload & activate admin UI · CLI
?p=/… served by the artifact

Inside a .sifront

  • meta.json name, title, version + the theme contract (require_keys)
  • bundle.js the whole app — styles injected, fonts inlined as data URIs
  • exactly two entries — the admin unpacks the ZIP in the browser; the backend stores bundle/meta/version and never opens a ZIP

sifpress1 — the default theme

  • Home, /article/$slug and a 404 route (TanStack Router)
  • Glass surfaces, light / dark / system themes
  • Ambient & matrix canvas backgrounds (KV-swappable)
  • Sidebar with avatar frame, pinned posts, tags, search
  • KaTeX math, syntax highlighting, reading progress + TOC

Customize without code

The theme's identity lives in namespaced KV keys — declared with defaults in meta.json, overridden from Admin → KVs, guest-readable for visitors.

  • sifpress1.sidebar.welcome
  • sifpress1.sidebar.about
  • sifpress1.sidebar.avatar
  • sifpress1.sidebar.pinned
  • sifpress1.sidebar.links
  • sifpress1.footer.text
  • sifpress1.background.kind
  • sifpress1.article.bottom

agent-assisted theming

Restyle it with skills

Deeper changes — layout, motion, a whole new look — are a coding task, and the repo hands your AI agent the design rules as skills: knowledge files it loads before touching the theme, so restyles stay faithful to the design system.

Bundled skills — .agents/skills/

  • apple-design fluid motion, springs, materials, reduced-motion rules
  • my-glass-webui-design glass-control / apple-panel / ambient-bg — why each rule exists

Pi and opencode both read .agents/skills/ automatically. Ask for the restyle, review the diff, build and upload.

restyle & ship
# restyle with live reload
cd siffronts/sifpress1 && pnpm dev

php buildfront.php                           # -> dist/sifpress1.sifront
php dist/index.php inject_sifront sifpress1  # dev: push into the DB
# ship: admin UI -> Sifronts -> Update, or
# php sifpress.php update_sifront dist/sifpress1.sifront --activate

quick start

From download to admin UI in four steps

Grab sifpress.php from the releases page, run two CLI commands, sign in — the server only needs PHP. Building from source is for local development (below).

01 Download & place
# grab the newest sifpress.php from the releases page
curl -LO https://github.com/liyu1981/sifpress/releases/latest/download/sifpress.php

mkdir -p /var/www/html
cp sifpress.php /var/www/html/
02 Create the config
# writes sifpress_config.php + creates ./var/sifpress (DB folder)
cd /var/www/html
php sifpress.php setup

# keep the DB elsewhere -- at creation, or adjust later:
php sifpress.php setup --db-dir=/srv/sifpress-db --force
php sifpress.php config --set SIFPRESS_DB_DIR=/srv/sifpress-db
03 Migrate
# applies the embedded migrations, seeds the first admin
cd /var/www/html
php sifpress.php migrate
04 Open the admin UI
# sign in at
https://example.com/sifpress.php?p=sifpress/admin

# first login: admin / admin -- password change is forced

local development

Building from source instead

Hacking on Sifpress itself needs Node.js, pnpm and the PHP CLI. The dev server rebuilds on save, and a release build produces the same sifpress.php the releases page ships.

clone · install · serve
git clone https://github.com/liyu1981/sifpress.git
cd sifpress
pnpm install

php build.php          # dev artifact  -> dist/index.php
./dev.sh               # http://localhost:5000, rebuilds on change

php build.php release  # release       -> dist/sifpress.php
Server PHP 8.3+ · pdo_sqlite (FTS5) · mbstring · fileinfo
Optional curl, zlib — features degrade gracefully
Build only Node.js + pnpm — never on production

inside the repo

Fragments in, one artifact out

The source stays readable as small PHP fragments and typed React workspaces; the build does the packing.

PHP fragments — src/

  • env.phpversion & extension checks
  • bootstrap.phpconstants + core helpers
  • db.phpSQLite open, pragmas, migrations
  • auth.phpsessions, RBAC, page grants
  • api.phpJSON API handler
  • spa.phpSPA serving + meta injection
  • backup.phpsnapshot, tar, prune, cron
  • router.phpassembled last — dispatches

Frontend — pnpm workspace

  • admin_ui/React 19 + TanStack Router/Query
  • ui_sdk/typed APIs, auth, rewrite layer
  • sifronts/public themes → .sifront ZIPs
  • Tailwind CSS v4 + shadcn/ui
  • Milkdown WYSIWYG markdown editor
  • TypeScript strict, Biome formatted
  • light / dark / system theming
  • en / zh i18n, route-aware titles

In the box

  • Articles with tags, search & front matter
  • Assets with browser-generated thumbnails
  • SEO settings, sitemap & robots
  • Analytics head tags (gtag / Plausible)
  • Roles: admin / editor / viewer
  • Self-update from a release manifest
  • CLI: setup · migrate · backup · config
  • GitHub Actions release pipeline

Ship a whole site as one file

Read the source, grab the latest release artifact, or clone it and make it your own — the build is a single command.