This repository was archived by the owner on May 29, 2026. It is now read-only.
feat: scaffold the JSON manifest renderer pattern as the template default (template-manifest-v1)#27
Merged
Conversation
Spec the canonical Tier-4 scaffolding for the JSON manifest renderer pattern in nextcloud-app-template. Codifies hydra ADR-024's "new apps MUST adopt the manifest from inception" requirement at the source — the template — rather than retrofitting per app. Includes proposal, design, tasks, and 10 REQ-TMV1-* requirements covering manifest contents, bootstrap pattern, registry contract, webpack alias, dependency floor, and the manifest-first README quickstart.
Add the canonical template manifest with 4 example pages (one each of type dashboard / index / detail / settings) and 4 menu entries. Declares openregister as the default dependency. Settings page demonstrates the version-info rich-section widget. Add src/customComponents.js as the empty-by-default registry contract with a single example placeholder (CustomExample) so the registry's role is visible to first-time cloners. The manifest does NOT reference CustomExample by default — it only ships as documentation. Add tests/validate-manifest.js (copied from decidesk's reference) for Ajv-based schema validation. Wired up via npm run check:manifest. Trim l10n/en.json to a clean baseline aligned with the new manifest strings; add an empty l10n/en_US.json placeholder.
Adopt decidesk's mount-survivable bootstrap pattern (commits 50e4df7c
+ 866ff132) as the template default:
main.js:
- Import bundledManifest from './manifest.json' and customComponents
from './customComponents.js'.
- Build vue-router routes from manifest.pages[*].{id,route} via a
routesFromManifest() helper that uses a shallow-cloned
CnPageRenderer ({ ...CnPageRenderer }) — required because Vue 2's
Vue.extend() mutates the component options object with a _Ctor
cache, which throws against the lib's frozen barrel exports.
- Pass shallow-cloned defaultPageTypes and customComponents to
App.vue as props.
- Mount on #content immediately, NOT inside loadTranslations'
callback (NC dev installs commonly 404 the /l10n/<locale>.json
route, which would silently kill boot). Translation load is
fire-and-forget; strings fall back to English on miss.
App.vue:
- Mount <CnAppRoot> with manifest + customComponents + pageTypes
props, app-id, translateForApp closure, and permissions array.
- Provide an objectSidebarState reactive channel via provide() and
mount <CnObjectSidebar> in the #sidebar slot — the standard
pattern for CnDetailPage → host-rendered sidebar.
settings.js + AdminRoot.vue:
- Keep the Nextcloud admin app-settings webpack entry-point (a
distinct surface from the manifest's type:'settings' SPA page).
Replace the deleted views/settings/AdminRoot.vue with a minimal
placeholder NcSettingsSection that documents the divergence.
Delete the legacy shell:
- src/router/index.js (routes built from manifest at boot).
- src/navigation/MainMenu.vue (CnAppNav replaces it).
- src/views/Dashboard.vue (manifest type:'dashboard' replaces it).
- src/views/settings/ (manifest type:'settings' replaces it).
…README
package.json:
- @conduction/nextcloud-vue ^0.1.0-beta.3 → ^1.0.0-beta.12 (the
published lib version with the Vue.extend frozen-component fix).
- @nextcloud/router ^2.0.1 → ^3.1.0 — required by @nextcloud/vue
8.37+ (NcDashboardWidget / NcAvatar import getBaseUrl, missing
from router 2.x).
- Add ajv ^8.17.1 + ajv-formats ^3.0.1 devDependencies for the
manifest validator.
- Add scripts.check:manifest → node tests/validate-manifest.js
(satisfies the fleet adoption spec's build-time validation gate).
webpack.config.js:
- Add @nextcloud/axios$ alias to force the lib's transitive axios
import to resolve to the app's installed copy (decidesk pattern,
commit ed34703c). Without the $ exact-match suffix webpack walks
up to the lib's own node_modules and loads a second axios
instance, breaking shared interceptors / CSRF tokens.
eslint.config.js:
- Override no-console / n/no-process-exit / n/shebang for the
tests/validate-manifest.js Node CLI script.
README.md:
- Lead with manifest-first messaging in the intro paragraph and
in the OpenRegister callout.
- Add an "Adding a page (manifest-first)" section that documents
the page-type table and tells cloners to edit src/manifest.json
rather than writing per-page Vue files. Custom Vue components
are only required for type:"custom" pages.
- Add a "Renaming the app" section listing the files where the
app id appears (the manifest itself does NOT carry the id).
- Update the directory-structure diagram to reflect the new
layout (manifest.json, customComponents.js, no router/, no
navigation/).
Contributor
Quality Report — ConductionNL/nextcloud-app-template @
|
| Check | PHP | Vue | Security | License | Tests |
|---|---|---|---|---|---|
| lint | ✅ | ||||
| phpcs | ✅ | ||||
| phpmd | ✅ | ||||
| psalm | ✅ | ||||
| phpstan | ✅ | ||||
| phpmetrics | ✅ | ||||
| eslint | ✅ | ||||
| stylelint | ✅ | ||||
| composer | ✅ | ✅ 100/100 | |||
| npm | ✅ | ✅ 425/425 | |||
| PHPUnit | ✅ | ||||
| Newman | ✅ | ||||
| Playwright | ⏭️ |
Coverage: 0% (0/3 statements)
Quality workflow — 2026-05-09 16:37 UTC
Download the full PDF report from the workflow artifacts.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to subscribe to this conversation on GitHub.
Already have an account?
Sign in.
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Make
nextcloud-app-templatethe canonical Tier-4 scaffolding for the JSON manifest renderer pattern. After this PR, every new Conduction Nextcloud app generated from this template starts with a working manifest-driven shell on firstnpm install && npm run build.Implements hydra ADR-024 at the source — the template — rather than retrofitting per app:
What ships
src/manifest.json— minimal opinionated 4-page manifest, one each ofdashboard | index | detail | settings, withdependencies: ["openregister"], schema-validates against@conduction/nextcloud-vue@1.0.0-beta.13's 1.2.0 schema (zero errors).src/main.js— Tier-4 mount-survivable bootstrap (decidesk's50e4df7c+866ff132): shallow-clonedCnPageRenderer/defaultPageTypes/customComponentsto dodge Vue 2's_Ctormutation against frozen barrel exports; routes built frommanifest.pages[*]; mount on#contentimmediately, NOT insideloadTranslations.src/App.vue—<CnAppRoot>shell withmanifest/customComponents/pageTypes/app-id/translate/permissionsprops;objectSidebarStateprovide channel;<CnObjectSidebar>in the#sidebarslot.src/customComponents.js— empty-by-default registry contract with one example placeholder (CustomExample) so the registry's role is visible to first-time cloners. Manifest does NOT reference it by default.src/views/CustomExample.vue— trivial example custom component documenting when to reach fortype: "custom"(rarely).tests/validate-manifest.js— Ajv-based schema validator copied from decidesk;npm run check:manifestruns it.webpack.config.js—@nextcloud/axios$alias (decidesk pattern) so the lib's transitive axios import resolves to the app's installed copy.package.json—@conduction/nextcloud-vue^0.1.0-beta.3 → ^1.0.0-beta.12;@nextcloud/router^2.0.1 → ^3.1.0 (NC-vue 8.37 needsgetBaseUrl);ajv+ajv-formatsdevDeps;check:manifestscript.README.md— manifest-first quickstart with a page-type table; tells cloners to editsrc/manifest.jsonrather than writing per-page Vue files.src/router/index.js,src/navigation/MainMenu.vue,src/views/Dashboard.vue,src/views/settings/.Validation results
OpenSpec change
openspec/changes/template-manifest-v1/— proposal, design (with smoke-test recipe), tasks (all ticked), and 10 REQ-TMV1-* requirements.Test plan
npm install && npm run build && npm run check:manifest. Verify all three exit zero.make dev-link && docker exec nextcloud php occ app:enable app-template, browse to/index.php/apps/app-template/. Expected: CnAppNav renders 3 left-side menu entries (Dashboard, Items, Documentation) + Settings in the footer; Dashboard renders the placeholder widget; Settings renders the version-info widget._Ctor", "[CnAppRoot] manifest is required", "[useAppManifest] schema validation failed".src/router/,src/navigation/MainMenu.vue,src/views/Dashboard.vue,src/views/settings/) have no remaining references in the codebase.Out of scope
make new-app NAME=...scaffolder (manual rename remains; left for a follow-up).lib/Service,lib/Repair/InitializeSettings.php) — the template stays pre-wired for OR because most new Conduction apps use OR; opting out is a 4-line README delta./api/manifestoverride endpoint (Tier 4 ships bundled-only per ADR-024 §4).