A system for creating academic content that can be rendered in multiple formats (slides, notes, papers) from a single source. LaMD provides a rich set of macros and contexts for handling different content types and output formats.
Full documentation is available at:
Key sections:
The system relies on the generic preprocessor, gpp (https://github.com/logological/gpp).
On Linux:
apt-get install gppOn macOS:
brew install gpp# Install lamd using pip
pip install lamd
# Or install from source using Poetry
git clone https://github.com/lawrennd/lamd.git
cd lamd
poetry installTo populate minimal agent hints (Cursor rules + AGENTS.md/CLAUDE.md blocks) in a LaMD-using repository (e.g. talks/, execed/), run this from that repo root. The installer writes files into the current directory (it doesn’t require any LaMD-specific files to already exist in the repo).
bash -c "$(curl -fsSL https://raw.githubusercontent.com/lawrennd/lamd/main/scripts/install-minimal.sh)"To also create a local venv and install lamd (so maketalk is available without system Python), add:
bash -c "$(curl -fsSL https://raw.githubusercontent.com/lawrennd/lamd/main/scripts/install-minimal.sh)" -- --with-venvLaMD requires:
- Python 3.11 or higher
- gpp preprocessor
- Pandoc (for document conversion)
- Additional Python packages (installed automatically):
- lynguine
- python-frontmatter
- pandas
- python-liquid
Create a _lamd.yml in your project root to configure pandoc flags and other settings:
LaMD uses a modular configuration system based on makefiles and markdown frontmatter:
Configuration is organized into flag files for different document types:
make-cv-flags.mk: Configuration for CV documentsmake-talk-flags.mk: Configuration for talk documents- etc.
These flag files:
- Extract configuration from markdown frontmatter using
mdfield - Define document-specific settings and paths
- Are included by the make system as needed
Configuration can come from:
- Markdown frontmatter (primary source)
- Flag files (document-type specific)
- Environment variables (for system-wide settings)
For a talk document:
- The markdown file's frontmatter defines basic settings along with _lamd.yml that contains the defaults.
make-talk-flags.mkextracts these settings usingmdfield- The make system includes these flags
- The Python code (
mdpp.py) respects these settings
LaMD provides several utility scripts:
maketalk: Converts talk files from markdown to other formatsmakecv: Converts CVs from markdown to other formatsflags: Extracts pandoc flags from_config.ymlmdfield: Extracts fields from markdown headersdependencies: Lists dependencies in markdown filesmdpeople: Generates people macros from YAML definitionsmdlist: Generates lists from YAML definitions
The mdpeople script provides a powerful way to manage information about people in your documents. It generates macros for displaying profile images and information consistently.
Usage:
# Generate people macros from YAML file
mdpeople generate -i people.yml -o talk-people.gpp
# List all defined people
mdpeople list -i people.yml
# Check for missing images or invalid URLs
mdpeople verify -i people.ymlExample people.yml:
- given: Peter
family: Piper
image: people/peter-piper.png
url: https://pepper-pickers.com/
title: Neil Lawrence
- given: Jack
family: Spratt
image: people/jacks.png
url: https://lowfatyoghurts.com/jackspratt
title: Jack SprattUsing generated macros:
\include{talk-people.gpp}
\section{Team}
Our team includes \neillawrencePicture{15%} and \carlhenrikekPicture{15%}- Multiple output formats (HTML, PDF, PPTX)
- Context-aware content rendering
- Rich macro system for content reuse
- Media handling (images, videos, diagrams)
- Bibliography management
- People and team pages
- Exercise and assignment support
- Code testing and execution support (
--code test)
Create a new talk:
# Create talk file
echo "---
title: My Talk
author: Your Name
---
\section{Introduction}
\notes{Detailed notes here}
\slides{
* Bullet points
* For slides
}" > talk.md
# Build different formats
maketalk talk.md --format slides
maketalk talk.md --format notesLaMD supports code extraction and testing through the --code test option:
# Extract all code blocks for testing/execution
mdpp input.md --code test --macros-path macros/
# Use \testcode macro for test-specific code
\testcode{
import numpy as np
result = np.mean([1, 2, 3, 4, 5])
assert result == 3.0
print("Test passed!")
}The --code test option enables all code inclusion flags (-DCODE=1, -DPLOTCODE=1, -DHELPERCODE=1, -DDISPLAYCODE=1, -DMAGICCODE=1, -DTESTCODE=1) to ensure all code blocks are available for extraction and execution.