root@arranvanaerschot ~ /portfolio/cases/streetbrat-magazine · less
↑ q to quit
root@arranvanaerschot:~/cases$ cat streetbrat-magazine.md

./streetbrat-magazine

built the entire editorial stack for a culture publication from scratch

kind
platform
year
2026
stack
.NET 10 · PostgreSQL · Next.js 16 · AWS S3 · Docker

Streetbrat is a culture publication covering art, beauty, fashion, film, music, and more. Off-the-shelf platforms — Squarespace, WordPress — impose structure that fights a brand like this at every turn: rigid themes, lowest-common-denominator image handling, CMS UIs built for blog posts not editorial spreads. I built the whole stack from scratch instead: a .NET 10 API, a Next.js 16 reader site, and a bespoke admin that gives editors the tools they actually need — focal-point image picking, multiple hero layouts, a pitch inbox, newsletter broadcasts, and a full audit log. Four months from first commit to production.


the problem

Three things a generic platform can't give a culture publication:

Image control. Hero images are the product. Squarespace centers everything. I needed per-image focal-point picking so a portrait doesn't get its face cropped out on mobile, and per-article hero layout choice (stacked, split, title-over, full-bleed) so each piece can be art-directed.

An owned editorial pipeline. Pitch inbox → draft → review → publish is a workflow, not a blog. There's no plugin that maps cleanly to it without bringing three other things you don't want.

A reader experience that isn't a theme. The frontend needed to be the brand, not a customised template. That means total control over fonts (Druk), typography scale, spacing, and navigation — none of which survive a theme engine intact.

"We tried three platforms. They all made the site look like every other site."

— editor, kickoff


the approach

Three constraints, in order:

Editorial UX first, API second. I spent the first two weeks sketching the admin screens before writing a line of API code. The data model fell out of what editors needed to do, not the other way around.

Own the auth surface. A bespoke CMS with a weak login is worse than Squarespace. ASP.NET Identity with TOTP 2FA, account lockout, token-stamp revocation, and magic-byte validation on uploads — the security posture had to match the access model.

Server-first frontend. Next.js App Router with React Server Components by default. No client-side state that doesn't need to be client-side. Server Actions for all mutations. The reader site fetches from the .NET API at request time; there's no build-time export step to break.

editorial pipeline
pitch inbox
draft
review
publish
runtime
admin panel
.NET 10 API
next.js reader · RSC
data
postgres · articles
S3 · images
identity · TOTP
audit log

The image pipeline is a single POST to the API: magic-byte check, dimension validation, strip EXIF, upload to S3, return a URL with the focal-point coordinate stored alongside. The Next.js <Image> component uses the coordinate to set CSS object-position — no client-side crop, no canvas, no lambda.

Every admin action — article create/update/delete, user changes, settings edits — writes to an append-only audit log. On-call for a one-person editorial team means you need to be able to answer "what changed and when" at 11pm.


outcome

Hero Layouts
4
stacked · split · title-over · full-bleed
Image Control
focal·pt
per image, per article
Auth
TOTP
2FA + lockout + stamp revocation
Migrations
45
zero manual schema changes in prod
Controllers
27
articles · images · newsletter · pitches · more
Commits
220
Jan → May 2026

before / after

before

brand fit
theme constraints, perpetual overrides
image handling
auto-centered, no focal control
hero layouts
1 (whatever the theme does)
pitch workflow
email thread + spreadsheet
newsletter
third-party, separate login
audit trail
none
2FA
optional, platform-dependent

after

brand fit
total — fonts, spacing, colour, motion owned
image handling
drag-to-focal, coordinate stored per image
hero layouts
4, chosen per article in the editor
pitch workflow
inbox → draft → publish in one UI
newsletter
in-house broadcasts via Resend, same admin
audit trail
append-only log, every admin action
2FA
TOTP enforced, no bypass

what i'd do differently

Newsletter and pitch inbox were retrofitted. I built them late in the project, which meant retrofitting the domain model. Both should have been in the schema from week one — the access patterns were predictable.

One Next.js app for both admin and reader. The admin is a single Next.js app sharing the reader's routing. It works, but the admin and reader have meaningfully different caching and auth needs. I'd separate them into distinct Next.js apps behind the same reverse proxy next time — cleaner cache boundaries, simpler middleware.

Integration tests after launch. I delayed writing integration tests until after launch. The FluentValidation rules are correct, but I had to verify that by reading code rather than running tests. Three edge cases in the image pipeline would have been caught earlier.


what shipped

  • A .NET 10 API (27 controllers, 45 migrations, TOTP 2FA, audit log) running in Docker on a Linux VM.
  • A Next.js 16 reader site — six editorial categories, four hero layouts, focal-point images, article TOC, sitemap, structured SEO fields.
  • A bespoke admin panel: custom built article page editor, image manager, pitch inbox, newsletter broadcasts, social links, redirects, tags, site settings, user management, analytics dashboard.
  • A deployment stack: single multi-target Dockerfile, docker-compose for the full environment, automatic migration on startup.

"We finally have a site that looks like us."

— editor, launch day

root@arranvanaerschot:~/cases$
← back to ~/projects
./streetbrat-magazine · case study · arran van aerschotset in jetbrains mono