This Editor Is Now Live - New Home?
This post is both an announcement and a proof-of-life signal.
The internal blog editor on Dangerous Metrics is now live, functional, and no longer pretending to work while quietly doing nothing. More importantly, it crossed the line from “toy” to “infrastructure”. That means this is very likely where my blog content will live going forward.
This post also exists to stress-test rendering. If you are reading this in the blog view and everything looks sane, the pipeline is doing its job.
What Was Built
There is now a full, authenticated blog authoring workflow backed by a database, not static files, not markdown on disk, and not a third-party CMS.
At a high level:
-
A sidebar lists blog post summaries only
-
Clicking a post hydrates the full document on demand
-
A rich text editor (TinyMCE) handles authoring
-
Posts are stored as HTML plus extracted plain text
-
The reader renders exactly what the editor produces
This separation matters more than it sounds.
The Problem That Forced the Redesign
Originally, clicking a post loaded the title but not the content.
At first glance this looked like a React issue.
Then it looked like a TinyMCE lifecycle issue.
Then it looked like state synchronization madness.
It was none of those.
The real issue was simpler and more fundamental: the sidebar list endpoint was returning summaries, not full documents. The UI was trying to load content that literally was not there.
Once that was acknowledged, everything snapped into focus.
The Architectural Fix
The solution was not to fight React harder or abuse editor APIs. The solution was to respect data shape boundaries.
There are now two very clear concepts:
1. Blog post summaries
Used only for the sidebar.
They contain:
-
id
-
title
-
status
-
updated timestamp
They explicitly do not contain HTML content.
2. Full blog posts
Loaded only when a post is selected for editing.
They contain:
-
title
-
slug
-
status
-
full HTML body
-
timestamps
This means the editor only ever receives real, complete data, and the sidebar stays fast and lightweight.
Why the Editor Now Works Reliably
TinyMCE is not React. It does not want to be treated like a controlled textarea. Once that was accepted, the integration became straightforward.
The editor now:
-
Mounts fresh per post using a stable key
-
Receives its content exactly once, at initialization
-
Owns its internal document state
-
Is queried only at save time
No effects trying to “sync” content. No races. No haunted state.
The result is boring behavior, which is exactly what you want from tooling.
Backend Details (Because This Is Dangerous Metrics)
The backend routes are split intentionally:
-
/api/editor/blog/listreturns summaries only -
/api/editor/blog/get?id=Xreturns a full document -
/api/editor/blog/savewrites HTML and extracted text -
/api/editor/blog/deleteremoves a post
MariaDB stores the canonical HTML. The plain text version exists for search, indexing, and future analysis.
Database access uses a connection pool, not ad hoc connections, which avoids the class of intermittent failures that only show up under real usage.
Why This Matters Going Forward
This editor is not meant to be a CMS in the traditional sense. It is an internal authoring tool that happens to produce public-facing content.
That distinction matters.
It means I can:
-
Write short notes or long technical posts in the same place
-
Mix serious documentation with off-the-rails observations
-
Let the content evolve without fighting tooling
-
Keep everything under my own control
If this holds up under real usage, this is where future blog content will live.
A Quick Rendering Checklist
If you are reading this and you see:
-
Proper headings
-
Bullet lists
-
Bold and italic text
-
Clean paragraph spacing
-
Code blocks rendered correctly
Then the editor, storage, and reader are all doing what they are supposed to do.
If not, congratulations, we found the next thing to fix.
Closing Thought
This whole exercise is a reminder that most “frontend bugs” are really data contract bugs wearing a UI costume.
Once the contracts are honest, the systems stop arguing with you.
More to come.