You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Home: bring the Documents list to parity with Settings → Documents #390
Home shows a short Documents card for a signed-in person. Settings → Documents shows the Merged list with many more features. This issue brings the Home card to parity with Settings → Documents by reusing the Settings code, not by building a second list.
The maintainer's request, quoted exactly:
"let's update the list of document that we show up in the pwa version in the landing page like what we did in the document setting pannel"
Screenshots of both surfaces will be added by the maintainer.
This issue overturns earlier rulings.#247 and apps/webapp/CLAUDE.md §Documents list Favorites say Home reads the Owner live list only (scope: 'owned'). #247 also says Home has no sort, no search, no row menu, no grid and no Date buckets. The request above reverses those rules. The Open decisions section asks which of them change.
Why
A person who joined a pad cannot find it from Home today. Home lists only pads they own.
The same document shows different marks on Home and in Settings. Home has no avatars, no owner name and no ⋮ menu.
A person must open Settings to rename, favorite or copy the link of a pad they see on Home.
One list implementation is cheaper to keep correct than two.
Current behaviour
Home card: apps/webapp/src/components/pages/home/HomeDocuments.tsx, mounted in HomePage.tsx inside HomeCollapseRegion.
It calls useOwnerDocuments({ scope: 'owned', searchQuery: '', sortKey: 'lastOpenedAt_desc' }) with refetchOnWindowFocus: 'always'.
It shows the first 8 rows of the first page (HOME_DOCUMENTS_LIMIT). The page size is 20 (DOCUMENTS_PAGE_SIZE). Both read from code, not measured.
Each row is a button: LuFileText, DocumentRowLabel (title, star, lock, eye) and documentListDate. That date reads "Never opened" when lastOpenedAt is null.
"See all" shows only when total > 8. It opens Settings on the Documents tab.
The card hides while loading, on error and when the list is empty.
The gate is sign-in and isAuthServiceAvailable only. It is not gated on isPWAInstalled. So the same card shows in a browser tab and in the installed app. The rule "Do not gate that list on isPWAInstalled" must stay.
Command jump (components/commandJump/CommandJump.tsx) uses the same query key (owned, empty search, lastOpenedAt_desc). It fetches only while its dialog is open.
Settings list: apps/webapp/src/components/settings/components/DocumentsSection.tsx, loaded with next/dynamic from SettingsPanel.tsx.
Merged list (all) by default; Show filter all / owned / joined
Joined rows
Never
Yes, with the owner's name
Sort
Fixed Last opened
Last modified (default), Last opened, Date created, Name A→Z, Name Z→A
Search
No
Yes, debounced 350 ms (read from code, not measured)
List / grid
List only
Both
Favorites pinned, star
Pinned, star shown
Pinned, star, hairline after the block
Date buckets
No
Yes, on date sorts
Collaborator avatars
No
DocumentMembersCluster, up to 4 faces
⋮ menu
No
Open in new tab, Copy link, Rename, Duplicate, Favorite, Private, Read-only, Delete
Rename (F2)
No
Inline in list; dialog in grid
Delete with Undo
No
Inline Undo banner, 6 s (read from code, not measured)
Trash entry
No
Yes
Empty states
Card hidden
"No documents yet." with Create; Joined has its own text
Row cap
8, then See all
Pages of 20 with Load more
Backend. No new route is needed. GET /documents?scope=all already returns the Merged list (buildMemberScopeTiers in apps/hocuspocus.server/src/api/services/documents.service.ts). It pins only the caller's own Favorites, and it sorts a non-owned row as never opened.
Bug found during research (Owner live list pin order).buildDocumentsOrderBy pins with favorites: { _count: 'desc' }. That counts the Favorite rows of every user, not only the caller's. isFavorite counts only the caller's row. So a row can pin above others with no star, and a row with two Favorite rows outranks a row with one. The Home screenshot shows this: an unstarred row sits between two starred rows. The Merged list tiers use favorites: { some: mine } and are correct. This bug also reaches Settings "Owned by me" and Command jump.
Proposed behaviour
A signed-in person opens /, in a tab or in the installed app. The Documents card shows the Merged list by default: owned rows plus Joined rows.
Rows look and act like Settings list rows. A Joined row names its owner. A shared pad shows its avatar cluster. Favorites pin first with a star and a hairline.
The ⋮ menu offers the same actions as in Settings for the same row, following ownership. A Joined row offers only Open in new tab and Copy link.
A write from Home (rename, favorite, private, delete) updates every documents list, because useOwnerDocumentsCache already patches every key under ['documents', uid].
"See all" opens Settings → Documents. Settings shows the same scope and sort as Home.
A signed-out visitor sees no card and no documents request.
On a phone, the card still collapses when the keyboard opens, like the footer.
Scope
Slice 1, backend. Pin only the caller's Favorites on the Owner live list. Use the favorites: { some: { userId } } rule that the Merged list tiers already use. Deploy before slice 2.
Slice 2, data. Home reads the Merged list. Home and Settings read the same scope and sort session keys, so they share one query key.
Slice 3, rows. Home renders DocumentListRow and buildDocumentsListItems, with useDocumentMembers for the visible rows. Load them on the client after the profile arrives, so signed-out / loads no extra JS.
Slice 4, controls. Add the controls the maintainer picks below. Reuse the Settings Select, labels and session keys.
Slice 5, delete and rename. Lift the delete-and-Undo flow out of DocumentsSection so Home and Settings share it. Pick the rename path that survives keyboard collapse on a phone.
Out of scope
Command jump scope. It stays "places and owned pads" (CONTEXT.md §Pad tools).
New design tokens, sizes or species. Build from .cursor/docs/design-system.md §DocumentsSection and §Landing & history as written.
Gating the card on isPWAInstalled.
Caching the list in Cache Storage, the service worker, or Home GSSP.
Open decisions
Each item needs a maintainer ruling. The recommendation is mine, with the reason.
Default scope. Recommend the Merged list (all). That is the request, and it matches Settings.
Show filter on Home. Recommend yes, a compact Select that shares docsplus:my-docs-scope. Then Home and Settings never disagree.
Sort control and default. Recommend a sort Select that shares docsplus:my-docs-sort, default Last modified. Under Last opened, every Joined row sorts as never opened, so an 8-row card can hide every Joined row. This reverses Honest install line, Documents on Home, and a quiet Home Install #247, which chose Last opened.
Search on Home. Recommend no. The slug card is already a text field. On a phone, focus raises the keyboard, and HomeCollapseRegion then collapses the card that holds the search field. Command jump already searches owned pads.
Grid view. Recommend no. The card is max-w-2xl, and 8 rows of paper previews make Home very tall. See all gives the grid.
Avatars. Recommend yes. One batched RPC for the visible rows, and a solo pad shows nothing.
⋮ menu. Recommend yes, the same DocumentRowMenu. Its phone sheet already falls back to <body> when no dialog wraps it. Home already mounts GlobalDialog for the confirms.
Rename on a phone. Inline rename raises the keyboard, and the card collapses under the input. Recommend RenameDocumentDialog on Home below sm, and inline rename on desktop.
Delete on Home. Recommend yes, with the same inline Undo banner inside the Home card, lifted into shared code. The alternative is to leave Delete out of the Home menu.
Date buckets. Recommend yes, through buildDocumentsListItems, so both lists use one builder. The cost is header rows inside an 8-row card.
Row cap and See all. Recommend keep 8 rows and See all, with no Load more. See all shows when total > 8.
Empty states. Recommend: hide the card only when the Merged list is empty. When the Show filter narrows to zero rows, show the Settings empty text inside the card, so the filter stays reachable.
Signed-in owner: Home lists owned rows and Joined rows in one order. Each row matches Settings for the same scope and sort.
Owner Favorites pin first with a star. No row pins without a star (slice 1).
A Joined row names its owner. It has no star. Its ⋮ shows only Open in new tab and Copy link. F2 does nothing on it.
A person with Joined rows only and no owned pads sees those rows. A person with no rows sees no card.
A private or deleted pad the caller does not own never appears.
Visitor or signed-out: no card, and no request to /documents or get_document_member_previews.
Auth unavailable or fetch error: the card hides with no toast, and the slug card still works.
The card shows in a browser tab and in the installed app. It is not gated on isPWAInstalled.
A rename, Favorite, Private or Delete from Home also shows in Settings → Documents without a reload, and the reverse.
See all opens Settings → Documents with the same scope and sort as Home.
Each control the maintainer approves works on Home. Each control he rejects is absent.
Phone: the card collapses when the keyboard opens. No input the person is typing in collapses with it.
Phone: the ⋮ menu opens the documentRowMenu sheet. Back and Escape close it. Every target is at least 44 px.
Light and dark, in every theme, the card uses only the tokens and recipes in design-system.md.
Performance: Home and Settings with the same scope and sort share one query key, so See all does not refetch the documents page inside staleTime.
Performance: Home makes one /documents request and at most one members request per visit.
Performance: the JS that a signed-out visitor loads on / does not grow. Compare the next build route table before and after.
Verification
Run make dev-local. Confirm the webapp port first, because it is not always 3000.
Sign in as an owner who has a Favorite, a private pad, and a pad shared with a second account. Check Home against Settings → Documents for each scope and sort.
Sign in as a second account that has only joined pads. Check the Joined rows and their owner names.
Sign out. Check the network panel for no documents request.
Check light and dark.
Check the installed app and a browser tab.
Check the phone shell with a mobile user agent on iOS Safari and Android Chrome. The mobile shell is user-agent gated, so a narrow window alone does not produce it.
Never run next build while the dev server uses the same .next directory. Stop the server first for the bundle check.
Summary
Home shows a short Documents card for a signed-in person. Settings → Documents shows the Merged list with many more features. This issue brings the Home card to parity with Settings → Documents by reusing the Settings code, not by building a second list.
The maintainer's request, quoted exactly:
Screenshots of both surfaces will be added by the maintainer.
This issue overturns earlier rulings. #247 and
apps/webapp/CLAUDE.md§Documents list Favorites say Home reads the Owner live list only (scope: 'owned'). #247 also says Home has no sort, no search, no row menu, no grid and no Date buckets. The request above reverses those rules. The Open decisions section asks which of them change.Why
Current behaviour
Home card:
apps/webapp/src/components/pages/home/HomeDocuments.tsx, mounted inHomePage.tsxinsideHomeCollapseRegion.useOwnerDocuments({ scope: 'owned', searchQuery: '', sortKey: 'lastOpenedAt_desc' })withrefetchOnWindowFocus: 'always'.HOME_DOCUMENTS_LIMIT). The page size is 20 (DOCUMENTS_PAGE_SIZE). Both read from code, not measured.LuFileText,DocumentRowLabel(title, star, lock, eye) anddocumentListDate. That date reads "Never opened" whenlastOpenedAtis null.total > 8. It opens Settings on the Documents tab.isAuthServiceAvailableonly. It is not gated onisPWAInstalled. So the same card shows in a browser tab and in the installed app. The rule "Do not gate that list onisPWAInstalled" must stay.components/commandJump/CommandJump.tsx) uses the same query key (owned, empty search,lastOpenedAt_desc). It fetches only while its dialog is open.Settings list:
apps/webapp/src/components/settings/components/DocumentsSection.tsx, loaded withnext/dynamicfromSettingsPanel.tsx.DocumentListRow,DocumentGridTile,DocumentRowMenu,DocumentMembersCluster,DocumentRowLabel.buildDocumentsListItems(Favorites hairline and Date buckets).useOwnerDocuments,useDocumentMembers(RPCget_document_member_previews),useOwnerDocumentsCachefor every optimistic write.docsplus:my-docs-scope,docsplus:my-docs-sort,docsplus:my-docs-view.owned)all) by default; Show filterall/owned/joinedDocumentMembersCluster, up to 4 facesBackend. No new route is needed.
GET /documents?scope=allalready returns the Merged list (buildMemberScopeTiersinapps/hocuspocus.server/src/api/services/documents.service.ts). It pins only the caller's own Favorites, and it sorts a non-owned row as never opened.Bug found during research (Owner live list pin order).
buildDocumentsOrderBypins withfavorites: { _count: 'desc' }. That counts the Favorite rows of every user, not only the caller's.isFavoritecounts only the caller's row. So a row can pin above others with no star, and a row with two Favorite rows outranks a row with one. The Home screenshot shows this: an unstarred row sits between two starred rows. The Merged list tiers usefavorites: { some: mine }and are correct. This bug also reaches Settings "Owned by me" and Command jump.Proposed behaviour
/, in a tab or in the installed app. The Documents card shows the Merged list by default: owned rows plus Joined rows.useOwnerDocumentsCachealready patches every key under['documents', uid].Scope
favorites: { some: { userId } }rule that the Merged list tiers already use. Deploy before slice 2.DocumentListRowandbuildDocumentsListItems, withuseDocumentMembersfor the visible rows. Load them on the client after the profile arrives, so signed-out/loads no extra JS.Select, labels and session keys.DocumentsSectionso Home and Settings share it. Pick the rename path that survives keyboard collapse on a phone.Out of scope
CONTEXT.md§Pad tools)..cursor/docs/design-system.md§DocumentsSection and §Landing & history as written.isPWAInstalled.Open decisions
Each item needs a maintainer ruling. The recommendation is mine, with the reason.
all). That is the request, and it matches Settings.Selectthat sharesdocsplus:my-docs-scope. Then Home and Settings never disagree.Selectthat sharesdocsplus:my-docs-sort, default Last modified. Under Last opened, every Joined row sorts as never opened, so an 8-row card can hide every Joined row. This reverses Honest install line, Documents on Home, and a quiet Home Install #247, which chose Last opened.HomeCollapseRegionthen collapses the card that holds the search field. Command jump already searches owned pads.max-w-2xl, and 8 rows of paper previews make Home very tall. See all gives the grid.DocumentRowMenu. Its phone sheet already falls back to<body>when no dialog wraps it. Home already mountsGlobalDialogfor the confirms.RenameDocumentDialogon Home belowsm, and inline rename on desktop.buildDocumentsListItems, so both lists use one builder. The cost is header rows inside an 8-row card.total > 8.Acceptance criteria
/documentsorget_document_member_previews.isPWAInstalled.documentRowMenusheet. Back and Escape close it. Every target is at least 44 px.design-system.md.staleTime./documentsrequest and at most one members request per visit./does not grow. Compare thenext buildroute table before and after.Verification
make dev-local. Confirm the webapp port first, because it is not always 3000.next buildwhile the dev server uses the same.nextdirectory. Stop the server first for the bundle check.References
apps/webapp/src/components/pages/home/HomeDocuments.tsx,HomePage.tsx,HomeCollapseRegion.tsxapps/webapp/src/components/settings/components/DocumentsSection.tsx,DocumentListRow.tsx,DocumentRowMenu.tsx,DocumentMembersCluster.tsx,DocumentRowLabel.tsxapps/webapp/src/components/settings/hooks/useOwnerDocuments.ts,documentsCache.ts,useDocumentMembers.tsapps/webapp/src/components/settings/utils/documentsListItems.ts,documentListDate.ts,documentsQueryKey.tsapps/webapp/src/components/commandJump/CommandJump.tsxapps/hocuspocus.server/src/api/services/documents.service.ts(buildDocumentsOrderBy,buildMemberScopeTiers)apps/hocuspocus.server/src/api/controllers/documents.controller.ts(list scope)CONTEXT.md§Documents list, §Document access, §Pad toolsapps/webapp/CLAUDE.md§Documents list Favorites, §Landing Page Shell And PWA, §Settings Takeover And The Owner List Cache.cursor/docs/design-system.md§DocumentsSection, §Landing & history