Skip to main content

App design principles

Every Conduction app — OpenRegister, OpenCatalogi, Procest, Pipelinq, MyDash, the dozen others — looks and works the same way on first sight. Same five structural pieces, same place, same behaviour. That recognisability isn't an accident: it's what @conduction/nextcloud-vue enforces, and what makes a user who's learnt one app productive in any of the others within minutes.

This page explains the chassis — the abstract layout shared by every app — the five atoms that make up the chassis, and the stacked views the library composes on top so you don't have to lay each atom out by hand.

The chassis: one shape, every app

Every Conduction product surface is built on the same three-region chassis: a topbar across the top, a left navigation down the side, and a main column filling the rest. The contents differ wildly — a register browser, a process inbox, a dashboard, a chat archive — but the bones are identical, so the user never has to relearn where things live.

OpenRegister
Procest
MyDash

Three different apps. Same shape: topbar with the user menu, left nav with the app sections, main column with whatever the page is doing. That's the chassis. @conduction/nextcloud-vue is what gives you that shape with one component (CnAppRoot) plus a JSON manifest.

Five atoms, one chassis

Inside the chassis sit five recurring building blocks. Every page in every app composes some subset of these — they are the atoms of the design system. Each card below focuses on one atom: the focused zone is at full opacity with a KNVB-orange outline, the rest fades to 25% so you see where the atom sits, not just what it is.

.topbar

Topbar

App · Desk · always

The Nextcloud chrome row. Sits across every page unconditionally because every Conduction app lives inside Nextcloud's workspace. The shelf icons are the cross-app navigation; per-app links never go here.

.nav

Left navigation

App · required · Desk: never

The per-app sidebar. Carries this app's own primary navigation, plus a footer pinned to the bottom for global access (Settings, Feedback). The active item is the only place cobalt-100 backgrounds a row.

.col

Main column

App · Desk · always

The work surface. In an App pattern, the column opens with a .pageHeader (title + actions), then KPI strip and panels. In a Desk pattern, .col nests inside .grid to become a full-bleed widget canvas with no page header.

.pageHeader

Page header

Index · Detail · Desk: never

The first row of .col on every Index and Detail template. Carries the page title (left) and exactly two action buttons (right): one ghost (secondary), one primary (filled cobalt). The header tracks .col's width: full-spread when the sidebar is closed, constrained when it is open.

.detail

Sidebar

App · optional · Desk: never

The right-hand sidebar. Optional, dismissible, anchored to the active record or the active view. Carries an icon + title + description in a header, then a tabbed body (Search / Columns by default). Class stays .detail for code; we call it the Sidebar in copy.

Mapped to the library's components:

AtomLibrary componentNotes
TopbarInherited from Nextcloud's NcAppHeaderThe library doesn't own this atom — it inherits the cross-app shelf, search, and user menu from the workspace.
Left navigationCnAppNavDriven by manifest.menu[]. One level of nesting, permission-filtered, sortable via order.
Main columnA stacked view (CnIndexPage, CnDetailPage, CnDashboardPage, CnSettingsPage)Whatever the active route renders.
Page headerCnPageHeaderTitle + description + icon + per-page action buttons. Uniform across Index and Detail pages.
SidebarCnIndexSidebar on Index, CnObjectSidebar on DetailToggleable, never required.

These five atoms cover almost every screen Conduction ships. New apps don't invent new atoms — they compose the existing ones in the right shape.

Stacked views: the library's job

Wiring the five atoms together by hand on every page would be repetitive and inconsistent. @conduction/nextcloud-vue exposes them as stacked views — opinionated higher-level components that arrange the atoms for the most common page shapes:

  • CnIndexPage — Topbar + Left nav + Page header + Main (table/cards + filter bar + pagination + CRUD dialogs) + Sidebar (search + facets). Schema-driven: feed it a JSON Schema and you get a sortable, filterable, editable list page in one prop.
  • CnDetailPage — Topbar + Left nav + Page header + Main (stats / charts / cards) + Sidebar (object metadata, files, notes, audit trail). For pages that show one thing in depth.
  • CnDashboardPage — Topbar + Left nav + Page header + Main (drag-and-drop widget grid). For high-level overviews with KPIs, charts, tile-shortcuts.
  • CnSettingsPage — Topbar + Left nav + Page header + Main (sectioned forms wired to IAppConfig). For admin / configuration screens.

Pick the stacked view that matches the page's purpose; the chassis comes free. Per-page customisation happens through slots and props, never through re-laying-out the atoms.

Why this matters

Three things follow from the chassis-plus-atoms-plus-views discipline:

  1. Cross-app muscle memory. A user who learnt where things are in OpenRegister navigates Procest the first time without reading docs.
  2. Consistent accessibility, theming, i18n. All five atoms inherit Nextcloud's CSS variables, NL Design System tokens, and standard ARIA — no per-app drift.
  3. Composability stays cheap. A new app describes its content in a JSON manifest and a schema; the chassis renders it.

Where to next

  • App manifest — the JSON contract that fills and configures the atoms.
  • Schemas and registers — how data structure flows from the backend register into the frontend stacked views.
  • Component reference — every Cn* component used by the stacked views, with live demos.