Skip to content

Replace workspaces with nested collections - #1

Merged
mshddev merged 4 commits into
mainfrom
collections
Sep 4, 2026
Merged

mshddev merged 4 commits into
mainfrom
collections

Conversation

@mshddev

@mshddev mshddev commented Sep 4, 2026

Copy link
Copy Markdown
Owner

Summary

Workspaces are gone. Documents are top-level with a globally unique slug, and collections are optional folders that nest like a file tree. A document lives at the root or in exactly one collection.

Breaking. This changes every document URL, the API surface, the database schema, and the skill's script flags.

What changed

  • URLs. Browser: /docs/<slug>, /collections/<slug>, /collections, /archive?collection=<slug>. API: /api/docs/... and /api/collections/.... Old /workspaces paths return 404.
  • Collections. GET /api/collections returns a flat list with parentSlug, documentCount, and childCount; the client builds the tree. POST creates (optionally inside a parent), PATCH renames or reparents, DELETE needs an empty collection. Reparenting into your own descendant is rejected.
  • Publishing. The publish body takes an optional collectionSlug (null for the root, omitted to leave an existing document where it is). Republishing identical content with a new collection moves it without a new version but rotates the ETag.
  • Migration to schema 10. Documents from the default workspace move to the root, every other workspace becomes a root collection, and the migration refuses to run if a document slug exists in more than one workspace.
  • Web. The dashboard is a folder view with breadcrumbs. Browsing shows a folder's direct contents; searching reaches into subfolders and labels each match with its path. The collections page manages the tree.
  • Skill. Both scripts drop --workspace; publish-document.mjs gains --collection <slug> and --root. The watcher event no longer carries workspaceSlug. Reinstall the skill after upgrading.

Verification

  • Typecheck, build, and tests are green: 102 server tests, 69 web tests.
  • The migration ran against a copy of a real schema-9 database (45 documents, 4 workspaces): foreign keys clean, all documents, versions, and feedback batches present.
  • End-to-end pass on an isolated stack: both skill scripts (create, feedback watcher, republish with --feedback-match, move to root, stale ETag 412), and the browser flows for dashboard, folder view, move, archive and unarchive, a three-level collection tree with reparenting and the delete guard, root search into nested folders, and submitting a comment plus instruction from the review page.

Not in this PR

The architecture docs under docs/ still describe workspaces as design history. No version bump; the changelog has an Unreleased entry.

🤖 Generated with Claude Code

Documents are now top-level with a globally unique slug, served at
/docs/<slug> in the browser and /api/docs/<slug> in the API. Collections
are optional folders that nest through a parent; a document lives at the
root or in exactly one collection.

Schema 10 migrates existing data: documents from the "default" workspace
move to the root, every other workspace becomes a root collection, and the
migration refuses to run if a slug exists in more than one workspace.

The skill scripts drop --workspace; publish-document.mjs gains
--collection and --root. Reinstall the skill after upgrading.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@mshddev mshddev self-assigned this Sep 4, 2026
mshddev and others added 3 commits September 4, 2026 14:21
- Refuse to migrate a workspace slugged "root", which the document list
  reserves for documents outside every collection
- Let /api/archive?collection=root name archived root documents, matching
  the document list filter
- Indent nested option labels with non-breaking spaces so the tree shows
- Render the 404 page for an unknown collection instead of an empty folder
- Explain that a collection slug derives from its name on slug conflicts

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The reserved-slug migration error told users to rename the workspace,
but renaming never changed a slug. Name the SQL that does instead.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
A collection whose documents are all archived read as empty while
refusing deletion. The folder view now names the archived count with a
link to the archive, and the delete hint says archived documents count.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@mshddev
mshddev merged commit e77ea6e into main Sep 4, 2026
1 check passed
@mshddev
mshddev deleted the collections branch September 4, 2026 07:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant