docs/quickstart.org
226 lines · 7028 bytes
15 symbols in this file
Two commandsWhat init createdAdapting it to org files you already haveSOURCE is the URL rootCommon layoutsOUTPUT can live inside the sourceWhere config and templates goA worked exampleWrite a pageControl the URLKeep something unfinished out of the buildChange the designAdd a blog indexBuild for realNext
Quick start
- Two commands
- Adapting it to org files you already have
- Write a page
- Change the design
- Add a blog index
- Build for real
- Next
Two commands
orgo init my-site
orgo serve my-site -o _site
Open 127.0.0.1:3000. Edit my-site/index.org in your editor, save, and the page reloads
on its own.
init writes only files that do not already exist, so running it inside a directory that
already has content is safe and additive.
What init created
my-site/
orgo.toml every setting, commented — all at their defaults but `theme`
index.org the home page
blog/first-post.org a post, to show the collection working
templates/
base.html the page layout — edit this
list.html the blog index
tags.html the tag index
feed.xml an RSS feed
Adapting it to org files you already have
You do not need init, a config file, or templates. Every command takes the same two
paths:
orgo serve <SOURCE> -o <OUTPUT>
SOURCE is the URL root
This is the one thing worth getting right, and it is not "the project directory" — it is
the directory whose contents should sit at the top of your site. A file at
SOURCE/blog/post.org is published at /blog/post.html.
So if your writing lives in a content/ subdirectory, point at content/, not at the
repository around it:
cd ~/my-site
orgo serve content -o _site # → /blog/post.html
Pointing one level too high still builds, which is what makes it worth saying out loud. It just builds the wrong site:
orgo serve . -o _site # → /content/blog/post.html
Every URL gains a /content/ prefix, and every non-org file in the repository —
README.md, build scripts, licence files — is copied into the output as a site asset.
If you see either symptom, you picked the directory above the one you meant.
Common layouts
| Your files | Command |
|---|---|
~/notes/*.org |
orgo serve ~/notes -o /tmp/notes-site |
my-site/content/**/*.org |
cd my-site && orgo serve content -o _site |
my-site/*.org at the top level |
cd my-site && orgo serve . -o _site |
| Org files scattered in a code repo | Do not. Copy or symlink the ones you publish into one directory. |
OUTPUT can live inside the source
orgo serve . -o _site is fine: the output directory is recognised and skipped, so
the build never copies its own output back into itself. Nothing dot-prefixed is published
either, so .git stays out of a site built from a repository root.
Where config and templates go
Both live in the source directory — SOURCE/orgo.toml and SOURCE/templates/ — and
neither is published. If you would rather keep the config elsewhere, name it:
orgo serve content -o _site --config config/orgo.toml
A worked example
A repository laid out as content/ (org files), theme/ (unrelated), build.py:
cd ~/my-site
# What is actually in there, before trusting anything with it.
orgo audit content
# Build it somewhere disposable and look.
orgo serve content -o /tmp/preview
# Happy with it? Build for real, failing on broken links.
orgo build content -o _site --strict
The audit reports which org constructs appear, how often, and whether each is supported — names, counts and line numbers only, never your text. See Auditing a corpus.
Nothing in your files has to change. With no config you get a complete site: a built-in layout, navigation across your top-level pages, and syntax highlighting.
Write a page
Any .org file under the source directory becomes a page at the matching path.
notes/rust/borrowing.org becomes notes/rust/borrowing.html.
#+TITLE: Borrowing
#+DATE: <2026-02-02 Mon>
#+FILETAGS: :rust:notes:
#+DESCRIPTION: How the borrow checker thinks about lifetimes.
An opening paragraph, which becomes the excerpt in listings when there is no
description.
* A heading
Ordinary org: *bold*, /italic/, ~code~, [[https://orgmode.org][links]], and lists.
#+BEGIN_SRC rust
fn main() {}
#+END_SRC
The keywords are all optional. #+TITLE: names the page, #+DATE: orders it in
listings, #+FILETAGS: groups it on tag pages, and #+DESCRIPTION: is its summary.
Control the URL
By default the filename decides the URL. #+SLUG: overrides it, which is how a
date-prefixed filename becomes a clean address:
#+TITLE: Borrowing
#+SLUG: borrowing-explained
2026-02-02-borrowing.org now publishes as borrowing-explained.html.
Keep something unfinished out of the build
#+DRAFT: t
The page is not written, and does not appear in listings or navigation. Preview it while
you work with --drafts:
orgo serve my-site -o _site --drafts
Change the design
Everything visual lives in templates/base.html. It is an ordinary
minijinja (Jinja2) template, and replacing it replaces the
whole layout:
<!DOCTYPE html>
<html lang="{{ site.language }}">
<head>
<meta charset="utf-8">
<title>{{ page.title }} — {{ site.title }}</title>
<link rel="stylesheet" href="{{ root }}style.css">
</head>
<body>
<nav>{% for item in nav %}<a href="{{ item.url }}">{{ item.title }}</a>{% endfor %}</nav>
<h1>{{ page.title }}</h1>
{{ body | safe }}
</body>
</html>
root is the ../ prefix back to the site root, so the same template works at any
depth. Any other file in the source directory — style.css, images, fonts — is copied to
the output untouched.
Editing a template rebuilds every page that uses it, so the browser reloads while you are still looking at it. The full list of variables is in Templates.
Add a blog index
Listing pages have no source file; they are declared in orgo.toml:
[[collections]]
source = "blog"
output = "blog/index.html"
template = "list.html"
title = "Blog"
sort = "date"
order = "desc"
nav = true
That is also how you get tag pages, pagination and an RSS feed — same mechanism, more settings. See Collections.
Build for real
orgo build my-site -o _site --strict
--strict turns broken internal links and parse diagnostics into a non-zero exit, which
is what you want in CI. Deployment is just copying _site somewhere; see
Deploying.
Next
- Command reference — every command and flag.
- Configuration — every setting in
orgo.toml. - Org support — exactly which org syntax is handled.