How we got here
The opening post — on building joshualawrence.info, the blog, and the photo site as three surfaces of the same place.
I’ve lost count of how many times I’ve tried to build a personal website. Embarrassing number, honestly. Every time it starts the same way — big notions board, grand plans, all this talk about the perfect headless CMS and the design system that’s going to change everything. Dark mode and light mode, obviously. An RSS feed that doesn’t just work but sparks joy. The whole deal.
Then life happens. The domain expires. The site gathers dust for two years. Repeat.
This time I did it backwards. I stopped planning and started building. Smallest thing that works, shipped, then fix it later. I think I was just tired of my online presence being a GitHub profile and nothing else. I wanted a corner of the internet that actually felt like mine.
The three little apps
The main site is almost boring in its simplicity. Plain HTML, CSS, and a tiny Node script to serve it. That’s it. No framework, no build step, nothing. It’s a one-page portfolio that loads before you’ve finished clicking the link. I wanted a place that just exists — quiet, fast, like a business card that doesn’t try too hard. You know the type.
The blog — this thing you’re reading right now — runs on Astro with Markdown content collections and Decap CMS for when I’m feeling lazy and want to write from a browser. But every post is a Markdown file in a folder. Git is the source of truth. The CMS is just a nice wrapper. I know myself well enough to know that if publishing took more effort than opening a text file, I’d never do it. So I made the path from thought to published post as short as I possibly could.
The photo site is the one I’m proudest of. It’s a Hono app — TypeScript, MySQL, server-rendered JSX templates. There’s a little admin area with cookie-based auth where I can upload photos, write captions, and publish collections. The public side is a lightbox gallery that works on any screen. I built it because I take an absurd number of photos every time I travel — Spain, Ireland, Malta, random weekends in Kent — and I got tired of them sitting on my hard drive, unseen by anyone but me. They’ve got a proper home now.
All three share a look and feel — warm colours, minimal layout, light and dark mode — synced from one CSS file by a tiny script. No design token pipeline, no CSS-in-JS, none of that nonsense. Just a CSS file with custom properties. Works perfectly.
Why three apps and not one big one?
Honest answer? I’ve been burned too many times. The main site never needs rebuilding. The blog builds fresh when I publish. The photo site needs a server because uploading photos requires auth and file handling. If I’d shoved them all into one Next.js or Astro monolith, I’d be fighting some framework assumption on at least one surface. This way each one uses what fits.
Downside is duplication — every app has its own Dockerfile, its own package.json, its own deploy config. Whatever. The theme stays consistent, the pipeline pushes all three, it works. I’ll take working over elegant any day.
The domain situation
- joshualawrence.info — the main portfolio, my little corner
- blog.joshualawrence.info — you’re here, hi
- photos.joshualawrence.info — photo collections
Each one has its own nginx config, its own Docker compose setup, its own port range. A reverse proxy on the host routes traffic. About as boring as infrastructure gets. I mean that as a compliment. Boring stuff doesn’t wake you up with a notification at 2am.
What’s next
The blog needs proper category and tag archive pages, a decent RSS feed, maybe pagination if I ever write enough. The photo site has a list — album descriptions, a map view, better mobile navigation. The main site is mostly done, which is a genuinely nice feeling for once.
But this post isn’t really about what’s next. It’s the opening note. The one that says I’m here, this is my corner, it’s live enough to count as real.
There’s something about publishing a site you built with your own hands. It doesn’t need to be fancy. It just needs to exist. And now it does, and that feels pretty good.