GreenGale uses AT Protocol Lexicons to define its data schemas. The GreenGale namespace has two main record types: document and publication. These map closely to the standard.site document and publication collections, which are also available for dual-publishing but are optional for GreenGale use.
Collections
| Collection | Key | Description |
|-----------|-----|-------------|
| app.greengale.document | tid | Blog posts |
| app.greengale.publication | literal:self | Publication configuration (one per user) |
| site.standard.document | tid | Cross-platform blog posts (dual-published) |
| site.standard.publication | tid | Cross-platform publication metadata |
app.greengale.document
A markdown document with theme, image, SVG, and LaTeX support. This is the primary record type for blog posts, and the only record required to publish to GreenGale.
Required fields: content, url, path, title, publishedAt
{
"lexicon": 1,
"id": "app.greengale.document",
"defs": {
"contentRef": {
"type": "object",
"description": "Reference to external content via AT-URI. Used in site.standard.document content union.",
"required": ["uri"],
"properties": {
"uri": {
"type": "string",
"format": "at-uri",
"description": "AT-URI pointing to the full document content"
}
}
},
"main": {
"type": "record",
"description": "A markdown document with extended theme and LaTeX support.",
"key": "tid",
"record": {
"type": "object",
"required": ["content", "url", "path", "title", "publishedAt"],
"properties": {
"content": {
"type": "string",
"maxLength": 100000,
"description": "Markdown content of the document"
},
"url": {
"type": "string",
"format": "uri",
"maxLength": 2048,
"description": "Base publication URL (e.g., https://greengale.app)"
},
"path": {
"type": "string",
"maxLength": 500,
"description": "Document path relative to the publication URL (e.g., /handle/rkey)"
},
"title": {
"type": "string",
"maxLength": 1000,
"description": "Document title"
},
"subtitle": {
"type": "string",
"maxLength": 1000
},
"publishedAt": {
"type": "string",
"format": "datetime",
"description": "Publication timestamp"
},
"theme": {
"type": "ref",
"ref": "app.greengale.blog.defs#theme"
},
"visibility": {
"type": "string",
"enum": ["public", "url", "author"],
"default": "public",
"description": "Controls who can view this document"
},
"ogp": {
"type": "ref",
"ref": "app.greengale.blog.defs#ogp"
},
"blobs": {
"type": "array",
"items": {
"type": "ref",
"ref": "app.greengale.blog.defs#blobMetadata"
}
},
"tags": {
"type": "array",
"maxLength": 100,
"items": {
"type": "string",
"maxLength": 100,
"maxGraphemes": 50
},
"description": "Tags to categorize the document. Avoid prepending with hashtags."
}
}
}
}
}
}
Field Details
| Field | Type | Required | Description |
|-------|------|----------|-------------|
| content | string | Yes | Markdown body (max 100,000 chars) |
| url | uri | Yes | Base publication URL |
| path | string | Yes | Path relative to publication URL |
| title | string | Yes | Document title (max 1,000 chars) |
| subtitle | string | No | Subtitle (max 1,000 chars) |
| publishedAt | datetime | Yes | Publication timestamp |
| theme | ref | No | Theme preset or custom colors |
| visibility | enum | No | public (default), url, or author |
| ogp | ref | No | Open Graph image metadata |
| blobs | array | No | Embedded image references |
| latex | boolean | No | Legacy field (always enabled) |
| tags | array | No | Categorization tags |
contentRef
Used in site.standard.document's content union to reference the full GreenGale document by AT-URI, avoiding content duplication across collections.
Special Formatting
Bluesky Posts
Links to Bluesky posts are extracted from post content and converted to embeds on the frontend by default.
@-Mentions
The standard internet handle, an @ symbol followed by a domain name, when found in post content will be automatically converted on the frontend into a clickable link to that user's profile.
In addition to Markdown, GreenGale includes rendering for KaTeX and SVG.
Mathematical Expressions
GreenGale posts support KaTeX math rendering in the post content via remark-math and rehype-katex.
Inline math — wrap expressions with single dollar signs:
The quadratic formula is $x = \frac{-b \pm \sqrt{b^2 - 4ac}}{2a}$ for any quadratic equation.
Display math — wrap expressions with double dollar signs on their own lines:
$
\int_{-\infty}^{\infty} e^{-x^2} dx = \sqrt{\pi}
$
To render a literal dollar sign without triggering math mode, escape it with a backslash: \$.
See the KaTeX supported functions for a full reference of available commands.
SVG
Posts support SVG diagrams via fenced code blocks in the post content. Use the svg language tag for the code block: