agentleFS
MannyFlussMannyFluss/claude-skills/integrate-godot-frontend-scene/SKILL.md

integrate-godot-frontend-scene

Skill0 starsChanged 7 months agoMITView on GitHub

Interview the user about how to wire a drafted Godot frontend leaf scene into the existing game/renderer. Covers placement in the scene tree, backend event binding, animation/reactivity (tweens, state transitions), and lifecycle boundaries. Use after a frontend scene has been drafted and the user wants to make it live in the game. Generates integration patches, coordinator scripts, or renderer modifications.

The file

Show its rules and text

We split this skill into the rules it gives an agent

14 rules. About 0 are common, 8 are distinctive, and 6 are very specific to this project.

  • ≈0

    Common · estimate

    Many files like this have a rule of this kind.

  • ≈8

    Distinctive · estimate

    This author's own choices. Worth a look.

  • 6

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Very specific:

    Ask: "Which drafted frontend scene are we integrating?" The user names a folder under frontend/scenes/ or an existing scene like …

    line 13
  2. Distinctive:

    If the user's plan starts adding new backend logic, new game rules, or modifying core systems, STOP and redirect: "That belongs in a …

    line 26
  3. Very specific:

    Default recommendation: Start static in game_session.tscn if it's UI/HUD.

    line 48
  4. Very specific:

    Polled: Read in _process or on a timer.

    line 72
  5. Very specific:

    Default recommendation: Use create_tween() in the coordinator.

    line 102
  6. Distinctive:

    Never removed, only hidden/shown

    line 115
  7. Distinctive:

    Remove on backend event (e.g., enemy dies → health bar freed)

    line 117
  8. Distinctive:

    Remove on scene change

    line 118
  9. Distinctive:

    After the interview, generate one or more of these:

    line 161
  10. Very specific:

    If modifying an existing scene (e.g., adding the coordinator to game_session.tscn):

    line 198
  11. Distinctive:

    If the integration is just connecting existing signals:

    line 212
  12. Distinctive:

    Skill: Should the health drop instantly or animate down?

    line 270
  13. Distinctive:

    Skill: Should it flash red when damage is taken?

    line 278
  14. Very specific:

    Add HealthBarCoordinator to game_session.tscn

    line 295

≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

Integrate Godot Frontend Scene

Take a self-contained drafted frontend leaf scene and wire it into the live game. This skill is the counterpart to draft-a-godot-frontend-scene — drafting creates the widget; this makes it react and animate.

Invocation Flow

  1. Identify the target scene. Ask: "Which drafted frontend scene are we integrating?" The user names a folder under frontend/scenes/ or an existing scene like bluescreen_overlay.
  2. Interview the user on the five integration branches. See The Five Branches below. Each branch resolves dependencies before moving to the next.
  3. Generate integration artifacts. Depending on answers, produce one or more of:
    • A coordinator script (res://scenes/frontend/coordinators/<feature>_coordinator.gd)
    • Modifications to an existing renderer/session script (shown as a diff/patch)
    • A new parent .tscn that embeds the leaf scene + adds animation logic
    • Signal connection snippets
  4. Warn on scope creep. If the user's plan starts adding new backend logic, new game rules, or modifying core systems, STOP and redirect: "That belongs in a backend or game design task, not frontend integration."

The Five Branches

Walk through these in order. Do not skip branches. For each question, provide a recommended default based on existing project patterns.

Branch 1: Placement — Where does this live in the tree?

Q1.1: Which existing scene owns this?

  • game_session.tscn (top-level UI container, owns HUD, overlays, viewports)
  • game_renderer.tscn (world renderer inside the SubViewport, Node2D)
  • A new or existing sub-scene (e.g., hud_container, combat_overlay)
  • A standalone coordinator that gets added dynamically

Q1.2: Static or dynamic spawn?

  • Static: Embedded in a .tscn file, always present. Example: bluescreen_overlay is always in game_session.tscn but hidden.
  • Dynamic: Instantiated at runtime in response to an event. Example: damage numbers spawning on hit.

Q1.3: Is there a container/pool?

  • Single instance (one health bar per player)
  • Multiple instances (enemy health bars, floating text) — needs a pool or factory pattern

Default recommendation: Start static in game_session.tscn if it's UI/HUD. Start dynamic via coordinator if it's world-space (enemy bar, floating text).


Branch 2: Backend Binding — What data/events drive this?

Q2.1: What backend signal or state change triggers updates? Options in this project's architecture:

  • mutation_applied signal on BackendInstance
  • A specific BackendRead query (polling)
  • Direct signal from GameState or a subsystem
  • Custom signal emitted by another frontend coordinator

Q2.2: Which @export on the leaf scene should change? Map backend events to leaf scene properties:

Backend EventLeaf Scene @exportTransformation
player.hp_changedcurrent_healthDirect assignment
enemy.spawnedmax_healthRead from enemy data
game.score_updateddisplay_valueFormat with commas

Q2.3: Is the data polled or pushed?

  • Pushed: Connect a signal. Example: backend.mutate.mutation_applied.connect(_on_mutation).
  • Polled: Read in _process or on a timer. Example: _backend.read.player().health().

Default recommendation: Pushed via mutation_applied is the project's PHILOSOPHY #1. Only poll if the backend has no signal for that state.


Branch 3: Reactivity — How does it change over time?

Q3.1: Instant or animated transitions?

  • Instant: Direct assignment. leaf.current_health = new_value.
  • Animated: Tween the property over time. TweenFactory.tween_property(leaf, "current_health", old, new, 0.3).
  • Staged: Multi-step. Flash red, then tween health down, then shake.

Q3.2: What animation library/pattern? In this project, options are:

  • create_tween() directly in the coordinator
  • A shared TweenFactory or AnimationPool if one exists
  • Custom _process interpolation (discouraged, but possible)
  • Shader-driven animation (e.g., entry_progress uniform on a shader material)

Q3.3: What triggers animation cancellation?

  • Rapid successive events (damage spam) — kill old tween, start new?
  • State changes mid-animation (heal while damage tween running) — blend or snap?
  • Scene removal mid-animation — clean up tween to avoid orphaned references?

Q3.4: Does it react to layout changes?

  • Viewport resize → recalculate dynamic limits?
  • Parent container resize → reflow?
  • Camera zoom/position → update world-space position?

Default recommendation: Use create_tween() in the coordinator. Always kill stale tweens before starting new ones. Handle viewport resize via the existing get_tree().root.size_changed signal.


Branch 4: Scope & Lifecycle — When does it exist?

Q4.1: Spawn condition

  • On scene load (always there, maybe hidden)
  • On game start / round start
  • On specific backend event (e.g., level_up.offered)
  • On user input (e.g., open inventory)

Q4.2: Despawn/visibility condition

  • Never removed, only hidden/shown
  • Auto-remove after animation completes (e.g., floating damage text)
  • Remove on backend event (e.g., enemy dies → health bar freed)
  • Remove on scene change

Q4.3: Cleanup guarantees

  • Disconnect signals on removal?
  • Free tween references?
  • Return to object pool instead of queue_free()?

Q4.4: Can multiple instances coexist?

  • No (singleton overlay)
  • Yes, finite (2-3 buff icons)
  • Yes, unbounded (floating combat text — needs pooling)

Default recommendation: Static for UI, dynamic with queue_free() for transient world elements. Always disconnect signals in _exit_tree().


Branch 5: Edge Cases & Interactions

Q5.1: What happens if the backend data arrives before the frontend is ready?

  • Buffer the event and apply when ready?
  • Ignore until next signal?
  • Snap to current state on _ready()?

Q5.2: What happens if the leaf scene is missing?

  • Crash (fail fast — acceptable in dev)
  • Log error and skip (graceful degradation)
  • Spawn a placeholder

Q5.3: Does this block input or interact with other frontend?

  • Modal overlay (blocks clicks behind it)?
  • Non-interactive (pure display)?
  • Emits signals that OTHER coordinators consume?

Q5.4: Should this emit its own events?

  • Signal back to backend? (Usually no — frontend observes, does not command)
  • Signal to sibling coordinators? (e.g., damage_dealt → combat_text_spawner)

Default recommendation: On _ready(), snap to current backend state. Fail fast with push_error() if the leaf scene is missing from the expected node path. Frontend should never signal back to backend; use a coordinator-to-coordinator signal if siblings need to react.


Output Artifacts

After the interview, generate one or more of these:

A. Coordinator Script

A new .gd file that owns the leaf scene instance and manages its lifecycle:

class_name HealthBarCoordinator
extends Node

@export var leaf_scene: PackedScene
@export var target_node_path: NodePath

var _leaf: HealthBar
var _tween: Tween

func _ready() -> void:
    _leaf = leaf_scene.instantiate()
    get_node(target_node_path).add_child(_leaf)
    _sync_from_backend()
    Backend.instance.mutation_applied.connect(_on_mutation)

func _on_mutation(mutation: Mutation) -> void:
    if mutation is DamageMutation:
        _animate_health(mutation.new_hp, mutation.old_hp)

func _animate_health(new_val: float, old_val: float) -> void:
    if _tween and _tween.is_valid():
        _tween.kill()
    _tween = create_tween()
    _tween.tween_property(_leaf, "current_health", old_val, new_val, 0.3)

func _exit_tree() -> void:
    if _leaf:
        _leaf.queue_free()

B. Patch / Diff

If modifying an existing scene (e.g., adding the coordinator to game_session.tscn):

Show the user:

Add to scenes/frontend/game_session.gd:
  + const HEALTH_BAR_COORDINATOR = preload("...")
  + @onready var _health_bar = HEALTH_BAR_COORDINATOR.new()

Add to scenes/frontend/game_session.tscn node tree:
  + [node name="HealthBarCoordinator" type="Node" parent="."]
  +     script = ExtResource("health_bar_coordinator")

C. Signal Wiring Snippet

If the integration is just connecting existing signals:

# In your existing script (e.g., game_session.gd):
func _setup_health_bar() -> void:
    var bar = $HealthBar  # or instantiate dynamically
    backend.read.player().health_changed.connect(
        func(new, old): bar.current_health = new  # or tween
    )

Scope Guardrails

This skill is NOT for:

  • Modifying backend logic (core/, Backend, GameState)
  • Adding new game rules or mutations
  • Creating new frontend leaf scenes (use draft-a-godot-frontend-scene)
  • Designing new backend-to-backend signals

If the user asks for any of the above:

"That sounds like backend/game design work, not frontend integration. After that's implemented, come back and I'll wire the frontend to it."


Quick Reference

ConcernDefaultOverride When
PlacementStatic in game_sessionWorld-space or transient elements
Backend bindingmutation_applied signalNo signal exists for that state
Animationcreate_tween() in coordinatorShared tween factory exists
SpawnOn _ready()Event-driven (level up, enemy spawn)
DespawnHide, don't removeTransient world elements
Multi-instanceSingletonCombat text, enemy bars
ScopeFrontend only—

Example Session

User: Integrate the health bar I just drafted.

Skill: Which scene owns it — the HUD in game_session, or the world renderer?

User: HUD.

Skill: Static in the .tscn or spawned dynamically?

User: Static, always visible.

Skill: What backend data drives it?

User: Player health.

Skill: Is there a mutation_applied signal for damage/heal, or do we poll?

User: There's a DamageMutation and HealMutation.

Skill: Should the health drop instantly or animate down?

User: Animate down over 0.2s. If hit again while animating, snap to the new value and re-tween.

Skill: What about healing — same animation speed?

User: Yes.

Skill: Should it flash red when damage is taken?

User: Yes, briefly.

Skill: Where does that flash live — in the leaf scene or the coordinator?

User: Hmm... the leaf exposes flash_intensity as an export. Tween that.

Skill: Got it. What about scope — does this health bar ever go away?

User: No, it's always there.

Skill: Edge case: what if the player dies? Hide the bar or show 0?

User: Show 0.

Skill: Proposed integration:

  • Add HealthBarCoordinator to game_session.tscn
  • Connect mutation_applied → check for Damage/Heal → tween current_health and flash_intensity
  • On _ready(), snap to current player HP
  • On _exit_tree(), kill tween and disconnect

Confirm? [Y/n/details]

User: Yes.

Skill: → Generates scenes/frontend/coordinators/health_bar_coordinator.gd + patch instructions for game_session.tscn.

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.