Ravi Wiki Blueprint
A living record of building Ravi Wiki from first principles.
Ravi Wiki is my small, self-owned corner of the internet. It is where I publish ideas, essays, observations and work without placing another platform between the source and the reader.
This Blueprint records how it is being built.
It is not a changelog and it is not a collection of terminal transcripts. It is the public trail of the questions we asked, the choices we made, the things that failed, the evidence that changed our minds and the principles that survived.
The detailed engineering records remain in the repository. The Builder's Journal preserves the experience and meaning of building. This page sits between them. It explains the machinery in language I can return to, and that another person can follow.
Last updated: 27-sep-2026
The system today
Ravi Wiki currently follows a small path:
Markdown on my Mac
↓
Git repository
↓
Reproducible static build
↓
Verified release
↓
Caddy web server
↓
raviwiki.com
The repository is the authority. A page is not accepted because it looks right on one machine. The build checks its structure, links and metadata. Publication checks that the committed source produces deterministic artifacts, that the server receives the intended release and that the public bytes match what was built.
The current public release contains 30 public URLs, including a dedicated homepage, Ideas, Essays and Logs. The earlier release remains available as a rollback target.
For ordinary writing, the complexity is hidden behind a small operator workflow. I can take a finished Markdown file, author its page and move through verified publication without manually reconstructing the machinery each time. The production decision still belongs to me.
Principles
Evidence before architecture
We start with the smallest system that can reveal what is true. We add structure when observed behaviour requires it, not because a larger architecture feels more impressive.
The repository is the authority
The public site must be reconstructable from committed source. A working copy, a server edited by hand or an AI conversation is not the canonical system.
Stop safely
A refusal is useful behaviour. When identity, structure, links, tests or production state do not match the contract, the system should stop before creating a harder problem.
Verification follows the real contract
"It worked" is not enough. We ask whether the right commit produced the right bytes, whether the public server is serving those bytes and whether rollback still means what we think it means.
Human judgment remains at consequential boundaries
AI can investigate, challenge, implement and verify. It does not inherit the authority to publish, weaken authentication or make an irreversible production decision. Those boundaries remain explicit.
Learning must travel
Ravi Wiki is also a small engineering laboratory. A lesson becomes useful when it is demonstrated here, recorded honestly and then evaluated for transfer to larger work such as MV Horizon.
Before the Blueprint
The Blueprint begins after the foundations were already in place. BP01 is the first feature recorded in this format; it is not the beginning of Ravi Wiki.
Ravi Wiki had moved from a domain and a small server to a reproducible Markdown publishing system. HTTPS, release directories, a live pointer, rollback, deterministic builds, provenance and public verification had been established. Ideas and essays had their own collections while their public URLs remained short. The rw command had gradually reduced ordinary authoring, editing and publishing to a few deliberate actions without removing the checks underneath.
Those milestones will be backfilled only from verified repository evidence. Until then, this short prehistory is intentionally a summary rather than a reconstructed chronology.
Feature index
| ID | Date | Feature | Status | Permalink |
|---|---|---|---|---|
| BP04 | 27-sep-2026 | Daily Log becomes a running public record | Live | BP04 |
| BP03 | 16-sep-2026 | Safe page deletion | Live | BP03 |
| BP02 | 15-sep-2026 | Ravi Wiki Blueprint and recurring feature record | Live | BP02 |
| BP01 | 14-sep-2026 | Dedicated homepage and root publishing | Live | BP01 |
BP04 · 27-sep-2026 · Daily Log becomes a running public record
Status: Live
Public surface: Logs
Launch: 5600afa
Current form: 22521e6
Why we built it
I wanted a small public record of work and thinking: not social media, not a second blog and not an attempt to narrate every day. The useful unit was a concise note that could accumulate quietly over time.
The first question was where that record should live. A database or separate publishing system would have made a small habit depend on another service. Instead, each day became one Markdown file in the repository. That keeps the source visible, reviewable and recoverable, while allowing more than one entry on the same day.
The first release proved the authoring model. It did not yet prove the reader experience.
What looked simple
At first, /logs was a reverse-chronological list of dates. It was structurally correct: a reader could find every day, and every day had its own short, flat address.
But it asked the reader to do unnecessary work. The page repeated “Daily Log” beside every date and required another click to read each entry. It was a filing system, not a running record.
The correction looked visual, but it crossed the content model, build, authoring command, publishing shapes, deletion behaviour, anchors, homepage navigation and verification. The important question was not how to make the list prettier. It was how to show one public record without creating a second source of truth.
What changed
/logs is now a readable, reverse-chronological running log. It is generated from the canonical daily Markdown files, so entry text is authored once and appears both on its own day page and in the public record.
Dates retain their compact, durable addresses, such as /27sep2026. The running page also gives each date an anchor such as /logs#27sep2026, and each entry an address such as /logs#27sep2026-2. The corresponding daily page carries the same entry anchor.
The authoring model remains deliberately small:
one Markdown page per day
↓
one or more concise entries
↓
rw log appends safely
↓
the build derives /logs
The homepage now links to the record quietly, beside Blueprint:
Blueprint · Logs
The primary navigation remains unchanged.
What went wrong
The original index followed the storage structure too closely. One file per date is a good authoring model, but it does not mean readers should have to open one page per date.
Changing /logs into a generated view exposed an older assumption in the publishing workflow. A new ordinary collection page had always arrived with a changed collection index, and a deleted one had always removed an index entry. Once the log index became derived rather than maintained by hand, that shape was no longer truthful.
The answer was not to weaken publishing generally. A narrow Daily-Log-only rule now allows a new or deleted date page to stand alone. Ordinary page and collection behaviour remains unchanged, and mixed changes are still refused.
One limitation remains visible rather than hidden. Entry anchors are stable while entries are appended normally. If someone manually reorders or removes an earlier entry, later position-based anchors change. The system records this honestly instead of pretending that a convenience identifier is independent of its source order.
The decisions
The daily Markdown page remains the authority. /logs is a derived public view, not another document someone has to update.
The public model keeps both levels of addressability. A date is useful when referring to a day as a whole; an entry is useful when referring to one observation within it. Both are generated deterministically from the date slug and the entry’s position.
The publishing and deletion exception is specific to content/logs/ and fails closed. It exists because the log index is generated; it does not create a more permissive route for essays, ideas or other pages.
The old grouped divider was removed with the old index-only presentation. A running record should be read as a sequence, not as batches of links.
Evidence
The first Daily Log release is recorded as RW-DEP-012. It made ten dated pages containing eleven entries public.
The current running-record release is commit 22521e6, recorded as RW-DEP-013. Before publication, two clean builds were byte-identical. The complete check passed with 214 content checks, 55 authoring checks, 38 Daily Log checks, 95 editing checks, 411 publishing checks, 179 artifact checks and 83 interface checks.
After deployment, all 30 public URLs returned 200 and every response body matched its trusted build artifact. The previous release was preserved as the rollback target. No web-server configuration changed.
What I learned
A source model and a reader model do not have to look alike.
One Markdown page per day remains the simplest way to author this record. A single running page is the simplest way to read it. Treating either one as the whole product would have forced the other to become worse.
The revision also reinforced a useful constraint: derived views should remove maintenance, not merely move it. The moment /logs stopped being a manually maintained list, the build, publishing workflow and deletion workflow all had to agree on what that meant.
The initial list was not a failure of engineering. It was useful evidence. It made the missing reader experience obvious while the underlying source model was still easy to preserve.
Transferable learning
For larger systems, keep authoritative records and public or operational views distinct. A view should be reproducible from its source and should not create a second place where the same fact can drift.
When a derived view changes an existing workflow shape, make the compatibility rule narrow, explicit and tested. “Allow this one truthful exception” is safer than “make the rule more flexible.”
Finally, permanence is a contract, not a visual detail. Before adding a permalink, decide what it names, what keeps it stable and what can legitimately cause it to change.
What remains open
The running log will grow. Pagination or archival grouping can wait until the current single-page form becomes difficult to use.
Topics, people links, search, private logs and comments remain out of scope. The public log is intentionally small: concise entries, clear addresses and one repository-authoritative source.
None of these is an automatic commitment. They are the next visible choices.
BP03 · 16-sep-2026 · Safe page deletion
Status: Live
Removed surface: /hptest
Release: 9ac176a
Why we built it
Ravi Wiki could add pages and change them, but it had no ordinary way to remove one. That gap matters more than it first appears. A system that can only grow eventually pushes you toward bypassing its ordinary workflow with low-level Git commands or direct changes on the server, and those are exactly the habits this project exists to avoid.
So deletion had to arrive the way everything else arrives here. It had to begin in the repository, stay understandable while it is happening, remain recoverable if I change my mind, and produce the same publication evidence that adding a page produces. Taking a page off the site should change what is currently true in public without erasing the record that it was ever there.
The first deliberate target was /hptest, a temporary page I used while working on the homepage. It had finished its job and had been sitting in public ever since, which made it both the honest first candidate and a low-risk one.
What looked simple
It looked like three small steps: delete one Markdown file, remove one line from the collection index, publish. What it actually touched was most of the system: deletion crossed canonical identity, authored links, generated indexes, working-tree classification, commit creation, artifact inventory, public verification and rollback preservation.
The asymmetry took me a while to see clearly. Adding a page proves presence: the page is there and it serves the bytes we expect. Deleting one requires proving absence, and absence is the harder claim, because a missing page can mean either a deliberate removal or a deployment mistake.
What changed
The whole workflow is now two commands:
./rw delete hptest
./rw publish
rw delete begins by requiring a completely clean repository, so the deletion is unambiguously the only thing in front of me. It resolves the name through the same locator rw edit uses, so a page means the same thing to both commands. Version 1 accepts ordinary collection pages only, and refuses the homepage, singletons, collection indexes, unknown or ambiguous names, symlinks, paths resolving outside the content folder, and any page something else still links to.
Before touching anything it shows the title, slug, collection, source path, public URL, the exact index entry that will disappear, the exact files that will change, and the command that undoes it. Then it asks for the confirmation typed exactly as delete hptest.
On that confirmation it removes exactly two things: content/essays/hptest.md, and the single generated entry for that page in content/essays/index.md. If any part of the preparation or verification that follows fails, both files are restored byte for byte, so there is no such thing as a half-finished deletion. What it leaves behind is unstaged and uncommitted, which means nothing public has changed yet.
rw publish accepts only that exact two-file shape. It reconstructs the deleted page's slug from the copy Git still holds at the previous commit, because the file that declared it is gone by then, and commits with the subject content: delete hptest.
The publishing step learned the part I think matters most. It compares the inventory of the release going out with the one coming in, and whatever the old release served and the new one does not is a removal. It announces those removals before asking for production confirmation, and after the switch it requires each of them to answer 404 with no redirect.
Nothing is deleted from the live server. A release is a new immutable directory, so removal is expressed as absence from the new release rather than as a file being erased. No web-server configuration changed, and the previous release remains on disk as the rollback target.
What went wrong
Nothing broke in production, but the design found four things worth recording. The page locator had already learned, when the Blueprint was published, to resolve singletons and collection indexes so they could be edited. Deletion therefore could not rely on those pages failing to resolve, because they resolve perfectly well. The refusals had to be written explicitly.
Before this feature, rw publish refused every working tree containing a deletion, including a valid one. That was correct while nothing could produce a safe deletion, and it became the main obstacle once something could.
The publishing step verified that every page in the new release was served correctly, but had no way of knowing that a page I had deliberately removed was actually gone. A removal could have been published with no proof that anything had changed in public.
The build turned out to be stricter than I expected, which was a pleasant discovery. It already refused both halves of an incomplete deletion: a page removed while its index entry remained, and an index entry removed while the page remained.
One smaller thing is worth keeping. My first version validated a singleton deletion in the wrong order and complained about a missing companion index, when the truthful answer was simply that the page was not an ordinary collection page. Reordering the checks fixed the message, and a refusal is only useful if it names the real reason. A collection's last page, by contrast, needed no special handling at all, because an empty generated region was already valid.
The decisions
Version 1 deletes ordinary pages only. Retiring a whole section changes the shape of the site rather than its contents, and deserves its own design rather than being folded in here.
Preparation is separated from publication. The local deletion is a complete, reviewable act that changes nothing public, and publishing it is a second decision. The confirmation is the slug typed back rather than a yes or no. Typing the name makes me identify the page a second time and makes a reflexive confirmation less likely.
A page something still links to is refused rather than silently broken. The page's own generated collection entry is not treated as such a link, because that entry is bookkeeping the system maintains and removes as part of the same act. Publication requires an exact working-tree shape, and identity comes from repository evidence rather than from what I typed, including reading the deleted file's previous version to recover its slug.
Removal is absence from a new immutable release, and the page is never deleted directly from the live server. In public, removal means 404 with no redirect, because a retired page that quietly redirects somewhere else has not been retired at all. The previous release is preserved as the rollback target, rollback was not exercised simply to create theatre, and human authorization stays at both consequential boundaries: the destructive preparation, and the production confirmation.
Evidence
The architecture was audited first and recorded as RW-DELETE-001, before any code existed. The implementation is commit d4ff456, and the first production deletion is release 9ac176a, recorded as RW-DEP-010.
The deletion commit changed exactly two content paths: content/essays/hptest.md was deleted, and content/essays/index.md lost one generated entry. That second change was checked rather than trusted. The expected index was rebuilt from the previous commit using the build's own entry-removal function and compared byte for byte, and it matched apart from that single line.
The repository's complete check ran 810 assertions with zero failures: 147 content, 55 authoring, 95 editing, 406 publishing flow and 107 artifact checks. Two clean builds were byte-identical, and the candidate release contained 17 pages, one fewer than before.
After deployment, all 17 surviving public URLs returned 200 and every response body matched its trusted build artifact. /hptest returned 404, with no redirect and the expected empty response body. The Essays index no longer linked to it, and no live page linked to it at all. The web-server configuration was unchanged. The deployment transcript records the previous release 7ff7f654 as preserved and as still retaining the removed page, and rollback was not exercised.
What I learned
Deletion is not the opposite of preservation. I had been treating them as opposites, which is why the feature felt uncomfortable before I built it. A good deletion removes something from the current public surface while keeping its history recoverable, and those two things turn out to be compatible rather than in tension.
Absence needs evidence of its own. A successful build of the remaining pages proves nothing about the page I meant to remove, because those pages would build perfectly well whether or not the removal reached the server. The removed address has to be checked directly.
A destructive command should say what it is about to do in ordinary language before it does it. The part of rw delete I value most is not any of its refusals. It is the short summary it prints before asking, which lets me notice a mistake while it is still free to fix. Separating preparation from publication created the same kind of pause: between the two commands the deletion exists only on my machine, and a single restore command puts it back.
The system became more trustworthy by learning to say no. Most of this work was not the deletion itself but the list of deletions it refuses to perform, and the whole feature still reduces to two commands.
Transferable learning
For MV Horizon and other larger systems, the first idea is that negative-state verification is a real contract. A system that retires data, routes or artifacts should prove they are absent where they are supposed to be absent, not merely that everything else still works.
Immutable releases are what make a destructive-looking action reversible. The new state does not destroy the old state, so strictness about the removal and the ability to undo it stop competing with each other.
Separate intent, preparation, authorization and verification into distinct steps, so each can be reviewed, refused or undone on its own terms. Derive removal sets by comparing a known before and after inventory rather than relying on a list someone maintains by hand, because a derived set cannot be forgotten. Refuse a deletion while live references remain, and keep the distinction between current truth and historical evidence deliberate rather than accidental.
A safe workflow does not remove consequences. It makes them visible, bounded and recoverable.
What remains open
Version 1 deliberately does not delete singletons, collection indexes or the homepage. Pages with authored inbound links must have those links updated and published first, as a separate deliberate act.
The running user guide still needs the deletion commands added to it, and future deletions should use this same generic workflow rather than anything built for a particular page.
Rollback remains available and was not exercised during this feature. Historical releases continue to retain deleted pages, which is what makes rollback meaningful, and a release-retention policy remains a separate question that has not been addressed. No further deletion capability should be added without evidence of a real need for it.
BP02 · 15-sep-2026 · Ravi Wiki Blueprint and recurring feature record
Status: Live
Public surface: Blueprint
Release: df6715a
Why we built it
Ravi Wiki already kept careful records, but none of them did this particular job. The deployment records preserve operational evidence, and they are written for the moment a release has to be trusted or undone. The Builder's Journal preserves the experience and meaning of building. Neither of them explains, feature by feature, why the system changed shape and what the change actually cost.
This page is the middle layer. It connects purpose, architecture, failures, evidence and founder learning in language I can return to in a year, and that another person can follow without access to the repository.
It is also my answer to what building in public should mean. I did not want to publish terminal transcripts, and I did not want to pretend that every internal detail is interesting. I wanted to publish the reasoning and the evidence behind it.
What looked simple
This looked like one recurring Markdown page and a quiet link on the homepage. The writing would be the work, and the machinery was already there.
Two small choices turned out to carry the feature. The document's feature index is a Markdown table, and the page is a singleton whose whole source is a single index.md. Each of those quietly assumed a capability the site did not yet have.
What changed
blueprint became a declared singleton alongside about, now and work, so it publishes at /blueprint under the existing metadata, canonical, sharing and provenance rules. No Blueprint-specific rendering or publishing path was added.
The homepage gained a quiet monospace Blueprint link beneath its navigation. The primary row is unchanged and still reads Essays · Ideas · Work · Now, because those four are the settled navigation and this is an aside beside them rather than a fifth item inside them.
The build learned to render Markdown tables, with only the table elements registered rather than the whole GFM extension.
The page locator learned that a section index is a page someone can ask for, so rw edit blueprint now resolves content/blueprint/index.md. rw publish learned one additional accepted shape: exactly one modified singleton source that already exists at the last commit. It continues to refuse new, deleted, renamed, staged and mixed states, and no new command was created for any of this.
What went wrong
The renderer could not render the feature index. The build used CommonMark with no extensions, and no page on the site had ever contained a table, so nothing had exposed that limitation before. The obvious fix was to switch on the full GFM extension, and I measured what that would do before doing it. It would also have enabled strikethrough and bare-URL autolinking, which changed the rendered output of four already published essays. Published bytes are not something to change as a side effect of teaching the build a new block, so the table elements were registered on their own.
rw edit blueprint then failed outright. The page finder walked ordinary pages and skipped every index.md, which meant no section index had ever been reachable by name. Essays and Ideas carried the same latent limitation, and nobody had noticed because nobody had needed to edit a section index through the tool.
The last failure was visible rather than structural. At 320 pixels the feature index pushed the entire page sideways. The document measured 345 pixels wide inside a 320 pixel window, and the word Permalink was cut off at the edge of the screen. Every structural check had passed, because nothing structural was wrong. The fix follows the rule the site already applies to long code lines, and lets the table scroll inside its own box rather than widening the page:
table { display: block; overflow-x: auto; max-width: 100%; }
After that the document measured exactly 320 pixels again, and the final column could be reached by scrolling the table while the page itself stayed still.
I would rather record these as discoveries than as embarrassments. Each one was a capability the site was missing, and each was found by asking the site to describe itself.
The decisions
The public name is /blueprint, because that is what a person would type and remember. The BP identifiers belong to the entries rather than to the page, so BP01, BP02 and everything after them are addressable on their own at permanent anchors such as /blueprint#bp02.
Dates display as dd-mon-yyyy, and entries appear newest first. The Blueprint is an ordinary singleton using the generic site contracts rather than a new structural class.
Only the table elements are enabled, and the table itself is styled as little as possible. Containment is the only rule it receives, and everything else is the browser's own rendering.
The homepage link is quiet through size and position rather than through fading, because a link a reader cannot comfortably read is not restraint.
Human authorization stays exactly where it was. Committing and deploying remain deliberate acts, and this page does not soften either of them.
The Blueprint is updated after a meaningful feature rather than after every implementation gate.
Evidence
The feature shipped as commit df6715a. The release generated 18 pages, and all 18 public URLs returned 200 with every response body matching its trusted build artifact. /blueprint carries commit-bound provenance for that commit, and its metadata, canonical URL, BP01 anchor and homepage link were each verified against the published bytes.
The repository's complete check ran 734 assertions with zero failures: 142 content, 55 authoring, 57 editing, 387 publishing flow and 93 artifact checks. Two clean builds were byte-identical.
The page was inspected in a real browser at 1280 by 900, at 390 pixels and at 320 pixels. After the table fix there was no page-level horizontal overflow at any of those widths, the primary homepage navigation stayed on one line at all three, and fragment navigation to /blueprint#bp01 landed on the BP01 entry.
The previous release remained preserved as the rollback target, and rollback was not exercised.
What I learned
A public record is only worth keeping if maintaining it is easier than reconstructing it later. That is the reason the Blueprint had to work through the ordinary editing and publishing path instead of receiving a command of its own.
Writing it exposed real gaps in the system, and that happened precisely because the page had to use the same machinery as every other page. A document that describes a system turns out to be a reasonable way to test whether that system can describe itself.
The 320 pixel failure taught me something I had been quietly conflating. Tests and inspection are different kinds of evidence. The structural checks proved the page was structurally valid. Only looking at it showed that it was hard to use. Neither one substitutes for the other.
A recurring record earns its credibility on the second entry rather than the first. BP01 established a rule, and BP02 is the first opportunity to actually follow it.
Transferable learning
For MV Horizon and other larger systems, the useful idea is that documentation can act as a product probe. If a system cannot describe its own evolution through its normal workflow, its authoring model is probably too special-cased, and writing the description is a cheap way to discover that.
The second idea is about how to add capability. Both additions here were deliberately narrow: table rendering rather than all of GFM, and generic section resolution rather than a Blueprint-specific lookup. A narrow addition that preserves existing behaviour is easier to justify, easier to verify, and far less likely to disturb something already published.
The third is about what a public trail should contain. Compress the decisions, the failures, the evidence and the learning, and leave out both the secrets and the transcripts.
What remains open
/hptest is still public and still waiting for a verified deletion workflow. That workflow is the next product change I expect to make, and once it has been accepted it should be recorded here as BP03.
Work and Now remain deliberately unavailable until those pages exist. Earlier Ravi Wiki milestones may be backfilled, but only from verified evidence rather than from memory.
The running user guide should gain deletion commands only after deletion has been implemented and verified, and not before.
None of these is an automatic commitment. They are the next visible choices.
BP01 · 14-sep-2026 · Dedicated homepage and root publishing
Status: Live
Public surface: raviwiki.com
Release: 86d937b
Why we built it
Ravi Wiki had pages but no real front door. Visiting the root address redirected to Ideas. That was a sensible beginning, but it no longer described the site.
I wanted a homepage that did very little and did it clearly: say who I am, say what I am doing and offer a few paths into the wiki. No portrait, no large navigation system and no attempt to turn the wiki into a personal-brand landing page.
The final page contains four short paragraphs, followed by Essays, Ideas, Work and Now. Work and Now remain muted text until those pages exist, so the homepage does not pretend that an unfinished part of the site is available.
What looked simple
At first this appeared to be a small content and design task. Write the copy, choose the typography, add the links and publish /.
The design did become simple. The route did not.
Every existing page lived below a named path. The build produced files such as ideas/index.html, and the server redirected the root address to /ideas. A homepage introduced a different artifact: index.html at the root of the release.
That one change crossed the complete system:
content model
↓
build destination
↓
artifact inventory
↓
link verification
↓
server routing
↓
rollback behaviour
A new page is usually content. A new root URL is architecture.
What changed
The build gained a dedicated root-page class rather than disguising the homepage as an ordinary collection or singleton. The homepage still uses the same Markdown parser, metadata rules, stylesheet and provenance system as every other page, but it has its own restrained layout without the ordinary masthead, byline or back link.
Publication learned that a release may legitimately contain a root index.html. It now derives the expected behaviour from the release being examined:
- a release with a homepage must serve
/with status 200 and the exact trusted bytes; - a historical release without a homepage must redirect
/to/ideas; - rollback must restore whichever behaviour belongs to the release selected.
The web-server rule follows the active release. If that release contains index.html, it serves the homepage. If it does not, the historical redirect returns automatically. This keeps rollback a one-step release change rather than a release change followed by a configuration repair.
What went wrong
The first visual experiment included an ASCII portrait. In the Markdown source it looked playful. On the rendered page it became a large block of punctuation that overwhelmed everything around it. The experiment did its job: it showed us what not to ship. The final homepage removed the portrait and kept only the name, four paragraphs, navigation and a quiet last-updated line.
The experiment also contained a link to /work before that page existed. Local content checks passed earlier in the authoring path, but production verification refused the release because every internal link must resolve to a page generated by that release. Nothing reached the server.
A spelling correction exposed another contract. The page's index gloss was stored both in the page metadata and in the generated collection entry. Correcting one without regenerating the other created a mismatch, and publication stopped again. The failure was accurate: two supposed representations of the same fact had diverged.
The root page then revealed three assumptions in the deployment path: artifacts were expected to live inside named directories, / was expected to redirect forever and the server configuration itself was pinned as immutable. Each assumption had once been useful. None was wrong until the product changed.
Finally, two temporary operator scripts failed before installation. One hid a remote privilege prompt inside captured output. The next authenticated successfully but ran the requested command outside the privileged boundary. Both failures stopped before the live configuration changed. The third version made the prompt visible, placed the command inside the privilege boundary, created a verified backup, installed the committed configuration and reloaded rather than restarted the server.
These were not elegant moments. They are exactly why this Blueprint exists.
The decisions
We chose a source-first transition. The complete homepage, publishing support, server configuration and verification tests were committed and pushed before the server configuration was touched. The server received the configuration from that exact committed source, not from an uncommitted working file.
We installed the routing change while the old release was still live. That made the new rule observable while dormant: / continued redirecting to /ideas, all 16 existing pages remained byte-identical and the live release did not move. Only after that proof passed did we publish the homepage release.
We also kept the previous release intact. A rollback was not performed merely for theatre, but its behaviour was derived and verified: selecting the old release would remove the root artifact and restore the redirect without another server edit.
Evidence
The accepted release produced 17 public URLs. All 17 returned status 200 after deployment, and every public body hash matched the trusted build artifact. The homepage's public bytes matched its root index.html. The server configuration matched the committed configuration. The earlier release remained preserved as the rollback target.
Before publication, the repository's complete check ran 678 assertions across content, authoring, editing, publishing flow and artifact verification, with zero failures. The release was bound to commit 86d937b.
What I learned
The number of gates initially felt disproportionate to a small homepage. In hindsight, the important distinction was not page size. It was topology.
The homepage altered the meaning of the root URL, the shape of a valid release and the behaviour expected during rollback. Once traced as a path from source to build to artifact to router to verification to recovery, the work became understandable.
Some of the gates were unavoidable because they protected a real production boundary. Some were the cost of discovering assumptions late. The better question for the next unusual feature is therefore not, "How small does this look?" It is, "Which contracts does this cross?"
The failed scripts added a second lesson. Safety does not require every attempt to succeed. It requires failed attempts to stop before they make the situation worse, and to leave enough evidence to understand the next move.
Transferable learning
For MV Horizon and other larger systems, this feature suggests a practical test for apparently small changes:
Source
→ Build
→ Artifact
→ Router
→ Verification
→ Rollback
If a change crosses several of these boundaries, estimate and govern it as an architectural change even when the visible result is only one page.
It also reinforces a principle already visible throughout Ravi Wiki: authority and execution should be separate. AI can carry a large share of the reasoning and implementation, while authenticated access, production confirmation and acceptance remain with the human operator.
What remains open
The /hptest experiment remains public and can be removed through a separate, verified deletion workflow. Work and Now remain deliberately unlinked until their pages exist. Earlier milestones can be backfilled when their evidence has been traced rather than reconstructed from memory.
None of these is an automatic commitment. They are the next visible choices.
How this Blueprint will evolve
Every accepted feature receives a sequential identifier: BP01, BP02, BP03 and so on. The display date uses dd-mon-yyyy, such as 14-sep-2026.
Each entry has a permanent, title-independent anchor. BP01 will remain available at /blueprint#bp01 even if its title is refined later. Dates and titles provide context; the BP identifier provides continuity.
Entries appear newest first. Each records the feature's purpose, user-visible change, important architecture, decisions, failures, evidence, founder reflection, transferable learning and open questions.
The Blueprint is updated after a meaningful feature, not after every implementation gate. Whenever practical, its entry ships in the same release as the feature. Internal-only changes may wait for the next normal public release rather than causing a deployment solely to update this page.
The aim is not to make every detail public. The aim is to make the reasoning traceable.