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.jsrather than introducing a second transport abstraction. - Keep the local bridge in
scripts/local-markdown-bridge.mjsas the canonical local workflow backend. - Treat hosted editing as a Forgejo-backed provider layered through
generator-apirather 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:
BooleanCodeColorComputeDateTimeFileHiddenImageKeyValueListMapMarkdownNumberObjectRelationRichTextSelectStringTextUUID
- 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, andKeyValuestructures must be reusable across collection types Relationmust 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_itemscategoriesskillstestimonialspages
- example collections:
Educational Platform- example collections:
coursesinstructorslessonscategorieseventsblog_postspages
- example collections:
Blog Workspace- example collections:
postsseriesnoteslinkspages
- example collections:
Documentation Site- example collections:
documentsversionscategoriestutorialspages
- example collections:
Research Lab- example collections:
peopleprojectspublicationsdatasetseventsfunderspages
- example collections:
Academic Website- example collections:
profilepublicationstalksteachingstudentsprojectscv_sectionspages
- example collections:
Booking Management Website- example collections:
servicesresourcesproviderslocationsavailability_rulesbooking_pagesfaqspages
- example collections:
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.yamldata/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: trueRecommended 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/schemaGET /cms/collectionsGET /cms/entries?collection=<name>GET /cms/entry?collection=<name>&path=<path>POST /cms/entry/createPOST /cms/entry/writePOST /cms/entry/deleteGET /cms/relation/options?collection=<name>&q=<query>GET /cms/assetsPOST /cms/assets/uploadGET /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
localmode as the authoritative local workflow - keep
webdavmode 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.yamlanddata/cms/collections/*.yamlas 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, andGET /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:
StringTextMarkdownRichTextBooleanNumberDateTimeSelectImageFileListObjectKeyValue
- 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, andPOST /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
Relationas 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
ImageandFilefield 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-apior 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:
- keep existing markdown/config/bib/quiz/structured-block flows working
- introduce schema-driven editors for new collection-driven content
- migrate narrow special editors onto shared field components where they fit
- 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:
CoursesInstructorsLessonsCategoriesTagsPages
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 WebsiteDocumentation SiteResearch LabAcademic WebsiteBooking 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:
- schema
- content library
- shared fields
- persistence adapters
- relations
- repo-managed asset library
- Forgejo hosted backend
- extension surface
- 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.