Extras
Reference for Extras, ExtraBlock, and ExtraCharacterSheet — covers, character sheets, bonus art, interviews, and gated bonus content.
The optional top-level extras section holds bonus content around the story itself: covers, character sheets, author information and interviews, bonus/fan art, and behind-the-scenes material. Extras can be opened from hotspots via the openExtras action, listed in the player UI, and gated behind a paywall.
Extras
Defined as $defs/Extras. All properties are optional; single blocks vs. arrays as noted:
| Property | Type | Description |
|---|---|---|
cover | ExtraBlock | The work's cover presentation. |
alt_cover | ExtraBlock or ExtraBlock[] | One alternate cover, or a non-empty array of them (array form added within 1.6.0). |
character_sheets | ExtraCharacterSheet[] | Character sheets, each linked to one or more characters. |
author_info | ExtraBlock | About the author(s). |
author_interviews | ExtraBlock[] | Interview blocks. |
bonus_art | ExtraBlock[] | Bonus artwork. |
fan_art | ExtraBlock[] | Fan artwork. |
behind_the_scenes | ExtraBlock[] | Making-of material. |
Read alt_cover as "one or many": exporters write the single-object form when there is exactly one alternate cover and an array when there are several. @panelwave/player accepts both from the release after 1.2.0 (not yet published at the time of writing); 1.2.0 and earlier show only the single-object form.
ExtraBlock
Defined as $defs/ExtraBlock — the generic bonus-content unit. All properties are optional.
| Property | Type | Default | Description |
|---|---|---|---|
id | Identifier | — | Block ID (referenced by openExtras hotspot actions). |
title | LocalizedString | — | Block title. |
text | LocalizedString | — | Body text. |
images | array | — | Image entries: { "assetId": Identifier, "caption": LocalizedString }. |
audio | AudioTrack[] | — | Attached audio — see Audio. |
video | VideoLayer[] | — | Attached video — see Video. |
shareable | boolean | true | Whether the block may be shared. |
gated | boolean | false | Whether the block sits behind a paywall/entitlement. |
contentType | enum | — | Primary media type: image, video, audio, pdf, text. |
url | string | — | Direct URL for the content (alternative to catalog assets). |
thumbnail | string | — | Thumbnail URL. |
width | integer ≥ 0 | — | Media width in pixels. |
height | integer ≥ 0 | — | Media height in pixels. |
durationMs | number ≥ 0 | — | Media duration in milliseconds. |
mimeType | string | — | MIME type of the content. |
downloadable | boolean | false | Whether readers may download the content. |
requiredTier | string | — | Subscription tier required to view (used with gated). |
ExtraBlock is intentionally an open object — the schema does not set additionalProperties: false here, so tools may attach additional fields. ExtraCharacterSheet, by contrast, is closed (unevaluatedProperties: false), but since format 1.7 both accept x- extension fields (^x- pattern properties).
Gating semantics
Two fields cooperate with monetization:
gated: truemarks the block as locked content; pair it with aPaywallRuleof scopeextraswhoserefIdis the block'sid(see Paywall).requiredTiernames the subscription tier that unlocks it.
ExtraCharacterSheet
Defined as $defs/ExtraCharacterSheet — an ExtraBlock plus a required character link:
| Property | Type | Required | Description |
|---|---|---|---|
(all ExtraBlock properties) | — | — | Inherited via allOf. |
characterId | Identifier | One of the two | The character from meta.characters this sheet belongs to. |
characterIds | Identifier[] (unique, at least one) | One of the two | All characters on an ensemble sheet, in display order (added within 1.6.0). |
At least one of characterId and characterIds is required. When characterIds is present it is the authoritative list; exporters also keep characterId set to its first entry, so consumers that only read the single id still find a character.
Unlike the base block, no properties beyond ExtraBlock + characterId / characterIds are allowed.
Example
{
"extras": {
"cover": {
"id": "ex-cover",
"title": { "en-US": "Cover", "de-DE": "Umschlag" },
"images": [
{
"assetId": "img-cover",
"caption": { "en-US": "City Noir cover", "de-DE": "Stadt Noir Umschlag" }
}
],
"shareable": true,
"gated": false
},
"character_sheets": [
{
"id": "ex-sheet-mira",
"characterId": "char-mira",
"title": { "en-US": "Mira — Character Sheet" },
"text": { "en-US": "Early concept notes and turnarounds for Mira." },
"images": [
{ "assetId": "img-mira-turnaround", "caption": { "en-US": "Turnaround" } }
],
"gated": true,
"requiredTier": "premium"
}
],
"behind_the_scenes": [
{
"id": "ex-bts-inks",
"title": { "en-US": "Inking process" },
"contentType": "video",
"url": "https://cdn.example.com/extras/inking-timelapse.mp4",
"thumbnail": "https://cdn.example.com/extras/inking-thumb.jpg",
"mimeType": "video/mp4",
"durationMs": 120000,
"downloadable": false,
"gated": true
}
]
}
}
Related pages
- Paywall — gating extras with
scope: "extras"rules - Hotspots — the
openExtrasaction - Meta — characters referenced by
characterId/characterIds - CMS Extras — authoring extras in the CMS