Cards & Layout
Cards and layout shells in the app are built from a set of shared components in src/components/ui/ and wired together through Next.js App Router route-group layouts. The design-token contract that governs card colors and typography lives in Design Tokens.
Overview
Section titled “Overview”The layout system has two layers. The component layer provides card shells, feed wrappers, and two-column shells that feature pages compose. The route layer provides App Router layout.tsx files that establish persistent chrome, authorization guards, and segment-level error boundaries for settings and auth surfaces.
Cards follow a token contract: all backgrounds and text sizes come from design-system tokens defined in src/styles/globals.css and src/styles/typography.css. No raw Tailwind color or size utilities are used (design-system.md).
Card & Feed Components
Section titled “Card & Feed Components”Key components from src/components/ui/cards/ and src/components/ui/layout/:
CondensedCardShell/CondensedCardCover/CondensedCardActions— the three-piece condensed card family used across article and project listsCollapsibleCard— a card that expands and collapses its bodyGenericInfiniteFeed— infinite-scroll wrapper used by article and project feedsResponsiveCardList— a grid/list toggling wrapper for card collectionsTwoColumnShell— the primary page shell (topbar + sidebar + main content); used by(dashboard)/layout.tsxSidebarShell— a simpler sidebar + content shell for single-entity pages
The full catalog for cards is at UI Cards and for layout at UI Layout.
Architecture
Section titled “Architecture”flowchart TD
DashLayout["(dashboard)/layout.tsx\nTwoColumnShell + SidebarProvider"] --> OrgLayout["(organizations)/layout.tsx\norg account-type guard"]
DashLayout --> PersonalLayout["(personal)/layout.tsx\nuser account-type guard"]
OrgLayout --> MembersLayout["members/layout.tsx\nowner/admin guard + NavTabs"]
MembersLayout --> MembersPage["members/page.tsx"]
MembersLayout --> InvitationsPage["invitations/page.tsx"]
MembersLayout --> RequestsPage["requests/page.tsx"]
OrgLayout --> OrgFeedPages["projects/page.tsx\narticles/page.tsx"]
PersonalLayout --> PersonalFeedPages["my-articles/page.tsx\nmy-projects/page.tsx\norganizations/page.tsx\norganizations/invitations/page.tsx\norganizations/requests/page.tsx"]
AuthLayout["(auth)/layout.tsx\nAuthMarketingPanel"] --> AuthPages["login · signup · forgot/reset password · verify-email"]
Layout Shells
Section titled “Layout Shells”The (dashboard)/layout.tsx provides all visible chrome: it wraps content in TwoColumnShell with AppTopbar and DashboardSidebar. The two settings sub-layouts beneath it are authorization guards, not chrome layers:
settings/(organizations)/layout.tsx— redirects to/settingsif the active account is not an organisationsettings/(personal)/layout.tsx— redirects to/settingsif the active account is not a user
The members/layout.tsx goes further: it checks getUserOrgRole and redirects non-owners/non-admins to the organisation page, then renders OrgMembersHeader and NavTabs (member list, invitations, and join requests).
The (auth)/layout.tsx is a flat shell with no dashboard chrome; it renders AuthMarketingPanel alongside its children for the marketing split-screen on auth pages.
Failure Modes & Edge Cases
Section titled “Failure Modes & Edge Cases”- A feed page that throws during render is caught by the co-located
error.tsxat the same segment. The(personal)shell stays mounted, so navigation is never lost — seeorganizations/error.tsx. settings/(organizations)andsettings/(personal)are near-identical paths but protected by opposite account-type checks. Switching active account without reloading can land a user on the wrong guard; both redirect to/settingsrather than showing a blank page.- A card author reaching for a raw Tailwind color or size utility breaks the token contract. The
docs/design-system.mdrule is the only guardrail — there is no lint enforcement for this today.
Operational Notes
Section titled “Operational Notes”Shell persistence is a direct effect of the App Router layout hierarchy: TwoColumnShell (in the dashboard layout) does not re-render when navigating between settings child pages. Moving between organisation settings tabs swaps only the leaf page.tsx, keeping the sidebar and topbar mounted.
Token-driven styling keeps the generated CSS bounded by the token list rather than by the number of pages. For token definitions see Design Tokens.
Related Links
Section titled “Related Links”- UI Primitives — all ui component folders
- Design Tokens — color and typography tokens used by cards and shells
- UI Cards — card component catalog
- UI Layout — layout component catalog
- dashboard layout.tsx
- docs/design-system.md — token definitions source