Skip to main content

I built an admin panel from scratch in 2026 and I'd do it again

May 25, 2026
6 min read
brain-dumpengineering-decisionsnext-jsbuild-vs-buy

Open any indie hacker forum and you'll find the same advice. Don't build your own CMS. Use Sanity. Use Payload.

Use Strapi. Use Notion as a CMS. Use literally anything pre-built.

Reasonable advice in general. I ignored it. Booplex runs on a hand-rolled admin panel I built from zero — auth, post editor, project editor, media management, settings, schema migrations, the works.

It took three months of part-time work. I'd do it again. Here's the honest math, including the parts where the don't-roll-your-own crowd is right.

What I actually built

Booplex's admin lives at /hq behind session auth. Inside:

  • Post + project CRUD with a Lexical-based editor
  • Media library with S3/FTP backends
  • Per-page SEO management — title, description, OG, canonical, schema type, AI metadata overrides
  • Settings — site URL, email/SMTP, analytics, AI provider config, security
  • An installer wizard for fresh deployments (WordPress-style — DB config, admin account, site info)
  • A WordPress-style schema migration system so existing installs can upgrade without SSH
  • Database backup + restore

About 8,000 lines of TypeScript across the admin code. Plus shared schema, validation, and types with the public site.

What it cost

Real numbers from my git log:

PhaseTime
Initial auth + post CRUD~28 hours
Lexical editor integration~22 hours
Media library~16 hours
Settings + installer~30 hours
Schema migration system~20 hours
Edge cases, bug fixes, polish (ongoing)~50+ hours
Total~166 hours over 3 months

That's not a small number. About 4 weeks of full-time work if I'd done it intensively.

What the alternatives would have cost

I evaluated four options seriously before deciding:

Sanity

Time to set up: ~10 hours. Monthly cost at my content volume: $0–15.

What I'd lose: deep integration with my SEO system, the ability to ship custom schema migrations, full control over the admin UI/UX.

Payload CMS

Time to set up: ~20 hours. Monthly cost: $0 (self-hosted).

What I'd lose: same as Sanity, plus Payload's admin UI is good but not mine. The site has a brutalist aesthetic. The admin sharing that aesthetic is part of the appeal.

Strapi

Time to set up: ~15 hours. Monthly cost: $0–29.

What I'd lose: same as above. Plus Strapi v4 had breaking changes that hit hard for active users — gave me pause.

WordPress + Next.js headless

Time to set up: ~25 hours. Monthly cost: $5–40 depending on hosting.

What I'd lose: the joy. I've done enough WordPress in my life. The thought of going back made my soul slightly leave my body.

Why custom won anyway

Three reasons that aren't covered in the standard build-vs-buy spreadsheet:

1. The admin IS a tool I'm building

Booplex isn't a content site that needs a CMS. It's a personal site where the CMS itself is partly the work. The admin panel is the product in some real sense — it's where I prove out the AI workflows and SEO automation I write about. A commercial CMS would have meant grafting my work onto someone else's foundation.

Doable, but the integration points get awkward.

Specifically: the per-page AI metadata feature (shipping in schema v13 — aiPurpose, aiSummary, aiTopics, aiTargetAudience) wouldn't have been a 2-hour migration in Sanity. It would have been a fight against the framework's plugin architecture, every time.

2. The compounding speed-up of owning every layer

When something breaks, I fix it. No tracking a bug into a third-party repo, no waiting for a maintainer response, no submitting an upstream PR and hoping it merges. Every line of the admin is mine. I'm responsible for all of it, which is the obvious downside — and also the obvious upside.

This compounds. Every month, I make 3-4 small improvements to the admin. None of them would have been worth doing in a commercial CMS because each would require either custom code grafted onto the framework or a feature request to someone else's roadmap.

3. The CMS-portability tax I never wanted to pay

Commercial CMSes optimize for portability. Their data model is generic so it can serve every kind of site. That genericism is the tax — the schema can't fully express what my site needs, because the schema is designed for sites that don't yet exist.

My schema is specific. Post has aiPurpose because my site uses it. Project has caseStudy relations because my site has case studies. The schema reflects my site shape, not the average shape of all sites.

Where the don't-roll-your-own crowd is right

Three places the standard advice applies:

1. Auth is hard

I rebuilt auth from scratch. Session cookies, password hashing, rate limiting, CSRF. It works. It also took 30+ hours and I'm not 100% confident I haven't missed something subtle.

NextAuth/Auth.js exists for a reason. If I were starting today, I'd use it.

2. Email/SMTP is annoying

Configuring SMTP, handling bounces, building a queue, dealing with TLS handshake oddities. Worth using a service (Resend, Postmark) rather than rolling. I did roll, and I regret about 60% of that decision.

3. Media management is a tar pit

Storage backends, image optimization, blur placeholders, responsive variants, CDN integration. Each piece is a project. I'm still polishing this part of the admin 18 months in. A commercial CMS would have solved this in an afternoon.

What I'd tell someone considering the same path

Build your own admin if:

  • The admin is itself part of what makes your site distinctive
  • You're going to keep iterating on it for years, not months
  • Your data model is genuinely specific (not just "posts and pages")
  • You enjoy the work — this isn't a small qualifier

Don't build your own admin if:

  • You need it operational this month
  • You're building for clients who need staff training
  • The admin is auxiliary to your real work, not part of it
  • You haven't shipped a Next.js app before

The honest version

Building the admin panel was partly a rational decision and partly an emotional one. I like making things. Owning every layer felt right. The work is more satisfying when the tools I'm using to do the work are also mine.

That's not a metric I can put in a build-vs-buy spreadsheet. But it's real. Three months in, I was still energized to add features. If I'd been gluing my SEO workflow onto Strapi, I think I'd have given up by month two.

So yes, the don't-roll-your-own crowd is right in aggregate. They're also wrong for me. If you're closer to my profile than the median founder, the math might tilt your way too.

FAQ

How long does it take to build a custom CMS in Next.js?

For a personal-scale CMS with posts, pages, media, and settings: 100–200 hours of focused work. Faster if you're using prebuilt auth (NextAuth) and editor (TipTap or Lexical with templates).

What's the cheapest commercial CMS for a small site?

Sanity's free tier handles small personal sites at $0/month. Payload CMS self-hosted is $0. Strapi self-hosted is $0. Most CMS pricing kicks in at team/multi-project scale.

Why not use WordPress?

WordPress is fine for many sites. For a developer who wants tight control of the data model, the schema, and the integration points with custom code, it adds more friction than it removes.

How do you handle schema migrations in a custom CMS?

WordPress-style additive patches with IF NOT EXISTS SQL. Each schema change ships as a versioned patch. Existing installs run an in-admin updater. More on Booplex's approach in the schema cookbook.

Is a custom admin panel a security risk?

It can be. Auth and input validation are the load-bearing parts. If you're not confident there, use a battle-tested library or framework for those pieces specifically — even if the rest of the admin is custom.

Would you do it again?

Yes. For this site, with this scope, knowing what it cost — yes. Different project, different shape, the answer might flip.

Topics:brain-dumpengineering-decisionsnext-jsbuild-vs-buy

Found This Useful?

Share it with someone who might learn from my mistakes!