CON-11: archive a page, and find it again in the archive - #94
Merged
Merged
Conversation
Archiving a page is not a state you set on it — Nostr events are immutable, so there is nothing to set. It is another revision on top of the current head, carrying an `archived` tag, with the content and the placement travelling along unchanged. Restoring publishes the same revision without the tag. `Page.archived` is read off the head, so the tree, the search and the breadcrumbs all honour it without being told, and the history stays complete on both sides of the move: an archived page can be read, compared and blamed exactly as before. The placement (`31818`) is deliberately left alone. It has no effect while a page is out of the tree, and deleting it would make a restore land the page wherever its title sorts to rather than where it was. Subpages do not go with the parent; they move up to the top level. That is the one thing people assume the other way round, so the confirmation says it, counted. Confirming happens in the app, not in the browser. `ConfirmDialog` wraps a native `<dialog>` — the top layer, the backdrop, the focus trap and Escape come from the platform — and the confirming button says the act rather than `OK`, with Cancel holding the focus. jsdom ships `HTMLDialogElement` without implementing any of its behaviour, hence the shim in `src/test`.
Archiving without somewhere to look is a one-way door: the only route back to a page was a link somebody still happened to have. So the archive gets an address. A row under the page tree leads to `/s/:group/archive`, with a count beside it when there is something in it, and the view lists what was archived — newest first, ties broken by slug so the order does not shuffle between renders — with the author, the date and one button per row to bring a page back. The space overview links there too, under its page list. The route sits above `:slug` in the table, so `archive` is a route and not a page that happens to be called that. A page whose slug normalises to one of the app's own words is shadowed by it — `new` and `search` have had that since they were added — and that is CON-50, not this branch.
molgerz
force-pushed
the
feat/con-11-archive-page
branch
from
September 16, 2026 23:35
c1125e2 to
c76b660
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Archiving takes a page out of the tree, the search and the space overview
without deleting anything, and the archive is a place you can walk into to
bring one back.
How it works
Nostr events are immutable, so archiving is not a state change but another
revision: a
1818on top of the current head carrying anarchivedtag,with the content and the placement travelling along unchanged. Restoring is
the same publish without the tag.
Page.archivedis read off the head, sothe tree, the search and the overview all get it for free, and the history
stays complete on both sides of the move.
The placement (
31818) is deliberately left alone. It has no effect while apage is out of the tree, and deleting it would make a restore land the page
wherever its title sorts to instead of where it was.
Subpages do not go with the parent — they move up to the top level. The
confirmation says so, counted, because it is the one thing people assume the
other way round.
What you can see
Archive this page, and on an archived page a callout withBring the page back.Archiverow under the page tree, with a count whenthere is something in it.
/s/:group/archive— what was archived, newest first, with author anddate, and one button per row to bring it back.
says that it is archived; a trail stops at an archived parent.
Confirming
window.confirmis gone.ConfirmDialogwraps a native<dialog>, so thetop layer, the backdrop, the focus trap and Escape come from the platform.
The confirming button says the act rather than
OK, and Cancel holds thefocus. jsdom ships
HTMLDialogElementwithout implementing any of itsbehaviour, hence the shim in
src/test.Notes
the same feature "hide" with a tombstone revision. This branch sits on
mainand carries no NIP-09 deletion code.mainafter this lands — it currently carries both the old CON-11implementation and the abandoned CON-10 commits.
archive,neworsearchis shadowed bythe app's own route. That is older than this branch and filed as CON-50.
Gates
typecheck,lint,test(48 files / 468 tests) andbuildall pass.