Fill out Step 5 (Shots/Prompts) for AIMVDashboard by compiling shot prompts, indexing them, and validating readiness in the shots page. Use when asked to complete or verify Step 5 prompt artifacts.
Complete prompt outputs so the Step 5 page has fully usable shot content for all target platforms. This step transforms canon data (characters, locations, style, cinematography) and shot intent into standalone, platform-specific prompts with A/B/C/D camera variations.
projects/<project-id>/bible/characters.json — character identity anchorsprojects/<project-id>/bible/locations.json — location identity anchorsprojects/<project-id>/bible/visual_style.json — style rules + negative promptprojects/<project-id>/bible/cinematography.json — camera rules + constraintsprojects/<project-id>/bible/shot_list.json — shot sequence with timing + intentprojects/<project-id>/reference/ — reference image libraries (for generation)projects/<project-id>/prompts/ organized by platform:
prompts/kling/SHOT_XX_option_A.txt through option_D.txtprompts/seedream/SHOT_XX_option_A.txt through option_C.txtprompts/nanobanana/SHOT_XX_option_A.txt (static frame prompts)prompts/suno/music_prompt.txt (music generation prompt)projects/<project-id>/prompts_index.json — compiled index of all promptsdefault if not specified.bible/characters.jsonbible/locations.jsonbible/visual_style.jsonbible/cinematography.jsonbible/shot_list.jsonprompts/<platform>/.npm run index -- --project <project-id>
shot_list.json appears in prompts_index.json.If the server is running, generate prompts via the agent endpoint:
POST /api/agents/prompt-runs?project=<id> — triggers prompt compilation for all shotsFor each shot, follow these steps:
shot = shot_list.shots[i]
characters = shot.characters.map(c => lookup in characters.json)
location = lookup shot.location.id in locations.json
timing = shot.timing
intent = shot.intent
cameraIntent = shot.cameraIntent
For each character in the shot:
Primary characters (full anchor):
[physicalCore.age] [physicalCore.build], [physicalCore.skinTone].
[faceSignature.structure], [faceSignature.eyes], [faceSignature.hair].
[costume.default.description] with [costume.default.signature].
Secondary characters (compact anchor):
[physicalCore.age] [physicalCore.build], [faceSignature.hair], [costume.default.signature].
[setting.type], [setting.scale], [setting.architecture].
[atmosphere.lighting]. [atmosphere.weather].
Colors: [atmosphere.colorPalette].
Visual anchors: [ALL items from visualAnchors array].
See Platform-Specific Best Practices below for each platform's structure.
[visual_style.negativePromptBase] + [platform-specific additions]
| Variation | Lens | Angle | Movement | Composition |
|---|---|---|---|---|
| A | Default (35mm anamorphic) | Eye-level | Shot's intended movement | Rule of thirds |
| B | 50mm standard | Low angle | Static hold or slower variant | Centered |
| C | 24mm wide | High angle | Different allowed movement | Leading lines |
| D | 85mm portrait | Eye-level | Tracking or orbit | Depth layering |
What NEVER varies across A/B/C/D:
Each file follows this header format:
=== SHOT {ID} - Variation {VAR} ({LABEL}) ===
Shot: {ID} | Section: {SECTION} | Time: {START}s-{END}s ({DURATION}s)
Version: 2026-02-08
Variation: {VAR}
--- {PLATFORM} PROMPT ---
{PROMPT BODY}
--- NEGATIVE PROMPT ---
{NEGATIVE PROMPT}
--- DIRECTOR NOTES ---
{intent.why}. Emotional beat: {intent.emotionalBeat}.
prompts/kling/SHOT_XX_option_[A-D].txtPrompt Structure:
Forbidden in Kling prompts:
cinematography.json.cameraMovement.forbiddenprompts/seedream/SHOT_XX_option_[A-C].txtPrompt Structure ("Create 2 Images"):
Create 2 Images.
Image 1: [Complete scene setup]
[Character full identity anchor]
[Location with all visual anchors]
[Action state A — the starting moment]
[Camera: framing, lens, composition]
[Lighting and atmosphere]
Image 2: Same [character description], same location.
[What changed: emotional shift, subtle pose change, light change]
[Emotional beat: "emotional weight has shifted from X to Y"]
[Same camera framing maintained]
SeedDream Rules:
Variation Strategy:
prompts/nanobanana/SHOT_XX_option_[A-D].txtRequired Elements:
Motion Verb Conversion Table:
| Motion Verb | Static Equivalent |
|---|---|
| walking | mid-stride pose, one foot forward |
| running | frozen sprint position, hair swept back |
| turning | angled stance, looking over shoulder |
| falling | suspended in air, body tilted |
| dancing | frozen dance pose, arms extended |
| reaching | arm extended toward object |
| sitting down | seated position |
| looking around | head slightly turned, eyes directed |
prompts/suno/music_prompt.txtStructure: Genre → Mood arc → Tempo/BPM → Instrumentation → Production style → Vocal style → Song structure
Forbidden terms: camera, lens, shot, frame, light, shadow, neon, scene, character. See Step 2 skill for the complete Musical Translation Guide.
Before saving prompts, verify for each file:
visual_style.json.negativePromptBase.project=default
node -e "
const fs = require('fs');
const base = 'projects/' + process.env.P + '/';
let ok = true;
// Check prompts_index.json
const idxPath = base + 'prompts_index.json';
if (!fs.existsSync(idxPath)) { console.error('Missing: prompts_index.json'); process.exit(1); }
try {
const idx = JSON.parse(fs.readFileSync(idxPath, 'utf8'));
if (!Array.isArray(idx.shots) || idx.shots.length === 0) {
console.error('No shots in prompts index'); ok = false;
} else {
console.log('Indexed shots: ' + idx.shots.length);
}
} catch (e) { console.error('Invalid index: ' + e.message); ok = false; }
// Check shot_list coverage
try {
const shots = JSON.parse(fs.readFileSync(base + 'bible/shot_list.json', 'utf8'));
const idx = JSON.parse(fs.readFileSync(idxPath, 'utf8'));
const indexedIds = new Set((idx.shots || []).map(s => s.id || s.shotId));
for (const shot of (shots.shots || [])) {
if (!indexedIds.has(shot.id)) {
console.error('Shot ' + shot.id + ' not in prompts index'); ok = false;
}
}
if (ok) console.log('All shots indexed: OK');
} catch (e) { console.error('Coverage check: ' + e.message); }
// Check prompt directories exist
const promptDir = base + 'prompts/';
if (fs.existsSync(promptDir)) {
const dirs = fs.readdirSync(promptDir).filter(f => fs.statSync(promptDir + f).isDirectory());
console.log('Prompt directories: ' + dirs.join(', '));
}
if (!ok) process.exit(1);
console.log('Step 5 complete.');
" P="$project"
npm run index -- --project <id> to rebuild the index.skills/_shared/references/universal-prompt-rules.md for platform constraints and identity anchor methodology.references/system-prompt-best-practices.md for detailed per-platform guidance.Step 5 is complete only when the prompts index is populated and every shot has prompt files for the target platforms.