feat(slides): add persistent branding with per-slide visibility control

- Add branding overlays: logo, title, author, and footer text
- Use Reveal.js theme CSS variables for automatic color adaptation
- Inline SVGs for currentColor support on any theme
- Per-slide control via HTML comments:
  - <!-- no-branding -->: hide all elements
  - <!-- no-header -->: hide logo + title
  - <!-- no-footer -->: hide author + footer
- Fix body-level CSS selectors for proper visibility
- Add comprehensive documentation in example slides
This commit is contained in:
George Cushen
2026-01-13 15:36:32 +00:00
parent 1352d89867
commit aa9edea5df
16 changed files with 902 additions and 17 deletions
+70
View File
@@ -16,6 +16,76 @@ Supports math, syntax highlighting, diagrams, speaker notes, and much more!
- path: github.com/HugoBlox/kit/modules/slides
```
## Branding & Customization
### Logo and Overlays
Add consistent branding across all slides by configuring `slides.branding` in your site config or slide front matter:
```yaml
# In hugo.yaml (site-wide) or slide front matter (per-deck)
params:
slides:
branding:
logo:
filename: "logo.png" # File in assets/media/
position: "top-left" # top-left, top-right, bottom-left, bottom-right
width: "80px" # Logo width
margin: "20px" # Distance from edges
title:
show: true # Show presentation title overlay
text: "Short Title" # Optional: Override auto-detected title
position: "bottom-left"
author:
show: true # Show author name overlay
position: "bottom-right"
footer:
text: "© 2026 Copyright" # Footer text (e.g. copyright)
position: "bottom-center" # bottom-center, bottom-left, bottom-right
```
### Hooks System
Inject custom content into presentations without modifying module files. Create partials in your project's `layouts/_partials/hooks/` directory:
| Hook | Location | Use Case |
|------|----------|----------|
| `slide-header/` | Top of presentation | Course code, session info |
| `slide-footer/` | Bottom of presentation | Social handles, copyright |
| `slide-head-end/` | End of `<head>` | Custom CSS, fonts, analytics |
| `slide-body-end/` | End of `<body>` | Custom JS, Reveal.js plugins |
Example: Create `layouts/_partials/hooks/slide-footer/social.html`:
```html
<div style="font-size: 0.5em; opacity: 0.6;">
@yourhandle · yoursite.com
</div>
```
See `_example.html` files in each hook directory for more examples.
## Per-Slide Visibility
Control branding visibility on individual slides using HTML comments:
- `<!-- no-branding -->`: Hide all branding elements (logo, header, footer)
- `<!-- no-header -->`: Hide only the header (and logo)
- `<!-- no-footer -->`: Hide only the footer
Example:
```markdown
---
<!-- no-branding -->
## Full Screen Image Slide
This slide will have no branding overlays.
```
## Usage
[View the documentation](https://docs.hugoblox.com/content/slides/)
@@ -0,0 +1,129 @@
/*
* HugoBlox Slides Branding Styles
*
* Default styles for slide branding elements (logo, overlays, headers/footers).
* These styles ensure branding elements don't interfere with slide content.
*/
/* Logo container */
#slide-logo {
position: fixed;
z-index: 100;
pointer-events: none;
transition: opacity 0.3s ease;
color: var(--r-main-color, #fff);
}
#slide-logo img {
width: 100%;
height: auto;
max-height: 60px;
}
#slide-logo svg {
width: 100%;
height: auto;
max-height: 60px;
fill: currentColor;
}
/* Title and author overlays */
#slide-title-overlay,
#slide-author-overlay,
#slide-footer-text-overlay {
position: fixed;
z-index: 100;
pointer-events: none;
font-family: var(--r-main-font, inherit);
color: var(--r-main-color, #fff);
font-size: 0.7em;
opacity: 0.8;
max-width: 40%;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
text-shadow: 0 1px 2px rgba(0, 0, 0, 0.5);
}
#slide-footer-text-overlay {
font-size: 0.6em;
opacity: 0.7;
}
/* Header and footer hook containers */
.slide-header,
.slide-footer {
position: fixed;
left: 0;
right: 0;
z-index: 100;
pointer-events: none;
display: flex;
align-items: center;
padding: 10px 20px;
}
.slide-header {
top: 0;
justify-content: space-between;
}
.slide-footer {
bottom: 0;
justify-content: space-between;
}
/* Visibility Control via data-state classes (applied to body by JS) */
body.no-branding #slide-logo,
body.no-branding #slide-title-overlay,
body.no-branding #slide-author-overlay,
body.no-branding #slide-footer-text-overlay,
body.no-branding .slide-header,
body.no-branding .slide-footer {
/* biome-ignore lint/complexity/noImportantStyles: Required to override Reveal.js styles */
display: none !important;
}
body.no-header .slide-header,
body.no-header #slide-logo,
body.no-header #slide-title-overlay {
/* biome-ignore lint/complexity/noImportantStyles: Required to override Reveal.js styles */
display: none !important;
}
body.no-footer .slide-footer,
body.no-footer #slide-author-overlay,
body.no-footer #slide-footer-text-overlay {
/* biome-ignore lint/complexity/noImportantStyles: Required to override Reveal.js styles */
display: none !important;
}
/* Re-enable pointer events for interactive elements within header/footer */
.slide-header a,
.slide-header button,
.slide-footer a,
.slide-footer button {
pointer-events: auto;
}
/* Hide branding in print mode for cleaner PDFs */
@media print {
#slide-logo,
#slide-title-overlay,
#slide-author-overlay,
#slide-footer-text-overlay,
.slide-header,
.slide-footer {
opacity: 0.5;
}
}
/* Respect Reveal.js overview mode */
.reveal.overview #slide-logo,
.reveal.overview #slide-title-overlay,
.reveal.overview #slide-author-overlay,
.reveal.overview #slide-footer-text-overlay,
.reveal.overview .slide-header,
.reveal.overview .slide-footer {
display: none;
}
@@ -63,6 +63,30 @@ pluginOptions.plugins = enabledPlugins;
Reveal.initialize(pluginOptions);
// Handle data-state for branding visibility
// Apply classes to body since branding elements are body-level siblings of .reveal
const applySlideState = (event) => {
const body = document.body;
if (!body) return;
// Remove previous state classes from body
body.classList.remove("no-branding", "no-header", "no-footer");
// Get current slide's data-state
const currentSlide = event?.currentSlide || Reveal.getCurrentSlide();
if (currentSlide) {
const state = currentSlide.getAttribute("data-state");
if (state) {
state.split(" ").forEach((s) => {
body.classList.add(s);
});
}
}
};
Reveal.on("ready", applySlideState);
Reveal.on("slidechanged", applySlideState);
// Disable Mermaid by default.
if (typeof slides.diagram === "undefined") {
slides.diagram = false;
@@ -0,0 +1,157 @@
{{/*
Slide Branding Component
Renders persistent branding elements (logo, title overlay, etc.) that appear
across all slides in a presentation.
Configuration (site.Params.slides.branding or .Params.slides.branding):
logo:
src: "media/logo.png" # Path to logo image
alt: "Organization Logo" # Alt text
position: "top-left" # top-left, top-right, bottom-left, bottom-right
width: "100px" # Logo width
margin: "20px" # Distance from edges
title:
show: true # Show presentation title
position: "bottom-left" # Position of title text
author:
show: true # Show author/presenter name
position: "bottom-right" # Position of author text
*/}}
{{/* Merge page-level config with site-level defaults */}}
{{ $site_branding := site.Params.slides.branding | default dict }}
{{ $page_branding := .Params.slides.branding | default dict }}
{{ $branding := merge $site_branding $page_branding }}
{{/* Logo rendering */}}
{{ with $branding.logo }}
{{ if .filename }}
{{ $resource_path := printf "media/%s" .filename }}
{{ $logo_resource := resources.Get $resource_path }}
{{ with $logo_resource }}
{{ $position := $branding.logo.position | default "top-left" }}
{{ $width := $branding.logo.width | default "80px" }}
{{ $margin := $branding.logo.margin | default "20px" }}
{{ $alt := $branding.logo.alt | default "Logo" }}
{{/* Calculate CSS position based on position string */}}
{{ $positionCSS := "" }}
{{ if eq $position "top-left" }}
{{ $positionCSS = printf "top: %s; left: %s;" $margin $margin }}
{{ else if eq $position "top-right" }}
{{ $positionCSS = printf "top: %s; right: %s;" $margin $margin }}
{{ else if eq $position "bottom-left" }}
{{ $positionCSS = printf "bottom: %s; left: %s;" $margin $margin }}
{{ else if eq $position "bottom-right" }}
{{ $positionCSS = printf "bottom: %s; right: %s;" $margin $margin }}
{{ else }}
{{/* Custom position - expect CSS string */}}
{{ $positionCSS = $position }}
{{ end }}
<div id="slide-logo" style="{{ $positionCSS | safeCSS }} width: {{ $width }};" aria-label="{{ $alt }}">
{{/* Inline SVGs to enable currentColor, use img for other formats */}}
{{ if strings.HasSuffix .Name ".svg" }}
{{ .Content | safeHTML }}
{{ else }}
<img src="{{ .RelPermalink }}" alt="{{ $alt }}">
{{ end }}
</div>
{{ end }}
{{ end }}
{{ end }}
{{/* Title overlay (optional) */}}
{{ if $branding.title }}
{{ with $branding.title }}
{{ if .show }}
{{ $position := .position | default "bottom-left" }}
{{ $margin := .margin | default "20px" }}
{{ $positionCSS := "" }}
{{ if eq $position "top-left" }}
{{ $positionCSS = printf "top: %s; left: %s;" $margin $margin }}
{{ else if eq $position "top-right" }}
{{ $positionCSS = printf "top: %s; right: %s;" $margin $margin }}
{{ else if eq $position "bottom-left" }}
{{ $positionCSS = printf "bottom: %s; left: %s;" $margin $margin }}
{{ else if eq $position "bottom-right" }}
{{ $positionCSS = printf "bottom: %s; right: %s;" $margin $margin }}
{{ end }}
<div id="slide-title-overlay" style="{{ $positionCSS | safeCSS }}">
{{ .text | default $.Title }}
</div>
{{ end }}
{{ end }}
{{ end }}
{{/* Author overlay (optional) */}}
{{ if $branding.author }}
{{ with $branding.author }}
{{ if .show }}
{{ $position := .position | default "bottom-right" }}
{{ $margin := .margin | default "20px" }}
{{ $positionCSS := "" }}
{{ if eq $position "top-left" }}
{{ $positionCSS = printf "top: %s; left: %s;" $margin $margin }}
{{ else if eq $position "top-right" }}
{{ $positionCSS = printf "top: %s; right: %s;" $margin $margin }}
{{ else if eq $position "bottom-left" }}
{{ $positionCSS = printf "bottom: %s; left: %s;" $margin $margin }}
{{ else if eq $position "bottom-right" }}
{{ $positionCSS = printf "bottom: %s; right: %s;" $margin $margin }}
{{ end }}
{{/* Get author from page params or first author */}}
{{ $author := "" }}
{{ with $.Params.authors }}
{{ if reflect.IsSlice . }}
{{ $author = index . 0 }}
{{ else }}
{{ $author = . }}
{{ end }}
{{ end }}
{{ with $.Params.author }}
{{ $author = . }}
{{ end }}
{{ if $author }}
<div id="slide-author-overlay" style="{{ $positionCSS | safeCSS }}">
{{ $author }}
</div>
{{ end }}
{{ end }}
{{ end }}
{{ end }}
{{/* Footer text overlay (optional) - e.g. for copyright */}}
{{ if $branding.footer }}
{{ with $branding.footer }}
{{ if .text }}
{{ $position := .position | default "bottom-center" }}
{{ $margin := .margin | default "20px" }}
{{ $positionCSS := "" }}
{{ if eq $position "top-left" }}
{{ $positionCSS = printf "top: %s; left: %s;" $margin $margin }}
{{ else if eq $position "top-right" }}
{{ $positionCSS = printf "top: %s; right: %s;" $margin $margin }}
{{ else if eq $position "bottom-left" }}
{{ $positionCSS = printf "bottom: %s; left: %s;" $margin $margin }}
{{ else if eq $position "bottom-right" }}
{{ $positionCSS = printf "bottom: %s; right: %s;" $margin $margin }}
{{ else if eq $position "bottom-center" }}
{{ $positionCSS = printf "bottom: %s; left: 50%%; transform: translateX(-50%%);" $margin }}
{{ end }}
<div id="slide-footer-text-overlay" style="{{ $positionCSS | safeCSS }}">
{{ .text | markdownify }}
</div>
{{ end }}
{{ end }}
{{ end }}
@@ -0,0 +1,39 @@
{{/*
Slides Hook Loader - Independent Implementation
This is a self-contained hook system for the slides module that doesn't
depend on the blox module. Users can create partials in their own project's
layouts/_partials/hooks/{hook-name}/ directory.
Usage: {{ partial "functions/slides_get_hook" (dict "hook" "slide-header" "context" .) }}
Available hooks for slides:
- slide-header: Top of presentation (inside .reveal, above .slides)
- slide-footer: Bottom of presentation (inside .reveal, below .slides)
- slide-head-end: End of <head> tag (for custom CSS/JS)
- slide-body-end: End of <body> tag (for custom JS)
Input: dict with "hook" (string) and "context" (page context)
Output: Renders all partials found in the hook directory
*/}}
{{ $loaded := false }}
{{ $partial_dir := printf "hooks/%s/" .hook }}
{{ $context := .context }}
{{ $hook_dir_path := path.Join "layouts/_partials" $partial_dir }}
{{/* Use try to gracefully handle missing directories */}}
{{ with try (os.ReadDir $hook_dir_path) }}
{{ with .Value }}
{{ range . }}
{{ if not .IsDir }}
{{ $partial_path := path.Join $partial_dir .Name }}
{{ partial $partial_path $context }}
{{ $loaded = true }}
{{ end }}
{{ end }}
{{ end }}
{{ end }}
{{/* Debug: uncomment to see if hooks are loaded */}}
{{/* return $loaded */}}
@@ -0,0 +1,22 @@
{{/*
Example Slide Body-End Hook
This hook allows injecting custom JavaScript at the end of the <body>
tag, after Reveal.js has been loaded. Useful for:
- Custom Reveal.js plugins
- Analytics tracking on slide changes
- Custom keyboard shortcuts
- Integration with other JS libraries
To use this hook, create a file at:
layouts/_partials/hooks/slide-body-end/your-custom-script.html
*/}}
{{/* Uncomment below to track slide changes with console logging */}}
{{/*
<script>
Reveal.on('slidechanged', event => {
console.log('Slide changed to:', event.indexh, event.indexv);
});
</script>
*/}}
@@ -0,0 +1,20 @@
{{/*
Example Slide Footer Hook
This is an example file showing how to create custom footer content
that appears at the bottom of every slide in a presentation.
To use this hook, create a file at:
layouts/_partials/hooks/slide-footer/your-custom-footer.html
The content will be rendered inside a <div class="slide-footer"> container.
Example usage: show social media handle or contact info
*/}}
{{/* Uncomment below to show author's social handle in footer */}}
{{/*
<div style="font-size: 0.5em; color: rgba(255,255,255,0.5); padding: 10px; text-align: right; width: 100%;">
@yourhandle
</div>
*/}}
@@ -0,0 +1,25 @@
{{/*
Example Slide Head-End Hook
This hook allows injecting custom CSS or JavaScript into the <head>
section of the presentation. Useful for:
- Custom fonts
- Additional CSS frameworks
- Analytics scripts
- Custom Reveal.js configurations
To use this hook, create a file at:
layouts/_partials/hooks/slide-head-end/your-custom-head.html
*/}}
{{/* Uncomment below to add custom font */}}
{{/*
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Fira+Code&display=swap" rel="stylesheet">
<style>
.reveal pre code {
font-family: 'Fira Code', monospace;
}
</style>
*/}}
@@ -0,0 +1,30 @@
{{/*
Example Slide Header Hook
This is an example file showing how to create custom header content
that appears at the top of every slide in a presentation.
To use this hook, create a file at:
layouts/_partials/hooks/slide-header/your-custom-header.html
The content will be rendered inside a <div class="slide-header"> container.
Available context variables:
.Title - Presentation title
.Params - All front matter parameters
.Params.authors - List of authors
.Params.course - Course code/name
.Params.venue - Event venue
.Date - Presentation date
Example usage:
*/}}
{{/* Uncomment below to show course code in header */}}
{{/*
{{ with .Params.course }}
<div style="font-size: 0.6em; color: rgba(255,255,255,0.6); padding: 10px;">
{{ . }}{{ with $.Params.lecture_number }} · Lecture {{ . }}{{ end }}
</div>
{{ end }}
*/}}
+31 -1
View File
@@ -26,7 +26,20 @@
{{/* Each `<section>` defines a new slide. */}}
{{/* Only begin new slide `<section>` if not already added by custom `slide` shortcode. */}}
{{ if not (in . "data-noprocess") }}
<section{{ if $isHidden }} data-visibility="hidden"{{ end }}>
{{/* Parse visibility comments */}}
{{ $state := slice }}
{{ if in . "<!-- no-branding -->" }}
{{ $state = $state | append "no-branding" }}
{{ end }}
{{ if in . "<!-- no-header -->" }}
{{ $state = $state | append "no-header" }}
{{ end }}
{{ if in . "<!-- no-footer -->" }}
{{ $state = $state | append "no-footer" }}
{{ end }}
<section{{ if $isHidden }} data-visibility="hidden"{{ end }} {{ if gt (len $state) 0 }}data-state="{{ delimit $state " " }}"{{ end }}>
{{ end }}
{{ $slideContent | safeHTML }}
</section>
@@ -35,4 +48,21 @@
{{ end }}
{{ end }}
</div>
{{/* Branding elements - placed inside .reveal but outside .slides to be persistent and fixed */}}
{{/* Branding overlay (logo, title, author) */}}
{{ $pageContext := index . 0 }}
{{ partial "components/slide-branding" $pageContext }}
{{/* Hook: slide-header */}}
<div class="slide-header">
{{ partial "functions/slides_get_hook" (dict "hook" "slide-header" "context" $pageContext) }}
</div>
{{/* Hook: slide-footer */}}
<div class="slide-footer">
{{ partial "functions/slides_get_hook" (dict "hook" "slide-footer" "context" $pageContext) }}
</div>
</div>
@@ -1,5 +1,23 @@
{{/*
Present Baseof - Presentation output only
Hook Points Available:
- slide-head-end: End of <head> for custom CSS/JS
- slide-header: Top of presentation (inside .reveal wrapper)
- slide-footer: Bottom of presentation (inside .reveal wrapper)
- slide-body-end: End of <body> for custom JS
Branding Configuration (site.Params.slides.branding or page front matter):
logo:
src: "media/logo.png"
position: "top-left" # top-left, top-right, bottom-left, bottom-right
width: "100px"
title:
show: true
position: "bottom-left"
author:
show: true
position: "bottom-right"
*/}}
<!doctype html>
@@ -38,6 +56,13 @@
{{- $theme := $.Param "slides.theme" | default "black" -}}
<link rel="stylesheet" href="{{ $cdn_url_reveal }}/dist/theme/{{ $theme }}.min.css">
{{/* Load branding CSS */}}
{{ $branding_css := resources.Get "css/slides-branding.css" }}
{{ with $branding_css }}
{{ $branding_css = . | minify | fingerprint }}
<link rel="stylesheet" href="{{ $branding_css.RelPermalink }}">
{{ end }}
{{/* Hugo Chroma Syntax Highlighter */}}
{{ $hl_theme := $.Param "slides.highlight_style" | default "dracula" }}
{{ $hl_theme_path := printf "css/libs/chroma/%s.css" $hl_theme }}
@@ -58,6 +83,10 @@
document.head.appendChild(link);
})();
</script>
{{/* Hook: slide-head-end - Custom CSS/JS injection point */}}
{{ partial "functions/slides_get_hook" (dict "hook" "slide-head-end" "context" .) }}
</head>
<body>
@@ -80,7 +109,8 @@
{{ $slidejs := resources.Get "js/hugoblox-slides.js" | js.Build (dict "params" (dict "slides" $.Params.slides )) | fingerprint }}
<script src="{{ $slidejs.RelPermalink }}"></script>
{{ partial "functions/get_hook" (dict "hook" "body-end" "context" .) }}
{{/* Hook: slide-body-end - End of body for custom JS */}}
{{ partial "functions/slides_get_hook" (dict "hook" "slide-body-end" "context" .) }}
</body>
</html>
@@ -0,0 +1 @@
<svg role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><title>Markdown</title><path fill="currentColor" d="M22.27 19.385H1.73A1.73 1.73 0 010 17.655V6.345a1.73 1.73 0 011.73-1.73h20.54A1.73 1.73 0 0124 6.345v11.308a1.73 1.73 0 01-1.73 1.731zM5.769 15.923v-4.5l2.308 2.885 2.307-2.885v4.5h2.308V8.078h-2.308l-2.307 2.885-2.308-2.885H3.46v7.847zM21.232 12h-2.309V8.077h-2.307V12h-2.308l3.461 4.039z"/></svg>

After

Width:  |  Height:  |  Size: 421 B

@@ -1 +0,0 @@
<svg id="visual" viewBox="0 0 960 540" width="960" height="540" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1"><path d="M0 104L87 158L175 125L262 131L349 163L436 163L524 168L611 174L698 136L785 104L873 125L960 147L960 0L873 0L785 0L698 0L611 0L524 0L436 0L349 0L262 0L175 0L87 0L0 0Z" fill="#003223"></path><path d="M0 185L87 195L175 212L262 217L349 206L436 239L524 233L611 222L698 185L785 147L873 190L960 190L960 145L873 123L785 102L698 134L611 172L524 166L436 161L349 161L262 129L175 123L87 156L0 102Z" fill="#013b2d"></path><path d="M0 228L87 249L175 287L262 309L349 303L436 336L524 298L611 282L698 260L785 255L873 287L960 255L960 188L873 188L785 145L698 183L611 220L524 231L436 237L349 204L262 215L175 210L87 193L0 183Z" fill="#014537"></path><path d="M0 357L87 395L175 347L262 368L349 428L436 449L524 363L611 390L698 352L785 379L873 368L960 401L960 253L873 285L785 253L698 258L611 280L524 296L436 334L349 301L262 307L175 285L87 247L0 226Z" fill="#024f42"></path><path d="M0 541L87 541L175 541L262 541L349 541L436 541L524 541L611 541L698 541L785 541L873 541L960 541L960 399L873 366L785 377L698 350L611 388L524 361L436 447L349 426L262 366L175 345L87 393L0 355Z" fill="#02594e"></path></svg>

Before

Width:  |  Height:  |  Size: 1.2 KiB

@@ -5,16 +5,45 @@ date: 2024-01-01
type: slides
summary: "A quick tour of recent research highlights: multimodal LLMs, efficient training, and responsible AI."
slides:
theme: black
highlight_style: dracula
diagram: true # Enable Mermaid diagrams
theme: black # Options: black, white, league, beige, sky, night, serif, simple, solarized
highlight_style: dracula # Code syntax highlighting theme
diagram: true # Enable Mermaid diagrams for flowcharts, etc.
reveal_options:
controls: true
progress: true
slideNumber: true
hash: true
controls: true # Show navigation arrows
progress: true # Show progress bar
slideNumber: true # Show slide numbers
hash: true # Update URL when navigating slides
# BRANDING: Add logo, title overlay, and footer to your presentation
# All settings are optional - remove any you don't need
branding:
# LOGO: Display your organization's logo
logo:
filename: "slides-logo.svg" # File in assets/media/ folder (SVG recommended for any theme)
position: "top-right" # Options: top-left, top-right, bottom-left, bottom-right
width: "50px" # Logo width (height scales automatically)
# margin: "20px" # Distance from edge (optional, default: 20px)
# TITLE OVERLAY: Show presentation title on every slide
title:
show: true # Set to false to hide
position: "bottom-left" # Options: top-left, top-right, bottom-left, bottom-right
# text: "Short Title" # Optional: override the page title with custom text
# margin: "20px" # Distance from edge (optional)
# AUTHOR OVERLAY: Show author name on every slide
# author:
# show: true
# position: "bottom-right"
# FOOTER TEXT: Display copyright, conference name, etc.
footer:
text: "© 2026 HugoBlox" # Supports Markdown (e.g., links)
position: "bottom-center" # Options: top-left, top-right, bottom-left, bottom-right, bottom-center
---
<!-- no-branding -->
# Example Talk
### Dr. Alex Johnson · Meta AI
@@ -319,3 +348,138 @@ This slide won't appear in the presentation but remains in source for reference.
Note:
Thank you for your attention! Feel free to reach out with questions or contributions.
---
## 🎨 Branding Your Slides
Add your identity to every slide with simple configuration!
**What you can add:**
| Element | Position Options |
|---------|-----------------|
| Logo | top-left, top-right, bottom-left, bottom-right |
| Title | Same as above |
| Author | Same as above |
| Footer Text | Same + bottom-center |
Edit the `branding:` section in your slide's front matter (top of file).
---
## 📁 Adding Your Logo
1. Place your logo in `assets/media/` folder
2. Use SVG format for best results (auto-adapts to any theme!)
3. Add to front matter:
```yaml
branding:
logo:
filename: "your-logo.svg" # Must be in assets/media/
position: "top-right"
width: "60px"
```
**Tip:** SVGs with `fill="currentColor"` automatically match theme colors!
---
## 📝 Title & Author Overlays
Show presentation title and/or author on every slide:
```yaml
branding:
title:
show: true
position: "bottom-left"
text: "Short Title" # Optional: override long page title
author:
show: true
position: "bottom-right"
```
Author is auto-detected from page front matter (`author:` or `authors:`).
---
## 📄 Footer Text
Add copyright, conference name, or any persistent text:
```yaml
branding:
footer:
text: "© 2024 Your Name · ICML 2024"
position: "bottom-center"
```
**Tip:** Supports Markdown! Use `[Link](url)` for clickable links.
---
<!-- no-branding -->
## 🔇 Hiding Branding Per-Slide
Sometimes you want a clean slide (title slides, full-screen images).
Add this comment at the **start** of your slide content:
```markdown
<!-- no-branding -->
## My Clean Slide
Content here...
```
☝️ **This slide uses `<!-- no-branding -->`** — notice no logo or overlays!
---
<!-- no-header -->
## 🔇 Selective Hiding
Hide just the header (logo + title):
```markdown
<!-- no-header -->
```
Or just the footer (author + footer text):
```markdown
<!-- no-footer -->
```
☝️ **This slide uses `<!-- no-header -->`** — footer still visible below!
---
<!-- no-footer -->
## ✅ Quick Reference
| Comment | Hides |
|---------|-------|
| `<!-- no-branding -->` | Everything (logo, title, author, footer) |
| `<!-- no-header -->` | Logo + Title overlay |
| `<!-- no-footer -->` | Author + Footer text |
☝️ **This slide uses `<!-- no-footer -->`** — logo still visible above!
---
## 🚀 Get Started
1. Copy this example's front matter as a starting point
2. Replace logo with yours in `assets/media/`
3. Customize positions and text
4. Use `<!-- no-branding -->` for special slides
**Pro tip:** Set site-wide defaults in `config/_default/params.yaml` under `slides.branding`!
@@ -0,0 +1 @@
<svg role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><title>Markdown</title><path fill="currentColor" d="M22.27 19.385H1.73A1.73 1.73 0 010 17.655V6.345a1.73 1.73 0 011.73-1.73h20.54A1.73 1.73 0 0124 6.345v11.308a1.73 1.73 0 01-1.73 1.731zM5.769 15.923v-4.5l2.308 2.885 2.307-2.885v4.5h2.308V8.078h-2.308l-2.307 2.885-2.308-2.885H3.46v7.847zM21.232 12h-2.309V8.077h-2.307V12h-2.308l3.461 4.039z"/></svg>

After

Width:  |  Height:  |  Size: 421 B

@@ -8,16 +8,36 @@ venue: "Hugo Blox Tutorial"
featured: true
type: slides
slides:
theme: black
highlight_style: dracula
diagram: true
theme: black # Options: black, white, league, beige, sky, night, serif, simple, solarized
highlight_style: dracula # Code syntax highlighting theme
diagram: true # Enable Mermaid diagrams for flowcharts, etc.
reveal_options:
controls: true
progress: true
slideNumber: true
hash: true
controls: true # Show navigation arrows
progress: true # Show progress bar
slideNumber: true # Show slide numbers
hash: true # Update URL when navigating slides
# BRANDING: Add logo, title overlay, and footer to your presentation
# All settings are optional - remove any you don't need
branding:
# LOGO: Display your organization's logo
logo:
filename: "slides-logo.svg" # File in assets/media/ folder (SVG recommended for any theme)
position: "top-right" # Options: top-left, top-right, bottom-left, bottom-right
width: "50px" # Logo width (height scales automatically)
# TITLE OVERLAY: Show presentation title on every slide
title:
show: true # Set to false to hide
position: "bottom-left" # Options: top-left, top-right, bottom-left, bottom-right
# FOOTER TEXT: Display copyright, conference name, etc.
footer:
text: "© 2026 HugoBlox" # Supports Markdown (e.g., links)
position: "bottom-center" # Options: top-left, top-right, bottom-left, bottom-right, bottom-center
---
<!-- no-branding -->
# Markdown Slides
### Write in Markdown. Present Anywhere.
@@ -164,3 +184,127 @@ Use `{{</* slide background-color="#hex" */>}}`
- Docs: [docs.hugoblox.com](https://docs.hugoblox.com)
*Built with Markdown Slides*
---
## 🎨 Branding Your Slides
Add your identity to every slide with simple configuration!
**What you can add:**
| Element | Position Options |
|---------|-----------------|
| Logo | top-left, top-right, bottom-left, bottom-right |
| Title | Same as above |
| Author | Same as above |
| Footer Text | Same + bottom-center |
Edit the `branding:` section in your slide's front matter (top of file).
---
## 📁 Adding Your Logo
1. Place your logo in `assets/media/` folder
2. Use SVG format for best results (auto-adapts to any theme!)
3. Add to front matter:
```yaml
branding:
logo:
filename: "your-logo.svg" # Must be in assets/media/
position: "top-right"
width: "60px"
```
**Tip:** SVGs with `fill="currentColor"` automatically match theme colors!
---
## 📝 Title & Author Overlays
Show presentation title and/or author on every slide:
```yaml
branding:
title:
show: true
position: "bottom-left"
text: "Short Title" # Optional: override long page title
author:
show: true
position: "bottom-right"
```
Author is auto-detected from page front matter (`author:` or `authors:`).
---
## 📄 Footer Text
Add copyright, conference name, or any persistent text:
```yaml
branding:
footer:
text: "© 2024 Your Name · ICML 2024"
position: "bottom-center"
```
**Tip:** Supports Markdown! Use `[Link](url)` for clickable links.
---
<!-- no-branding -->
## 🔇 Hiding Branding Per-Slide
Sometimes you want a clean slide (title slides, full-screen images).
Add this comment at the **start** of your slide content:
```markdown
<!-- no-branding -->
## My Clean Slide
Content here...
```
☝️ **This slide uses `<!-- no-branding -->`** — notice no logo or overlays!
---
<!-- no-header -->
## 🔇 Selective Hiding
Hide just the header (logo + title):
```markdown
<!-- no-header -->
```
Or just the footer (author + footer text):
```markdown
<!-- no-footer -->
```
☝️ **This slide uses `<!-- no-header -->`** — footer still visible below!
---
<!-- no-footer -->
## ✅ Quick Reference
| Comment | Hides |
|---------|-------|
| `<!-- no-branding -->` | Everything (logo, title, author, footer) |
| `<!-- no-header -->` | Logo + Title overlay |
| `<!-- no-footer -->` | Author + Footer text |
☝️ **This slide uses `<!-- no-footer -->`** — logo still visible above!