Documentation / Design & UI
Component source of truth
The /components route is the canonical UI catalog. Its source files live in src/components, and its registry is src/lib/component-catalog.ts. Pages, account settings, and gallery examples use those same implementations.
The shared website header links directly to /components/icons, a searchable browser for the public kit's verified free Pixelarticons set or an initialized product's installed collection. Icons has its own resource page without the component catalog sidebar. See ICONS.md. Gallery pages provide preview, example code, component source, copy, reset, search, and theme controls; mobile navigation opens in a sheet.
Library conventions
Use shadcn's base-nova Base UI components and the semantic tokens in src/app/globals.css. Pixelarticons supplies the icons. Install additional primitives with bunx --bun shadcn add <component> and inspect dependency and theme CSS changes. Use Base UI's render composition prop for triggers and buttons. Label controls, support keyboard use, and use distinct thumbLabels for range-slider thumbs.
The palette has three independently editable eleven-shade scales: primary, accent, and neutral. Primary starts with the same Zinc values as neutral. Default actions, selected controls, links, focus rings, and React Bits control tokens use semantic primary; surfaces, text, and routine hover states use neutrals. Checkbox checked/mixed states, selected radios, active switches, slider fills/thumbs, and avatar fallbacks/badges/group counts deliberately use accent-500, with neutral-950 foregrounds on accent fills. Other controls retain primary styling. Reserve numbered brand accent shades for deliberate highlights and data visualization. shadcn's semantic accent is a neutral hover/selection surface, distinct from the brand accent scale. Preview all three scales and their usage at /brand, and follow the UI colors skill.
The shared PublicShell supplies TooltipProvider and a default Toaster for public marketing and resource pages. AppShell supplies them independently for Overview and Settings. Import toast from sonner. The toast preview mounts an additional Toaster with a dedicated ID to isolate its notifications.
Scrollbars use a shared, minimal native treatment: transparent tracks and slim indicators that appear while their region scrolls, then hide after inactivity. The root Providers mounts useScrollActivity once for the document, nested overflow regions, and portaled controls; styling lives in src/app/globals.css. Keep ordinary overflow-auto/overflow-x-auto/overflow-y-auto containers and native wheel, touch, trackpad, and keyboard behavior. Give standalone scrollable regions an accessible name and keyboard focus when they contain no focusable controls. The nested vertical and horizontal examples in /components/app-shell use this same global behavior. See LOADING_MOTION.md for timing and verification.
Loading and motion are part of this library. Use ContentSkeleton for incoming content and PendingButton or PendingIndicator for an action after interaction. Keep existing content visible while actions run. For new coordinated entrances and list changes, use the registered primitives from src/components/motion/primitives.tsx, powered by motion/react. The Loading & motion collection previews these same implementations, and src/lib/motion.ts re-exports their shared runtime settings. Read LOADING_MOTION.md before adding loading feedback or motion.
/components/motion-primitives demonstrates PageEntrance, Reveal, RevealText, ContentReveal, MotionList, and InteractiveSurface. /components/motion-dashboard composes them into a representative dashboard. Reuse the view in src/components/dashboard/motion-dashboard.tsx with real resolved data and callbacks; example records and simulated actions stay in the gallery. The homepage, workspace, settings, Brand, and catalog pages use shared entrances; workspace summary cards use InteractiveSurface, and notes and account entity lists use shared content and list motion. Native controls, overlays, and the sidebar use the runtime timing settings. Static selections and dense invoice records retain their existing semantics.
For selected headline metrics, use AnimatedNumber from src/components/motion/animated-number.tsx, previewed at /components/animated-number. The shared Progress and ProgressValue in src/components/ui/progress.tsx animate a bar and its label from the same value; use them together rather than attaching a separate animated number. Their examples are at /components/progress and in the motion dashboard. Both components use the shared value animation hook and settings. Existing Progress consumers inherit the updated behavior, while ordinary numbers remain static unless explicitly composed with AnimatedNumber.
The catalog contains portable core controls, shared motion, and connected application components. Vendor component collections are installed directly into derived products rather than redistributed by the kit; see REACT_BITS_CATALOG.md. Only catalog slugs are generated; source is read during static generation, never from user-provided paths or the Cloudflare runtime filesystem.
Reuse and extend
- Search the catalog and
/componentsbefore creating UI. Import the existing component fromsrc/components; compose oursrc/components/uiprimitives for new controls. - Keep reusable rendering in
src/components, not in route files or gallery examples. A connected component reads service data and passes it to an exported view. Both the app and the gallery render that view. Preserve existing service authorization and provider boundaries. - Register each new component in
src/lib/component-catalog.ts, includingsourceFile, description, and usage guidance. UseadditionalSourceFilesfor companion implementations such as Field's Label. - Add
src/components/gallery/examples/<slug>.tsxand its explicit dynamic import inexample-loaders.ts. Import the registered implementation. Use local sample state and callbacks; never change real accounts, create real keys, or charge a customer from a preview. Include applicable populated, empty, loading, error, and permission states. - Run
bun run checkandbun run build:cloudflare. Open the preview, try its controls, inspect its source tab, and verify narrow screens. Test service behavior through the connected component separately.
The gallery is a catalog of the source; it is not a runtime dependency of the application. Sample fixtures must stay under src/components/gallery. The component source tab reads implementations at build time, so deployed previews and displayed source come from the same build. Component detail pages keep Previous/Next navigation fixed above the device safe area below lg, with reserved content space; desktop navigation stays inline.
Account components
| Catalog route | Connected component | Shared preview view |
|---|---|---|
/components/auth-buttons | AuthButtons | AuthButtonsView |
/components/user-menu | UserMenu | UserMenuView |
/components/team-switcher | TeamSwitcher | TeamSwitcherView |
/components/account-settings | AccountSettings | AccountSettingsView |
/components/profile-settings | ProfileSettings | ProfileSettingsView |
/components/security-settings | SecuritySettings | Email, password, sign-in methods, and MFA views |
/components/notification-settings | NotificationSettings | NotificationSettingsView |
/components/session-settings | SessionSettings | SessionSettingsView |
/components/team-settings | TeamSettings | Team, member, and invitation views |
/components/api-key-settings | ApiKeySettings | ApiKeySettingsView |
/components/billing-settings | BillingSettings | Billing, product, and invoice views |
/components/account-actions | AccountDangerSettings | AccountDangerSettingsView |
/components/account-controls | Shared account controls | The same forms, confirmations, avatars, and feedback |
/components/app-shell | AppShell | AppShellView |
/components/app-navigation | Navigation in AppShell | AppNavigationView |
/components/notes | Notes | NotesView |
/components/theme-toggle | ThemeToggle | ThemeToggle |
Use the connected export in application code. Views accept already resolved data and actions; they do not replace Hexclave, Convex, or backend authorization. The existing provider handles session resolution. Project settings and team permissions are resolved in the connected account components.
AppShell is mounted once in src/app/(workspace)/layout.tsx for the connected application under /app. It supplies a collapsible desktop sidebar, mobile drawer, compact location header, main landmark, shared gutters, and application content width. Its destinations are Overview and Settings; a separate Website and resources group links back to the public site, Docs, and Components. Sidebar accepts mobileTitle and mobileDescription for an accessible drawer name; the shell uses “Main navigation”.
Optional Hexclave account slots have independent loading/error boundaries. Fully signed-in users get the connected TeamSwitcher and UserMenu; signed-out and restricted users get the existing AuthButtons. Public resources use PublicShell without account lookups or account controls. /app retains the redirect guard and its identity-keyed Convex provider. Keep auth hooks out of AppShellView and gallery fixtures out of production.
/components/app-shell previews the actual AppShellView with teams, personal/empty accounts, long names, signed-out/onboarding states, account loading, and compact account-error recovery. The view renders an embeddable section by default; the connected shell supplies mainId="main-content". /components/app-navigation previews its actual AppNavigationView inside SidebarProvider. Desktop collapse state survives navigation, while internal navigation closes the mobile drawer. Set keyboardShortcut={false} on nested SidebarProvider or AppShellView previews so Ctrl/Cmd+B only toggles the application sidebar.
GalleryShell supplies only section navigation: a desktop catalog list and a labelled “Component section” sheet on smaller screens. It lives under src/app/(public)/(resources)/components/(catalog)/layout.tsx, so the Icons route stays outside the component sidebar. AccountSettingsView similarly uses desktop section links and a labelled “Settings section” selector. Its required onTabChange callback switches the supplied section; the connected AccountSettings updates the existing /app/settings?tab=... URLs. Local navigation switches at lg; Components has one desktop section sidebar beneath the public header, while Settings remains within the application sidebar.
Selected global and component-library navigation uses the primary foreground with a neutral active background. Sidebar labels and icons follow --sidebar-primary, which maps to --primary; changing the primary palette does not require changing the sidebar's neutral surfaces.
Optional vendor authentication and billing examples do not replace the connected Account group above. Installing vendor source in a product does not grant permission to redistribute it through this template or registry.
Hexclave continues to host login, signup, recovery, verification, MFA challenges, and onboarding. Stripe continues to own secure card entry and hosted payment surfaces. These are intentional service boundaries. The local entry buttons, menus, settings, and surrounding UI come from this library.
Enforcement
bun run check:components validates unique entries, source paths, loaders, and examples. Every visual source under src/components must be covered, and each example must import its registered source. The only exclusions are gallery infrastructure and providers.tsx.
The check also rejects production imports of gallery code, direct Base UI imports outside src/components/ui, and rendering named Hexclave visual imports in production. SDK hooks and the root Hexclave provider remain supported. bun run check and the existing CI workflow run this check. The rules in AGENTS.md require the same workflow for future changes.
Throughout owned application components, native UI controls, and app routes, it also rejects separate loader icons, ad hoc pulse/spin classes, visible standalone loading text, and plain buttons that swap labels for a pending state. New components are covered automatically. Only PendingIndicator owns the loader icon. Use the registered loading components. Accessible loading labels remain supported. Gallery code retains its presentation fixtures; registry membership does not bypass the loading rules.
These checks enforce registration and import boundaries; review still needs to catch copied markup or components used for the wrong purpose. Gallery fixture tests establish isolated rendering and local interactions, not live OAuth or billing correctness.
Distribution
The gallery catalog describes previews. Root registry.json describes the two installable shadcn bundles, motion-primitives and animated-metrics, and references their same source files. Build payloads with bun run build:registry; never maintain a second TSX implementation in generated JSON. Release dependencies use the exact runtime version. Preserve target aliases and complete dependency declarations when changing bundled files.
Shared behavior lives in @nintu/creator-core-runtime; editable visual source remains under src/components. A runtime upgrade does not replace customized components. Read distribution for the public template, npm package, and registry bundles, and updating for source-diff updates. Keep component coverage checks intact when extracting code.
Public documentation
The public guides render an explicit source allowlist from src/lib/docs.ts. Markdown is read during static generation through src/lib/docs-content.ts; it is not read from user-supplied paths or the Worker filesystem. Shared heading IDs and link rewriting keep the article, table of contents, and repository Markdown in agreement. Only registered guides become routes.
PublicShell has explicit marketing and resources variants selected by the route-group layouts under src/app/(public). Marketing uses full-width content and a full footer; resources share bounded content width, gutters, and a compact footer. Both use the same header with Docs, Components, Brand, and Icons. The kit also shows Updates and Star on GitHub; initialized products keep their own name and omit upstream promotion. The application is a secondary Open demo link in the kit or Open app in initialized products.
The public shell owns the main landmark; PublicShellView previews omit mainId to render an embedded section. Its catalog example covers both variants and initialized product mode. DocsShell adds one responsive section navigation, with a labelled “Documentation section” mobile drawer; DocArticle, DocMarkdown, and CodeBlock render the same source with semantic headings, tables, and real clipboard feedback. Their catalog previews import those implementations. Documentation changes update the Markdown source rather than a second website copy.