MiniCMS lets you write, edit, schedule and re-skin an entire portfolio site from a single browser tab. No FTP, no opening files in a code editor, no waiting for a build to finish. You sign in, change what you want to change, click Publish, and seconds later the public site reflects it — loading as fast as any hand-coded HTML page, because that is exactly what it serves. The complexity stays out of your way: there is one sidebar, one publish button, and one help panel that answers questions inline as you edit.
A single sidebar groups every editing module — Pages, Blog, Media, Themes, Fonts, Settings — with a hover-grace submenu so nothing collapses on the wrong twitch of the mouse. On a phone the sidebar becomes a hamburger. The same colour palette runs across both the admin and the live site, so what you see while editing matches what visitors get.
A hand-coded HTML portfolio is fast and clean, but the moment you want to add a blog post, fix a typo in a project description, or change the accent colour, you are back in a code editor, syncing assets, and pushing a release. Over time the friction wins — you stop updating the site because every small change feels like an event. The shop-window you built starts looking out of date and that is the worst possible signal for a portfolio.
MiniCMS lives at the same domain as the site. You sign in, write or edit something, drop in an image, hit Publish — and the public version of the site is regenerated as ordinary HTML, CSS and images. Those static files are served directly by the webserver, so visitors get the exact same instant load profile as a hand-coded site. The admin only does work while you are actively editing; the public side has no runtime cost and nothing to break under load.
Write with formatting, links, images, embedded YouTube and code blocks — the same gestures you would use in any document editor. An HTML view is there for the rare moment you want to drop into raw markup, but you never have to.
Whatever you type or paste is cleaned before it goes live. Pasted content keeps its meaning — links, emphasis, lists — but loses anything that could break the page: scripts, surprise tracking pixels, malformed styling. You can write freely without worrying about what came along for the ride.
Three places a piece of content can live: Draft (only you can see it), Published (live on the next publish), Scheduled (auto-goes-live at a date and time you choose). Past-dated scheduled entries are rejected, so a slipped year or wrong month can't silently lose a post.
Scheduled posts go live on their own — you don't have to be at your laptop at midnight. The site checks every few minutes and only re-publishes when something is actually due, so nothing rebuilds for the sake of it.
Pick a built-in palette or tweak your own colours with a live preview — no guesswork, you see the change as you make it. A whole theme exports to a single file you can back up, send to someone, or load into another site that runs MiniCMS.
Six self-hosted font families come ready to use, and you can upload your own. Three independent slots — body text, code, and headings — can be combined however you like, so you don't have to settle for someone else's type pairing.
Every image you upload is re-encoded for the web, has its EXIF metadata stripped (no leaking the GPS location from a holiday photo), and is paired with a smaller modern-format version. Visitors get whichever is faster for their browser — you don't have to think about it.
This is what visitors actually see — plain, fast HTML with images that adapt to their device and code blocks that copy to the clipboard in one click. No spinning loaders, no framework warm-up, no surprise blank flashes while something hydrates.
Publishing is safe by design: the new version of the site is assembled in a staging directory and only swaps in when it's complete. If anything fails halfway through a rebuild, your visitors carry on seeing the previous version — they never land on a half-built page. A daily backup runs automatically in the small hours, keeping two weeks of database + uploads history. Logging in uses bcrypt-hashed passwords; every form carries a CSRF token; no single endpoint can be hammered thanks to per-route rate limiting.
Try MiniCMS live — write a post, swap the theme, upload an image, schedule something for tomorrow, hit Publish. You get a private per-visitor sandbox: your changes are visible only to you and are wiped after 30 minutes of inactivity, so nothing you do affects anyone else.
Admin login: demo / demo. Only a few sandboxes run at once — if they're all in use you'll see a brief notice; try again in a couple of minutes.
Sole author. Full-stack work — Fastify route layer, SQLite schema and migrations (idempotent ensureColumn helper for SQLite's ADD COLUMN limitations), service layer with embedded prepared statements, Eta templates for both the admin and the regenerated public site, the TipTap integration with server-side sanitisation, the publish pipeline, themes/fonts editors, scheduled-publish via systemd, the Apache reverse-proxy snippet, and the deploy/backup units. Tests use the native node --test runner — no transpile, no bundler, no framework boilerplate.
Two interesting bits. First, the storage convention for the three-state lifecycle: instead of adding a status column, I reinterpret the existing published integer together with a nullable published_at — draft is (0, NULL), published is (1, NULL|past), scheduled is (1, future). That keeps pre-existing rows behaving identically and avoids a wider migration. Second, the auto-publish trigger needed a guard so the static site is not regenerated every five minutes for nothing. The runner compares the most recent successful publish_log timestamp against any due rows' published_at — if nothing has crossed the line since the last publish, the script exits silently. Lex-comparing timestamps required normalising SQLite's CURRENT_TIMESTAMP output to ISO-8601 UTC, because 'T' > ' ' made same-instant strings look different in WHERE predicates.
A site visitors cannot tell apart from a hand-coded one — same HTML, same load speed, same lack of runtime weight — but with all the comfort of a database behind it. You can write a post on the train and schedule it for Monday morning; you can swap the entire colour palette in thirty seconds; you can drop in a screenshot and have it served in a modern format without thinking about it. Used in production for attv.uk-adjacent sites and as the starting point for every new portfolio I build.
MiniCMS works as a single-author tool today. The ideas below would extend what it can do without making the day-to-day editing experience any heavier. Vote for the ones you'd want first:
hreflang switcher automatically so visitors land on their language/en/, /pl/, etc. — with the right one chosen by default