Three Doors: Announcing the New Site
Why ali.mk is now a house with three doors instead of one crowded room.
contents
I started the journey of having a personal web footprint with my first website horotat.com. That is right after the time that I passed the course Web Design during my bachelor’s. I started from wordpress, the moved to pure HTML, and adding CSS to it later on. I have always wanted an effective, personal, and customized digital presence. But for many years, I was very confused as in, what do I really want from my personal website. Since for now, I am in academia, this was a perfect opportunity for me to establish a real base for presenting myself properly in the scientific society. That is when I discovered Jekyll around 2018. I moved to Jekyll using GitHub Pages to deploy my static, fast website. After exploring much, I endded up with the amazing Chirpy theme. It has a great active commmunity around it who are taking it forward to date, and make it even better.
In the meantime, I figured out the north macedonian domain of .mk which was the exact initials of my last name (Mahmoudi Kamelabad) and I noticed that my short and long first names (ali and alireza) are both available for this domain so I quickly grabbed them and I love them very much. I must say, I have never seen a better personal website domain than mine! So I became: ali.mk and alireza.mk.
As I grew and did my career and personality, I felt that I need more than one dimension to present online, each of which have their own audience; yet, the information of each would mostly be noise for the other ones---a recruiter scrolling past political essays to find my CV, a fellow researcher wading through film reviews to find a publication, a friend getting a wall of BibTeX before the actual writing. Everyone got the whole of me, whether they’d asked for it or not. It worked, technically. It never quite felt right. That is where the idea of the three door came from.
The people I needed to talk to are:
- Professionals Hiring: who would want to quickly get to know about my skills, passion, and match for their workflow and business.
- Academics: the fellow researchers and scientists who can access my papers, resources, and contributions to science.
- Readers and Followers: a place where I could publish my non-academic writings, whether political, opinion, diary, etc.
The new site fixes that by not trying to be one thing. The root page is a threshold — you pick a door, and each door opens onto a self-contained room that never cross-surfaces the others’ content:
- /research — publications, field notes, the academic CV. For fellow researchers.
- /work — experience, toolbox, craft notes, the availability line. For people hiring.
- /life — essays (politics and opinion included), the shelf of films and shows, the running/hiking log, the parts of me that don’t belong on a CV.
Nothing is hidden — everything is still public and indexed — the separation is about surfacing, not secrecy. A recruiter reading Work is simply never pitched an essay about closing my Twitter account; a reader in Life is never handed a CV. The only threads back are the wordmark, which always returns to the threshold, and a quiet footer line: “elsewhere in the house.”
The design language
Once the three-room idea was settled, the visual language had to do two contradictory things: read as one coherent person, and let each room have its own temperament. The solve was to fix almost everything — type, spacing, the warm paper-and-ink base — and let exactly one thing vary: an accent color per room, used sparingly enough that color still means something (“which room am I in”) instead of just decorating the page.
Type is doing more work than color, actually. Headlines and the wordmark are set in Instrument Serif, with the occasional word breaking into italic — Research — a signature move I made myself use sparingly, at most once per view, after an early draft turned it into a tic. Long-form essay text sits in Newsreader, sized and leaded for actual reading rather than scanning. Numerals — years in a publication list, in a BibTeX block — get JetBrains Mono, and nowhere else; an earlier pass had mono-caps in the navigation and it immediately read as a developer’s terminal rather than someone’s front door, so that idea died fast.
Color always means “which room am I in,” never decoration.
Research got a blue that reads scholarly and a little cold on purpose; Work got a green that’s meant to feel dependable; Life got a warm orange-red, on paper that warms half a shade to match. Dark mode isn’t an inversion — it’s a second, separately tuned palette, system-synced by default with a manual override that remembers your choice.
The tokens themselves, for anyone curious enough to check the CSS:
/* base — light */
--paper: #F7F2E9; --ink: #1C1712; --ink-2: #6C6053; --ink-3: #A2937F;
/* base — dark */
--paper: #141009; --ink: #F2EADC; --ink-2: #A99A85; --ink-3: #6E6252;
/* rooms light dark */
--research: #2447C5; #7B94FF;
--work: #166E5A; #4CC7A4;
--life: #D14E24; #FF7847;
Building it
The honest version of this story includes a false start. An earlier attempt at rebuilding the site tried to do the room-separation via subdomains, three fully separate themes, and Strapi — a headless CMS — running in its own Docker container. It was technically impressive and operationally exhausting: every room ended up looking like it came from a different template rather than one house, and writing a single post meant a server had to be up somewhere first. I shelved it. The only thing worth keeping was the thinking around how publication data should be modeled, which survived into this version.
What I actually wanted was smaller than a CMS with more features — it was the ability to write a post from whatever device I had open, without spinning anything up first. That’s what sent me looking past headless CMSes entirely, toward something that would commit straight to Git. What shipped reflects that: a static Astro site, one content pipeline where a post declares which room(s) it belongs to in its front matter, no CSS framework — just custom properties and plain CSS, because the design system is small enough that a framework would be more ceremony than help. Editing happens through Pages CMS, a lightweight browser editor that commits straight to this repo and triggers a deploy — no admin server to run, no separate database to back up. I’m typing this very announcement into a form field, and in a few minutes it’ll be a live page.
Built with:
Under the hood
Content lives in a couple of Astro content collections, each checked against a schema — a post’s rooms array has to contain at least one of research | work | life, dates get coerced automatically, and anything that doesn’t match fails the build rather than showing up broken in someone’s browser. One shared layout renders a post regardless of which room it’s in, which is also why something like an optional cover photo only had to be written once to work everywhere.
Routing follows the room structure directly — no server, no database, just static files generated at build time:
graph TD
classDef research fill:#2447C5,stroke:#2447C5,color:#fff
classDef work fill:#166E5A,stroke:#166E5A,color:#fff
classDef life fill:#D14E24,stroke:#D14E24,color:#fff
T["/ — threshold"] --> R["/research"]:::research
T --> W["/work"]:::work
T --> L["/life"]:::life
R --> RP["publications"]:::research
R --> RN["notes"]:::research
R --> RC["cv"]:::research
R --> RCon["contact"]:::research
W --> WN["notes"]:::work
W --> WC["cv"]:::work
W --> WCon["contact"]:::work
L --> LE["essays"]:::life
L --> LS["shelf"]:::life
L --> LA["about"]:::life
Fig. 1 — routing, colored by room: research in blue, work in green, life in orange.
The node colors above are the exact room tokens from the block earlier — not a coincidence, the diagram is styled from the same three hex values as the site.
Deployment is the same shape as the CMS itself: everything funnels down to a single git push to the v2 branch, whether that push comes from a terminal or from Pages CMS saving a form.
graph LR
classDef gha stroke:#2088FF,stroke-width:2px
classDef cf stroke:#F38020,stroke-width:2px
classDef logo stroke:#A2937F,stroke-width:1.5px
A["Edit in Pages CMS"] --> B["<span><img src='/assets/images/icons/github.svg' width='24' height='24'/></span>"]
C["<span><img src='/assets/images/icons/git.svg' width='24' height='24'/></span>"] --> B
B --> D["<img src='/assets/images/icons/github-actions.svg' width='22' height='22'/> <img src='/assets/images/icons/astro.svg' width='22' height='22'/>"]:::gha
D --> E["<img src='/assets/images/icons/cloudflare-pages.svg' width='22' height='22'/> <img src='/assets/images/icons/rocket.svg' width='22' height='22'/>"]:::cf
E --> F["<span><img src='/assets/images/icons/threshold-lines.svg' width='34' height='34'/></span>"]:::logo
Fig. 2 — an edit becomes a live page: git/GitHub, GitHub Actions running an Astro build, Cloudflare Pages deploying it, landing at ali.mk.
Nothing to patch, nothing to back up, no build step I have to remember to run by hand — the whole loop from “edit a field” to “it’s live” takes under a minute.
Zoomed out, the whole system is small enough to draw on one diagram: content and code meet at the v2 branch, GitHub Actions turns that into static files, Cloudflare serves them at the edge, and a visitor’s browser reports back a single privacy-respecting pageview.
graph TB
classDef gha fill:#2088FF,stroke:#2088FF,color:#fff
classDef cf fill:#F38020,stroke:#F38020,color:#fff
classDef gc fill:#0EA5A0,stroke:#0EA5A0,color:#fff
subgraph Authoring
CMS["Pages CMS<br/>(browser form)"]
Term["Terminal<br/>(git push)"]
end
CMS -->|commit| Repo["GitHub<br/>v2 branch"]
Term -->|push| Repo
Repo --> CI["GitHub Actions<br/>astro build"]:::gha
CI -->|static HTML/CSS/JS| CDN["Cloudflare Pages<br/>edge network"]:::cf
CDN --> Visitor["Visitor's browser"]
Visitor -.->|one pageview,<br/>no cookies| GC["GoatCounter"]:::gc
Fig. 3 — the whole system in one picture: authoring, build, hosting, and analytics.
Analytics, briefly
The pageview count on this site comes from GoatCounter — open source, no cookies, no personal data collected, nothing to justify in a cookie banner because there’s nothing to consent to. The only wrinkle is that this site does client-side page transitions (Astro’s view transitions swap content without a full reload), so a plain analytics snippet that only fires onload would count the first page of every visit and miss the rest. The fix was small: disable GoatCounter’s automatic count and fire it manually on astro:page-load, an event Astro dispatches on the initial load and every soft navigation after it — so every room, every essay, every publication page gets counted exactly once, however someone got there.
Standing on open source
None of this exists without a long list of people who gave their work away for free. This site runs on Astro and TypeScript, validates its content with Zod, renders the diagrams above with Mermaid, highlights its code blocks with Shiki (bundled straight into Astro), draws its brand logos from Simple Icons, sets its type with self-hosted Fontsource packages of Instrument Sans, Instrument Serif, Newsreader, and JetBrains Mono, and gets edited through Pages CMS — a genuinely lovely piece of software for something I don’t pay a cent for. GoatCounter covers analytics, GitHub Actions covers the build, and Cloudflare Pages covers hosting, all on free tiers that exist because someone decided small personal projects deserve good infrastructure too. And further back, this whole habit started with Jekyll and the Chirpy theme, which is still out there being maintained by people who owe me nothing.
If you maintain any of the above: thank you. Genuinely.
What it’s for
The point was never to look different for its own sake. It was to stop asking one page to perform three roles simultaneously, and to stop self-censoring by architecture — quietly softening an opinion, or leaving out a film review, because it might sit two scrolls away from someone deciding whether to fund my next project. Now the writing can be as direct as it needs to be in whichever room it belongs to, because the room it belongs to is the only room it’s in.
Come in through whichever door fits why you’re here. Or, if you’re curious, try all three — that’s kind of the point of having them.
Comments
Select any passage above to comment on it directly. Markdown supported.
Loading comments…