diff --git a/.gitignore b/.gitignore
index 9f02b37e4..911c25585 100644
--- a/.gitignore
+++ b/.gitignore
@@ -12,8 +12,9 @@
.phpunit.cache/
/node_modules/
-/website/node_modules/
-/website/.docusaurus/
+/docs/node_modules/
+/docs/build/
+/docs/.docusaurus/
/js/
/custom_apps/
/config/
@@ -64,8 +65,6 @@ test-solr-connection.php
**/adds *
**/implements *
-website/.docusaurus/
-
phpqa/
# Docker AI models (too large for git)
@@ -75,8 +74,3 @@ docker/dolphin/models/
!issues/
!issues/**
-# TODO: fix whatever is wrong with these files that causes them to always end up in git changes
-website/docs/Features/img_4.png
-website/docs/Features/img_5.png
-website/docs/features/img_4.png
-website/docs/features/img_5.png
diff --git a/docusaurus/docusaurus.config.js b/docs/docusaurus.config.js
similarity index 92%
rename from docusaurus/docusaurus.config.js
rename to docs/docusaurus.config.js
index d392ba614..d9c1e0bd6 100644
--- a/docusaurus/docusaurus.config.js
+++ b/docs/docusaurus.config.js
@@ -20,7 +20,11 @@ const config = {
// metadata like html lang
i18n: {
defaultLocale: 'en',
- locales: ['en'],
+ locales: ['en', 'nl'],
+ localeConfigs: {
+ en: { label: 'English' },
+ nl: { label: 'Nederlands' },
+ },
},
presets: [
@@ -29,10 +33,11 @@ const config = {
/** @type {import('@docusaurus/preset-classic').Options} */
({
docs: {
- path: '../docs',
+ path: './',
+ exclude: ['**/node_modules/**'],
sidebarPath: require.resolve('./sidebars.js'),
editUrl:
- 'https://github.com/conductionnl/openregister/tree/main/docusaurus/',
+ 'https://github.com/conductionnl/openregister/tree/main/docs/',
},
blog: false,
theme: {
@@ -94,6 +99,10 @@ const config = {
label: 'GitHub',
position: 'right',
},
+ {
+ type: 'localeDropdown',
+ position: 'right',
+ },
],
},
footer: {
diff --git a/docs/i18n/nl/code.json b/docs/i18n/nl/code.json
new file mode 100644
index 000000000..a9fda26fe
--- /dev/null
+++ b/docs/i18n/nl/code.json
@@ -0,0 +1,313 @@
+{
+ "theme.ErrorPageContent.title": {
+ "message": "Deze pagina is gecrasht.",
+ "description": "The title of the fallback page when the page crashed"
+ },
+ "theme.BackToTopButton.buttonAriaLabel": {
+ "message": "Scroll naar boven",
+ "description": "The ARIA label for the back to top button"
+ },
+ "theme.blog.archive.title": {
+ "message": "Archief",
+ "description": "The page & hero title of the blog archive page"
+ },
+ "theme.blog.archive.description": {
+ "message": "Archief",
+ "description": "The page & hero description of the blog archive page"
+ },
+ "theme.blog.paginator.navAriaLabel": {
+ "message": "Paginanavigatie blog",
+ "description": "The ARIA label for the blog pagination"
+ },
+ "theme.blog.paginator.newerEntries": {
+ "message": "Nieuwere items",
+ "description": "The label used to navigate to the newer blog posts page (previous page)"
+ },
+ "theme.blog.paginator.olderEntries": {
+ "message": "Oudere items",
+ "description": "The label used to navigate to the older blog posts page (next page)"
+ },
+ "theme.blog.post.paginator.navAriaLabel": {
+ "message": "Paginanavigatie blog",
+ "description": "The ARIA label for the blog posts pagination"
+ },
+ "theme.blog.post.paginator.newerPost": {
+ "message": "Nieuwer bericht",
+ "description": "The blog post button label to navigate to the newer/previous post"
+ },
+ "theme.blog.post.paginator.olderPost": {
+ "message": "Ouder bericht",
+ "description": "The blog post button label to navigate to the older/next post"
+ },
+ "theme.tags.tagsPageLink": {
+ "message": "Laat alle tags zien",
+ "description": "The label of the link targeting the tag list page"
+ },
+ "theme.colorToggle.ariaLabel": {
+ "message": "Schakel tussen donkere en lichte modus (momenteel {mode})",
+ "description": "The ARIA label for the navbar color mode toggle"
+ },
+ "theme.colorToggle.ariaLabel.mode.dark": {
+ "message": "donkere modus",
+ "description": "The name for the dark color mode"
+ },
+ "theme.colorToggle.ariaLabel.mode.light": {
+ "message": "lichte modus",
+ "description": "The name for the light color mode"
+ },
+ "theme.docs.breadcrumbs.navAriaLabel": {
+ "message": "Broodkruimels",
+ "description": "The ARIA label for the breadcrumbs"
+ },
+ "theme.docs.DocCard.categoryDescription.plurals": {
+ "message": "1 artikel|{count} artikelen",
+ "description": "The default description for a category card in the generated index about how many items this category includes"
+ },
+ "theme.docs.paginator.navAriaLabel": {
+ "message": "Documentatie pagina",
+ "description": "The ARIA label for the docs pagination"
+ },
+ "theme.docs.paginator.previous": {
+ "message": "Vorige",
+ "description": "The label used to navigate to the previous doc"
+ },
+ "theme.docs.paginator.next": {
+ "message": "Volgende",
+ "description": "The label used to navigate to the next doc"
+ },
+ "theme.docs.tagDocListPageTitle.nDocsTagged": {
+ "message": "Een artikel getagd|{count} artikelen getagd",
+ "description": "Pluralized label for \"{count} docs tagged\". Use as much plural forms (separated by \"|\") as your language support (see https://www.unicode.org/cldr/cldr-aux/charts/34/supplemental/language_plural_rules.html)"
+ },
+ "theme.docs.tagDocListPageTitle": {
+ "message": "{nDocsTagged} met \"{tagName}\"",
+ "description": "The title of the page for a docs tag"
+ },
+ "theme.docs.versions.unreleasedVersionLabel": {
+ "message": "Dit is nog niet uitgegeven documentatie voor {siteTitle}, versie {versionLabel}",
+ "description": "The label used to tell the user that he's browsing an unreleased doc version"
+ },
+ "theme.docs.versions.unmaintainedVersionLabel": {
+ "message": "Dit is de documentatie voor {siteTitle} {versionLabel}, welke niet langer actief wordt onderhouden.",
+ "description": "The label used to tell the user that he's browsing an unmaintained doc version"
+ },
+ "theme.docs.versions.latestVersionSuggestionLabel": {
+ "message": "Voor de huidige documentatie, zie de {latestVersionLink} ({versionLabel}).",
+ "description": "The label used to tell the user to check the latest version"
+ },
+ "theme.docs.versions.latestVersionLinkLabel": {
+ "message": "laatste versie",
+ "description": "The label used for the latest version suggestion link label"
+ },
+ "theme.docs.versionBadge.label": {
+ "message": "Versie: {versionLabel}"
+ },
+ "theme.common.editThisPage": {
+ "message": "Bewerk deze pagina",
+ "description": "The link label to edit the current page"
+ },
+ "theme.common.headingLinkTitle": {
+ "message": "Direct link naar {heading}",
+ "description": "Title for link to heading"
+ },
+ "theme.lastUpdated.atDate": {
+ "message": " op {date}",
+ "description": "The words used to describe on which date a page has been last updated"
+ },
+ "theme.lastUpdated.byUser": {
+ "message": " door {user}",
+ "description": "The words used to describe by who the page has been last updated"
+ },
+ "theme.lastUpdated.lastUpdatedAtBy": {
+ "message": "Laatst bijgewerkt{atDate}{byUser}",
+ "description": "The sentence used to display when a page has been last updated, and by who"
+ },
+ "theme.navbar.mobileVersionsDropdown.label": {
+ "message": "Versies",
+ "description": "The label for the navbar versions dropdown on mobile view"
+ },
+ "theme.NotFound.title": {
+ "message": "Pagina niet gevonden",
+ "description": "The title of the 404 page"
+ },
+ "theme.tags.tagsListLabel": {
+ "message": "Tags:",
+ "description": "The label alongside a tag list"
+ },
+ "theme.admonition.caution": {
+ "message": "pas op",
+ "description": "The default label used for the Caution admonition (:::caution)"
+ },
+ "theme.admonition.danger": {
+ "message": "gevaar",
+ "description": "The default label used for the Danger admonition (:::danger)"
+ },
+ "theme.admonition.info": {
+ "message": "info",
+ "description": "The default label used for the Info admonition (:::info)"
+ },
+ "theme.admonition.note": {
+ "message": "notitie",
+ "description": "The default label used for the Note admonition (:::note)"
+ },
+ "theme.admonition.tip": {
+ "message": "tip",
+ "description": "The default label used for the Tip admonition (:::tip)"
+ },
+ "theme.admonition.warning": {
+ "message": "waarschuwing",
+ "description": "The default label used for the Warning admonition (:::warning)"
+ },
+ "theme.AnnouncementBar.closeButtonAriaLabel": {
+ "message": "Sluiten",
+ "description": "The ARIA label for close button of announcement bar"
+ },
+ "theme.blog.sidebar.navAriaLabel": {
+ "message": "Navigatie recente blogitems",
+ "description": "The ARIA label for recent posts in the blog sidebar"
+ },
+ "theme.CodeBlock.copied": {
+ "message": "Gekopieerd",
+ "description": "The copied button label on code blocks"
+ },
+ "theme.CodeBlock.copyButtonAriaLabel": {
+ "message": "Kopieer code naar klembord",
+ "description": "The ARIA label for copy code blocks button"
+ },
+ "theme.CodeBlock.copy": {
+ "message": "Kopieer",
+ "description": "The copy button label on code blocks"
+ },
+ "theme.CodeBlock.wordWrapToggle": {
+ "message": "Tekstterugloop in-/uitschakelen",
+ "description": "The title attribute for toggle word wrapping button of code block lines"
+ },
+ "theme.DocSidebarItem.expandCategoryAriaLabel": {
+ "message": "Categorie zijbalk uitklappen '{label}'",
+ "description": "The ARIA label to expand the sidebar category"
+ },
+ "theme.DocSidebarItem.collapseCategoryAriaLabel": {
+ "message": "Categorie zijbalk inklappen '{label}'",
+ "description": "The ARIA label to collapse the sidebar category"
+ },
+ "theme.NavBar.navAriaLabel": {
+ "message": "Main",
+ "description": "The ARIA label for the main navigation"
+ },
+ "theme.navbar.mobileLanguageDropdown.label": {
+ "message": "Talen",
+ "description": "The label for the mobile language switcher dropdown"
+ },
+ "theme.NotFound.p1": {
+ "message": "We kunnen niet vinden waar je naar op zoek bent.",
+ "description": "The first paragraph of the 404 page"
+ },
+ "theme.NotFound.p2": {
+ "message": "Neem contact op met de eigenaar van de website die naar de originele URL heeft geleid en laat weten dat de link niet meer werkt.",
+ "description": "The 2nd paragraph of the 404 page"
+ },
+ "theme.TOCCollapsible.toggleButtonLabel": {
+ "message": "Op deze pagina",
+ "description": "The label used by the button on the collapsible TOC component"
+ },
+ "theme.blog.post.readMore": {
+ "message": "Lees meer",
+ "description": "The label used in blog post item excerpts to link to full blog posts"
+ },
+ "theme.blog.post.readMoreLabel": {
+ "message": "Lees meer over {title}",
+ "description": "The ARIA label for the link to full blog posts from excerpts"
+ },
+ "theme.blog.post.readingTime.plurals": {
+ "message": "Een minuut leestijd|{readingTime} minuten leestijd",
+ "description": "Pluralized label for \"{readingTime} min read\". Use as much plural forms (separated by \"|\") as your language support (see https://www.unicode.org/cldr/cldr-aux/charts/34/supplemental/language_plural_rules.html)"
+ },
+ "theme.docs.breadcrumbs.home": {
+ "message": "Homepagina",
+ "description": "The ARIA label for the home page in the breadcrumbs"
+ },
+ "theme.docs.sidebar.collapseButtonTitle": {
+ "message": "Zijbalk inklappen",
+ "description": "The title attribute for collapse button of doc sidebar"
+ },
+ "theme.docs.sidebar.collapseButtonAriaLabel": {
+ "message": "Zijbalk inklappen",
+ "description": "The title attribute for collapse button of doc sidebar"
+ },
+ "theme.docs.sidebar.navAriaLabel": {
+ "message": "Docs zijbalk",
+ "description": "The ARIA label for the sidebar navigation"
+ },
+ "theme.docs.sidebar.closeSidebarButtonAriaLabel": {
+ "message": "Sluit navigatiebalk",
+ "description": "The ARIA label for close button of mobile sidebar"
+ },
+ "theme.navbar.mobileSidebarSecondaryMenu.backButtonLabel": {
+ "message": "← Terug naar het hoofdmenu",
+ "description": "The label of the back button to return to main menu, inside the mobile navbar sidebar secondary menu (notably used to display the docs sidebar)"
+ },
+ "theme.docs.sidebar.toggleSidebarButtonAriaLabel": {
+ "message": "Navigatiebalk schakelen",
+ "description": "The ARIA label for hamburger menu button of mobile navigation"
+ },
+ "theme.docs.sidebar.expandButtonTitle": {
+ "message": "Zijbalk uitklappen",
+ "description": "The ARIA label and title attribute for expand button of doc sidebar"
+ },
+ "theme.docs.sidebar.expandButtonAriaLabel": {
+ "message": "Zijbalk uitklappen",
+ "description": "The ARIA label and title attribute for expand button of doc sidebar"
+ },
+ "theme.blog.post.plurals": {
+ "message": "Een bericht|{count} berichten",
+ "description": "Pluralized label for \"{count} posts\". Use as much plural forms (separated by \"|\") as your language support (see https://www.unicode.org/cldr/cldr-aux/charts/34/supplemental/language_plural_rules.html)"
+ },
+ "theme.blog.tagTitle": {
+ "message": "{nPosts} getagd met \"{tagName}\"",
+ "description": "The title of the page for a blog tag"
+ },
+ "theme.blog.author.pageTitle": {
+ "message": "{authorName} - {nPosts}",
+ "description": "The title of the page for a blog author"
+ },
+ "theme.blog.authorsList.pageTitle": {
+ "message": "Auteurs",
+ "description": "The title of the authors page"
+ },
+ "theme.blog.authorsList.viewAll": {
+ "message": "Bekijk alle auteurs",
+ "description": "The label of the link targeting the blog authors page"
+ },
+ "theme.blog.author.noPosts": {
+ "message": "Deze auteur heeft nog geen berichten geschreven.",
+ "description": "The text for authors with 0 blog post"
+ },
+ "theme.contentVisibility.unlistedBanner.title": {
+ "message": "Verborgen page",
+ "description": "The unlisted content banner title"
+ },
+ "theme.contentVisibility.unlistedBanner.message": {
+ "message": "Deze pagina is verborgen. Zoekmachines indexeren deze niet en alleen gebruikers met een directe link kunnen deze openen.",
+ "description": "The unlisted content banner message"
+ },
+ "theme.contentVisibility.draftBanner.title": {
+ "message": "Concept pagina",
+ "description": "The draft content banner title"
+ },
+ "theme.contentVisibility.draftBanner.message": {
+ "message": "Deze pagina is een concept. Deze zal alleen zichtbaar zijn in de ontwikkelomgeving en uitgesloten worden van de productie build.",
+ "description": "The draft content banner message"
+ },
+ "theme.ErrorPageContent.tryAgain": {
+ "message": "Probeer opnieuw",
+ "description": "The label of the button to try again rendering when the React error boundary captures an error"
+ },
+ "theme.common.skipToMainContent": {
+ "message": "Ga naar hoofdinhoud",
+ "description": "The skip to content label used for accessibility, allowing to rapidly navigate to main content with keyboard tab/enter navigation"
+ },
+ "theme.tags.tagsPageTitle": {
+ "message": "Tags",
+ "description": "The title of the tag list page"
+ }
+}
diff --git a/docs/i18n/nl/docusaurus-plugin-content-docs/current.json b/docs/i18n/nl/docusaurus-plugin-content-docs/current.json
new file mode 100644
index 000000000..e1d8e9f31
--- /dev/null
+++ b/docs/i18n/nl/docusaurus-plugin-content-docs/current.json
@@ -0,0 +1,78 @@
+{
+ "version.label": {
+ "message": "Volgende",
+ "description": "The label for version current"
+ },
+ "sidebar.tutorialSidebar.category.Integrations Overview": {
+ "message": "Overzicht integraties",
+ "description": "The label for category Integrations Overview in sidebar tutorialSidebar"
+ },
+ "sidebar.tutorialSidebar.category.Core Features": {
+ "message": "Kernfunctionaliteiten",
+ "description": "The label for category Core Features in sidebar tutorialSidebar"
+ },
+ "sidebar.tutorialSidebar.category.Technical": {
+ "message": "Technisch",
+ "description": "The label for category Technical in sidebar tutorialSidebar"
+ },
+ "sidebar.tutorialSidebar.category.UseCases": {
+ "message": "Toepassingen",
+ "description": "The label for category UseCases in sidebar tutorialSidebar"
+ },
+ "sidebar.tutorialSidebar.category.api": {
+ "message": "api",
+ "description": "The label for category api in sidebar tutorialSidebar"
+ },
+ "sidebar.tutorialSidebar.category.development": {
+ "message": "ontwikkeling",
+ "description": "The label for category development in sidebar tutorialSidebar"
+ },
+ "sidebar.tutorialSidebar.category.Development": {
+ "message": "Ontwikkeling",
+ "description": "The label for category Development in sidebar tutorialSidebar"
+ },
+ "sidebar.tutorialSidebar.category.development-notes": {
+ "message": "ontwikkelnotities",
+ "description": "The label for category development-notes in sidebar tutorialSidebar"
+ },
+ "sidebar.tutorialSidebar.category.features": {
+ "message": "functionaliteiten",
+ "description": "The label for category features in sidebar tutorialSidebar"
+ },
+ "sidebar.tutorialSidebar.category.static": {
+ "message": "statisch",
+ "description": "The label for category static in sidebar tutorialSidebar"
+ },
+ "sidebar.tutorialSidebar.category.oas": {
+ "message": "oas",
+ "description": "The label for category oas in sidebar tutorialSidebar"
+ },
+ "sidebar.tutorialSidebar.category.Examples": {
+ "message": "Voorbeelden",
+ "description": "The label for category Examples in sidebar tutorialSidebar"
+ },
+ "sidebar.tutorialSidebar.category.ZaakRegister": {
+ "message": "ZaakRegister",
+ "description": "The label for category ZaakRegister in sidebar tutorialSidebar"
+ },
+ "sidebar.tutorialSidebar.category.technical": {
+ "message": "technisch",
+ "description": "The label for category technical in sidebar tutorialSidebar"
+ },
+ "sidebar.tutorialSidebar.category.testing": {
+ "message": "testen",
+ "description": "The label for category testing in sidebar tutorialSidebar"
+ },
+ "sidebar.tutorialSidebar.category.user": {
+ "message": "gebruiker",
+ "description": "The label for category user in sidebar tutorialSidebar"
+ },
+ "sidebar.tutorialSidebar.category.user-guide": {
+ "message": "gebruikershandleiding",
+ "description": "The label for category user-guide in sidebar tutorialSidebar"
+ },
+ "sidebar.tutorialSidebar.category.configuration": {
+ "message": "configuratie",
+ "description": "The label for category configuration in sidebar tutorialSidebar"
+ }
+}
diff --git a/docs/i18n/nl/docusaurus-theme-classic/footer.json b/docs/i18n/nl/docusaurus-theme-classic/footer.json
new file mode 100644
index 000000000..7b49b0c46
--- /dev/null
+++ b/docs/i18n/nl/docusaurus-theme-classic/footer.json
@@ -0,0 +1,22 @@
+{
+ "link.title.Docs": {
+ "message": "Documentatie",
+ "description": "The title of the footer links column with title=Docs in the footer"
+ },
+ "link.title.Community": {
+ "message": "Community",
+ "description": "The title of the footer links column with title=Community in the footer"
+ },
+ "link.item.label.Documentation": {
+ "message": "Documentatie",
+ "description": "The label of footer link with label=Documentation linking to /docs/intro"
+ },
+ "link.item.label.GitHub": {
+ "message": "GitHub",
+ "description": "The label of footer link with label=GitHub linking to https://github.com/conductionnl/openregister"
+ },
+ "copyright": {
+ "message": "Copyright © 2026 for Open Webconcept by Conduction B.V.",
+ "description": "The footer copyright"
+ }
+}
diff --git a/docs/i18n/nl/docusaurus-theme-classic/navbar.json b/docs/i18n/nl/docusaurus-theme-classic/navbar.json
new file mode 100644
index 000000000..d6b447225
--- /dev/null
+++ b/docs/i18n/nl/docusaurus-theme-classic/navbar.json
@@ -0,0 +1,22 @@
+{
+ "title": {
+ "message": "Open Register",
+ "description": "The title in the navbar"
+ },
+ "logo.alt": {
+ "message": "Open Register Logo",
+ "description": "The alt text of navbar logo"
+ },
+ "item.label.Documentation": {
+ "message": "Documentatie",
+ "description": "Navbar item with label Documentation"
+ },
+ "item.label.API Documentation": {
+ "message": "API Documentatie",
+ "description": "Navbar item with label API Documentation"
+ },
+ "item.label.GitHub": {
+ "message": "GitHub",
+ "description": "Navbar item with label GitHub"
+ }
+}
diff --git a/docusaurus/package-lock.json b/docs/package-lock.json
similarity index 100%
rename from docusaurus/package-lock.json
rename to docs/package-lock.json
diff --git a/docusaurus/package.json b/docs/package.json
similarity index 100%
rename from docusaurus/package.json
rename to docs/package.json
diff --git a/docusaurus/sidebars.js b/docs/sidebars.js
similarity index 100%
rename from docusaurus/sidebars.js
rename to docs/sidebars.js
diff --git a/docusaurus/src/components/HomepageFeatures/index.js b/docs/src/components/HomepageFeatures/index.js
similarity index 100%
rename from docusaurus/src/components/HomepageFeatures/index.js
rename to docs/src/components/HomepageFeatures/index.js
diff --git a/docusaurus/src/components/HomepageFeatures/styles.module.css b/docs/src/components/HomepageFeatures/styles.module.css
similarity index 100%
rename from docusaurus/src/components/HomepageFeatures/styles.module.css
rename to docs/src/components/HomepageFeatures/styles.module.css
diff --git a/docusaurus/src/css/custom.css b/docs/src/css/custom.css
similarity index 100%
rename from docusaurus/src/css/custom.css
rename to docs/src/css/custom.css
diff --git a/docusaurus/src/pages/index.js b/docs/src/pages/index.js
similarity index 100%
rename from docusaurus/src/pages/index.js
rename to docs/src/pages/index.js
diff --git a/docusaurus/src/pages/index.module.css b/docs/src/pages/index.module.css
similarity index 100%
rename from docusaurus/src/pages/index.module.css
rename to docs/src/pages/index.module.css
diff --git a/docusaurus/static/CNAME b/docs/static/CNAME
similarity index 100%
rename from docusaurus/static/CNAME
rename to docs/static/CNAME
diff --git a/docusaurus/static/img/logo.svg b/docs/static/img/logo.svg
similarity index 100%
rename from docusaurus/static/img/logo.svg
rename to docs/static/img/logo.svg
diff --git a/docusaurus/static/oas/Examples/KTB/ktb_2025-09-15.json b/docs/static/oas/Examples/KTB/ktb_2025-09-15.json
similarity index 100%
rename from docusaurus/static/oas/Examples/KTB/ktb_2025-09-15.json
rename to docs/static/oas/Examples/KTB/ktb_2025-09-15.json
diff --git a/docusaurus/static/oas/Examples/ZaakRegister/besluiten_2025-05-16_144320.json b/docs/static/oas/Examples/ZaakRegister/besluiten_2025-05-16_144320.json
similarity index 100%
rename from docusaurus/static/oas/Examples/ZaakRegister/besluiten_2025-05-16_144320.json
rename to docs/static/oas/Examples/ZaakRegister/besluiten_2025-05-16_144320.json
diff --git a/docusaurus/static/oas/Examples/ZaakRegister/catalogi_2025-05-27_105540.json b/docs/static/oas/Examples/ZaakRegister/catalogi_2025-05-27_105540.json
similarity index 100%
rename from docusaurus/static/oas/Examples/ZaakRegister/catalogi_2025-05-27_105540.json
rename to docs/static/oas/Examples/ZaakRegister/catalogi_2025-05-27_105540.json
diff --git a/docusaurus/static/oas/Examples/ZaakRegister/documenten_2025-05-30_154045.json b/docs/static/oas/Examples/ZaakRegister/documenten_2025-05-30_154045.json
similarity index 100%
rename from docusaurus/static/oas/Examples/ZaakRegister/documenten_2025-05-30_154045.json
rename to docs/static/oas/Examples/ZaakRegister/documenten_2025-05-30_154045.json
diff --git a/docusaurus/static/oas/Examples/ZaakRegister/project.md b/docs/static/oas/Examples/ZaakRegister/project.md
similarity index 100%
rename from docusaurus/static/oas/Examples/ZaakRegister/project.md
rename to docs/static/oas/Examples/ZaakRegister/project.md
diff --git a/docusaurus/static/oas/Examples/ZaakRegister/zaken_2025-05-16_144013.json b/docs/static/oas/Examples/ZaakRegister/zaken_2025-05-16_144013.json
similarity index 100%
rename from docusaurus/static/oas/Examples/ZaakRegister/zaken_2025-05-16_144013.json
rename to docs/static/oas/Examples/ZaakRegister/zaken_2025-05-16_144013.json
diff --git a/docusaurus/static/oas/Examples/publication-api-specification.json b/docs/static/oas/Examples/publication-api-specification.json
similarity index 100%
rename from docusaurus/static/oas/Examples/publication-api-specification.json
rename to docs/static/oas/Examples/publication-api-specification.json
diff --git a/docusaurus/static/oas/Examples/woo_djuma_2025-10-31_140736.json b/docs/static/oas/Examples/woo_djuma_2025-10-31_140736.json
similarity index 100%
rename from docusaurus/static/oas/Examples/woo_djuma_2025-10-31_140736.json
rename to docs/static/oas/Examples/woo_djuma_2025-10-31_140736.json
diff --git a/docusaurus/static/oas/Examples/woo_elastic_2025-07-07_123002.json b/docs/static/oas/Examples/woo_elastic_2025-07-07_123002.json
similarity index 100%
rename from docusaurus/static/oas/Examples/woo_elastic_2025-07-07_123002.json
rename to docs/static/oas/Examples/woo_elastic_2025-07-07_123002.json
diff --git a/docusaurus/static/oas/Examples/woo_register.json b/docs/static/oas/Examples/woo_register.json
similarity index 100%
rename from docusaurus/static/oas/Examples/woo_register.json
rename to docs/static/oas/Examples/woo_register.json
diff --git a/docusaurus/static/oas/clientRegisters.json b/docs/static/oas/clientRegisters.json
similarity index 100%
rename from docusaurus/static/oas/clientRegisters.json
rename to docs/static/oas/clientRegisters.json
diff --git a/docusaurus/static/oas/open-register.json b/docs/static/oas/open-register.json
similarity index 100%
rename from docusaurus/static/oas/open-register.json
rename to docs/static/oas/open-register.json
diff --git a/docusaurus/core/object.md b/docusaurus/core/object.md
deleted file mode 100644
index dcc429ab8..000000000
--- a/docusaurus/core/object.md
+++ /dev/null
@@ -1,98 +0,0 @@
-# Objects in OpenRegister
-
-Objects are the core data entities in OpenRegister that store and manage structured information. This document explains everything you need to know about working with objects.
-
-## Overview
-
-An object in OpenRegister represents a single record of data that:
-- Conforms to a defined schema
-- Belongs to a specific register
-- Has a unique UUID identifier
-- Can contain nested objects and file attachments
-- Maintains version history through audit logs
-- Can be linked to other objects via relations
-
-## Object Structure
-
-Each object contains:
-
-- `id`: Unique UUID identifier
-- `uri`: Absolute URL to access the object
-- `version`: Semantic version number (e.g. 1.0.0)
-- `register`: The register this object belongs to
-- `schema`: The schema this object must conform to
-- `object`: The actual data payload as JSON
-- `files`: Array of related file IDs
-- `relations`: Array of related object IDs
-- `textRepresentation`: Text representation of the object
-- `locked`: Lock status and details
-- `owner`: Nextcloud user that owns the object
-- `authorization`: JSON object describing access permissions
-- `updated`: Last modification timestamp
-- `created`: Creation timestamp
-
-## Key Features
-
-### Schema Validation
-- Objects are validated against their schema definition
-- Supports both soft and hard validation modes
-- Ensures data integrity and consistency
-
-### Relations & Nesting
-- Objects can reference other objects via UUIDs or URLs
-- Supports nested object structures up to configured depth
-- Maintains bidirectional relationship tracking
-
-### Version Control
-- Automatic version incrementing
-- Full audit trail of changes
-- Historical version access
-- Ability to revert to any previous version
-- Detailed change tracking between versions
-
-### Access Control
-- Object-level ownership
-- Granular authorization rules
-- Lock mechanism for concurrent access control
-
-### File Attachments
-- Support for file attachments
-- Secure file storage integration
-- File metadata tracking
-
-## API Operations
-
-Objects support standard CRUD operations:
-- Create new objects
-- Read existing objects
-- Update object data
-- Delete objects
-- Search and filter objects
-- Export object data
-- Revert to previous versions
-
-## Object Locking and Versioning
-
-### Version Control and Revert Functionality
-
-OpenRegister provides comprehensive version control capabilities:
-
-- Every change creates a new version with full audit trail
-- Changes are tracked at the field level
-- Previous versions can be viewed and compared
-- Objects can be reverted to any historical version
-- Revert operation creates new version rather than overwriting
-- Audit logs maintain full history of all changes including reverts
-- Revert includes all object properties including relations and files
-- Batch revert operations supported for related objects
-
-### Locking Objects
-
-Objects can be locked to prevent concurrent modifications. This is useful when:
-- Long-running processes need exclusive access
-- Multiple users/systems are working on the same object
-- Ensuring data consistency during complex updates
-
-#### Lock API Endpoints
-
-To lock an object via the REST API:
\ No newline at end of file
diff --git a/docusaurus/core/schema copy.md b/docusaurus/core/schema copy.md
deleted file mode 100644
index 5924311d2..000000000
--- a/docusaurus/core/schema copy.md
+++ /dev/null
@@ -1,5 +0,0 @@
-# Objects in OpenRegister
-
-Objects are the core data entities in OpenRegister that store and manage structured information. Objects
-
-## Register
\ No newline at end of file
diff --git a/docusaurus/core/schema.md b/docusaurus/core/schema.md
deleted file mode 100644
index 37b8737c2..000000000
--- a/docusaurus/core/schema.md
+++ /dev/null
@@ -1,496 +0,0 @@
-# Objects in OpenRegister
-
-Objects are the core data entities in OpenRegister that store and manage structured information. Objects are defined by schemas and can contain relationships to other objects within the same register or across different registers.
-
-## Schema Structure
-
-Schemas define the structure, validation rules, and relationships for objects in OpenRegister. Each schema contains:
-
-- **Properties**: Define the data fields and their types
-- **Required fields**: Specify which properties are mandatory
-- **Validation rules**: Define constraints and data formats
-- **Relationships**: Define connections to other objects via 'inversedBy' properties
-- **Configuration**: Define metadata behavior and file handling settings
-
-### Schema Configuration
-
-Schemas support various configuration options that control how objects are handled and displayed:
-
-#### Object Metadata Fields
-These configuration options define which object properties should be used for common metadata. All fields support **dot notation** for nested properties and **twig-like templates** for combining multiple fields.
-
-- **objectNameField**: (string) Field path or template for the object's display name
- - Simple path: 'naam' or 'contact.naam'
- - Twig-like template: '{{ voornaam }} {{ tussenvoegsel }} {{ achternaam }}'
- - If not configured, the object's UUID will be used as the name
-
-- **objectDescriptionField**: (string) Field path or template for the object's description
- - Simple path: 'beschrijving' or 'case.summary'
- - Template: '{{ type }}: {{ korte_beschrijving }}'
- - Used for object previews and search results
-
-- **objectSummaryField**: (string) Field path or template for the object's summary
- - Simple path: 'beschrijvingKort' or 'samenvatting'
- - Template: '{{ categorie }} - {{ status }}'
- - Used for condensed object information
-
-- **objectImageField**: (string) Field path for the object's image
- - Simple path: 'afbeelding' or 'profile.avatar'
- - Expected to contain base64 encoded image data or file references
- - Used for visual representation of objects in lists and details
-
-- **objectSlugField**: (string) Field path for generating URL-friendly slugs
- - Simple path: 'naam' or 'title'
- - Value will be automatically converted to URL-friendly format
- - Used for creating readable URLs and identifiers
-
-- **objectPublishedField**: (string) Field path for the publication date
- - Simple path: 'publicatieDatum' or 'published'
- - Supports various datetime formats (ISO 8601, MySQL datetime, etc.)
- - Controls when objects become publicly visible
-
-- **objectDepublishedField**: (string) Field path for the depublication date
- - Simple path: 'einddatum' or 'depublished'
- - Supports various datetime formats
- - Controls when objects are no longer publicly visible
-
-- **autoPublish**: (boolean) Automatically set published date on object creation
- - When set to 'true', objects will be automatically published (published date set to now) when created
- - Only applies to new objects - existing objects being updated are not affected
- - If an object already has a published date (from field mapping or explicit data), auto-publish is skipped
- - Works for both individual object creation and bulk imports
- - Default: 'false' (disabled)
-
-##### Twig-like Template Syntax
-For combining multiple fields, use the template syntax:
-
-```json
-{
- "objectNameField": "{{ voornaam }} {{ tussenvoegsel }} {{ achternaam }}",
- "objectDescriptionField": "{{ type }}: {{ beschrijving }}"
-}
-```
-
-- Use `{{ fieldName }}` to reference object properties
-- Supports dot notation: `{{ contact.email }}`
-- Empty/null values are handled gracefully
-- Excess whitespace is automatically cleaned up
-
-##### Example Configuration
-```json
-{
- "configuration": {
- "objectNameField": "{{ voornaam }} {{ achternaam }}",
- "objectDescriptionField": "beschrijving",
- "objectSummaryField": "beschrijvingKort",
- "objectImageField": "afbeelding",
- "objectSlugField": "naam",
- "objectPublishedField": "publicatieDatum",
- "objectDepublishedField": "einddatum",
- "autoPublish": true
- }
-}
-```
-
-#### File Handling Configuration
-These options control how files are handled within the schema:
-
-- **allowFiles**: (boolean) Whether objects of this schema can have file attachments
- - Default: false
- - When enabled, indicates this schema supports file uploads and management
- - Currently used for indication purposes (filtering not yet implemented)
-
-- **allowedTags**: (array of strings) Specifies which file tags/types are allowed for this schema
- - Example: ['image', 'document', 'audio', 'video']
- - Used for categorizing and filtering file attachments
- - Tags can be custom strings to match your use case
-
-#### Configuration Example
-```json
-{
- 'configuration': {
- 'objectNameField': 'person.fullName',
- 'objectDescriptionField': 'person.bio',
- 'objectImageField': 'person.avatar',
- 'allowFiles': true,
- 'allowedTags': ['image', 'document', 'identity']
- }
-}
-```
-
-#### Dot-Notation Paths
-The objectNameField, objectDescriptionField, and objectImageField use dot-notation to access nested properties:
-
-- **Simple property**: 'title' → accesses object.title
-- **Nested property**: 'person.name' → accesses object.person.name
-- **Deep nesting**: 'contact.address.street' → accesses object.contact.address.street
-
-If the specified field doesn't exist or contains invalid data, the system will gracefully fall back to default values.
-
-## Creating Objects
-
-### Simple Object Creation
-
-To create a basic object, send a POST request to the register endpoint with the object data:
-
-```json
-{
- 'title': 'My Organization',
- 'description': 'A sample organization',
- 'email': 'contact@example.com'
-}
-```
-
-### Creating Objects with Nested Related Objects
-
-OpenRegister supports creating objects with nested related objects in a single POST request. This is particularly useful for creating complex data structures where objects have relationships defined through 'inversedBy' properties.
-
-#### Structure for Nested Objects
-
-When a schema property has an 'inversedBy' relationship, you can provide related objects as nested arrays:
-
-```json
-{
- 'title': 'My Organization',
- 'description': 'A sample organization',
- 'email': 'contact@example.com',
- 'contactpersonen': [
- {
- 'naam': 'John Doe',
- 'email': 'john@example.com',
- 'telefoon': '+1234567890'
- },
- {
- 'naam': 'Jane Smith',
- 'email': 'jane@example.com',
- 'telefoon': '+0987654321'
- }
- ]
-}
-```
-
-#### How Nested Object Creation Works
-
-1. **Parent Object Processing**: The main object is validated and prepared for creation
-2. **Relationship Detection**: Properties with 'inversedBy' relationships are identified
-3. **Nested Object Creation**: Related objects are created first with proper back-references
-4. **Context Preservation**: The parent object maintains its register/schema context throughout the process
-5. **Final Creation**: The parent object is created with references to the related objects
-
-#### Example: Organization with Contact Persons
-
-Consider an organization schema with a 'contactpersonen' property that has 'inversedBy: "organisatie"':
-
-**POST Request:**
-```json
-{
- 'title': 'Acme Corporation',
- 'description': 'Technology company',
- 'website': 'https://acme.com',
- 'contactpersonen': [
- {
- 'naam': 'Alice Johnson',
- 'email': 'alice@acme.com',
- 'functie': 'CEO'
- },
- {
- 'naam': 'Bob Wilson',
- 'email': 'bob@acme.com',
- 'functie': 'CTO'
- }
- ]
-}
-```
-
-**What Happens:**
-1. Two contact person objects are created in the contactgegevens schema
-2. Each contact person gets a back-reference to the organization ('organisatie' property)
-3. The organization is created with references to both contact persons
-4. All objects are created in the correct register/schema context
-
-## Relationship Handling
-
-### InversedBy Properties
-
-The 'inversedBy' property defines bidirectional relationships between objects:
-
-- **Parent Object**: Contains an array of references to related objects
-- **Related Objects**: Automatically get a back-reference to the parent object
-- **Schema Mapping**: The system automatically determines the correct schema for related objects
-
-### Context Preservation
-
-OpenRegister ensures that:
-- Parent objects are created in their intended register/schema
-- Related objects are created in their appropriate register/schema
-- Context is preserved even during complex nested operations
-- Back-references are correctly established
-
-## Validation and Error Handling
-
-### Validation Modes
-
-- **Hard Validation**: Strict validation according to schema rules
-- **Soft Validation**: More lenient validation for flexibility
-
-### Common Errors
-
-- **Missing Required Properties**: Ensure all required fields are provided
-- **Invalid Data Types**: Check that data matches schema property types
-- **Relationship Errors**: Verify that related objects conform to their target schema
-- **Context Errors**: Ensure objects are created in the correct register/schema
-
-## Best Practices
-
-1. **Plan Your Structure**: Design your schemas with clear relationships
-2. **Use Nested Creation**: Create related objects together for data consistency
-3. **Validate Early**: Test your object structure before production
-4. **Monitor Creation**: Check that objects are created in correct contexts
-5. **Handle Errors**: Implement proper error handling for failed creations
-
-## API Endpoints
-
-- **Create Object**: 'POST /api/registers/{registerId}/objects'
-- **Update Object**: 'PUT /api/registers/{registerId}/objects/{objectId}'
-- **Get Object**: 'GET /api/registers/{registerId}/objects/{objectId}'
-- **Delete Object**: 'DELETE /api/registers/{registerId}/objects/{objectId}'
-
-## Example Use Cases
-
-### Customer Management
-Create customers with multiple addresses and contact methods in a single request.
-
-### Project Management
-Create projects with associated team members, tasks, and resources.
-
-### Content Management
-Create articles with embedded media, tags, and author information.
-
-### Inventory Management
-Create products with variants, suppliers, and pricing information.
-
-The nested object creation feature provides a powerful way to build complex data structures while maintaining data integrity and proper relationship management across your OpenRegister application.
-
-## Role-Based Access Control (RBAC)
-
-OpenRegister implements a comprehensive Role-Based Access Control system that allows you to restrict access to objects based on the schema's authorization configuration and the user's Nextcloud group membership.
-
-### Authorization Structure
-
-RBAC permissions are defined in the schema's 'authorization' property using a CRUD-based structure:
-
-```json
-{
- 'authorization': {
- 'create': ['editors', 'managers'],
- 'read': ['viewers', 'editors', 'managers'],
- 'update': ['editors', 'managers'],
- 'delete': ['managers']
- }
-}
-```
-
-### Permission Rules
-
-The RBAC system follows these fundamental rules:
-
-1. **Open Access by Default**: If no authorization is configured, all users have full CRUD access
-2. **Action-Level Control**: Permissions are granted per CRUD action (create, read, update, delete)
-3. **Group-Based Access**: Users must belong to specified Nextcloud groups to perform actions
-4. **Admin Override**: Users in the 'admin' group always have full access to all schemas
-5. **Owner Privilege**: Object owners always have full access to their specific objects regardless of group restrictions
-
-### Special Groups
-
-#### Admin Group
-- Always has full CRUD access to all schemas
-- Cannot be restricted through authorization configuration
-- Represents system administrators with unrestricted access
-
-#### Public Group
-- Represents unauthenticated/anonymous access
-- Can be explicitly granted permissions for public-facing schemas
-- Useful for read-only public data or anonymous submissions
-
-#### Object Owner
-- The Nextcloud user who created or owns a specific object
-- Has full CRUD access to their own objects regardless of schema authorization restrictions
-- Different objects in the same schema can have different owners
-- Object ownership cannot be overridden by group restrictions
-
-### Permission Logic
-
-The system evaluates permissions in this order:
-
-1. **Admin Check**: If user is in 'admin' group → Allow all actions
-2. **Owner Check**: If user is the object owner → Allow all actions on that specific object
-3. **Authorization Check**: If no authorization configured → Allow all actions
-4. **Action Check**: If specific action not configured → Allow action
-5. **Group Check**: If user's group is in authorized list → Allow action
-6. **Default**: Deny action
-
-### Configuration Examples
-
-#### Fully Open Schema
-```json
-{
- 'authorization': {}
-}
-```
-*All users can perform all CRUD operations*
-
-#### Read-Only Public Schema
-```json
-{
- 'authorization': {
- 'create': ['editors'],
- 'read': ['public'],
- 'update': ['editors'],
- 'delete': ['managers']
- }
-}
-```
-*Anyone can read, only editors can create/update, only managers can delete*
-
-#### Restricted Internal Schema
-```json
-{
- 'authorization': {
- 'create': ['staff'],
- 'read': ['staff'],
- 'update': ['staff'],
- 'delete': ['managers']
- }
-}
-```
-*Only staff can access, only managers can delete*
-
-#### Collaborative Schema
-```json
-{
- 'authorization': {
- 'create': ['contributors', 'editors'],
- 'read': ['viewers', 'contributors', 'editors'],
- 'update': ['editors'],
- 'delete': ['editors']
- }
-}
-```
-*Multiple groups with different permission levels*
-
-### Query Filtering
-
-When searching or listing objects, the RBAC system automatically filters results based on the user's read permissions:
-
-- Objects from schemas with no read restrictions are always included
-- Objects from restricted schemas are only included if the user has read permission
-- Admin users see all objects regardless of restrictions
-- Object owners see their own objects regardless of restrictions
-- **Published objects** are accessible to everyone if their published date has passed and depublished date hasn't
-- Filtering is applied at the database query level for optimal performance
-
-### Publication-Based Public Access
-
-OpenRegister supports automatic public access for published objects, regardless of schema authorization restrictions:
-
-#### Publication Logic
-Objects become publicly accessible when:
-- The 'published' field is set to a date/time in the past or present
-- The 'depublished' field is either null or set to a future date/time
-
-#### Publication Examples
-```json
-{
- 'name': 'Public Article',
- 'content': 'This article is publicly accessible',
- 'published': '2025-01-01T00:00:00+00:00',
- 'depublished': null
-}
-```
-
-```json
-{
- 'name': 'Temporary Public Content',
- 'content': 'Available for limited time',
- 'published': '2025-01-01T00:00:00+00:00',
- 'depublished': '2025-12-31T23:59:59+00:00'
-}
-```
-
-#### Use Cases
-- **Public Documentation**: Make help articles accessible to all users
-- **Announcements**: Publish news that everyone should see
-- **Time-Limited Content**: Create content with automatic expiration dates
-- **Progressive Disclosure**: Gradually release content based on publication schedules
-
-### Best Practices
-
-1. **Principle of Least Privilege**: Only grant necessary permissions to each group
-2. **Clear Group Names**: Use descriptive group names that reflect their intended access level
-3. **Regular Review**: Periodically review and update authorization configurations
-4. **Test Thoroughly**: Verify permissions work as expected before deploying to production
-5. **Document Decisions**: Maintain clear documentation about why specific permissions were granted
-
-### API Error Responses
-
-When RBAC blocks an unauthorized operation, the API returns consistent JSON error responses:
-
-#### Successful Operation
-```json
-{
- 'id': 'abc123',
- 'name': 'My Object',
- 'description': 'Created successfully'
-}
-```
-
-#### Permission Denied
-```json
-{
- 'error': 'User 'username' does not have permission to 'create' objects in schema 'Schema Name''
-}
-```
-
-All RBAC-related errors return HTTP status code 403 (Forbidden) with descriptive error messages.
-
-### Testing RBAC Permissions
-
-#### Positive Testing
-Verify users CAN perform authorized operations:
-```bash
-# Test authorized user can create
-curl -u 'editor:password' -X POST '/api/objects/1/49' -d '{'name': 'Test'}'
-
-# Expected: 200 OK with object data
-```
-
-#### Negative Testing
-Verify users CANNOT perform unauthorized operations:
-```bash
-# Test unauthorized user cannot create
-curl -u 'viewer:password' -X POST '/api/objects/1/49' -d '{'name': 'Should Fail'}'
-
-# Expected: 403 Forbidden with error message
-```
-
-#### Query Filtering Testing
-Test that READ operations filter results appropriately:
-```bash
-# Authorized user sees objects
-curl -u 'staff:password' '/api/objects/1/staff-schema'
-# Expected: Array of accessible objects
-
-# Unauthorized user sees empty results
-curl -u 'guest:password' '/api/objects/1/staff-schema'
-# Expected: Empty results array
-```
-
-### Security Considerations
-
-- RBAC permissions are enforced at the API level, not just the UI
-- Direct database access bypasses RBAC controls
-- Group membership changes in Nextcloud immediately affect OpenRegister permissions
-- Schema modifications require appropriate permissions to prevent privilege escalation
-- Always validate user permissions before performing any CRUD operations
-- **Comprehensive Testing**: Test both positive (authorized) and negative (unauthorized) scenarios
-- **JSON Responses**: All API errors return structured JSON, never HTML error pages
\ No newline at end of file
diff --git a/lib/Migration/Version1Date20250828120000.php b/lib/Migration/Version1Date20250828120000.php
index 993c88ce3..24fd2177a 100644
--- a/lib/Migration/Version1Date20250828120000.php
+++ b/lib/Migration/Version1Date20250828120000.php
@@ -40,15 +40,17 @@
*/
class Version1Date20250828120000 extends SimpleMigrationStep
{
- /**
- * @param IDBConnection $connection The database connection
- * @param IConfig $config The configuration interface
- */
+ /**
+ * Constructor.
+ *
+ * @param IDBConnection $connection The database connection
+ * @param IConfig $config The configuration interface
+ */
public function __construct(
private readonly IDBConnection $connection,
private readonly IConfig $config,
) {
- }
+ }//end __construct()
/**
* Apply database schema changes for faceting performance.
@@ -65,10 +67,7 @@ public function __construct(
*/
public function changeSchema(IOutput $output, Closure $schemaClosure, array $options): ?ISchemaWrapper
{
- /**
- * @var ISchemaWrapper $schema
- */
-
+ // @var ISchemaWrapper $schema
$schema = $schemaClosure();
if ($schema->hasTable('openregister_objects') === false) {