π¨ GenosDB Design Guide
Opinionated UI patterns, design tokens and page architectures for applications built on GenosDB β written for humans and AIs alike. If you (or your AI assistant) are building a GenosDB application and want it to look and behave like a first-class citizen of the ecosystem, follow this guide. The goal is coherence without complexity: every rule here is implementable in plain HTML + CSS + JavaScript, with no UI framework required.Two deployment shapes, one design language
GenosDB applications ship in two shapes, and this guide applies equally to both:- No-build (examples, testbeds, prototypes): three files β
index.html,styles.css,app.jsβ importing GenosDB from a CDN. Zero tooling. - Bundled (production apps): installed from npm and bundled into the app. Bun is the recommended bundler and runtime β
bun buildinlines GenosDBβs core, and the engineβs optional*.min.jsplugins are copied next to the output bundle. See Bundler Configuration for Bun, Vite, Webpack and esbuild setups.
1. Philosophy
- Content is the protagonist. Chrome (navigation, session, widgets) stays visually quiet; data takes the full viewport height. Never let a fixed panel steal reading space.
- Dark, minimal, precise. One dark theme, generous whitespace, subtle borders instead of shadows, restrained color reserved for meaning (roles, status, actions).
- The API dictates the UX. GenosDBβs methods have natural interface consequences β mnemonic identity wants a focused modal, the security state callback wants a reactive session pill, governance roles want visible badges, realtime deltas want live DOM. Design from the API, not against it.
- No UI frameworks, no dependencies for style. Design tokens + plain CSS cover everything, whether the app is a three-file example or a Bun-bundled product. The only sanctioned UI dependencies are functional (e.g. DOMPurify for untrusted content).
- Small surface, strong opinions. When in doubt, do less.
2. Design Tokens
Copy this:root block as-is. Every color, radius and spacing in your app must reference a token β never hardcode values in component rules.
Color mode: dark only
GenosDB applications ship dark-only by default β examples, testbeds and instruments add no theme state at all. For consumer-facing product apps, a theme toggle is a sanctioned opt-in pattern, with exact rules:- One icon button in the top bar, next to the session pill, with an
aria-label. The icon shows the mode youβll switch to (π while in light, βοΈ while in dark). - Implementation: a
data-themeattribute on<html>, a[data-theme="light"]block that redefines tokens only,localStoragepersistence, andprefers-color-schemeas the first-visit default.
- The golden rule: if enabling the toggle requires touching any component CSS, the token system is broken β fix the tokens, never patch components. A well-built toggle costs ~25 lines total and doubles as living proof that the design tokens work.
3. Typography & Data Display
- System font stack for UI text; monospace (
--mono) is mandatory for machine data: Ethereum addresses, node IDs, hashes, timestamps, peer IDs. - Addresses are never shown in full. Always
db.sm.abbrAddr(address)(e.g.0x1234...abcd), rendered in--mono+--text-tertiary. - Timestamps localize with
new Date(ts).toLocaleString()β never raw epoch numbers in the UI. - Untrusted content is always sanitized. Anything a peer can write (titles, descriptions, markdown) is escaped before
innerHTML, and rendered markdown passes through DOMPurify. A P2P app has no server to sanitize for you. - Missing attribution (nodes created before identity existed) renders as
by unknownβ never a broken or empty label.
4. Identity & Session
This is the most GenosDB-specific chapter: the Security Managerβs methods define the flow, the guide defines its shape. (Method-level best practices live in the SM API Reference; this section covers the visual pattern.)4.1 Login & registration: a centered modal
Identity actions live in a centered modal (native<dialog>), not in a sidebar panel or a separate page. Rationale: the mnemonic flow is short, focused and security-critical β a modal isolates it, keeps the app visible behind a dimmed backdrop, and disappears the instant the session activates.
The modal contains, in order:
- A one-paragraph hint explaining the trust model (e.g. what a guest can do, how roles are earned).
- One
<textarea>serving both purposes: paste an existing mnemonic, or display a freshly generated one (setreadOnlyafter generating;resize: none). - Action row:
Generate identityΒ·Copy phraseΒ·Login with mnemonicΒ·Protect with passkey(after generating) Β·Login with passkey(only ifdb.sm.hasExistingWebAuthnRegistration()). - Optional demo/superadmin shortcut for showcases.
No standing βSign inβ button β the modal IS the door. A distributed app has no server-side login page, so donβt emulate one with a persistent button. Open the identity modal automatically on every load without an active session: the newcomer immediately learns what an identity is and how roles are earned, and returning passkey users never see it β their session resumes silently and the security callback closes it.
- Dismissible (backdrop click,
Esc) but with no Γ close button β the app stays fully usable as a read-only guest behind it. - Logging out returns to phase 1 with the modal open β signed-out is the modalβs state.
- Re-entry without reloading is contextual, not chrome: a clickable read-only status hint, or the explanatory affordance of a gated control, re-opens the modal. The top-right area belongs to the session chip alone and stays empty while signed out.
4.2 Session: always top-right
An authenticated session renders anchored to the top-right of the content area (the universal convention users scan for), in the canonical format β abbreviated address first, role second:--mono + --text-secondary; the role reads as a quiet bracketed tag. Restraint over decoration: no saturated filled pills, no competing colors β the session area is chrome, not content.
- Signed out β the spot stays empty: the auto-opened modal is the door (Β§4.1), and contextual CTAs re-open it. No standing Sign-in button.
- The top bar is
position: stickyover the content scroll, with a subtle bottom border. db.sm.setSecurityStateChangeCallback(...)is the single source of truth: it toggles the pill/button, closes the modal, and resets the mnemonic textarea on logout. No UI state duplicates it.
4.3 Role badges
The live role (watched reactively on theuser:<address> node) renders as a quiet uppercase tag β tier color applied to the text (or a subtle border), never a filled background. Map ascending trust tiers to a fixed color ramp so every GenosDB app reads the same way:
Permission-gated controls (a βNew postβ button, a publish selector) show or hide from the same watched role β the UI reflects permissions, while the engine enforces them.
4.4 Presence & contribution: gate by degrees
Realtime collaboration surfaces are not all equal. Gate each one by the smallest trust step it actually needs β read-only guests stay welcome, while every contribution becomes attributable:
Two implementation rules:
- Disable gated controls, donβt hide them (
disabled+ an explanatorytitlesuch as βSign in to share your cameraβ): a visible-but-locked control teaches the trust model; a missing one just looks broken. - Ephemeral channel traffic (GenosRTC) does not pass through the graphβs RBAC β the role gate on the UI keeps honest peers silent, and the signed graph remains the source of truth that corrects any transient view.
5. Page Architecture by Application Type
All layouts share the same skeleton: sidebar (brand + nav + widgets) Β· sticky top bar (identity) Β· full-height content. What changes is the content organism.5.1 Collection apps (CMS, marketplace, gallery)
- Responsive card grid:
grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)). - Cards:
--bg-secondary,--border-subtle,--radius-md, hover =translateY(-2px)+--border-strong. Image on top (object-fit: cover), title, two-line clamped description, footer row with author tag (mono) and owner-only actions. - Secondary lists (βlatestβ, βrecent activityβ) are sidebar widgets β never a fixed bottom panel.
5.2 Admin panels & dashboards
Same skeleton; content organized as stat cards first, tables second. Tables use--border-subtle row separators (no zebra striping), mono for IDs/addresses, and row actions revealed on hover. Destructive actions are always --danger outline buttons, never filled by default.
5.3 Social / chat / realtime feeds
Single centered column (max-width ~680px) for the feed; composer pinned at the natural top or bottom of the column (not fixed over content). Presence (βN peers onlineβ) belongs in the top bar next to the session pill, in--text-tertiary.
5.4 Instruments & testbeds (monitors, probes, benches)
Centered narrow column (~440px), no sidebar. An uppercase eyebrow label, a large title, a one-line hint, then stat cards in a row (mono values) and proportional bars (grey track--bg-tertiary, solid --accent fill). These tools measure β every pixel should feel like an instrument, not a website.
Hard layout rules (learned the hard way)
- The content column owns the full viewport height. No global fixed footers.
- One responsive breakpoint is enough for examples: at
max-width: 820pxcollapse to a single column (sidebar becomes a top block). overflow-ylives on the content column, not onbody.
6. Canonical Components
Minimal CSS contracts β copy and restyle only via tokens. Toast (neveralert()): fixed bottom-center pill, --bg-elevated + --border-strong, slides up on .show, --danger border for errors, auto-dismiss ~3s. All operation feedback (saved, deleted, permission denied) goes through it: security errors from executeWithPermission read cleanly in a toast.
Modal: native <dialog> + ::backdrop dim with slight blur; --bg-elevated, --radius-lg; backdrop-click / Esc to dismiss β no close Γ.
Forms: labels above fields (small, --text-secondary, 600 weight); inputs on --bg-secondary with --border-strong, focus swaps border to --accent (no outlines, no glows). Read-only fields (e.g. auto-generated slugs) drop to --text-tertiary on --bg-primary.
Empty states: one sentence in --text-secondary that tells the user how to earn the change theyβre looking at (e.g. βNo posts yet. Earn the author role and create one!β) β in a governance world, empty states teach the ladder.
Permission hints: when a control is hidden by role, show a quiet --warn-tinted note explaining how to unlock it, instead of leaving users wondering.
7. Realtime UI Rules
- The DOM is the state. Subscribe once with
db.map(options, callback)and let deltas mutate the interface directly β no mirrored arrays or Maps for a single view. (An app-wide store fed by one subscription is legitimate when many views consume the same data.) - Handle all four actions explicitly β
initial,added,updated,removedβ each with its own branch. The canonical DOM gestures:initialβ append (arrives already sorted when you passfield/order),addedβ prepend (newest by definition),updatedβ rebuild and move to top,removedβ remove. The full event contract ({ id, value, edges, timestamp, action }) lives in the MAP Guide β reference it, donβt re-document it. - Let the engine own the ordering and the window. Pass
field+orderinstead of sorting in the app; pass$limitand let the engine emitadded/removedas nodes enter or leave the window. Cursors ($after/$before) are only meaningful over an explicitfieldorder. - Live-first verification: after any data-loading change, test with two browsers β creation in one must appear in the other without reloads.
8. Accessibility & Semantics
- Semantic elements:
<dialog>,<nav>,<main>,<article>,<button>(never clickable<div>s). - Text contrast on
--bg-primarymeets WCAG AA with the token palette β donβt lighten borders/text below the provided tertiary values. - Every icon-only button carries
aria-label. - No inline styles; all styling flows from CSS classes and tokens.
9. Checklist (for AIs and humans)
Before shipping a GenosDB app or example, verify:- β All colors/spacing/radii come from the token block β zero hardcoded values in components.
- β Dark theme only; no toggle unless the product truly requires it.
- β Login/registration lives in a centered
<dialog>with the single-textarea mnemonic flow; it auto-opens on every session-less load (dismissible via backdrop/Escβ no Γ button) β no standing Sign-in button, re-entry via contextual CTAs. - β Session sits top-right in the
abbrAddr [role]format (mono address, quiet tag, no filled pills); signed-out leaves that spot empty. - β Role badges follow the gray β green β blue β orange β violet trust ramp.
- β Addresses abbreviated + monospace; timestamps localized; remote content sanitized.
- β Content column takes full height; secondary lists are sidebar widgets, not fixed panels.
- β Feedback via toasts β no
alert()/confirm()except destructive-action confirms. - β Realtime: one subscription, four actions handled, ordering/window delegated to the engine.
- β Presence gated by degrees: watch anonymously Β· broadcast with an identity Β· contribute with an earned role (gated controls disabled, not hidden).
- β Verified live with two browsers.
Where this guide fits
- Token values and component contracts here are the reference implementation targets for the official examples and testbeds.
- Method-level identity flows: SM API Reference Β· query/realtime contracts: MAP Guide Β· pagination: Cursor-Based Pagination.