A newspaper-style Hugo theme designed for news sites, magazines, and blogs that want the aesthetic of a traditional broadsheet newspaper with modern performance.
Live Demo: ap7i.com
Note: This theme is in active development (v0.x). The configuration options, templates, and CSS classes may change before v1.0 stable release.
- Newspaper-style masthead with date, navigation, and site title
- Multi-column grid layouts for homepage stories
- Featured article support for lead stories
- Responsive design optimized for mobile reading
- Dark mode follows system preference automatically, respecting individual user settings
- Share buttons for LinkedIn, Facebook, X, and Reddit (optional, zero JavaScript)
- Fast performance - minimal JavaScript, optimized CSS
- Clean typography using Libre Baskerville (headlines) and Source Sans (body)
- Section labels for categorizing articles
- Reading time estimates
- SEO optimized with proper meta tags and semantic HTML
- Hugo Extended v0.158.0 or later (Extended for SCSS/CSS processing; that release introduced the
localesetting the templates read) - Git (for submodule installation)
This method allows you to easily update the theme and track which version you're using.
# Navigate to your Hugo site
cd your-hugo-site
# Add the theme as a submodule
git submodule add https://github.com/parkscloud/hugo-broadsheet.git themes/broadsheet
# Initialize and update (if cloning a site that already has the submodule)
git submodule update --init --recursiveTo update the theme later:
git submodule update --remote themes/broadsheetIf you want to modify the theme directly or don't want to use submodules:
cd your-hugo-site
git clone https://github.com/parkscloud/hugo-broadsheet.git themes/broadsheet
# Remove .git to avoid nested repo issues
rm -rf themes/broadsheet/.git- Download the latest release or main branch ZIP
- Extract to
your-hugo-site/themes/broadsheet/
Add to your hugo.toml:
theme = 'broadsheet'Full configuration example for hugo.toml:
theme = 'broadsheet'
# Generate robots.txt from the theme's template (see SEO below)
enableRobotsTXT = true
[params]
# Site tagline (appears below masthead title)
tagline = "All the news that's fit to print"
# robots.txt always allows every crawler and lists the sitemap. Set this to
# also name the major AI crawlers and say yes to AI training and AI answers.
# Off by default.
robotsAllowAI = false
# <title> and meta description limits, in characters. The defaults match
# Bing Webmaster Tools; 0 turns a limit off. See SEO below.
titleMaxLength = 70
descriptionMaxLength = 160
# How a tag page names itself in <title>; %s is the tag. Use "%s" for
# the bare name.
tagTitleFormat = "Posts tagged %s"
# Structured data (JSON-LD). Off unless enable = true; see SEO below.
[params.schema]
enable = true
logo = "images/logo.png" # publisher logo, relative to the site root
logoWidth = 600
logoHeight = 300
license = "https://creativecommons.org/licenses/by/4.0/" # optional
[params.schema.person] # optional: the site's main author
name = "Jane Smith"
url = "about/"
jobTitle = "Editor"
bylines = ["Jane Smith"] # front matter author values that mean this person
sameAs = ["https://www.linkedin.com/in/example/"]
[params.schema.aiMakers] # optional: add AI model families
Mistral = "Mistral AI"
# Show reading time on articles
showReadingTime = true
# Enable search functionality
enableSearch = true
# Enable share buttons (LinkedIn, Facebook, X)
enableShareButtons = true
# Footer links
[[params.footerLinks]]
name = "About"
url = "/about/"
[[params.footerLinks]]
name = "Contact"
url = "/contact/"
[menu]
[[menu.main]]
name = "News"
url = "/posts/"
weight = 1
[[menu.main]]
name = "Opinion"
url = "/opinion/"
weight = 2
[[menu.main]]
name = "Technology"
url = "/tech/"
weight = 3Posts support the following front matter:
---
title: "Article Headline"
date: 2026-01-01
draft: false
author: "Jane Reporter"
section: "Technology"
summary: "A brief summary that appears in article lists and the lead story."
image: "/images/article-image.jpg"
imageCaption: "Photo credit or description"
featured: true # Makes this the lead story on homepage
tags: ["breaking", "tech"]
---| Field | Description |
|---|---|
title |
Article headline |
date |
Publication date |
author |
Byline (e.g., "By Jane Reporter") |
section |
Section label (e.g., "Technology", "Opinion") |
summary |
Brief description for lists and featured display |
pageTitle |
Optional text for <title> in place of the headline; the heading on the page, Open Graph, Twitter and JSON-LD keep title |
image |
Featured image path |
imageCaption |
Image caption/credit |
featured |
Set true to make this the lead story |
tags |
Array of tags for categorization |
All images in Broadsheet use a 16:9 aspect ratio with object-fit: cover. This applies to:
- Article hero images
- Lead story images on homepage
- Story card thumbnails
Recommended specifications:
| Spec | Value |
|---|---|
| Aspect ratio | 16:9 |
| Dimensions | 1200×675 px |
| Format | WebP (with JPG or PNG fallback) |
| Max file size | 150 KB |
Usage in front matter:
image: "/images/posts/my-article.webp"
imageCaption: "Photo credit or description"Automatic fallback detection: When using WebP images, Broadsheet automatically provides a fallback for browsers that don't support WebP. The theme uses the HTML <picture> element to serve WebP to modern browsers while falling back to JPG or PNG for older ones.
At build time, Hugo checks which fallback file exists:
- If a
.jpgfile exists with the same base name, it uses JPG as the fallback - Otherwise, if a
.pngfile exists, it uses PNG as the fallback - If neither exists, the WebP is used directly (older browsers will show a broken image)
This auto-detection means you can use JPG fallbacks for photographs (smaller file size) and PNG fallbacks for graphics with transparency or sharp edges, without any configuration.
To use this feature:
- Save both formats with the same base name (e.g.,
my-article.webpandmy-article.jpg) - Reference only the
.webpfile in front matter - The theme automatically detects and uses the appropriate fallback
Preparation tips:
- Crop to 16:9 before uploading to avoid unexpected cropping
- Provide a JPG fallback for photographs (better compression)
- Provide a PNG fallback for graphics, screenshots, or images needing transparency
- Compress images to under 150KB for fast mobile loading
- Store in
static/images/and reference with absolute paths - Use Squoosh for easy browser-based conversion with visual comparison
The homepage displays articles in a newspaper-style layout:
- Lead Story - The most recent
featured: truearticle (or most recent if none featured) - Secondary Stories - Next 4 articles in a grid
- Earlier - Remaining articles in a list format (appears when you have more than 5 posts)
Lead story layout: When the featured post has an image, the layout is two-column (content + image). Without an image, content spans full width.
Broadsheet automatically adapts to the user's system preference using CSS media queries (prefers-color-scheme). There is no manual toggle—the theme respects whatever the user has configured on their device:
- iOS/Android users with auto-switching see the theme change with sunrise/sunset
- Users who prefer dark mode always see the dark theme
- Default system users see the light theme
This approach:
- Respects individual user preferences without requiring interaction
- Eliminates JavaScript for theme switching
- Works immediately on first page load (no flash of wrong theme)
Optional social sharing buttons appear at the end of articles when enabled:
[params]
enableShareButtons = trueSupported platforms: LinkedIn, Facebook, X (Twitter), Reddit
Implementation details:
- Zero JavaScript—uses simple share URLs that open each platform's share dialog
- No tracking scripts or external requests
- Icons use inline SVG (Feather Icons style, MIT licensed)
- Styled as subtle circular buttons that match the theme
When disabled (default), no share UI appears on article pages.
The footer includes a .cc-icon class for Creative Commons icons. To add CC license icons to your footer, use inline SVGs in your layouts/partials/footer.html:
<svg class="cc-icon" viewBox="0 0 24 24"><!-- CC icon path --></svg>
<svg class="cc-icon" viewBox="0 0 24 24"><!-- BY icon path --></svg>
CC BY 4.0The icons automatically scale with text size and inherit the link color.
Links in params.footerLinks whose URL starts with http:// or https:// open in a new tab with rel="noopener noreferrer"; relative links such as /about/ open in place.
Override CSS custom properties in your own stylesheet:
:root {
--color-accent: #1a5f7a; /* Change accent color */
--font-headline: 'Playfair Display', serif; /* Different headline font */
}Fonts are self-hosted for performance and privacy (no external requests):
- Headlines: Libre Baskerville (serif)
- Body: Source Sans 3 (sans-serif)
To use different fonts, replace the files in static/fonts/ and update the @font-face declarations in assets/css/broadsheet.css.
Use the .callout class to highlight example content, notes, or other material that should stand out from the main text. Callouts display with a shaded background and subtle left border.
Usage in markdown:
<div class="callout">
Your content here. Markdown formatting works inside the div,
but you need a blank line after the opening tag.
- Lists work
- **Bold** and *italic* work
- Headers work
</div>Note: Hugo requires unsafe = true in your markup configuration for raw HTML in markdown:
[markup.goldmark.renderer]
unsafe = trueBroadsheet is built for speed:
- Zero JavaScript for core functionality (dark mode via CSS media queries)
- Self-hosted fonts - no external requests to Google or other CDNs
- CSS-only layouts (no CSS frameworks)
- System font fallbacks for fast initial render
- Responsive images with lazy loading
- Minified output when built with
hugo --minify
Broadsheet follows SEO best practices:
- Proper H1 structure — The site title renders as
<h1>on the homepage only; inner pages use<h1>for the article title - Content-first page titles — Inner pages use
Article Title | Siteso the<title>opens with the same words as the<h1>; the homepage usesSite | tagline. Titles stay withinparams.titleMaxLength(default 70, Bing Webmaster Tools' limit): the site name is dropped when there's no room for it, and a headline that is still too long is cut at a word break with "…". A page'spageTitlefront matter replaces the headline in<title>, which suits a one-word headline (Bing reports "Title too short" under 15 characters), and tag pages readPosts tagged Name(params.tagTitleFormat). - Meta descriptions — Taken from the page's
descriptionfield, else its summary, else the site'sdescriptionparam, and kept withinparams.descriptionMaxLength(default 160). A longer text keeps its opening sentences, or is cut at a word break with "…" when they would be too short. Open Graph, Twitter and JSON-LD keep the full text. - Open Graph tags — Article images and descriptions are included for social sharing
- Twitter Cards — Large image cards for better visibility when shared
- Semantic HTML — Proper use of
<article>,<header>,<nav>,<footer>, and<time>elements - Canonical URLs — Prevents duplicate content issues
- Structured data (JSON-LD) — With
params.schema.enable = true, every page carries one JSON-LD@graphdescribing the publisher (Organization), the site's main author (Person, when configured), and theWebSite. Articles add aBlogPosting(headline, dates, images, author, publisher, section, tags, license,isAccessibleForFree) and aBreadcrumbList; the author's profile page becomes anAboutPage. Bylines that start with a known AI model family (Claude, GPT, Gemini, Grok, Kimi, Muse, Qwen, plus any inparams.schema.aiMakers) are described as the model, typedOrganization, with its maker asparentOrganizationand the configured person aseditor; other bylines become aPerson. The block is a data block, so it works under a strictscript-srcContent Security Policy with no'unsafe-inline'. - robots.txt — With
enableRobotsTXT = true, the theme writes a robots.txt that allows every crawler and lists the sitemap by absolute URL, replacing Hugo's built-in one-line default. Settingparams.robotsAllowAI = truealso names the major search and AI crawlers (GPTBot, OAI-SearchBot, ClaudeBot, Claude-SearchBot, PerplexityBot, Google-Extended, Applebot-Extended, and others) and adds yes signals for search, AI answers, and AI training in two formats: the IETF AI preferences draft'sContent-Usageand Cloudflare'sContent-Signal. The same group includes the proposed__usage_ai-trainingpolicy token withAllow: /, expressing an affirmative preference under that convention; a wildcard alone does not count. These signals communicate intent and do not guarantee inclusion or citations. If the site hasstatic/llms.txt, the file points to it. A site can override the whole file with its ownlayouts/robots.txt.
- Chrome, Firefox, Safari, Edge (latest versions)
- Mobile browsers (iOS Safari, Chrome for Android)
- Graceful degradation for older browsers
This project uses Semantic Versioning:
- 0.x.y - Development releases (current)
0.1.0- Initial release0.x.0- New features, may include breaking changes0.x.y- Bug fixes and minor improvements
- 1.0.0 - First stable release (when feature-complete and battle-tested)
- 1.x.y - Stable releases with backward compatibility
Current status: Pre-release development. Expect changes to templates, CSS classes, and configuration options before v1.0.
The exampleSite/ directory contains a complete demo site. To run it locally:
cd hugo-broadsheet/exampleSite
hugo server --themesDir /path/to/parent/of/hugo-broadsheetFor example, if your theme is at /home/user/repos/hugo-broadsheet:
cd /home/user/repos/hugo-broadsheet/exampleSite
hugo server --themesDir /home/user/reposWhen making changes to the theme, the example site will live-reload automatically.
Contributions are welcome! Please open an issue to discuss changes before submitting a PR.
MIT License - see LICENSE for details.
This theme includes the following third-party assets, which are distributed under their respective open-source licenses:
The fonts included in static/fonts/ are licensed under the SIL Open Font License 1.1, which permits:
- Free use in personal and commercial projects
- Modification and redistribution
- Bundling with other software
| Font | Copyright | License File |
|---|---|---|
| Libre Baskerville | 2012 Pablo Impallari, Rodrigo Fuenzalida | static/fonts/LICENSE-LibreBaskerville.txt |
| Source Sans 3 | 2010-2020 Adobe | static/fonts/LICENSE-SourceSans.md |
| Icon Set | Copyright | License File |
|---|---|---|
| Feather Icons | 2013-2023 Cole Bemis | static/fonts/LICENSE-FeatherIcons.txt |
Icons are embedded as inline SVG in templates (no external requests).
.callout prenow wraps text instead of horizontal-scrolling:white-space: pre-wrap; overflow-wrap: anywhere; overflow-x: visible;overrides the default.article-content pre { overflow-x: auto; }rule when a<pre>is nested inside a<div class="callout">. Use this pattern for long preformatted content that benefits from monospace structure but needs to wrap to the column width — e.g., an API call with a long string parameter, a long shell command, or a structured config file. Indentation is preserved; long lines wrap.
- Dark mode image support:
<picture>elements now auto-detect-darkvariants viafileExists()and serve them withmedia="(prefers-color-scheme: dark)"
- Widened list page layout from 720px to 1200px to match homepage width
- Auto-detect JPG or PNG fallback for WebP images at build time (JPG preferred for photos, PNG for graphics)
- Added PNG fallback support on homepage for WebP images using
<picture>element
- Standardized footer link styling: all links now show color change on hover without underlines
- Added markdown render hook for external links opening in new tabs
- Title format updated to show site name before page name
- Various layout and typography refinements
- Typography: Libre Baskerville by Pablo Impallari, Source Sans by Adobe
- Icons: Feather Icons by Cole Bemis