Write and compose in markdown (or HTML) - convert to HTML, LaTeX, and PDF.
- Convenient, though far from perfect
- Can handle interconnected content structures (auto numbering of sections, tables, figures, etc.;
.bib-based references and citations; among many other things. Also see example output) - Zero setup, no frameworks (requires only Docker with Pandoc-based image)
- Fully customizable (styling, metadata, layout, ...)
- Focus on writing instead of compiling (file-watcher + auto build)
Built on top of Pandoc (file format converter), and inspired by this pandoc book template.
📚 View the full documentation for detailed guides on configuration, templates, filters, and more.
docker run -u $(id -u):$(id -g) --rm -v "$(pwd):/app" -p 8000:8000 svbaelen/cowkit --initCustom port example:
docker run -u $(id -u):$(id -g) --rm -v "$(pwd):/app" -p 9500:8000 -e HOST_PORT=9500 svbaelen/cowkit --initFor default HTML output (and file watcher + HTTP server):
docker run -u $(id -u):$(id -g) --rm -v "$(pwd):/app" -p 8000:8000 svbaelen/cowkitCustom port example:
docker run -u $(id -u):$(id -g) --rm -v "$(pwd):/app" -p 9500:8000 -e HOST_PORT=9500 svbaelen/cowkitSee the config section to find out where to put what. Other examples can be found here.
You can specify a cowkit version with the image tag, e.g.,
cowkit:latest. For a non-docker runtime environment, see
development section.
Check available options for the cowkit utility with --help:
docker run -u $(id -u):$(id -g) --rm -v "$(pwd):/app" -p 8000:8000 svbaelen/cowkit --helpdocker image pull svbaelen/cowkit:latestconfig/config.yaml: main (output-independent) configconfig/<fmt>/config.yaml: output-specific config (can overwrite values set in mainconfig.yaml).config/<fmt>/templates/<file>: templates related to specific output formatssrc/<file>.md: content files written in markdown. Every section, subsection, paragraph, figure, etc. can have a separate file. In the metadata section of each markdown file (between---) you can add all kinds of metadata and config options supported by pandoc (and pandoc extensions), e.g., see here.
Set (different) config and/or template files via cowkit CLI arguments.
Additional functionality such as auto-reload can be disabled or extended via the header-includes section in the markdown metadata, e.g., see this example.
- See cowkit CLI examples here
- For an example output document, check out this webpage.
Create an alias to one or more relevant docker commands. Note that you can replace .bash_aliases with .bashrc or some other shell config file in your PATH:
# map to `cowkit`
CMD='docker run -u $(id -u):$(id -g) --rm -v "$(pwd):/app" -p 8000:8000 svbaelen/cowkit'
echo "alias cowkit='$CMD'" >> ~/.bash_aliases && source ~/.bash_aliasesNote that CLI arguments still work, e.g.:
cowkit --initcowkit --format pdf --template /path/to/template
Naturally, these commands can be updated or removed anytime in ~/.bash_aliases.
If re-running build process is too slow for you, open a ./config/<fmt>/config.yaml file and comment out stuff. Start with the Lua-based
filters (which will skip bibliography rebuilds). If still too slow, uncomment sections/chapters etc.
- Tested only on
- Ubuntu 22.04 and 24.04
- A fatal Pandoc error can crash the program (and file-watcher/builder), requiring the user to re-launch
- browser auto-reload after rebuild is based on LiveJS, however, sometimes a manual refresh is necessary on the browser tab to re-initialize this script. This seems to occur on layout changes (not always). Need to inspect!
docker build -t svbaelen/cowkit:latest -t svbaelen/cowkit:v0.2.0 . \
&& mkdir -p test && cd test \
&& rm -rf * \
&& docker run -u $(id -u):$(id -g) --rm -v "$(pwd):/app" \
-p 9500:8000 -e HOST_PORT=9500 svbaelen/cowkit --init \
&& docker run -u $(id -u):$(id -g) --rm \
-v "$(pwd):/app" -p 9500:8000 -e HOST_PORT=9500 svbaelen/cowkitcd ../ \
&& docker build -t svbaelen/cowkit:latest -t svbaelen/cowkit:v0.2.0 . \
&& cd test \
&& rm -rf * \
&& docker run -u $(id -u):$(id -g) --rm -v "$(pwd):/app" \
-p 9500:8000 -e HOST_PORT=9500 svbaelen/cowkit --init \
&& docker run -u $(id -u):$(id -g) --rm \
-v "$(pwd):/app" -p 9500:8000 -e HOST_PORT=9500 svbaelen/cowkitExample:
docker build -t svbaelen/cowkit:latest -t svbaelen/cowkit:v0.2.0 .Push to repo:
docker push svbaelen/cowkit --all-tagsNative Pandoc:
pandoc --defaults=./config/config.yaml --defaults=./config/html/config.yaml \
--template ./config/html/templates/default.htmlWith docker:
docker run --rm --volume "$(pwd):/data" \
--user $(id -u):$(id -g) pandoc/latex:latest \
--defaults=./config/config.yaml \
--defaults=./config/html/config.yaml --template ./config/html/templates/default.htmlpandoc --defaults=./config/config.yaml --defaults=./config/pdf/config.yamlWith docker:
docker run --rm --volume "$(pwd):/data" \
--user $(id -u):$(id -g) pandoc/latex:latest \
--defaults=./config/config.yaml --defaults=./config/pdf/config.yamlThis project is built on, or inspired by:
- Markdown
- Pandoc
- Edward Tufte
- Pandoc crossref
- Other Pandoc-based projects: