Fayad K. HassanContact

This Site and the CMS Behind It

A flat-file publishing system written from scratch: no database, no build step, no third-party request on any page, and every section editable from a browser.

Kind
Web app, PHP
Built with
Flat-file PHP, no database
Status
Live, this site
The elfayad.me homepage: the hero headline and the generative flame

The site you are reading, and the publishing system underneath it. Written from scratch rather than assembled, for the same reason as everything else here.

How it works

Every piece of content is a markdown file with front matter, sitting in a folder. There is no database to back up, migrate or watch fall over under load, and deploying is copying files. The admin side is a bcrypt login with CSRF protection on every action and a rate limit on failed attempts, a markdown editor with image upload, and an editor for each section of the public pages.

The homepage’s work section: one featured project, then a gallery of the rest, each project a markdown file
The public front end. Every project here is a flat markdown file, rendered on the fly, no database and no build step.

The decisions worth defending

No third-party requests. Fonts are self-hosted. The markdown editor is self-hosted and version-pinned rather than pulled from a public CDN, because an unpinned third-party script on the page that holds an admin session is somebody else’s code running with your privileges. The content security policy states the rule and the browser enforces it, so the claim is testable rather than asserted.

It works with JavaScript disabled. One small script folds the menu away on phones, steps the top bar aside while you read, and marks where you are in an essay’s contents. Nothing that matters depends on it: without it the menu shows as links and the contents are plain anchors.

Caching that tells the truth. Assets get a one-year immutable header only where the URL carries a content hash. Everything else gets a short life. An immutable header on a URL that can change is a promise the server cannot keep, and the symptom is a file you replaced that nobody ever sees.

The disclosure record on the security page, rendered from the same flat-file system
The security page. Every vendor row is a small markdown file, and where the credit is public the row links to the vendor’s own listing, so the claim is checkable. The drawing at the top of the page is generated from the same rows.

How it’s built

  • One token file holds every colour, type size, space, line height and letter-spacing, and a checker fails the build on any literal value anywhere else.
  • Six checks run before anything ships: the tokens, a list of banned design habits, contrast (prose at AAA), layout at six widths, third-party requests, and text laid over the artwork, measured from rendered pixels.
  • Three typefaces, all self-hosted and cut down to the characters the site uses: Inter, two weights of Bricolage Grotesque, and Source Serif 4 for reading.
  • Every picture is rendered by a script in a real browser with the site’s own fonts: the drawing from the disclosure record, the essay pictures, the diagrams and the share cards.
  • A print stylesheet, so an essay or the About page prints without the chrome.

Why build it at all

A personal site is the one system where you are the entire user base, the whole product team and the on-call rotation. It is a rare licence to build the thing properly rather than the thing that ships, and a reasonable place to show how you make engineering decisions when nobody is constraining them.

Want the longer version of how this works?