GitHub Actions to manage the deployment of the site to GitHub Pages.
Hugo is an open-source static site generator that provides us with templates,
content organisation in a standard directory structure, and a website generation
engine. You write the pages in Markdown (or HTML if you want), and Hugo wraps them up into a website.
All submissions, including submissions by project members, require review. We
use GitHub pull requests for this purpose. Consult
GitHub Help for more
information on using pull requests.
Updating a single page
If you’ve just spotted something you’d like to change while using the docs, Docsy has a shortcut for you:
Click Edit this page in the right (second) sidebar.
If you don’t already have an up-to-date fork of the project repo, you are prompted to get one - click Fork this repository and propose changes or Update your Fork to get an up-to-date version of the project to edit. The appropriate page in your fork is displayed in edit mode.
Make your changes and open a Pull Request. The maintainers will review, provide feedback, and merge.
Previewing your changes locally
If you want to run your own local Hugo server to preview your changes as you work:
Follow the instructions in
Getting started to install Hugo and any other tools you need.
Fork the
yusaopeny_docs repo into your own project, then create a local copy using git clone.
Run hugo server in the site root directory. By default, your site will be available at http://localhost:1313/. Now that you’re serving your site locally, Hugo will watch for changes to the content and automatically refresh your site.
Continue with the usual GitHub workflow to edit files, commit them, push the
changes up to your fork, and create a pull request.
Common options
Hugo has
a number of flags you can use to change local server behavior, here are a few we like:
--tlsAuto generate and use locally-trusted certificates to run the site over https
--buildDrafts include content marked as draft
--buildFuture include content with publishdate in the future
With all of these, you might end up with something like:
hugo serve --tlsAuto --buildDrafts --buildFuture
Creating an issue
If you’ve found a problem in the docs, but you’re not sure how to fix it yourself, please create an issue in the
yusaopeny_docs repo. You can also create an issue about a specific page by clicking the Create Issue button in the top right hand corner of the page.
Useful resources
Docsy user guide: All about Docsy, including how it manages navigation, look and feel, and multi-language support.
In addition to the
full documentation, here are some commonly used functions in the YMCA Website Services Docs.
General Styles
The YMCA Website Services Docs are written in
Markdown, an easy-to read and write formatting language.
The old documentation made heavy use of horizontal rules --- and slashes in headings ## // Heading. We try to use standard Markdown headings for organization and remove those visual indicators for better accessibility.
Headings with a page should start with level 2 ## in order to properly build the in-page navigation.
Links
Internal links should be made with Markdown and page-relative locations, like:
The old community documentation used headings inside blockquotes (starting each line with >). That formatting doesn’t work in Hugo. We can use
Docsy alerts instead.
{{%alerttitle="Warning"%}}This is a warning.
{{%/alert%}}
Warning
This is a warning.
Although blockquotes sometimes work just as well:
> **Warning:** This is a warning.
Warning: This is a warning.
Color swatches
The color shortcode can be used to display a small color swatch after a hex or RGB color value. Pass one quoted value for hex, or three numeric values for RGB.
When using this shortcode in code fences, use <> instead of %% as the shortcode delimiter so that the code is
not further rendered.
The include-remote-md shortcode fetches a remote markdown file and includes it in the page. This happens only when your Docsy project is built, so future changes of the remote markdown file are only included when you rebuild your project. See
docsy#1739
If the file has a H1 (# ....) instead of frontmatter, you can put the title line in as the second parameter and it will be removed instead. For example:
Linkcheck has some issues with localhost that we’re working on resolving. Until then, you can set up your local site to run through
Cloudflare Tunnel and then run it.
linkcheck -e https://your-site-url.example.com/docs/some/path --skip-file .linkcheck_skip.txt - run the linkchecker on internal (default) and external (-e) links with our custom ignore file (--skip-file).
## For Engineers, ## For Operators within one file
Drupal core
Per-issue snippets → consolidated by editor
Contributor writes snippet (knows their change best), editor assembles
Key pattern: none of these projects create separate files per persona per release. They all use one document where sections progressively become more technical.
Separate Files vs Sections Within One Document
Creating separate per-persona files for each release (e.g., content-editor/release-X.md, developer/release-X.md, site-builder/release-X.md, decision-maker/release-X.md) has clear strengths:
Each audience sees only what’s relevant to them
Targeted language per persona
Quantified metrics (67% faster, 93% less memory) — excellent communication
However, it introduces maintenance concerns:
Duplication: The same facts are repeated across multiple files with different wording. Fixing an error means finding and updating it in multiple places.
Maintenance scale: Every future release needs multiple coordinated documents.
No precedent: None of the major projects researched (Next.js, Laravel, Stripe, GitLab, Drupal core) use separate files per persona per release.
Recommended Structure
A structure that achieves persona targeting without duplication:
# Release X.Y.Z (YYYY-MM-DD)
## Summary (2-3 sentences — for everyone)
## What's New (feature highlights with anchor links — executives scan here)
## For Content Editors
- UI changes, new workflows, what changed in their daily work
## For Site Builders
- Config changes, Layout Builder updates, upgrade steps
## For Developers
- Breaking changes table (Was → Now → Migration)
- Code examples, API changes, removed modules
## Upgrade Instructions (copy-paste ready)
## Bug Fixes
## Full Changelog (link to GitHub release)
Why this works:
Single source of truth — each fact exists once
Persona targeting — each audience has a clear section to jump to
Shareable — anchor links let you share direct URLs to each persona section
Maintainable — one file to review, one file to fix errors in
Scales naturally — adding a new release = one new file, not five
Alternative: YAML Data + Hugo Templates
Since this documentation site uses Hugo, a more advanced zero-duplication approach is possible:
Store release facts in a data file (e.g., data/releases/v11.3.1.0.yaml)
Create Hugo templates that render persona-specific pages from the same data
Each persona page is auto-generated — zero manual duplication
This requires more upfront setup but eliminates duplication entirely.
Technical Review Requirement
Developer-facing release notes contain API examples and code snippets. These must be technically verified before publication:
Method signatures must match actual Drupal core and contrib module APIs
Service names must exist in the service container
Code examples must be runnable (not hypothetical)
Breaking changes must reference actual change records
Example of why this matters: Release 11.3.1.0 developer docs referenced $entity->delete(['force' => TRUE]) for the Trash module — this API does not exist. EntityInterface::delete() accepts zero parameters. The correct approach uses TrashManager::executeInTrashContext().