Skip to main content

Manifest + Bible Source (b2_manifest)

This source pulls structured content from any HTTPS-reachable folder layout:

<base_url>/manifest.json ← index of entries
<base_url>/<slug>/bible_public.json ← the brief / data for that entry
<base_url>/<slug>/portrait.png (+ other assets, referenced inside the bible)

It's brand-agnostic — each source instance points at one bucket. Multiple brands can each have their own source pointing at their own bucket. The schema is permissive: typed fields are extracted into queryable columns, anything else is preserved in metadata for AI prompts.


When to use this source

Use it if you (or your team) already:

  • Publish a JSON "brief" file per entry to a public bucket / CDN
  • Want a stable, file-backed pipeline (vs database-backed like Supabase)
  • Need rich, structured content (multi-language, nested fields) rather than flat title+body

Other source types:

  • Supabase — content lives in a Postgres table you control
  • Notion — content lives in a Notion database
  • GitHub — README/markdown files in a repo

What you need before setting it up

1. A public-readable HTTPS host

Examples that work:

  • DigitalOcean Spaces with custom domain (e.g. cdn.amplicast.io)
  • Backblaze B2 public bucket
  • AWS S3 public bucket / CloudFront distribution
  • Any static-file host you control (your own CDN, GitHub Pages, etc.)

The base URL is whatever resolves your manifest. Examples:

https://cdn.example.com ← custom domain
https://my-bucket.nyc3.cdn.digitaloceanspaces.com ← raw DO Spaces CDN

v1 only supports public-read. Private buckets (with access keys) on the roadmap.

2. A manifest.json at the base URL

The manifest is the index — it tells Amplicast which entries exist. Place at <base_url>/manifest.json (or override with the manifest_path config).

Full-URL style (preferred, every asset address resolved up-front):

{
"version": "1.0",
"generated_at": "2026-05-26T19:41:45.836Z",
"character_count": 1,
"characters": [
{
"slug": "entry-001-v1",
"name": "Entry Name (V1)",
"display_name": "Display Name",
"tagline_en": "short EN tagline",
"tagline_de": "kurze DE tagline",
"published_at": "2026-05-24T15:05:57Z",
"updated_at": "2026-05-26T18:41:31Z",
"bible_url": "https://cdn.example.com/entry-001-v1/bible_public.json",
"portrait_url": "https://cdn.example.com/entry-001-v1/portrait.png",
"additional_portraits": [
"https://cdn.example.com/entry-001-v1/portrait-alt-2.png"
]
}
]
}

Placeholder-style (simpler, fewer fields):

{
"version": "1",
"entries": [
{
"slug": "spring-launch",
"updated_at": "2026-05-21T14:00:00Z"
}
]
}

Field reference:

FieldRequiredNotes
characters OR entries (array)one of themArray of objects. Either key name is accepted.
entry.slugrequiredUnique identifier; also the folder name where the bible lives
entry.bible_urloptionalFull URL to the bible JSON. If absent, falls back to <base>/<slug>/<bible_filename> (default bible.json).
entry.updated_atrecommendedStored in metadata.bible_updated_at so future incremental sync can detect changes
entry.display_name / entry.nameoptionalUsed as fallback for title if bible doesn't have one
entry.published_atoptionalUsed as fallback for publish date
entry.portrait_urloptionalUsed as fallback for featured image
entry.additional_portraits (array)optionalFolded into media list

3. A bible JSON file per entry

Per the manifest's bible_url (Tirida) or by convention at <base>/<slug>/<bible_filename>.

Rich-shape bible (multiple known fields → typed columns + structured RawContent summary):

{
"slug": "entry-001-v1",
"name": "Entry Name (V1)",
"display_name": "Display Name",
"tagline_en": "short EN tagline",
"tagline_de": "kurze DE tagline",
"vibe_personality_en": "<short paragraph: how this entry's personality reads in EN>",
"vibe_personality_de": "<short paragraph: how this entry's personality reads in DE>",
"vibe_core_traits": ["trait-1", "trait-2", "trait-3"],
"vibe_core_traits_de": ["eigenschaft-1", "eigenschaft-2", "eigenschaft-3"],
"vibe_surprise_facts": ["<surprising fact about this entry>"],
"vibe_surprise_facts_de": ["<überraschender Fakt über diesen Eintrag>"],
"tribe_id": "sample-tribe-id",
"tribe_display_name": "Sample Tribe / Group / Series",
"size_category": "<short size descriptor>",
"size_estimate_cm": 0,
"habitat_keywords": {
"climate": "<one-word climate>",
"terrain": "<one-word terrain>",
"signature_features": ["<feature 1>"]
},
"diet_signature_foods": ["<food 1>"],
"primary_color": "#000000",
"color_palette": [
{"hex": "#000000", "name": "Color Name", "part": "body", "role": "primary"}
],
"portrait_url": "https://cdn.example.com/entry-001-v1/portrait.png",
"additional_portraits": ["https://cdn.example.com/entry-001-v1/portrait-alt-2.png"],
"_meta": {
"version": "1.1",
"published_at": "2026-05-24T15:05:57Z",
"updated_at": "2026-05-26T18:41:31Z"
}
}

The bible can be any shape. The fields above are the ones Amplicast knows how to extract into typed columns. Everything else is preserved in metadata.bible for AI prompts to read.

Minimal-shape bible (just title + body + tags — no structured fields):

{
"slug": "spring-launch",
"title": "Spring Launch — Day 1",
"body": "Long-form copy used as raw content for AI transforms.",
"tags": ["launch", "spring"],
"brand": "examplebrand",
"assets": [
{ "path": "assets/hero.png", "role": "featured" },
{ "path": "assets/c1.png", "role": "carousel" }
],
"publish_at": "2026-05-25T09:00:00Z"
}

4. Asset files (portraits, scene cards, etc.)

Referenced from the bible by URL (Tirida) or relative path (placeholder). Asset URLs must be on a publicly-fetchable host. Relative paths in the placeholder assets[].path are resolved against <base>/<slug>/.


How bible fields map to a content item

Amplicast extracts specific fields into typed columns (so they're queryable), then stashes the entire bible in metadata.bible so AI transforms have access to everything else.

Item columnSource (first non-empty wins)
titlebible.display_name → bible.name → bible.title → manifest entry.display_name/name → slug
content_subtype (brand)bible.brand → source config default_brand
featured_imagebible.portrait_url → bible.featured_image → bible.featured_image_url → bible.cover_image → manifest entry.portrait_url
media_urlsbible.additional_portraits + bible.media_urls + bible.gallery + bible.assets[].path + manifest entry.additional_portraits (deduped; featured excluded)
tagsbible.tags + bible.vibe_core_traits + bible.tribe_display_name (deduped)
published_atbible.publish_at → bible.published_at → bible._meta.published_at → bible._meta.updated_at → manifest entry.published_at
raw_contentstructured markdown summary auto-built from the most common bible fields (taglines, personalities, traits, surprising facts, tribe, habitat, diet, color). See "RawContent generation" below.
metadata.biblethe entire bible JSON object — every field preserved for downstream prompts
metadata.manifest_entrythe matching manifest entry object — preserved
metadata.slugthe slug
metadata.bucket_base_urlsource's base URL
metadata.bible_updated_atmanifest entry's updated_at (for incremental change detection)
metadata.target_platformsbible.target_platforms → source config default_target_platforms

RawContent generation

The fetcher builds a structured markdown summary from common bible fields. This is what the AI sees during caption / copy transforms — so it's optimized for readability and to expose multilingual content (EN + DE) side by side.

Example output for a rich-shape bible (placeholders show the structure; real content is whatever the bible holds):

# Display Name
_(Entry Name (V1))_

**Tagline (EN):** <short EN tagline>
**Tagline (DE):** <kurze DE tagline>

## Personality (EN)
<short paragraph: how this entry reads in EN>

## Personality (DE)
<short paragraph: how this entry reads in DE>

**Core traits (EN):** trait-1, trait-2, trait-3
**Core traits (DE):** eigenschaft-1, eigenschaft-2, eigenschaft-3

## Surprising facts (EN)
- <surprising fact>

## Surprising facts (DE)
- <überraschender Fakt>

**Tribe:** Sample Tribe / Group / Series _(id: sample-tribe-id)_
**Size:** <descriptor> (~N cm)

## Habitat
- Climate: <one word>
- Terrain: <one word>
- <signature feature 1>

## Diet
- <food 1>

**Primary color:** #000000

If your bible has a plain body or description field, it's appended at the end. So the placeholder shape ({title, body, …}) also produces a sensible RawContent.


Source config

Settings you pass when creating the source (in the dashboard or via POST /api/sources):

Config keyTypeDefaultPurpose
base_urlstringrequiredHTTPS prefix that resolves to the manifest and asset files
manifest_pathstringmanifest.jsonRelative path to the manifest from base_url
bible_filenamestringbible.jsonDefault filename to look for at <base>/<slug>/<filename> when a manifest entry has no bible_url. (Some setups use bible_public.json to distinguish from a private/admin shape.)
default_brandstringnoneSet as content_subtype when the bible has no brand field
default_target_platformsarray of stringsnoneSet as metadata.target_platforms when the bible has no target_platforms. Use platform account_key strings (see Channels).
limitnumber100Max entries to fetch per sync (in case the manifest grows large)

Example source config

{
"base_url": "https://cdn.example.com",
"bible_filename": "bible_public.json",
"default_brand": "examplebrand",
"default_target_platforms": ["examplebrand_instagram", "examplebrand_tiktok", "examplebrand_youtube"]
}

How sync works

  1. Amplicast fetches <base_url>/<manifest_path> and parses the entries
  2. For each entry, calls entry.bible_url if present, else <base>/<slug>/<bible_filename>
  3. Bible content is mapped into a content item; the full bible survives in metadata.bible
  4. The content item flows through the normal pipeline (AI transforms → review → publish)

Failure handling:

  • Missing manifest.json → source goes into error state (check Sources page for the error message)
  • Missing or malformed bible for a single slug → that slug is skipped, others continue (logged)

Tips

  • Use updated_at on every manifest entry. Without it, Amplicast can't tell what changed and re-processes everything each sync.
  • Keep slugs URL-safe. They become folder names and may appear in URLs. Stick to [a-z0-9-].
  • Test with one entry first. Set publish mode = Draft on the source, push one bible, verify the resulting content item looks right, then iterate.
  • The bible is your source of truth. If you change a field, bump the manifest entry's updated_at to trigger a re-sync.
  • Bible can be ANY shape — only specific known field names get extracted into typed columns. Everything else still lands in metadata.bible for AI prompts to read.

Roadmap

  • Private buckets with access keys (B2 native + S3-compatible)
  • Per-platform copy variants inside the bible (caption_instagram, caption_tiktok, …)
  • Webhook-driven instant sync (instead of polling on the sync schedule)
  • Bulk re-sync UI
  • Scene-card / tagline-card auto-discovery from asset_count metadata