agentsclimarketplace

Flame harness design

Skill tjdrhs90/flutter-flame-harness/skills/flame-harness-design

Phase 3 — define the Flutter design_tokens.dart spec (palette, typography, spacing), the game's art/visual concept, and the asset/audio sourcing plan.From its SKILL.md

Install
npx -y skills add tjdrhs90/flutter-flame-harness --skill flame-harness-design

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

SKILL.md

14.7 KB, as published. Nobody here has run it

flame-harness-design

Phase 3 of the flutter-flame-harness pipeline. Reads the latest PRD and config.md, then produces a design document that specifies the lib/ui/design_tokens.dart constants, the game's visual/art concept, and the asset and audio sourcing plan (including launcher icon and splash screen intent). Advances pipeline state to contract.

All file schemas (config.md, state.md, pipeline-log.md) and the phase transition table are defined in docs/harness-protocol.md — refer to that document as the single source of truth (§2 for state.md schema; §7 for the design → contract transition). Do not redefine schemas here.


Input

1. Read docs/harness/config.md

Extract:

KeyUse
app_ideaInforms visual tone (action vs. casual vs. puzzle)
app_nameUsed in splash screen heading and icon badge
app_slugUsed to derive asset directory naming conventions
default_languageThe user's conversation language; write copy samples in it

If config.md does not exist, abort with: flame-harness-design: docs/harness/config.md not found — run the orchestrator to bootstrap first.

2. Read the latest PRD

Find the most recent file matching docs/harness/plans/*-prd.md (sort descending by filename, take the first). If no PRD exists, abort with: flame-harness-design: no PRD found in docs/harness/plans/ — run flame-harness-plan first.

Extract from the PRD:

  • Genre & core mechanic — informs colour mood (e.g., dark sci-fi vs. bright hyper-casual)
  • Target age / tone — age rating and energy level of the visual style
  • Monetisation hook — AdMob placement type (banner at bottom → affects HUD spacing)
  • Win/lose conditions — informs what UI states need distinct visual treatment

Design tokens

Write a specification for lib/ui/design_tokens.dart that a generator phase Claude can implement verbatim as const Dart values. The spec must cover every sub-section below.

Colour palette

Derive a palette from the genre and tone. Use the following template — replace every <...> with a real hex colour and rationale:

Primary       <#RRGGBB>  — main brand / call-to-action colour
PrimaryDark   <#RRGGBB>  — pressed / shadow state of primary
Accent        <#RRGGBB>  — highlights, score text, power-up glows
Background    <#RRGGBB>  — game canvas and screen background
Surface       <#RRGGBB>  — card, dialog, overlay background
OnBackground  <#RRGGBB>  — text / icon colour on background
OnSurface     <#RRGGBB>  — text / icon colour on surface
Error         <#RRGGBB>  — error states, health loss flash

Rules:

  • Minimum contrast ratio of 4.5:1 for any text colour against its background.
  • Background and Primary must share the same temperature (both warm or both cool).
  • Accent must differ from Primary by at least 60° of hue to provide visual pop.
  • For dark-themed games (sci-fi, horror) set Background ≤ #333333; for bright hyper-casual games set Background ≥ #E0E0E0.

Typography scale

Specify font family, weight, and size for each role. If the game uses a custom font, name the Google Font and its import path; otherwise default to Roboto.

Display   family: <FontName>  weight: 900  size: 48 sp  — game title on main menu
Heading1  family: <FontName>  weight: 700  size: 32 sp  — screen headings
Heading2  family: <FontName>  weight: 700  size: 24 sp  — section headings, score
Body      family: <FontName>  weight: 400  size: 16 sp  — general UI text
Caption   family: <FontName>  weight: 400  size: 12 sp  — labels, tooltips
Button    family: <FontName>  weight: 600  size: 18 sp  — primary buttons
HUD       family: <FontName>  weight: 700  size: 20 sp  — in-game HUD counters

Use sp (Flutter TextScaler-aware) for all sizes. Game HUD text should use fontFeatures: [FontFeature.tabularFigures()] for score counters.

Spacing scale

Define a base unit and derive the full spacing scale. Typical base is 4 dp:

xs:   4 dp   — tight padding (icon labels)
sm:   8 dp   — inner card padding
md:  16 dp   — standard screen margin
lg:  24 dp   — section gap
xl:  32 dp   — screen top/bottom padding
xxl: 48 dp   — hero area padding

All layout constants in design_tokens.dart use these named values — no raw numbers in UI code. Spacing values are applied as const double fields.

Also define minTapTarget = 48.0 (dp) — every menu/overlay button must be at least this size (accessibility gate R10; pairs with the 4.5:1 contrast rule above).

Radius and elevation

radiusSm:   4 dp   — chip, small badge
radiusMd:   8 dp   — card, dialog
radiusLg:  16 dp   — bottom sheet, hero card
radiusFull: 999 dp — pill buttons

elevationSurface:  2 dp
elevationDialog:   8 dp
elevationFab:     12 dp

design_tokens.dart file template

The generator must emit a file with this exact structure:

// lib/ui/design_tokens.dart
// AUTO-GENERATED by flame-harness-design — do not edit manually.
// See docs/harness/plans/<date>-design.md for rationale.

import 'package:flutter/material.dart';

abstract class DesignTokens {
  // --- Colours ---
  static const Color primary       = Color(0xFF______);
  static const Color primaryDark   = Color(0xFF______);
  static const Color accent        = Color(0xFF______);
  static const Color background    = Color(0xFF______);
  static const Color surface       = Color(0xFF______);
  static const Color onBackground  = Color(0xFF______);
  static const Color onSurface     = Color(0xFF______);
  static const Color error         = Color(0xFF______);

  // --- Spacing ---
  static const double spaceXs  =  4;
  static const double spaceSm  =  8;
  static const double spaceMd  = 16;
  static const double spaceLg  = 24;
  static const double spaceXl  = 32;
  static const double spaceXxl = 48;

  // --- Radius ---
  static const double radiusSm   =   4;
  static const double radiusMd   =   8;
  static const double radiusLg   =  16;
  static const double radiusFull = 999;

  // --- Elevation ---
  static const double elevationSurface = 2;
  static const double elevationDialog  = 8;
  static const double elevationFab     = 12;

  // --- Typography helpers ---
  static const String fontFamily = '______';
}

Fill every ______ from the palette and typography spec written above.


Visual concept

Art direction

Describe the overall visual style in 3–5 sentences covering:

  1. Art style — pixel art / vector flat / hand-drawn / 3-D rendered sprites
  2. Colour mood — how the palette reinforces the genre's emotional tone
  3. World / environment — background theme (city, space, forest, dungeon, etc.)
  4. Character / enemy design — silhouette language (cute rounded vs. angular menacing)
  5. UI chrome style — whether overlays feel like HUD panels, storybook pages, arcade bezels, etc.

The description must be concrete enough that a sprite artist (or an AI image prompt) could reproduce the style without further guidance.

Sprite list (MVP)

List every sprite needed for the MVP core loop. For each sprite, specify:

SpriteDimensions (dp)FramesSource
Player idle64×644<see Asset plan below>
Player run64×648—
Enemy A48×484—
Background layer 1screen width × 2561—
............

Dimensions are in dp at 1× scale; the asset pipeline should export at 1×, 2×, and 3×.

Overlay and HUD layout

Describe the layout of each Flutter overlay:

  • Main menu — what elements are visible and their rough positions
  • In-game HUD — score, lives/health, pause button placement
  • Pause overlay — resume, restart, settings
  • Game-over screen — score, best score, restart, AdMob rewarded-ad revival button
  • Settings screen — BGM toggle, SFX toggle, language toggle

Each description maps directly to a Flutter widget in lib/screens/ or lib/ui/.


Asset/audio plan

Defaults the generator can always satisfy with no sourcing: audio = code-synthesized (tool/build_audio.dart → WAV); visuals = code-drawn (CustomPainter/Flame shapes from the palette). Specify sprite art below only if the concept needs it — choose CC0 pack or AI; the generator cleans sourced art's background with tool/strip_bg.dart. The harness never depends on art that isn't sourced, so a game can ship fully code-drawn.

Sprite and image assets

State for each visual asset whether it will be:

StrategyWhen to use
Free pack (itch.io / OpenGameArt / Kenney.nl)Hyper-casual games, generic shapes
AI-generated (Midjourney / DALL-E prompt)Custom style with specific prompt given
Custom drawnUnique brand-critical characters

For every free pack named, provide the pack URL and its license (CC0, CC-BY, etc.). For AI-generated assets, write the exact prompt template to use (substituting <genre> and <style> from the art direction above).

Assets must be declared in pubspec.yaml under flutter: assets:. Provide the directory entry (e.g., assets/images/) not individual file names — so that adding sprites does not require pubspec.yaml edits.

Audio assets

SoundTypeSourceLicense
Background musicloop (60–90 s)<free pack URL or AI prompt><license>
Jump / tap SFXone-shot (< 1 s)——
Hit / damage SFXone-shot——
Level completejingle (3–5 s)——
Game oversting (2–4 s)——

Recommended free sources: freesound.org (CC0 filter), opengameart.org audio section, itch.io free audio packs.

Audio files go in assets/audio/. Add assets/audio/ as a top-level assets entry in pubspec.yaml.

Package: flame_audio (wraps audioplayers). BGM uses FlameAudio.bgm.play(); frequent SFX use an AudioPool (see the Audio patterns in docs/game-gotchas.md).

Audio plan requirements (per docs/game-gotchas.md):

  • iOS format: bundle WAV (22 kHz mono 16-bit). iOS does not reliably play OGG — convert OGG/MP3 with ffmpeg -i in.ogg -ac 1 -ar 22050 -sample_fmt s16 out.wav.
  • Volume caps: specify safe per-channel caps (e.g. BGM ≤ 0.2, SFX ≤ 0.7) that become the GameConfig defaults; the user slider is a fraction of the cap.

flutter_launcher_icons

Branding art source: by default the generator draws the icon/splash from a shared code painter (tool/gen_icon.dart, design-token colors); choose AI-generated art here instead if the concept warrants it. Either way the generator (§5c.9) runs flutter_launcher_icons / flutter_native_splash and sets the localized app display name — design only specifies intent.

Specify the icon intent so the generator can configure flutter_launcher_icons:

# pubspec.yaml excerpt (dev_dependencies)
flutter_launcher_icons:
  android: true
  ios: true
  remove_alpha_ios: true
  image_path: "assets/icons/icon.png"                    # 1024×1024, no alpha (iOS + legacy)
  adaptive_icon_background: "<hex colour>"               # solid, opaque
  adaptive_icon_foreground: "assets/icons/icon-fg.png"   # safe-zone padded (NOT full-bleed)
  adaptive_icon_monochrome: "assets/icons/icon-mono.png" # Android 13+ themed icon
  min_sdk_android: 21
  web:
    generate: false

The icon must:

  • Be 1024×1024 pixels, PNG format; iOS icon.png is opaque (no alpha).
  • Follow the app's art direction (character portrait or logo on the Primary background).
  • Android adaptive foreground (icon-fg.png): the motif must sit inside the safe zone — the 108dp canvas is masked to ≤72dp and only the centre ~66dp is guaranteed unclipped, so keep ~25% padding on every side. Reusing the full-bleed icon.png here makes the icon look cropped/"zoomed" on Android. Background is a solid colour (Primary/Background), not an image.
  • Android themed icon (icon-mono.png): a single-colour (white-on-transparent) silhouette in the same safe zone; Android 13+ tints it to the user's theme. Without it the icon looks out of place among themed icons (Google Play increasingly expects one).

flutter_native_splash

Specify the splash screen intent for flutter_native_splash:

# pubspec.yaml excerpt
flutter_native_splash:
  color: "<Background hex>"          # matches DesignTokens.background
  image: assets/images/splash.png    # centred logo/character, 288×288 px recommended
  android_12:
    color: "<Background hex>"
    image: assets/images/splash.png
    icon_background_color: "<Primary hex>"
  ios: true
  android: true
  web: false

The splash image must:

  • Be 288×288 pixels, PNG with transparent background.
  • Show the app logo or the main character on a transparent field.
  • Feel consistent with the main menu's visual style.

Output

1. Write the design document

Create docs/harness/plans/<YYYY-MM-DD>-design.md (use today's UTC date).

If docs/harness/plans/ does not exist, create it before writing.

The document must include all of the following sections (downstream validators grep for these headings):

  • ## Design tokens — with palette table, typography scale, spacing scale
  • ## Visual concept — with art direction, sprite list, overlay/HUD layout
  • ## Asset/audio plan — with sprite sourcing table, audio table, flutter_launcher_icons config, flutter_native_splash config

Fill every section from the PRD and config.md; do not leave placeholder text.

2. Update state.md

Update docs/harness/state.md per docs/harness-protocol.md §2 and the transition rule in §7 (design → contract). Per §7 rule 2, a skill that completes successfully and advances the pipeline sets status: running together with current_phase and next_role in the same atomic write:

status: running
current_phase: design
next_role: contract
updated_at: "<ISO-8601 UTC now>"

Leave all other keys unchanged. Use Edit for a targeted update.

3. Append to pipeline-log.md

Append one row to docs/harness/pipeline-log.md per docs/harness-protocol.md §6:

| <ISO-8601 UTC now> | complete | design | design_tokens spec written; next: contract |

Error handling

  • If the PRD is missing or empty, abort with a clear message and set state.md to status: paused, pause_reason: manual_action.
  • If config.md cannot be read, abort immediately (do not write partial output).
  • If the genre or tone cannot be determined from the PRD, choose a neutral palette (dark background #1A1A2E, bright accent #E94560) and note the assumption in the design document under a ## Assumptions heading.

Keep looking

Skills are one crate of 627,801. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.