Section: Core Specification Version: 0.1
Assets are binary resources embedded within a Codex document. This includes images, fonts, and other files that are referenced by content blocks or presentation layers.
| Category | Directory | Purpose |
|---|---|---|
| Images | assets/images/ |
Photographs, diagrams, icons |
| Fonts | assets/fonts/ |
Typography resources |
| Embeds | assets/embeds/ |
Attached files (spreadsheets, data) |
assets/
├── images/
│ ├── index.json
│ ├── figure1.avif
│ ├── logo.png
│ └── diagram.svg
├── fonts/
│ ├── index.json
│ ├── roboto-regular.woff2
│ └── roboto-bold.woff2
└── embeds/
├── index.json
└── data.xlsx
Each asset category has an index file (index.json) that catalogs all assets:
{
"version": "0.1",
"assets": [
{
"id": "figure1",
"path": "figure1.avif",
"type": "image/avif",
"size": 45678,
"hash": "sha256:...",
"metadata": {...}
}
]
}| Field | Type | Required | Description |
|---|---|---|---|
id |
string | Yes | Unique identifier for referencing |
path |
string | Yes | File path relative to category directory |
type |
string | Yes | MIME type |
size |
integer | Yes | File size in bytes |
hash |
string | Yes | Content hash |
metadata |
object | No | Type-specific metadata |
Asset IDs:
- MUST be unique within their category
- SHOULD be URL-safe (alphanumeric, hyphens, underscores)
- SHOULD be human-readable when practical
| Format | MIME Type | Use Case | Compression |
|---|---|---|---|
| AVIF | image/avif |
Photos, general images | Best |
| WebP | image/webp |
Photos, general images | Good |
| PNG | image/png |
Lossless, transparency | Fair |
| JPEG | image/jpeg |
Photos (legacy) | Good |
| SVG | image/svg+xml |
Vector graphics | N/A |
Recommendation: Use AVIF for photographs and complex images, SVG for diagrams and icons.
{
"id": "figure1",
"path": "figure1.avif",
"type": "image/avif",
"size": 45678,
"hash": "sha256:...",
"metadata": {
"width": 1920,
"height": 1080,
"colorSpace": "sRGB",
"hasAlpha": false,
"dpi": 72
}
}| Field | Type | Description |
|---|---|---|
width |
integer | Width in pixels |
height |
integer | Height in pixels |
colorSpace |
string | Color space (sRGB, Display P3, etc.) |
hasAlpha |
boolean | Whether image has transparency |
dpi |
integer | Dots per inch (for print) |
For responsive images, multiple resolutions can be provided:
{
"id": "hero-image",
"path": "hero-image.avif",
"type": "image/avif",
"size": 125000,
"hash": "sha256:...",
"metadata": {
"width": 1920,
"height": 1080
},
"variants": [
{
"path": "hero-image-640.avif",
"width": 640,
"size": 25000
},
{
"path": "hero-image-1280.avif",
"width": 1280,
"size": 65000
}
]
}Variant integrity: Variants inherit the parent asset's hash algorithm. Implementations SHOULD compute and verify variant hashes using the same algorithm as the parent asset.
Variant selection: Renderers SHOULD select the variant closest to the display size. If displaying at 800px width, the 640px variant would be used (or the 1280px variant if the renderer prefers to scale down rather than up). If no variant is a good match, fall back to the full-resolution image.
Missing variants: If a variant file is missing from the archive, implementations MUST fall back to the full-resolution image. Missing variants SHOULD produce a warning but MUST NOT prevent the image from being displayed.
Content blocks reference images by path:
{
"type": "image",
"src": "assets/images/figure1.avif",
"alt": "System architecture diagram"
}| Format | MIME Type | Support |
|---|---|---|
| WOFF2 | font/woff2 |
Required |
| WOFF | font/woff |
Optional |
| TTF | font/ttf |
Optional |
| OTF | font/otf |
Optional |
Recommendation: Use WOFF2 for best compression and broad support.
{
"id": "roboto-regular",
"path": "roboto-regular.woff2",
"type": "font/woff2",
"size": 45000,
"hash": "sha256:...",
"metadata": {
"family": "Roboto",
"weight": 400,
"style": "normal",
"unicodeRange": "U+0000-00FF, U+0131, U+0152-0153"
}
}| Field | Type | Description |
|---|---|---|
family |
string | Font family name |
weight |
integer | Font weight (100-900) |
style |
string | Font style (normal, italic) |
unicodeRange |
string | Supported Unicode ranges |
Group related fonts:
{
"families": [
{
"name": "Roboto",
"fonts": [
{ "id": "roboto-regular", "weight": 400, "style": "normal" },
{ "id": "roboto-italic", "weight": 400, "style": "italic" },
{ "id": "roboto-bold", "weight": 700, "style": "normal" }
]
}
]
}Presentation layers reference fonts by family name:
{
"styles": {
"bodyText": {
"fontFamily": "Roboto, system-ui, sans-serif"
}
}
}For efficiency, fonts SHOULD be subsetted to include only used characters.
The metadata.unicodeRange field indicates the characters available.
Font embedding must comply with licensing terms. The index MAY include license information:
{
"id": "roboto-regular",
"path": "roboto-regular.woff2",
"license": {
"name": "Apache License 2.0",
"url": "https://www.apache.org/licenses/LICENSE-2.0"
}
}Embedded files are attachments that accompany the document but are not directly rendered (e.g., source data, supplementary materials).
{
"id": "source-data",
"path": "quarterly-data.xlsx",
"type": "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
"size": 125000,
"hash": "sha256:...",
"metadata": {
"filename": "Quarterly Financial Data.xlsx",
"description": "Source data for charts in this document",
"created": "2025-01-10T08:00:00Z"
}
}| Field | Type | Description |
|---|---|---|
filename |
string | Original filename (for display) |
description |
string | Human-readable description |
created |
string | Original file creation date |
Embedded files can be referenced from content using a paragraph block with a link mark pointing to the embedded file:
{
"type": "paragraph",
"children": [
{
"type": "text",
"value": "Download source data",
"marks": [
{
"type": "link",
"href": "assets/embeds/quarterly-data.xlsx",
"title": "Download source data"
}
]
}
]
}Already-compressed formats (AVIF, WebP, WOFF2) SHOULD be stored without additional ZIP compression:
ZIP entry: assets/images/photo.avif
Compression method: Store (0)
Uncompressed or less-compressed formats benefit from ZIP compression:
| Format | Recommended ZIP Compression |
|---|---|
| SVG | Zstandard or Deflate |
| PNG | Store (already compressed) |
| TTF/OTF | Zstandard or Deflate |
| XML/JSON | Zstandard or Deflate |
Each asset's hash MUST be verified when loading:
- Read asset file from archive
- Compute hash of file contents
- Compare with hash in index
- Reject on mismatch
Asset hashes use the same algorithm as document hashing (SHA-256 by default):
sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
By default, Codex documents SHOULD be self-contained. External references:
- MAY be allowed for non-critical assets
- MUST NOT be required for core content
- SHOULD include fallback content
{
"type": "image",
"src": "https://example.com/logo.png",
"external": true,
"fallback": "assets/images/logo-fallback.png",
"alt": "Company Logo"
}External references introduce risks:
- Privacy (tracking pixels)
- Availability (broken links)
- Integrity (content can change)
Implementations SHOULD:
- Warn users about external content
- Provide option to fetch and embed external resources
- Validate URLs against allowlists in sensitive contexts
| Asset Type | Recommendation |
|---|---|
| Photos | AVIF quality 60-80, max 2000px dimension |
| Icons | SVG preferred, or PNG with transparency |
| Fonts | WOFF2, subset to used characters |
| Documents | Consider compression or conversion |
Identical assets (same hash) SHOULD be stored only once:
{
"assets": [
{
"id": "logo-header",
"path": "logo.png",
"hash": "sha256:abc123..."
},
{
"id": "logo-footer",
"aliasOf": "logo-header"
}
]
}- All referenced assets exist in archive
- MIME types match file contents
- Hashes verify correctly
- Sizes match actual file sizes
- Images are valid and can be decoded
- Fonts are valid and contain declared glyphs
- Embedded files are not malicious
{
"version": "0.1",
"assets": [
{
"id": "cover",
"path": "cover.avif",
"type": "image/avif",
"size": 245000,
"hash": "sha256:a1b2c3...",
"metadata": {
"width": 1600,
"height": 900,
"colorSpace": "sRGB",
"hasAlpha": false,
"dpi": 150
}
},
{
"id": "architecture-diagram",
"path": "architecture.svg",
"type": "image/svg+xml",
"size": 12500,
"hash": "sha256:d4e5f6...",
"metadata": {
"width": 800,
"height": 600
}
}
]
}{
"version": "0.1",
"families": [
{
"name": "Source Serif Pro",
"fonts": [
{ "id": "source-serif-regular", "weight": 400, "style": "normal" },
{ "id": "source-serif-italic", "weight": 400, "style": "italic" },
{ "id": "source-serif-bold", "weight": 700, "style": "normal" }
]
}
],
"assets": [
{
"id": "source-serif-regular",
"path": "source-serif-pro-regular.woff2",
"type": "font/woff2",
"size": 35000,
"hash": "sha256:789abc...",
"metadata": {
"family": "Source Serif Pro",
"weight": 400,
"style": "normal",
"unicodeRange": "U+0000-00FF"
},
"license": {
"name": "SIL Open Font License 1.1",
"url": "https://scripts.sil.org/OFL"
}
}
]
}