Why My Blog Has No Admin Panel — And Doesn't Need One
When I built my landing page with a blog, the first obvious question was: which CMS should I use? WordPress? Filament? A custom admin panel in Laravel?
I used none of them. My posts are Markdown files that live in the repository. There are no forms, no WYSIWYG, no admin login. And after several published posts, I'm convinced that for a developer blog, this was the best decision I could have made.
The approach: Markdown + JSON + Git
The structure is simple. Each post is a folder inside database/seeders/posts/:
database/seeders/posts/
├── my_first_post/
│ ├── meta.json
│ ├── es.md
│ └── en.md
├── second_post/
│ ├── meta.json
│ ├── es.md
│ └── en.md
The meta.json contains the metadata: slugs, titles, excerpts, category, tags, and publish date. The .md files contain the content in each language.
{
"published_at": "2026-03-04",
"slug": {
"es": "mi-post-en-español",
"en": "my-post-in-english"
},
"title": {
"es": "Título en español",
"en": "Title in English"
},
"excerpt": {
"es": "Resumen corto...",
"en": "Short summary..."
},
"category": "architecture",
"tags": ["laravel", "markdown"]
}
An artisan command syncs everything to the database:
php artisan blog:sync
It reads the folders, creates or updates posts in the DB, and syncs categories and tags. That's it.
Why this works better than an admin panel
Real version control. Every change to a post is a Git commit. I can see the full edit history, roll back to any previous version, and I have automatic backups on the remote. An admin panel with a database doesn't give you that without extra configuration.
I write in my editor. VS Code with Markdown preview, syntax highlighting, Copilot for autocomplete. No admin panel textarea comes close to the experience of writing in a real code editor.
Bilingual by design. Each post has es.md and en.md in the same folder. The relationship between translations is implicit through the file structure. No "language" fields or "translation of" selectors in a form.
Zero attack surface. There's no /admin, no login, no public forms. Nothing to protect. Nothing for a bot to attack.
Deploy = publish. I write the post, commit, push, and CI/CD handles the rest. The workflow is identical to any code feature.
The problem I had to solve: dates
My initial approach had a subtle bug. Both the seeder and the sync command used now() for the published_at field:
'published_at' => now(),
This meant that every time I synced posts — for example, after adding a new one — all existing posts got updated with the current date. On the blog, every article appeared as published today.
The fix was moving the publish date to meta.json:
{
"published_at": "2026-03-04",
...
}
And in the sync command, preserving the existing date if the post already exists in the database:
$attributes = [
'title' => $meta['title'][$lang],
'excerpt' => $meta['excerpt'][$lang],
'content' => $content,
'status' => 'published',
'category_id' => $category->id,
'translation_key' => $folderName,
];
$existing = Post::where('slug', $slug)->where('lang', $lang)->first();
if (!$existing) {
$attributes['published_at'] = $meta['published_at'] ?? now();
}
$post = Post::updateOrCreate(
['slug' => $slug, 'lang' => $lang],
$attributes
);
If the post is new, it takes the date from meta.json (or now() as a fallback). If it already exists, it doesn't touch published_at. Simple.
The full workflow to publish a post
1. Create a folder in database/seeders/posts/my-new-post/
2. Write meta.json with metadata
3. Write es.md and en.md with the content
4. php artisan blog:sync (to verify locally)
5. git add + commit + push
6. Automatic deploy
There's nothing to learn beyond what you already know as a developer. It's Git. It's Markdown. It's an artisan command.
When would you actually need an admin panel?
This approach has clear limits:
- If a non-technical person will publish content. A marketing editor isn't going to git push.
- If you need scheduled publishing. You can implement it, but a CMS gives you that out of the box.
- If you're publishing daily. Beyond a certain volume, the friction of creating folders and files adds up.
For a personal developer blog that publishes a couple of times a month, it's perfect. You have total control, zero extra dependencies, and your content lives where it should: in the repository.
The takeaway
Not everything needs an admin panel. Sometimes the simplest solution — files in a repository — is also the most robust. You get version control for free, backups for free, and a publishing workflow you already know by heart.
If you're a developer thinking about starting a blog, consider this before installing a CMS. You might not need one.
I'm Rubén Rangel, a Senior Full-Stack Developer with 17+ years of experience building production web applications. Currently at Ansira, I work on a SaaS marketing automation platform serving 100+ brands. I integrate AI into my workflow to build faster, smarter, and with higher quality. Open to full-time opportunities and contracts.