This is the single authoring examples page. Its source is markup-examples.md.
The hero above, images and table below, form near the end, and onward links all
use the same components as the rest of the site.
- Complete page front matter
- Headings and text
- Left, right and full-width images
- Scrollable tables
- Heroes and carousels
- Where next and related pages
- Forms
- Internal and external links
- Redirects
- Collections, hierarchy and site settings
Complete page front matter
Create a .md file at the site root. YAML between the first two --- lines
configures the page; Markdown after the second line is its body. Use two spaces
per level, never tabs. Quote text containing : and use actual booleans
(true and false, without quotes).
---
layout: page
title: Getting involved
permalink: /getting-involved/
parent: /about/
description: Ways to take part in the CHERI community.
hero:
size: large
summary: Find a useful starting point for your next conversation.
where-next:
title: Working groups
action: Explore groups
url: /working-groups/
image:
src: /assets/images/placeholders/landscape-left.svg
alt: Working together in the CHERI community
width: 1200
height: 800
related-pages:
- title: Membership
action: Explore membership
url: /membership/
- title: CHERI Alliance
action: Visit the website
url: https://cheri-alliance.org/
target: _blank
rel: noopener noreferrer
---
image groups all properties belonging to the same image. Use the same map
under each carousel slide and where-next. Listing images use a
thumbnail map with the same properties. Keep width and height for natural-ratio
body and onward images: they reserve space before loading. Omit them from
carousel, thumbnail and social-icon maps, where CSS already reserves the frame.
When supplied, they describe source pixels, not the responsive display size. fit
accepts cover or contain; position accepts left, center or right.
Cropping matters in fixed frames such as thumbnails and carousel slides;
body and onward images keep their natural proportions.
Use 800 × 800 (1:1) for speaker and member thumbnails,
1600 × 900 (16:9) for news and event thumbnails, 1200 × 800 (3:2) for left/right
body images, 1600 × 900 (16:9) for full-width images and 1920 × 1080 (16:9)
for slider images. Placeholder labels show the aspect ratio, not a pixel size.
News, events and sliders keep 16:9 frames; speaker and member frames stay square.
cover crops and contain adds
space without stretching the image.
Optional settings can be omitted. The default light theme and hero come from
_config.yml. summary is the visible lead below the heading, with or without
a hero; description supplies search metadata. The old page-level intro and
hero.text fields have been consolidated into summary. form.intro remains
a separate, used field for the form’s own instructions.
Order front matter as shown: page metadata and listing thumbnail first, then
hero settings, dates/byline, summary, slider, listing/form, Where next, related
pages and footer/overlay settings. Omit optional values you do not need.
Use hero: false for an ordinary page heading and image-overlay: false to
disable body-image enlargement on a page. The delivered Home page alone is dark.
Headings and text
The layout supplies the page’s H1. Start the body at H2 (##) and use H3/H4
for subsections. Keep a blank line between paragraphs and around lists.
## Plan your next step
Write a short introduction with **important words** or *gentle emphasis*.
### Choose a subject
- Record the context.
- Identify the next question.
#### Keep a useful record
1. Describe your starting point.
2. Link to the relevant resources.
> A quotation or short callout belongs in a blockquote.
[Browse resources]({{ '/resources/' | relative_url }}).
Example subsection
This is a rendered H3 followed by bold text, emphasis and inline code.
Example detail
This is a rendered H4. Heading levels express the structure of the content.
Kramdown creates heading IDs for links; an explicit ID such as
## Plan your next step {#plan} stays stable when you change the title.
Left, right and full-width images
These are ordinary Markdown images with Kramdown attributes directly after
the closing parenthesis. Keep the asset path inside relative_url so it also
works when the site is hosted in a repository subdirectory.
Left image
{: .image-left width="1200" height="800" loading="lazy"}
Write the paragraphs that should flow beside the image here.
On desktop, this image sits on the left and the text flows beside it. Begin with the subject of the image and explain why it belongs in this section. Alternative text should convey what a reader needs to understand, rather than repeat a filename.
Use enough prose to establish the context and explain the next step. The shared styles limit floated images to 40% of the content width, with a maximum width of 28rem and height of 20rem. On smaller screens, the image and text stack.
Right image
{: .image-right width="1200" height="800" loading="lazy"}
Write the paragraphs that should flow beside the image here.
This image uses the same dimensions and responsive rules, aligned to the right. The next section heading clears the float automatically. There is no need to add empty paragraphs or manual line breaks to position it.
Use width and height to describe the real asset dimensions and reduce
layout movement while the image loads. The browser still scales it to fit.
The visible size label on a placeholder describes its source canvas.
Full-width image
{: .image-full width="1600" height="900" loading="lazy"}
Full width means the width of the content area. Images keep their proportions.
Click these body images to enlarge them; add .no-zoom alongside the alignment
class to opt out. The expanded image fills the available viewport while keeping
its proportions, a small outer margin, its caption and an accessible Close
button. Escape closes it and restores focus. Carousel images always follow
the slide’s link.
Scrollable tables
Write a normal Markdown table. No special HTML wrapper is needed. On a narrow screen, swipe or scroll horizontally inside the table to reach the right-hand columns. With JavaScript enabled, overflowing tables can also receive keyboard focus so the arrow keys can scroll them. The CSS scrolling fallback works without JavaScript.
| Component | Image source | Fit | Source size | Destination |
| --- | --- | --- | --- | --- |
| Body image | full-width.svg | Natural proportions | 1600 × 900 | Image enlargement |
| Carousel | slider.svg | cover | 1920 × 1080 | Slide URL |
| News | news-thumbnail.svg | cover | 1600 × 900 | News page |
| Speaker | speaker-portrait.svg | cover | 800 × 800 | Speaker page |
| Event | event-thumbnail.svg | cover | 1600 × 900 | Event page |
| Member logo | member-logo.svg | contain | 800 × 800 | Member page |
{: aria-label="Image configuration examples"}
| Component | Image source | Fit | Source size | Destination |
|---|---|---|---|---|
| Body image | full-width.svg | Natural proportions | 1600 × 900 | Image enlargement |
| Carousel | slider.svg | cover | 1920 × 1080 | Slide URL |
| News | news-thumbnail.svg | cover | 1600 × 900 | News page |
| Speaker | speaker-portrait.svg | cover | 800 × 800 | Speaker page |
| Event | event-thumbnail.svg | cover | 1600 × 900 | Event page |
| Member logo | member-logo.svg | contain | 800 × 800 | Member page |
The attribute line immediately after the table gives the scrollable region a
useful accessible label. For column alignment, use :---, :---: or ---:
in the separator row.
Heroes and carousels
Heroes are enabled by default and reuse title and summary. Their optional
settings are size and title; only supply a title override when it differs
from the page title. size: large uses the prominent Home treatment; omitting
size uses the standard treatment. Dates and an optional news byline appear
between the title and summary. Set hero: false for a normal heading instead.
Add this slider map to the page’s front matter. It renders as a separate
section below the hero. See the live carousel on Home.
slider:
title: Explore CHERI
autoplay: true
interval: 5000
slides:
- title: Discover CHERI
text: Explore capabilities and memory safety.
image:
src: /assets/images/placeholders/slider.svg
alt: Introduction to CHERI
fit: contain
action: Discover CHERI
url: /discover/
- title: CHERI Alliance
text: Visit the Alliance website.
image:
src: /assets/images/placeholders/slider.svg
alt: CHERI Alliance community
fit: cover
position: right
action: Visit the website
url: https://cheri-alliance.org/
target: _blank
rel: noopener noreferrer
Every slide should have a url. Clicking its image, title, text, action or
background follows that URL; the whole slide is one keyboard-accessible link.
Unicode ● dot selectors below the slide let readers choose another slide.
Each is a native button with an accessible slide label; the current dot is
larger and uses the main text colour. The dots have 44px minimum targets for
touch and keyboard use.
There is no carousel image zoom.
The CTA uses the same text-and-arrow styling as the site’s other card links.
The carousel sits outside the hero, with equal-width image and text columns on
desktop and a single stacked column on mobile. Unicode dot selectors are centred
below the slide. If hero: false, the carousel follows the body so the page’s
ordinary heading comes first.
interval is in milliseconds, with a minimum of 3000. Home and the example above
advance every five seconds. Hovering over the carousel and clicking a dot
selector do not stop playback; selecting a slide starts a fresh five-second
interval. Playback waits while a slide link has keyboard focus or the tab is
hidden, then resumes automatically. Reduced-motion preferences disable autoplay;
playback resumes if that preference is turned off. Set autoplay: false or omit
it for manual selection. If you omit interval, it defaults to 5000 milliseconds.
Without JavaScript, the first slide’s complete link remains usable.
Where next and related pages
Both are optional. Where next contains a title, action, URL and optional image.
It has no description or introductory paragraph. Related pages are a list of
title/action cards. target and rel work in either component.
where-next:
title: Discover CHERI
action: Continue
url: /discover/
image:
src: /assets/images/placeholders/landscape-left.svg
alt: Introduction to CHERI
width: 1200
height: 800
related-pages:
- title: Membership
action: Explore membership
url: /membership/
- title: CHERI Alliance on GitHub
action: View repositories
url: https://github.com/CHERI-Alliance
target: _blank
rel: noopener noreferrer
Forms
Select layout: forms and put form in front matter. The live form near the
bottom of this page uses the configuration below. Fields stack on mobile;
size: half shares a desktop row, while size: full spans both columns.
Omitted sizes default to full width. Keep field names unique.
layout: forms
form:
id: example-form
title: Rendered form example
intro: Fields marked * are required.
action: ''
method: post
submit: Send enquiry
demo: 'Demonstration form: no submission service is connected.'
fields:
- name: name
label: Your name
type: text
size: half
required: true
autocomplete: name
placeholder: Full name
- name: email
label: Email address
type: email
size: half
required: true
autocomplete: email
placeholder: you@example.org
help: Use an address where we can reply.
- name: topic
label: Enquiry topic
type: select
size: full
required: true
placeholder: Choose a topic
options:
- label: Membership
value: membership
- label: Technical enquiry
value: technical
- name: message
label: Your message
type: textarea
size: full
rows: 6
required: true
placeholder: Tell us what you would like to discuss.
Supported field types are text, email, tel, textarea and select.
required, placeholder, help and autocomplete are optional. Select options
group their visible label and submitted value beneath options.
An empty action deliberately renders a non-submitting demonstration, including
when JavaScript is disabled. To receive submissions, set action to your real
HTTPS form-service endpoint or an existing backend route and choose method:
post or get. GitHub Pages itself cannot process a form; the receiving service
must handle delivery and confirmation. Merely changing the button label does
not connect it to a service.
Internal and external links
Yes: Kramdown supports external-link attributes. Keep the attribute list immediately after the link, on the same line.
[Local resources]({{ '/resources/' | relative_url }})
[Choose a platform]({{ '/build/#choose-a-platform' | relative_url }})
[CHERI Alliance](https://cheri-alliance.org/){: target="_blank" rel="noopener noreferrer"}
CHERI Alliance
is a rendered external link. target="_blank" opens a new tab/window according to
the visitor’s browser settings; rel="noopener noreferrer" isolates it from the
opener. These attributes work without JavaScript.
Use the same attribute names beside url in front matter and navigation data:
- title: CHERI Alliance
url: https://cheri-alliance.org/
target: _blank
rel: noopener noreferrer
This works in menus, social links, sliders, Where next, related pages, listing
cards and Subscribe. A _blank target also adds missing noopener/noreferrer
tokens without discarding other rel values, such as nofollow.
Omit both attributes for ordinary internal links. The content script retains
its fallback that opens unmarked off-site HTTP(S) links in a new tab. An
explicit target: _self (or Kramdown target="_self") is respected, as are named
targets. There is no external front-matter flag or required CSS class.
Redirects
Manage redirects centrally in _redirects/, with one Markdown file per source
path. The collection is configured to output HTML, and its defaults omit the
site shell, navigation parent and sitemap entry. Redirects never appear in
content listings. Only two front-matter fields are needed.
For _redirects/examples.md:
---
permalink: /examples/
redirect_to: /markup-examples/
---
For _redirects/alliance-website.md:
---
permalink: /alliance-website/
redirect_to: https://cheri-alliance.org/
---
Both examples are included in this kit. Open /examples/ returns to this page; open /alliance-website/ redirects to the Alliance website.
permalink is the old/source path. Use a root-relative directory URL ending in
/, or an explicit .html path. redirect_to is a root-relative internal path
or a complete HTTP(S) URL. Internal destinations may include a query or fragment.
Do not add baseurl to either field; the enabled jekyll-redirect-from plugin
adds the deployment prefix to internal destinations and leaves external URLs
unchanged. Redirects navigate the current tab.
Run this before building, using the same optional baseurl as the build:
bundle exec ruby scripts/check_redirects.rb
bundle exec ruby scripts/check_redirects.rb /cheri-preview
The checker rejects duplicate source/output paths, collisions with real pages
or assets, missing internal destinations and redirect loops. It also checks
legacy redirect_from aliases if you retain any. The existing /examples/
alias has moved into the collection; do not define it in both places.
These are static HTML redirects, using the existing plugin’s refresh page,
canonical destination and fallback link. They do not set HTTP 301/302 status
codes; configure those at the host if needed. redirect_to and redirect_from
retain their plugin-required underscores.
Collections, hierarchy and site settings
News files live in _posts/YYYY-MM-DD-slug.md; events, members and speakers
live in _events/, _members/ and _speakers/. Collection defaults select
their layouts and parents. Use this grouped thumbnail on a detail page:
thumbnail:
src: /assets/images/placeholders/news-thumbnail.svg
alt: News image for a community update
fit: cover
position: center
The listing frame reserves space, so no width/height fields are needed here.
For an event, use event-thumbnail.svg; events get a 16:9 frame automatically.
News also gets a 16:9 frame. Speaker and member frames stay square. Member logos normally use
fit: contain. News sorts newest first; events sort
earliest first. Event front matter uses date: 2026-11-18 and optional
end-date: 2026-11-19. Member and speaker cards show only their image and title.
parent points to the permalink of an existing page and supplies breadcrumbs.
Use nav-title to shorten a breadcrumb label. A page with layout: index lists
its children automatically; listing.title changes the section heading and
listing.columns: 2, 3 or 4 sets the desktop grid. Avoid cycles in the parent chain.
layout: index
title: Resources
permalink: /resources/
parent: /
listing:
title: Explore resources
columns: 3
For an events directory, group the settings that control its listing:
layout: list
title: Events
permalink: /events/
summary: Workshops and community sessions.
listing:
collection: events
sort: date
action: View event
Listings sort ascending unless listing.order: desc is supplied. Use
listing.compact: true for image-and-title cards, as on Speakers and Members.
Index listings derive their children from parent and do not need a collection.
Optional news author and company
Both fields are optional and independent. They appear after the date on a news post, with a separator only when both are present. Omit either field completely when it is unknown; do not add empty placeholders. The byline appears on the detail page. Demo news posts use Dan Sullivan, Adam Finney and Mike Eftimakis.
---
title: A community update
description: Metadata describing the article.
thumbnail:
src: /assets/images/placeholders/news-thumbnail.svg
alt: A community discussion
author: Dan Sullivan
company: Example company
summary: A short visible introduction to the article.
---
Save the post as _posts/YYYY-MM-DD-slug.md; the filename supplies its date.
The hero and normal-heading layouts both support the optional byline.
In _data/navigation.yml, nest child items under links. A parent link and its
submenu disclosure remain separate controls. Header mega-menus use
type: megamenu, columns and a list of subcategories, each with title and
links. In _config.yml, subscribe controls the shared call to action:
subscribe:
enabled: true
title: Stay connected with CHERI
action: Subscribe
url: /subscribe/
Set enabled: false to hide it globally, or subscribe: false in a single
page’s front matter. For a signup service in a new tab, set an HTTPS url,
target: _blank and rel: noopener noreferrer in the site configuration.
For the complete syntax, see Kramdown’s documentation and Jekyll’s redirect plugin.
Colours and the body watermark
Theme settings live in _sass/settings.scss. Light-theme section colours use
variables such as these; the $theme-dark map contains the corresponding dark
values:
$colour-page: rgba(#ffffff, 0.53);
$colour-hero: rgba(#fdece3, 0.37);
$colour-card: rgba(#eef5f8, 0.35);
$colour-watermark: rgba(#125770, 0.32);
$colour-link-hover: #ba1e1e;
The opacity argument ranges from 0 (transparent) to 1 (solid). It applies
only to the background; text and controls remain opaque. Keep enough contrast
with the patterned body beneath the section. The dark Subscribe band keeps
its own background.
The background uses the logo’s rounded outer hexagon in a composed honeycomb. Staggered rows, diagonal tonal ribbons and larger anchor cells make it work as a standalone background. Every cell has a transparent centre and an outline made from 1px horizontal lines separated by 1px gaps, clipped inside the original contour. The spacing stays fixed in CSS pixels as the hexagons scale. Cells remain separated and retain the original proportions. The logo files are unchanged; there is no grain layer.
Adjust watermark in each theme to change the colour or strength. Set its
alpha to 0 to hide it. Section opacity controls how much detail shows through
the hero, cards and onward links. These settings do not need page front matter
and do not affect text opacity.
Ordinary text links turn red on hover. link-hover uses a lighter red in dark
mode to remain readable. Navigation links, cards, buttons and image links keep
their established behaviour.
Rendered form example
Fields marked * are required. This example does not send submissions.