Skip to content

feat(library): open on the org home folder, system folders inside it - #5381

Open
vibegui wants to merge 1 commit into
mainfrom
vibegui/library-home-folders-first
Open

feat(library): open on the org home folder, system folders inside it#5381
vibegui wants to merge 1 commit into
mainfrom
vibegui/library-home-folders-first

Conversation

@vibegui

@vibegui vibegui commented Jul 29, 2026

Copy link
Copy Markdown
Contributor

Why

The Library leaked its implementation at every turn:

  • It opened on a synthetic root view listing volumes — a card named after the org slug, subtitled "Your organization's home folder", sitting next to uploads / outputs / public — with Recently added pushed above them. Folders, the thing you actually came for, were below the fold.
  • Clicking the org card navigated to browse path home, so the breadcrumb and the <h1> both read "home". Nobody knows that {org_name} == home.
  • The folder name was rendered twice (breadcrumb + heading), burning vertical space.
  • The search box said "Search all files" even three folders deep.

What changed

  1. Lands on the org's home folder, named after the org. The path="" root view is deleted — home is the top of the tree, and the breadcrumb starts at homeDisplayName(org.slug). Nothing in the UI says "home".
  2. uploads / outputs / public are system folders inside home, in a graphite folder tone (vs Finder-blue for folders people make) so "the product fills this" reads at a glance. public presents as skills. Mounts and browse paths are untouched — orgFsMountPath and the agent-facing org/home/… paths are unchanged.
  3. Duplicate <h1> gone. The breadcrumb is the only name; the search box moves into the reclaimed header row.
  4. Search really scopes. volume + prefix query params on GET /fs/search thread down to a new pathPrefix filter in searchFiles. Global at the home root ("Search all files…"), scoped to the current subtree everywhere else ("Search files in decks…") — the label now matches the behavior instead of lying about it.
  5. Recently added moves to the bottom of home, and only appears there. It's cross-volume, so it would be a lie inside a single folder.

Two bugs the restructure exposed

Both are consequences of home becoming a real browsable folder, fixed in this PR rather than left for a hardening pass:

  • mkdir/move were bound to the upload volume. "New folder" at the landing view would have created the folder in uploads, and drag-move at home would have moved within the wrong volume. They now bind to the browsed volume. Uploads still target uploads from the landing view (unchanged behavior).
  • The empty-area right-click → new-folder gate fired only at the root, which now has entry cards under it. Right-clicking a card would have opened rename and new-folder. It now keys off defaultPrevented, which the cards already set.

Also fixes "See in library" — dead since it set main: "library:<path>", a tab id no parser handles — and routes its hardcoded English label through t().

Screenshots

Home (landing) Inside a folder
Folders first (system folders lead, graphite + glyph + read-only eye on skills), then Files, then Recently added. Breadcrumb reads the org slug. {org} > decks, placeholder scopes to the folder.
Scoped search Global search
"sales" inside decks1 result. Same query at home → 5 results, every volume.

Testing

  • Unitlocation.test.ts gains isHomeRoot + segmentLabel cases.
  • Real-Postgres integration — new searchWithEffectivePublic case covers prefix scoping: recursive under the dir, a same-prefix sibling dir (reports-archive) excluded, _ treated literally, and composition with volume narrowing. Verified it fails when the prefix filter is removed.
  • End-to-end against a real dev server (throwaway Playwright spec, not committed): signup → seed files across home/uploads/outputs → walk home → folder → system folder → skills. Asserted the landing view names the org and has no <h1>, section order is Folders, Files, Recently added, the scoped search returns 1 where the global returns 5, skills is read-only with no write actions, and a new folder created at the landing view lands in home (checked over the API, not just the UI).
  • bun run fmt, bun run check, bun run lint (same 16 pre-existing warnings, 0 errors), bunx knip clean. bun test apps/web/src: 2173 pass / 23 fail vs. baseline 2171 / 23 — same pre-existing failures, +2 from the new tests.

Docs

studio/library.mdx (en + pt-br) rewritten to describe the home-first tree, the system folders, and the scoped search. The sandbox mount table now shows <your-org>/uploads → org/upload etc., making explicit that the presentation moved and the mounts did not.

Deliberately skipped

  • Multi-volume search scope at the public sets listing (stays global there — volume === null).
  • Hoisting the system cards above the Skills/Brands sections; they're first among Folders, not first on the page, when a skill dir sits in the home root.
  • Declaring path/skill/brand in the route validateSearch schemas. Verified in @tanstack/router-core that unknown params survive both navigation and reload ({...parentSearch, ...strictSearch}, search.strict unset) — which is why ?skill= works today. Unchanged by this PR either way.

🤖 Generated with Claude Code


Summary by cubic

Open the Library directly in your org’s home folder and show uploads/outputs/public as system folders inside it. Search now scopes to the current folder (or stays global at home) for results that match the placeholder.

  • New Features

    • Home-first navigation: breadcrumb starts at your org; duplicate heading removed; search moved into the header.
    • System folders inside home: graphite-toned icons; public presents as “skills” and is read-only. Mounts and browse paths are unchanged.
    • Scoped search: GET /fs/search accepts volume and prefix to filter by volume and directory subtree; cross-volume at home, scoped elsewhere.
    • “Recently added” moved to the bottom of home and only appears there.
  • Bug Fixes

    • New folder and drag-move act on the browsed volume (not uploads); uploads from the landing view still go to uploads.
    • Right‑click new-folder only fires on empty space, avoiding conflicts with card rename.
    • “See in library” now navigates via the files tab using path, and its label is localized.

Written for commit a7d892f. Summary will update on new commits.

Review in cubic

The Library leaked its implementation. It opened on a synthetic "root" view
listing *volumes* — a card named after the org slug ("Your organization's home
folder") next to uploads/outputs/public, with "Recently added" pushed above
them. Clicking the org card navigated to browse path `home`, so the breadcrumb
and the `<h1>` both read "home" — a word no member has any reason to connect to
their org. The folder name was rendered twice, and the search box promised
"Search all files" from three folders deep.

- Lands on the org's home folder, named after the org. The `path=""` root view
  is gone; home is the top of the tree and the breadcrumb starts there.
- uploads / outputs / public render as system folders *inside* home, in a
  graphite folder tone so "the product fills this" reads at a glance. `public`
  presents as "skills". Mounts and browse paths are unchanged.
- Drops the duplicate `<h1>`; the breadcrumb is the only name, and the search
  box moves into that row.
- Search now really scopes: `volume` + `prefix` params on GET /fs/search thread
  down to a `pathPrefix` filter in `searchFiles`, so "Search files in decks"
  searches decks. Global at the home root, as the placeholder says.
- "Recently added" moves to the bottom of home, and only appears there — it's
  cross-volume, so it would be a lie inside a single folder.

Two bugs the restructure exposed, fixed here:

- mkdir and drag-move were bound to the *upload* volume. Now that home is a
  real browsable folder, "New folder" at the landing view would have created in
  `uploads`; they bind to the browsed volume instead. Uploads still target
  `uploads` from the landing view, per the previous behavior.
- The empty-area right-click-to-create-folder gate fired at the root, which now
  has entry cards under it — it would have opened rename *and* new-folder
  together. It keys off `defaultPrevented` (which the cards already set).

Also fixes "See in library", dead since it set a `main: "library:<path>"` tab
id no parser handles, and translates its hardcoded label.

Verified end-to-end against a real dev server + Postgres (signup, seeded files
across volumes, walked home → folder → system folder → skills, confirmed the
scoped search returns 1 result where the global one returns 5, and that a new
folder at the landing view lands in `home`).

Co-Authored-By: Claude <noreply@anthropic.com>
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