← cd ../work
Designer and lead engineer · 2026

PammyPanel

A self-hosted control panel that lets a non-technical owner run her websites, forms, media and databases from a phone.

TypeScriptFastifyReactPostgreSQLMariaDBPodmansystemdnginx
Studio canvas showing four connected tables of a recipe database
Studio: tables and their connections, drawn and dragged

$ cat architecture.svgAt a glance

BrowsernginxTLS, rate limitsPanel Postgresrootless containerPanelFastify + Reactunprivileged userGatevisitor sign-in, forms,data APIHelpersone job eachsitefs · site filesthumbs · no networkpammydb · databasesmail · Resend onlyroutes · nginx -tapps · WordPressStatic site filesOwner's databasesPostgresand MariaDBpanel.*owner's sitesadmin socketUnix sockets

$ cat the-problem.mdThe problem

Pamela built websites in the FTP days. She knows HTML and CSS, some JavaScript and very little SQL. She wanted interactive sites (a blog, a guest book, an RSVP list, a recipe book) without handing a stranger root on her server or learning a hosting dashboard. PammyPanel gives her those features in plain words, with guides written for her.

It now runs two live sites: pammy.org for one owner, and lesfleursdelanuit.com, a five-person setup that also hosts other apps.

$ cat architecture.mdArchitecture

$ cat security-boundaries.mdSecurity boundaries

The web app runs unprivileged. File, routing, database and mail work goes to small helper services over Unix sockets, started by systemd socket activation, each with one narrow job. Hosted apps and their databases run in rootless Podman containers under Quadlet. Domains, hosts and routes are rendered into nginx config and checked with nginx -t before anything goes live.

$ cat testing-and-deployment.mdTesting and deployment

About 100,000 lines of TypeScript, with 71 unit test files and 65 Playwright end-to-end specs. Every release goes through a build that runs the type checks and both test suites, then a verify script on the live server checks services, nginx, permissions and pages before the release counts as installed. The latest full run: 2,956 checks passed, 0 failed.

$ cat whats-next.mdWhat’s next

Shared contracts between modules, a Supabase-like backend for authentication and realtime data across Postgres and MariaDB, and narrower helper permissions.

$ ls screenshots/On screen

From the test and demo servers, so the people and data shown are made up or public samples.

Dashboard with unread responses, waiting requests and form counts
Dashboard: what needs attention today
The recipes table shown as an app, with cooks, servings and tags
App view: a database table as a friendly list
Form settings with approval and publishing switches in plain words
Forms: switches in plain words
File Explorer with a folder tree and a grid of files
File Explorer