Gophern is a professional, local Markdown presentation engine built with Go and htmx. It compiles standard Markdown files into sleek, interactive online slideshows featuring a synchronized presenter console, real-time Server-Sent Events (SSE) state synchronization, and a self-contained PDF exporter.
- Blazing Fast Markdown Rendering: Uses Goldmark for GFM-compliant markdown compiling.
- Server-Side Code Highlighting: Syntax highlights code blocks using Chroma, compiling them into inline CSS styles for zero external dependency rendering.
- Aspect Ratio Lock: Strictly maintains a professional 16:9 layout viewport, auto-scaling to fit the browser window.
- Presenter Dashboard: Features a clock, elapsed timer, current/next slide previews, and real-time speaker notes display.
- SSE Real-Time Sync: Synchronizes slide navigation in real-time between the main viewer and presenter console.
- Self-Contained Export: Renders every slide via a locally installed headless Chrome and assembles them into a single, portable PDF that can be opened offline anywhere.
Ensure you have Go (version 1.22 or higher) installed.
You can install Gophern directly using Go's package manager:
go install github.com/gophernment/gophern@latestEnsure your Go bin directory ($GOPATH/bin or ~/go/bin) is added to your system's PATH.
Alternatively, clone the repository and install it locally:
git clone https://github.com/gophernment/gophern.git
cd gophern
go install .Gophern provides two main subcommands: serve and export.
Start the local HTTP server to display slides and enable presenter synchronization:
gophern serve [-port 8080] example.mdThe port also defaults to the PORT environment variable when -port isn't given (-port always wins if both are set):
PORT=3000 gophern serve example.md- Open the Presentation View at
http://localhost:8080/. - Open the Presenter Console at
http://localhost:8080/presenter.
Navigating slides on either window (using arrow keys, space, or buttons) will automatically sync the other window instantly via Server-Sent Events.
A fullscreen toggle button always sits in the bottom-right corner of the Presentation View. The prev/next nav buttons and the slide-number indicator (1 / 12) are hidden by default — enable them per deck with showControls / showSlideNumber in the global frontmatter (see Show/Hide Navigation Controls).
Export the presentation into a single self-contained PDF for distribution or offline use:
gophern export [-o output.pdf] example.mdEach slide is rendered through a locally installed headless Chrome/Chromium (required for export; serve does not need it) and captured as a full-resolution image, one per PDF page — so the exported file looks exactly like the live view, including gradients, backgrounds, and syntax-highlighted code, with no server or browser needed to view it afterward.
Slides are separated by three hyphens (---) on a blank line:
# Slide One
Content goes here.
---
# Slide Two
Another slide.You can define slide properties using YAML frontmatter blocks at the beginning of the slides.
- Global settings should be placed on the first slide (Slide 0).
- Local settings override themes, layouts, or backgrounds for individual slides.
---
title: "Project Pitch"
theme: "slate"
layout: "cover"
background: "linear-gradient(135deg, #0f172a 0%, #1e293b 100%)"
color: "#ffffff"
---
# Main Cover Slidedefault: Normal vertical flex layout.cover: Centered cover page layout with gradient background support.two-cols: Dual-column layout (useful for side-by-side text/images or text/code blocks).
Set the deck's main fonts with fonts.sans / fonts.mono in the global frontmatter (first slide). Override just one slide's heading font with headerFont in that slide's local frontmatter — everything else on the slide keeps using the main font.
---
title: "Project Pitch"
fonts:
sans: 'Space Grotesk'
mono: 'JetBrains Mono'
---
# Uses the main font
---
headerFont: "Poppins, sans-serif"
---
# This slide's heading uses its own fontNote:
servemode (and/presenter) automatically link to Google Fonts for any custom font you set (fonts.sans,fonts.mono,headerFont), so most Google Font names just work — no extra setup needed. This does reach out to Google's CDN over the network.exportrenders with only locally-available or built-in fonts — if the font you named isn't installed on the machine runningexport, the PDF falls back to the built-in stack (Interfor sans,Fira Codefor mono) instead.
Each font field accepts a full comma-separated CSS font stack, not just one name. This is useful when your primary font has no glyphs for a script like Thai — list a script-specific font after it as a fallback:
---
title: "งานนำเสนอ"
fonts:
sans: "Poppins, 'Noto Sans Thai'"
---
# หัวข้อ (Poppins สำหรับ Latin, Noto Sans Thai สำหรับไทย)The browser tries each font in order per character, so Latin text renders in Poppins and Thai text automatically falls through to Noto Sans Thai. In serve/presenter, every real font name in the stack is fetched from Google Fonts (generic CSS keywords like sans-serif are ignored, not fetched).
The prev/next buttons and the slide-number indicator (1 / 12) in the Presentation View are hidden by default. Turn them on per deck with showControls / showSlideNumber in the global frontmatter (first slide):
---
title: "Project Pitch"
showControls: true
showSlideNumber: true
---
# Main Cover SlideThe fullscreen toggle button is always visible regardless of these settings. This config only affects serve's Presentation View — the Presenter Console and export output are unaffected.
Add speaker notes inside an HTML comment (<!-- ... -->) placed at the very bottom of the slide block:
# Slide Title
Slide content here.
<!--
Remember to mention the architecture schema here!
-->This project is licensed under the MIT License.