Complete reference for Doco shortcodes, Markdown styling, and how to prompt Claude to write well-formatted documents
When asking Claude to write or convert documents for Doco, paste the following instruction block into your prompt. This teaches Claude all available formatting tools so it produces rich, well-structured pages on the first try.
You are writing a Markdown document for a Hugo documentation site called Doco. The site supports standard GitHub-Flavored Markdown plus the following custom shortcodes. Use them liberally to make the document scannable, visually structured, and easy to navigate.
Hints — colored callout boxes. Use for tips, warnings, and critical notes.
Tip or note content here.
Caution or caveat content here.
Critical warning or breaking change here.
Details — collapsible sections. Use for supplementary info, FAQs, or lengthy content that shouldn’t clutter the main flow.
Click to expand
Hidden content here. Supports full Markdown.
Tabs — switchable panels. Use when showing the same concept across platforms, languages, or config formats.
Content for first tab.
Content for second tab.
Columns — side-by-side layout (stacks on mobile). Use for comparisons, before/after, or splitting related content.
Left content.
Right content.
Style guidelines:
##) for major sections and h3 (###) for subsections — these appear in the sidebar TOCColored callout boxes with a left border. Three variants based on severity.
Hints support full Markdown inside — paragraphs, lists, code, links, bold, everything:
Environment variables must be set before running the server:
DATABASE_URL — connection string for PostgresSECRET_KEY — used for session signingDEBUG — set to true in development onlyexport DATABASE_URL="postgres://localhost:5432/myapp"
export SECRET_KEY="change-me"
See the configuration docs for the full list.
Deprecation notice: The v1/auth endpoint will be removed in the next major release.
| Old endpoint | New endpoint | Migration |
|---|---|---|
POST /v1/auth/login | POST /v2/session | Update path + body format |
GET /v1/auth/me | GET /v2/user/profile | Update path only |
This action is irreversible. Running DROP TABLE will permanently delete all data in the table. Always create a backup first:
pg_dump -t my_table mydb > backup.sql
Collapsible sections using the HTML <details> element. The title goes in quotes after the shortcode name.
Great for FAQs:
Doco uses client-side SHA-256 hash comparison. Passwords are never stored in plaintext — only their hashes appear in the front matter. The protect.js script compares the user’s input against the hash using the Web Crypto API.
Unlock state is cached in sessionStorage, so users only enter the password once per browser session.
assets/js/protect.js.Passwords aren’t stored anywhere — only hashes. If you lose the password, generate a new hash and update the _index.md front matter:
printf '%s' 'new-password' | shasum -a 256 | cut -d' ' -f1
Replace the passwordHash value in both the cascade.params and params blocks.
Great for troubleshooting:
This usually means a layout file is missing or misnamed. Check that:
layouts/_default/ or layouts/partials/# List all layout files to verify
find layouts -type f -name "*.html"
Pagefind runs as a post-build step. If search isn’t working:
public/pagefind/ was created before the upload stepdata-pagefind-body is present on your content divsIn local dev (hugo server), search won’t return results — that’s expected. To test locally, run:
mise exec -- hugo && npx -y pagefind --site public --serve
Switchable tabbed panels. Wrap tab panels inside a tabs container. Each tab gets a name in quotes.
Platform-specific instructions — the most common use case:
Install with Homebrew:
brew install hugo
Verify the installation:
hugo version
Install with your package manager:
# Ubuntu/Debian
sudo apt install hugo
# Arch
sudo pacman -S hugo
# Snap (any distro)
sudo snap install hugo
Install with Chocolatey or Scoop:
# Chocolatey
choco install hugo-extended
# Scoop
scoop install hugo-extended
Language/framework comparisons:
import hashlib
password = "my-secret"
hash = hashlib.sha256(password.encode()).hexdigest()
print(hash)
const encoder = new TextEncoder();
const data = encoder.encode("my-secret");
const hash = await crypto.subtle.digest("SHA-256", data);
const hex = Array.from(new Uint8Array(hash))
.map(b => b.toString(16).padStart(2, "0"))
.join("");
console.log(hex);
printf '%s' 'my-secret' | shasum -a 256 | cut -d' ' -f1
Configuration format comparisons:
baseURL = "https://doco.example.com"
title = "My Docs"
[params]
masterPasswordHash = "abc123..."
[markup.goldmark.renderer]
unsafe = true
[markup.tableOfContents]
startLevel = 2
endLevel = 3
baseURL: "https://doco.example.com"
title: "My Docs"
params:
masterPasswordHash: "abc123..."
markup:
goldmark:
renderer:
unsafe: true
tableOfContents:
startLevel: 2
endLevel: 3
{
"baseURL": "https://doco.example.com",
"title": "My Docs",
"params": {
"masterPasswordHash": "abc123..."
},
"markup": {
"goldmark": {
"renderer": { "unsafe": true }
},
"tableOfContents": {
"startLevel": 2,
"endLevel": 3
}
}
}
API response examples:
{
"status": 200,
"data": {
"id": "usr_abc123",
"email": "user@example.com",
"role": "admin"
}
}
{
"status": 401,
"error": {
"code": "UNAUTHORIZED",
"message": "Invalid or expired token"
}
}
Responsive multi-column grid. Columns sit side-by-side on desktop and stack vertically on mobile.
Two columns — comparisons, pros/cons, before/after:
Three columns — steps, features, or categories:
Create a new folder under content/ with an _index.md that sets up the project and password cascade.
Add .md files to the folder. Use shortcodes, headings, code blocks, and tables to structure the content.
Push to main. GitHub Actions builds, indexes for search, and deploys to Pages automatically.
Columns with mixed content:
Endpoint
POST /api/v2/documents
Headers
| Header | Value |
|---|---|
Authorization | Bearer <token> |
Content-Type | application/json |
Request body
{
"title": "My Document",
"content": "# Hello\n\nWorld.",
"tags": ["guide", "v2"]
}
content field accepts raw Markdown.Shortcodes nest freely. Here are patterns that work well together.
CREATE TABLE users (
id SERIAL PRIMARY KEY,
email VARCHAR(255) NOT NULL UNIQUE,
name VARCHAR(255),
created_at TIMESTAMP DEFAULT NOW()
);
CREATE INDEX idx_users_email ON users(email);
DROP INDEX IF EXISTS idx_users_email;
DROP TABLE IF EXISTS users;
cd frontend
npm install
npm run dev
Runs on http://localhost:5173
cd backend
go run ./cmd/server
# or with live reload
air
Runs on http://localhost:8080
This is what a well-structured feature doc looks like using all available tools:
Webhooks allow your application to receive real-time notifications when events occur. Instead of polling the API, you register a URL and we send POST requests to it.
Register a webhook endpoint in your dashboard or via the API:
curl -X POST https://api.example.com/v2/webhooks \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"url": "https://yourapp.com/hooks/incoming",
"events": ["document.created", "document.updated"]
}'
200 status within 5 seconds or the delivery will be retried.Every webhook delivery includes a JSON body:
{
"event": "document.created",
"timestamp": "2026-02-18T12:00:00Z",
"data": {
"id": "doc_xyz",
"title": "New Document",
"created_by": "usr_abc"
}
}
| Field | Type | Description |
|---|---|---|
event | string | The event type that triggered the webhook |
timestamp | string | ISO 8601 timestamp of the event |
data | object | Event-specific payload |
All deliveries include an X-Signature-256 header. Verify it to ensure the request came from us:
import hmac, hashlib
def verify_signature(payload, signature, secret):
expected = hmac.new(
secret.encode(),
payload,
hashlib.sha256
).hexdigest()
return hmac.compare_digest(f"sha256={expected}", signature)
| Event | Trigger |
|---|---|
document.created | A new document is created |
document.updated | A document’s content or metadata changes |
document.deleted | A document is permanently deleted |
user.invited | A new user is invited to the workspace |
user.removed | A user is removed from the workspace |
Failed deliveries are retried with exponential backoff:
| Attempt | Delay |
|---|---|
| 1st retry | 1 minute |
| 2nd retry | 5 minutes |
| 3rd retry | 30 minutes |
| 4th retry | 2 hours |
| 5th retry | 12 hours |
After 5 failed attempts, the webhook is disabled and you’ll receive an email notification.
Beyond shortcodes, these standard Markdown features are all styled and ready to use.
| Feature | Status | Notes |
|---|---|---|
| Hints | Stable | Three variants: info, warning, danger |
| Details | Stable | Collapsible with animated arrow |
| Tabs | Stable | Auto-wires click handlers via JS |
| Columns | Stable | Responsive grid, stacks on mobile |
| Search | Stable | Pagefind, indexed at build time |
Inline code like variable_name and fenced blocks with syntax highlighting:
func main() {
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Hello, Doco!")
})
log.Fatal(http.ListenAndServe(":8080", nil))
}
Ordered and unordered, including nested:
Blockquotes still work for attributable quotes or cited material. For callouts, prefer hints instead — they’re more visually distinct.
Images are supported with standard Markdown syntax and render with rounded corners:

Use --- to create visual section breaks between major topics (as seen throughout this page).