What MiniCMS Gives You
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.
Screenshots are being prepared — better yet, try the live sandbox below.
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.
The Problem It Solves
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.
The Approach
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.
Sanitised Rich-Text Editing
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.
Drafts & Scheduled Publishing
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.
Themes & Typography
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.
Media Pipeline
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.
Safety & Reliability
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.
Hosted Demo
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.
What's Inside
- Single sidebar that groups every editing module — Pages, Work portfolio, Blog, Menu, Media, Fonts, Themes, Settings — plus an inline Help centre so you never have to leave the admin to look something up
- Rich-text editor with formatting, links, image insert, YouTube embed and code blocks — plus an HTML view for the rare time you need raw markup
- Everything you paste or type is cleaned before going live: scripts, event handlers and unsafe URLs are stripped automatically
- Three-state lifecycle per post or page — Draft, Published, Scheduled — with scheduled items auto-going-live without you needing to be online
- Theme editor with five built-in palettes, live colour preview, and one-file import/export — back up or share a look in seconds
- Three independent font slots (body, code, headings) with six families included and your own WOFF2 uploads welcome
- Smart image handling: web-optimised re-encode, EXIF stripped, modern format paired with a fallback automatically
- One-click copy on every code block in the published site
- Wire up Google Analytics in two clicks — paste the Measurement ID into Settings, no code edits
- Atomic publish: a botched rebuild can never break the live site — the previous version stays in place until the new one is complete
- Automatic daily backup of database and uploads, with two weeks of history retained
- Hardened single-admin login — bcrypt password, signed session cookie, CSRF tokens, rate limiting
- No build step, no frameworks — the admin and the generated site are both plain modern JavaScript and HTML
My Role
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.
Technology Used
Challenges and Learning
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.
The End Result
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.
What's Next — Proposed Improvements
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:
Multiple authors with permissions
- Invite editors who can write and save drafts, while only you can publish
- Per-author audit log — see who changed what, and when
- Each author has their own profile shown on the blog posts they write
Full-text search across everything
- One search box in the admin that finds any post, page or media item by its content — not just title
- The same search built into the public site for visitors
- Powered by SQLite's built-in full-text search — nothing extra to install or maintain
Multi-language pages
- Edit the same page in several languages, linked together in the admin
- The public site adds an
hreflangswitcher automatically so visitors land on their language - Per-language URLs —
/en/,/pl/, etc. — with the right one chosen by default
Comments with moderation
- Optional comment thread on any blog post or project page
- Held for review before going live — spam never reaches readers
- Reply by email and your reply appears on the page
Mobile-first admin editor
- Phone-friendly editor with a sticky toolbar that doesn't fight the on-screen keyboard
- Upload straight from the phone camera or photo library
- Save and publish from one thumb-reachable button
Version history & one-click undo
- Every save creates a hidden snapshot — go back to any earlier version of any page
- Side-by-side diff between two versions so you can see exactly what changed
- Restore in one click — the live site updates on the next publish