Hugo CMS Roadmap

Hugo CMS Roadmap

This roadmap turns the current generator editor into a schema-driven Hugo CMS without abandoning the existing generator rules:

  • Hugo remains the render authority.
  • Markdown, front matter, and structured files remain the source of truth.
  • Browser editing must still resolve to diffable repository files.
  • Local editing stays bridge-first.
  • Hosted CMS work should target Forgejo-backed flows, not additional WebDAV-only product surface.

Scope Decisions

These decisions keep the roadmap aligned with the current generator architecture.

  • Keep Nowtype as the primary markdown-body editor.
  • Keep the provider seam in cdn/custom/toggleMarkdown.js rather than introducing a second transport abstraction.
  • Keep the local bridge in scripts/local-markdown-bridge.mjs as the canonical local workflow backend.
  • Treat hosted editing as a Forgejo-backed provider layered through generator-api rather than direct WebDAV feature growth.
  • Keep media repo-managed in this roadmap. Do not include S3 or other external media-storage work in these phases.
  • Keep review as repository change review. Do not introduce a database-backed CMS state store.

Current Starting Point

The repo already has useful seams that should be reused instead of replaced.

  • Provider abstraction already exists in cdn/custom/toggleMarkdown.js: local and WebDAV providers already expose read/write/list/stat/watch and some higher-level CMS-adjacent features such as review comments, review staging, token reads/writes, project image listing, and project upload.
  • The local bridge already publishes capabilities and high-level ops in scripts/local-markdown-bridge.mjs. Current implemented ops include page, section, menu, layout, token, attr, git, asset upload, and review-stage support.
  • The editor already has specialized file editors for markdown, config, BibTeX, SVG, quiz files, and several structured block types.
  • The current weakness is not lack of editing surface. The weakness is that the editing model is still mostly special-case and page-centric rather than collection-driven and schema-driven.

Product Target

The target CMS surface for generator should be:

  • collections:
    • entry collections
    • file collections
    • singletons
  • shared field engine:
    • Boolean
    • Code
    • Color
    • Compute
    • DateTime
    • File
    • Hidden
    • Image
    • KeyValue
    • List
    • Map
    • Markdown
    • Number
    • Object
    • Relation
    • RichText
    • Select
    • String
    • Text
    • UUID
  • UI:
    • content library
    • content editor
    • asset library for repo-managed assets
  • workflows:
    • local workflow
    • simple Forgejo workflow
  • later extension points:
    • custom preview styles
    • custom preview templates
    • custom editor components
    • custom field types
    • custom file formats
    • event hooks

Extensibility Requirement

The content model must stay generic enough to support multiple site archetypes without generator-core rewrites for each one.

Practical rules:

  • collection names and collection shapes must come from schema, not from generator code
  • nested Object, List, Map, and KeyValue structures must be reusable across collection types
  • Relation must work across arbitrary collection pairs rather than only a few hand-authored content families
  • path/slug/summary rules must be schema-configurable
  • collection editors must be driven by field definitions and persistence adapters, not by site-type-specific UI branches
  • any site-specific behavior that cannot fit the shared schema must go through the extension surface, not through more special-case core logic

If a new site type requires editing generator core just to define its content model, the CMS design is too rigid.

Required Archetype Coverage

The schema and field system should be considered incomplete until they can model all of the following without architectural exceptions:

  • Portfolio Website
    • example collections:
      • portfolio_items
      • categories
      • skills
      • testimonials
      • pages
  • Educational Platform
    • example collections:
      • courses
      • instructors
      • lessons
      • categories
      • events
      • blog_posts
      • pages
  • Blog Workspace
    • example collections:
      • posts
      • series
      • notes
      • links
      • pages
  • Documentation Site
    • example collections:
      • documents
      • versions
      • categories
      • tutorials
      • pages
  • Research Lab
    • example collections:
      • people
      • projects
      • publications
      • datasets
      • events
      • funders
      • pages
  • Academic Website
    • example collections:
      • profile
      • publications
      • talks
      • teaching
      • students
      • projects
      • cv_sections
      • pages
  • Booking Management Website
    • example collections:
      • services
      • resources
      • providers
      • locations
      • availability_rules
      • booking_pages
      • faqs
      • pages

These should not all require identical built-in templates. The requirement is that the content model, field engine, relation model, and content library can represent them cleanly.

Archetype Validation Matrix

Before the CMS schema is called stable, add example schemas for each archetype and prove that the shared engine can load and edit them.

Recommended fixture path family:

  • docs/examples/cms/portfolio/
  • docs/examples/cms/education/
  • docs/examples/cms/documentation/
  • docs/examples/cms/research-lab/
  • docs/examples/cms/academic/
  • docs/examples/cms/booking-management/

Each fixture should prove:

  • collections can be declared without core code edits
  • list/object/relation nesting is sufficient for the archetype
  • summary cards and content-library search still work
  • entry creation paths and slug templates are adequate
  • repo-managed assets can serve the archetype’s media needs
  • review and save flows still resolve to normal repository changes

Proposed Site-Side Schema Contract

The CMS model should live in the site repository, not in generator code.

Recommended path family:

  • data/cms/config.yaml
  • data/cms/collections/*.yaml

Recommended top-level collection shape:

kind: entry
name: courses
label: Courses
path: content/courses
format: markdown-frontmatter
summary:
  title: title
  description: description
  image: featured_image
sort:
  by: date
  direction: desc
fields:
  - name: title
    type: string
    required: true
  - name: instructor
    type: relation
    collection: instructors
    multiple: false
  - name: lessons
    type: relation
    collection: lessons
    multiple: true

Recommended config responsibilities:

  • data/cms/config.yaml
    • locales
    • collection order/grouping
    • workflow defaults
    • extension module registration
  • data/cms/collections/*.yaml
    • entry/file/singleton definition
    • path and format rules
    • field definitions
    • relation targets
    • summary/sort/filter metadata

This keeps collection metadata file-backed, reviewable, and readable by both the bridge and future hosted provider code.

Generator-Side Module Plan

New CMS work should not keep expanding one large toggleMarkdown.js file. It should extract into a small module family under cdn/custom/cms/.

Recommended new client modules:

  • cdn/custom/cms/schema.js
    • schema loading, validation, normalization
  • cdn/custom/cms/library.js
    • collection list, filters, search state, summaries
  • cdn/custom/cms/entry-editor.js
    • entry/file/singleton editor shell
  • cdn/custom/cms/fields/
    • one renderer/controller per field type
  • cdn/custom/cms/relations.js
    • relation lookup and display helpers
  • cdn/custom/cms/assets.js
    • repo-asset listing, upload, search, metadata helpers
  • cdn/custom/cms/extensions.js
    • hook registry and custom-field/component registration

Generator should also gain a machine-readable CMS manifest:

  • docs/cms-schema.manifest.json

That manifest should describe the supported collection kinds, field kinds, relation semantics, workflow modes, and extension hooks in the same spirit as the existing shortcode and editor manifests.

Bridge And Provider Plan

Local bridge

The existing local bridge should become the first full CMS backend.

Recommended new bridge endpoints in scripts/local-markdown-bridge.mjs:

  • GET /cms/schema
  • GET /cms/collections
  • GET /cms/entries?collection=<name>
  • GET /cms/entry?collection=<name>&path=<path>
  • POST /cms/entry/create
  • POST /cms/entry/write
  • POST /cms/entry/delete
  • GET /cms/relation/options?collection=<name>&q=<query>
  • GET /cms/assets
  • POST /cms/assets/upload
  • GET /cms/search?q=<query>

These should sit beside the current /capabilities, /list, /project/list, /project/upload, and review endpoints rather than replacing them immediately.

Provider abstraction

The provider contract in cdn/custom/toggleMarkdown.js should grow explicit CMS methods, for example:

  • readCmsSchema()
  • listCmsCollections()
  • listCmsEntries(collection, opts)
  • readCmsEntry(collection, path)
  • createCmsEntry(collection, payload)
  • writeCmsEntry(collection, payload)
  • deleteCmsEntry(collection, payload)
  • listRelationOptions(collection, query, opts)
  • listCmsAssets(opts)
  • uploadCmsAsset(target, file)
  • searchCmsContent(query, opts)

The current token/header/review methods should remain separate. They are useful, but they are not a substitute for a schema-aware CMS surface.

Hosted backend

Hosted CMS work should target Forgejo-backed transport, not more WebDAV-only feature work.

Practical rule:

  • keep local mode as the authoritative local workflow
  • keep webdav mode as compatibility for existing sites
  • route new hosted CMS capabilities through a Forgejo-aware provider, ideally backed by generator-api

That means new remote CMS work should prefer a future makeForgejoProvider(config) over expanding makeWebDavProvider(config) for collection semantics, relations, content library behavior, and workflow UX.

Phased Implementation Checklist

Phase 1: Schema foundation

  • Add data/cms/config.yaml and data/cms/collections/*.yaml as the documented site-side schema contract.
  • Add schema loader/validator code under cdn/custom/cms/schema.js.
  • Add local bridge endpoint GET /cms/schema.
  • Add provider methods for loading the normalized CMS schema.
  • Add docs/cms-schema.manifest.json.
  • Document the schema paths and collection kinds in the main docs.

Acceptance:

  • the browser can load a normalized collection schema from a site repo
  • invalid schemas fail with explicit field/collection errors
  • collection definitions are machine-readable rather than embedded in ad hoc UI
  • the same schema contract can represent the six required archetypes without adding site-type-specific core code

Phase 2: Content library

  • Add a collection-aware content library UI.
  • Add collection list, summary cards, sorting, and text filtering.
  • Add bridge endpoints GET /cms/collections, GET /cms/entries, and GET /cms/search.
  • Reuse the current file list only as a fallback, not as the primary CMS navigation surface.
  • Add a collection summary contract to the CMS manifest.

Acceptance:

  • editors can open content by collection rather than hunting by file path
  • entry collections, file collections, and singletons all appear in one library
  • collection summaries come from schema-defined summary fields
  • the library does not assume one canonical site shape such as only posts/pages

Phase 3: Shared field engine

  • Add cdn/custom/cms/fields/ with shared field renderers.
  • Implement first-pass support for:
    • String
    • Text
    • Markdown
    • RichText
    • Boolean
    • Number
    • DateTime
    • Select
    • Image
    • File
    • List
    • Object
    • KeyValue
  • Map markdown/rich-text bodies onto Nowtype rather than building a second WYSIWYG engine.
  • Reuse current config scalar typing experience where it helps, but move the control model into shared field components.

Acceptance:

  • ordinary collection editing no longer requires a new special editor per file family
  • the same field type renders consistently across entry, file, and singleton editors
  • markdown-body editing still round-trips through the existing markdown source
  • the field engine is flexible enough for portfolio, documentation, research, academic, and booking-oriented models, not only course-like content

Phase 4: Persistence adapters

  • Add persistence adapters for:
    • markdown entries with front matter
    • JSON/YAML data-file entries
    • file collections
    • singletons
  • Add bridge endpoints POST /cms/entry/create, POST /cms/entry/write, and POST /cms/entry/delete.
  • Reuse current page creation semantics where possible instead of inventing a second page-creation path.
  • Support slug/path templates in the schema contract.
  • Add duplicate/create-from-template support for common collection flows.

Acceptance:

  • entry creation, rename, save, and delete all resolve to normal repo files
  • file paths are derived from schema rules rather than hard-coded UI logic
  • singletons behave as named CMS entries rather than hidden path conventions

Phase 5: Relation model

  • Implement Relation as a first-class field type.
  • Add relation index/query support in the bridge.
  • Add GET /cms/relation/options.
  • Support one-to-one and one-to-many selection.
  • Support summary labels and search over relation targets.
  • Add relation integrity checks during save where feasible.

Acceptance:

  • collections can reference other collections without raw path editing
  • blog/news/course-style content models become practical
  • portfolio, research-lab, academic, and booking-management relation graphs are also representable without special-case relation logic
  • relation editing is faster and clearer than hand-editing slugs/ids in raw text

Phase 6: Repo-managed asset library

  • Build a CMS asset library on top of repo files and existing project asset listing/upload endpoints.
  • Generalize the current image picker into an asset-library surface.
  • Add schema-aware Image and File field integration.
  • Add asset search, folder/prefix filtering, upload, and preview metadata.
  • Add asset usage lookup where practical.

Do not include in this phase:

  • S3
  • external object storage
  • remote DAM synchronization

Acceptance:

  • editors can browse and upload repo-managed media from a shared asset UI
  • image/file fields use the same asset workflow
  • asset behavior is collection-aware but still file-backed

Phase 7: Forgejo-backed hosted workflow

  • Define a Forgejo-backed hosted provider contract.
  • Add a new hosted provider path instead of extending WebDAV for new CMS behavior.
  • Generalize current review-stage config into a broader Forgejo CMS backend config surface.
  • Route content-library, relation, and entry CRUD through generator-api or another Forgejo-aware backend layer.
  • Preserve the current review-branch / pull-request model for publish review.

Acceptance:

  • local workflow and hosted workflow expose the same CMS features
  • hosted editing is repo-native and Forgejo-native
  • review submission remains a visible repository change flow

Phase 8: Extension surface

  • Add a client-side extension registry under cdn/custom/cms/extensions.js.
  • Support:
    • custom preview styles
    • custom preview templates
    • custom editor components
    • custom field types
    • custom file formats
    • event hooks
  • Add site-level registration paths in the documented CMS config.
  • Keep extension loading explicit and file-backed.

Acceptance:

  • new content types can be extended without editing the generator core for every custom site need
  • extension points stay documented and discoverable
  • archetype-specific polish can land as extensions rather than new hard-coded collection families in core

Phase 9: I18n and translation

  • Add locale-aware schema support.
  • Support per-field translatable/non-translatable settings.
  • Support locale duplication and relation-aware translation flows.
  • Add translation-service integration only after the locale model is stable.

Acceptance:

  • multilingual sites can use the CMS without forking the content model
  • locale behavior is explicit in schema rather than hidden in path conventions

Migration Rule For Existing Special Editors

Do not try to delete all existing special editors at once.

Migration order should be:

  1. keep existing markdown/config/bib/quiz/structured-block flows working
  2. introduce schema-driven editors for new collection-driven content
  3. migrate narrow special editors onto shared field components where they fit
  4. leave truly format-specific editors as adapters over the shared CMS shell

That avoids a destabilizing rewrite while still moving the product toward a modular CMS architecture.

Suggested Pilot Order

Use one collection set that exercises relations first, then validate the same engine across the full archetype suite.

Recommended first pilot:

  • Courses
  • Instructors
  • Lessons
  • Categories
  • Tags
  • Pages

Why this pilot:

  • it fits the generator’s scientific/pedagogical direction
  • it forces Relation, List, Object, Markdown, RichText, Image, and singleton/file collection behavior
  • it exposes whether the content library and shared field engine are good enough before broader rollout

Required follow-up validation before calling the model stable:

  • Portfolio Website
  • Documentation Site
  • Research Lab
  • Academic Website
  • Booking Management Website

If one of those archetypes needs a bespoke generator-core collection system, the schema design is not extensible enough yet.

Practical Sequencing Rule

New work should follow this order:

  1. schema
  2. content library
  3. shared fields
  4. persistence adapters
  5. relations
  6. repo-managed asset library
  7. Forgejo hosted backend
  8. extension surface
  9. i18n/translation

If the order is inverted, the likely failure mode is more special-case UI and more transport-specific code before the core content model is stable.