NL Design is a Nextcloud administration app that selects an exact version of a bounded design profile and projects it onto selected Nextcloud web surfaces.
This repository is pre-release. It contains a hardened profile-selection slice and an architecture for a future, removable bridge to settings owned by Nextcloud's Theming app. It is not a drop-in claim of full organisational identity, accessibility compliance, or compatibility with every Nextcloud app.
- A manifest-backed inventory of 40 profile snapshots in
token-sets.jsonandcss/tokens/; 8 currently carry a statically gatednextcloud-core-v1projection and are selectable. - A profile library that combines read-only built-in profiles with immutable versions installed from the closed
nldesign-profile-pack/v1JSON format. - Admin-only exact-version selection with an initial deterministic revision, opaque transition revisions, stale-write rejection, one-step rollback, and bounded version history.
- Light/dark previews, profile search, version selection, and safe removal of installed versions that are neither active nor retained for rollback.
- A three-layer runtime stylesheet plan: local fonts, the selected projection,
and one range-gated
nextcloud-core-v1mapping shared by Nextcloud 32–34. - Native Nextcloud is the initial and explicitly selectable state; enabling the app does not choose an organisation's identity.
- Read-only recommendations for fields an administrator may choose to copy into Nextcloud Theming.
- Self-hosted Fira Sans files; runtime page loads do not contact a font CDN.
- Selecting a profile does not write to Nextcloud Theming.
- Existing administrator custom CSS remains authoritative and can override the projected Nextcloud variables. Resolve those explicit overrides when evaluating or adopting a profile; the app does not silently fight them.
- The isolated
OCA\Themingcompatibility prototype is not registered or load-bearing. - There is no raw TokenFile CRUD, arbitrary CSS upload, custom-override writer, generic configuration export, or automatic core-Theming apply flow. The profile installer accepts only the small closed semantic projection and generates CSS inside the app.
- Selector-based login-footer and app-menu presentation toggles are intentionally absent: the retired experiments changed more UI than their labels promised or lacked supported-major browser evidence.
- A
source-onlycatalogue entry is retained for provenance work but cannot be selected. Inclusion does not prove endorsement, official status, trademark permission, complete upstream provenance, or conformance. - CSS coverage varies by Nextcloud surface and app. A live compatibility matrix still has to be built from integration tests.
The governing design and delivery sequence are in architecture.md and roadmap.md.
Download the archive and checksum from the matching GitHub prerelease, then:
sha256sum --check nldesign-VERSION.tar.gz.sha256
tar -xzf nldesign-VERSION.tar.gz -C /path/to/nextcloud/custom_apps
php /path/to/nextcloud/occ app:enable nldesignThe archive contains the required top-level nldesign/ directory. Preserve the
owner and permissions used by the other apps in custom_apps. Prereleases are
unsigned integration candidates, not Nextcloud App Store releases.
cd /path/to/nextcloud/custom_apps
git clone https://github.com/DROG-group/nldesign.git
cd nldesign
npm ci --ignore-scripts
npm run build
php /path/to/nextcloud/occ app:enable nldesignThe app has no production Composer dependency. Install Composer's development dependencies only when running the PHP quality suite. A packaged release should already contain generated font files and need no Composer, Node, package registry, or CDN access at runtime.
The current app metadata declares maintained Nextcloud 32 through 34 and PHP 8.2 or newer. Static analysis is checked against the oldest supported OCP contract, and the load-bearing CSS uses only the documented variable and theme state intersection audited across those majors. A real multi-version Nextcloud integration matrix remains a release gate.
Open Administration settings → Theming → NL Design profiles.
Selecting an exact profile version saves immediately. The page shows:
- light and dark colour previews;
- grouped profiles with immutable version selectors and provenance labels;
- the active revision and rollback control;
- recent profile operations; and
- manual Nextcloud Theming recommendations, where the manifest contains them.
Use Install profile to add a local JSON pack. A pack must follow
nldesign-profile-pack/v1, use a new immutable
id + version identity, and contain only the allowlisted font and colour
roles. The server rejects unknown fields, arbitrary CSS/JavaScript, remote
assets, invalid colours, and primary/text pairs below the enforced contrast
threshold. Built-in versions cannot be overwritten. Installed versions are
stored in Nextcloud app data, not in the installed app directory.
Open pages may need a reload before the new stylesheet stack is visible everywhere. Selecting Native Nextcloud deactivates the profile without disabling the app, and the same revision/rollback contract applies.
The load-bearing path uses public Nextcloud application APIs:
packaged manifest/CSS ----+
+--> TokenSetService --> ProfileStateService
installed profile records-+ | |
in IAppData v v
TemplateStylesListener app-scoped IAppConfig
|
packaged CSS or digest-addressed generated CSS
The stylesheet order is explicit and unit-tested. For a built-in profile it is:
fonts
tokens/{active-profile}
compatibility/nextcloud-core-v1
An installed profile uses the same fonts → profile → core projection
precedence, but the middle layer is served by a public, immutable,
digest-addressed CSS route. The route revalidates the stored record before
returning generated CSS.
Private Nextcloud Theming classes may only appear below lib/Infrastructure/Nextcloud/Compatibility/. The architecture check prevents those names and installed-app file writes from leaking into the normal runtime path.
Requirements:
- PHP 8.2 or newer and Composer 2
- a maintained Node.js 24 or 26 release and npm
composer install
npm ci --ignore-scripts
composer check
npm test
npm run build
composer audit --locked
npm audit --audit-level=highDocumentation:
cd docusaurus
npm ci --ignore-scripts
npm run buildSee DEVELOPMENT.md for the complete workflow.
For a built-in release profile:
- Add
css/tokens/{id}.cssusing a lowercase kebab-case id. - Add exactly one matching
source-onlyentry totoken-sets.json. - Document the source version, transformation, rights status, and known gaps.
- To make it selectable, reduce it to the four
nextcloud-core-v1projection properties, change its status toready, and add only evidenced, allowlisted manual-Theming hints. Approved assets must be local. - Run
npm run check:manifest, the PHP suite, and representative Nextcloud surface tests.
Directory discovery is not the product API: the manifest and compiled stylesheet must both exist.
For an instance-local profile, prepare a profile-pack document from the provided example and install it through the administration page. Increment the semantic version for every content change; core and prerelease SemVer forms are supported, while build metadata is intentionally excluded from the path-safe identity. The app never mutates or overwrites an installed version in place.
The app code is licensed under EUPL-1.2. Fira Sans is bundled under the SIL Open Font License 1.1.
Organisation names, logos, colours, and other identity material can have usage conditions independent of the code licence. The package no longer distributes organization-specific logos or backgrounds. The previously copied Amsterdam Design System icon/logo package was unused and its package explicitly excluded those assets from the package's open-source licence, so it was also removed. Do not interpret a profile name as permission to represent that organisation.