Bouw een Nextcloud-app op de Conduction-stack, Deel 0: Drie paden, één leerlijn
Voor je een regel code schrijft, bepaal welk van de drie Conduction app-bouwpaden past bij de app die je in gedachten hebt. Traditioneel Nextcloud, OpenRegister + nextcloud-vue, of volledige manifest. Elk pad bouwt voort op wat het vorige je geeft, en de rest van de DeskDesk-serie leert het manifest-pad omdat dáár de curve steil in ons voordeel buigt.
Dit is Deel 0 van de zesdelige DeskDesk-tutorial, de oriëntatieronde. Voor scaffolds, schema's of manifests is het nuttigste dat we een nieuwe ontwikkelaar kunnen geven een eerlijke kaart van de drie manieren waarop Conduction-apps daadwerkelijk gebouwd worden, wat elk pad kost, en wat elk pad teruggeeft. De rest van de serie kiest één pad en laat de bonnetjes zien. Deel 0 legt uit waarom.
Iets anders is al vanaf minuut één belangrijk: het manifest-systeem en de @conduction/nextcloud-vue componentenbibliotheek zijn twee verschillende oppervlakken. Het manifest is de declaratieve wat, één manifest.json die navigatie, pagina's en configuratie beschrijft. nextcloud-vue is de rendering hoe, de Cn*-componenten waar het manifest naartoe dispatcht (CnAppRoot, CnPageRenderer, CnIndexPage, CnDetailPage, CnDashboardPage, en de rest). Technisch zijn ze los te koppelen. In de praktijk zijn ze zo verweven dat de rest van deze serie ze samen leert, en elke les noemt welk oppervlak hij aanraakt.
De drie paden in één oogopslag
Dezelfde DeskDesk-feature, een lijst met bureaus met een detailpagina, een boekingsdialoog, en een sidebar die audit-historie toont, kan op drie manieren gebouwd worden. Kies de tabelcel die klinkt als jouw team.
| Pad 1: Traditioneel Nextcloud | Pad 2: OpenRegister + nextcloud-vue | Pad 3: Manifest + nextcloud-vue | |
|---|---|---|---|
| Wat je schrijft | PHP-controllers, Doctrine entities + migraties, handgemaakte Vue-views, eigen routes, je eigen CRUD-endpoints | Schema's in JSON, register-configuratie, handgemaakte Vue-views opgebouwd uit Cn*-componenten, je eigen App.vue + router | Schema's in JSON, één manifest.json die pagina's + config beschrijft, alleen de echt-maatwerk-views als type: 'custom' |
| Per-app code voor de DeskDesk-feature hierboven | ~1500 LOC | ~600 LOC | ~30 LOC + het manifest |
| Waar de data leeft | App-private databasetabellen die je zelf hebt gedefinieerd | Een gedeeld OpenRegister-register, elke andere app op dezelfde Nextcloud kan via de registry lezen/schrijven | Hetzelfde als Pad 2 |
| RBAC, audit log, GraphQL, cross-app-referenties, bestandsbijlagen, calendar/contacts-integraties | Bouw elk zelf | Gratis, OpenRegister levert ze mee. Zie "Wat OpenRegister je hoe dan ook geeft" hieronder | Gratis, hetzelfde als Pad 2 |
| Lijstpagina's, detailpagina's, filter-sidebars, mass-action-dialogen | Bouw elk zelf | Hergebruik CnIndexPage, CnDetailPage, CnDashboardPage, schema stuurt kolommen en formulieren | Hergebruik dezelfde componenten, declaratief gedispatcht door CnPageRenderer vanuit je manifest.json |
Een priority-veld toevoegen aan bookings | Nieuwe migratie, nieuwe controller-code, nieuw Vue-veld, nieuwe validatie | Veld toevoegen aan schema → formulieren en tabellen pikken het automatisch op | Hetzelfde als Pad 2, schema-gedreven door en door |
| Een kanban-bord toevoegen (echt maatwerk) | Bouw het | Bouw het als Vue-component, mount het in je router | Bouw het als Vue-component, declareer {type:'custom', component:'PipelineBoard'} in het manifest |
| Onderhoudslast over 10 vergelijkbare apps | Elke app drift weg. 10 lijstpagina's, 10 detailpagina's, allemaal net iets anders. | Het Vue-oppervlak drift nog steeds, elke App.vue en router is handgeschreven. Schema-migraties blijven schoon. | Eén manifest-vorm over de hele vloot. Een lib-bump fixt elke app tegelijk. |
| Leercurve tot eerste werkende pagina | Laagst als je al Nextcloud-app-ontwikkeling kent. De patronen zijn gedocumenteerd. | Middelmatig, schema's + Cn*-componenten zijn nieuw maar goed uitgesleten. | Steilst in het begin, je moet eerst manifest-dispatch doorgronden. Na Deel 2 keert de curve om. |
| Plafond | Wat je in PHP + Vue kunt bouwen. Geen plafond maar ook geen hefboom. | Schema-gedreven CRUD schaalt prachtig. Maatwerkflows zijn nog steeds handgemaakte Vue. | Hetzelfde als Pad 2 plus: elke Conduction-app upgrade samen wanneer het manifest-schema of nextcloud-vue evolueert. |
Wanneer welk pad de juiste keuze is
Pad 1, Traditioneel Nextcloud is de juiste keuze wanneer:
- Je een Nextcloud-native feature levert zonder gebruik van cross-app gedeelde data (bijv. een Talk-command-extensie, een OAuth-provider, een calendar-provider-plugin).
- Je gedrag nodig hebt dat onder de datalaag leeft, file storage-hooks, dav-endpoints, sharing-extensies.
- Je een legacy-app onderhoudt waarvan de patronen ouder zijn dan OpenRegister en een herschrijving niet te rechtvaardigen is.
- Je expliciet de vrijheid nodig hebt om af te wijken van de Conduction-stack, bring-your-own-database, bring-your-own-frontend-framework, alles waar de beperkingen je zouden vertragen.
Pad 2, OpenRegister + nextcloud-vue is de juiste keuze wanneer:
- Je data fundamenteel CRUD is tegen een kleine set schema's, maar je de paginacompositie voorlopig handgeschreven wilt houden, misschien omdat de bestaande app al een eigen
App.vueheeft, of omdat je incrementeel wilt migreren. - Je aan het prototypen bent en eerst een paar handgemaakte views wilt voelen voor je commit aan een manifest-gedreven vorm.
- Het team de manifest-mechanica nog niet heeft geleerd en je een deadline hebt.
Pad 3, Manifest + nextcloud-vue is de juiste keuze wanneer:
- De app voornamelijk een verzameling register-backed CRUD-oppervlakken is met een paar maatwerkflows erbovenop, wat de overgrote meerderheid van Conduction-apps beschrijft.
- Je de app op de upgrade-trein wilt houden: lib-bumps, schema-verbeteringen, toegankelijkheidsverbeteringen stromen binnen zonder per-app-werk.
- Je vers begint. De totale tijd tot een werkende app op Pad 3 is minder dan op Pad 2 zodra je het één keer hebt gedaan, ook al is het eerste uur steiler.
- Je de navigatie wilt kunnen herontwerpen, een lijst voor een dashboard wilt wisselen, of een wiki-sectie wilt toevoegen door JSON te bewerken in plaats van Vue te herschrijven.
De DeskDesk-tutorialserie leert Pad 3. Deel 1 legt het chassis. Deel 2 introduceert het manifest. Deel 3 laat zien hoe één schema-annotatie boekingen in Nextcloud Calendar laat verschijnen zonder lijmcode. Deel 4 voegt een kennis-sidebar toe gevoed vanuit xWiki en levert de app op.
Wat OpenRegister je hoe dan ook geeft, ongeacht het pad
Dit onderdeel verrast mensen. OpenRegister is niet zomaar "een register met CRUD-endpoints", het is een dataplatform dat een aantal Nextcloud-native superkrachten meelevert op het moment dat je er een schema in stopt. Of je nu op Pad 2 of Pad 3 bouwt, je erft dit allemaal zonder het te schrijven:
Pad 2 en Pad 3 bouwen beide op dit fundament. Pad 1 niet, elk van de bullets hierboven is een apart engineering-project als je vanaf rauw Nextcloud begint.
Twee oppervlakken, één leerlijn
Een veelvoorkomende verwarring bij het lezen van de rest van deze serie: het manifest is niet hetzelfde als de componentenbibliotheek, ook al leren we ze samen.
- Het manifest is
src/manifest.json. Het is een JSON-document gevalideerd door een schema (https://raw.githubusercontent.com/ConductionNL/nextcloud-vue/main/src/schemas/app-manifest-v2.schema.json, op dit moment versie 2.7.0). Het beschrijft navigatie-entries, routes, en wat elke pagina rendert. Het heeft op zichzelf geen runtime-gedrag. - De componentenbibliotheek is
@conduction/nextcloud-vue. Het is een set Vue 2-componenten met de prefixCn*,CnAppRootmount de app-shell,CnPageRendererleest het manifest en dispatcht de juiste paginacomponent,CnIndexPage/CnDetailPage/CnDashboardPagerenderen de daadwerkelijke pagina-oppervlakken.
Je kunt de bibliotheek gebruiken zonder het manifest. Pad 2 in de tabel hierboven doet precies dat, een handgemaakte App.vue mount Cn*-componenten direct in een handgeschreven router. Je schrijft meer Vue, maar je houdt het schema-gedreven listing/detail/form-gedrag en je houdt alle OpenRegister-perks.
Je kunt het manifest niet gebruiken zonder de bibliotheek. Het manifest is betekenisloos totdat iets het leest, CnPageRenderer is dat iets. Dus het manifest-pad is altijd een manifest + bibliotheek-leerlijn.
De implicatie voor hoe je deze serie leest:
| Les | Manifest-oppervlak | Bibliotheek-oppervlak |
|---|---|---|
| Deel 1: Scaffold | nog geen | CnAppRoot-chassis |
| Deel 2: Schema's + manifest | introduceer manifest.json, page types, config-props | CnPageRenderer-dispatch, CnIndexPage + CnDetailPage props |
| Deel 3: Schema-gedreven integraties | onveranderd | calendar-provider-annotatie stroomt door CnDetailGrid |
| Deel 4: Knowledge-tab + ship | sidebar-tabs in config.sidebar, type: 'custom' voor de wiki-view | host-app SFC geregistreerd als custom component, CnObjectSidebar consumeert manifest-tabs |
Als je maar één ding onthoudt over de relatie: het manifest beantwoordt "wat moet deze app renderen"; de bibliotheek beantwoordt "hoe wordt dat gerenderd". De bibliotheek maakt het manifest levend.
Een notitie over één keer kiezen versus later kiezen
Je hoeft niet voor altijd een pad te kiezen. Apps bewegen routinematig tussen Pad 2 en Pad 3, een aantal Conduction-apps begon op Pad 2 en verhuisde naar Pad 3 zodra het team het manifest leerde. De migratie is meestal 1 tot 2 dagen voor een app met 5 tot 10 schema's, omdat de schema's helemaal niet veranderen; alleen App.vue + de router worden vervangen door CnAppRoot + een manifest.
Van Pad 1 naar Pad 2 of Pad 3 gaan is moeilijker omdat je de datalaag naar een register moet migreren. Plan dat als een echt project, niet als een refactor tussen sprints door.
