7-Day Ren'Py Steam Build Label and Asset Freeze Challenge Before Visual Novel Fest Upload - 2026
Your writer ships a script patch Tuesday. A CG file renames from scene03_happy.png to ch03_smile.png. Wednesday playtesters load the Steam demo and chapter two restarts—or saves refuse to load with a silent rollback to the title screen.
H2 2026 visual-novel and dating-sim fest cycles promote weekly builds. Ren'Py teams discover that build.classification, label renames, and bundled asset moves break persistent data faster than action games break physics. This Challenges & Community Hooks sprint runs seven weekday gates so producers can promote a fest branch without mid-week narrative chaos.
Non-repetition note: Recent passes shipped GDevelop save-path freeze, LUFS trailer tools, and engine export tutorials—this is the first Ren'Py build-label and asset freeze URL, not another Steam metadata parity checklist.
Why this matters now (May 2026)
- Visual novel fest density — October-adjacent VN festivals and Steam Next Fest slots reward short, polished demos with reliable saves across reinstalls.
build.classificationdrift — Debug builds promoted to public depots leave console traces and wrongconfig.versionstrings partners screenshot.- Mid-fest script patches — Writers fix typos by renaming labels; without a freeze map,
persistent.chapterpoints at removed code paths. - Asset bundle churn — Renaming
images/without updatingimagestatements invalidates saves that store file hashes or label ids. - Evidence pairing — BUILD_RECEIPT and Wednesday demo smoke need a
renpy_freeze_receipt_v1.jsonbefore branch promotion.
Direct answer: One gate per weekday; artifacts under release-evidence/renpy/freeze-week/; no fest promotion until Gate 7 shows freeze_pass: true.
Who this is for
- 1–4 person teams on Ren'Py 8.x shipping a Windows Steam VN or dating-sim demo
- Writers who patch
.rpyfiles during fest week without a label freeze list - Producers promoting Steam branches without a
build_labelon the title screen - Studios that already ran GDevelop or Construct freezes—same evidence culture, Ren'Py-specific surfaces
Time: ~40–55 minutes per weekday (~6 hours total). Weekends: review and read-aloud only.
Before you start — readiness checklist
- [ ]
release-evidence/renpy/folder exists - [ ]
config.versionandbuild.namedocumented for freeze week - [ ] Title screen shows
build_labelmatching BUILD_RECEIPT - [ ] One Windows Ren'Py build completed once (even if saves are broken)
- [ ] BUILD_RECEIPT template ready
- [ ] No new routes or endings during freeze week—typos and crash fixes only
- [ ] Playtest form captures
build_label,slot, andlast_label_seen
Rules of the challenge
- One owner signs each weekday log.
- Fail stops the day—fix before
gateN_pass. - Artifacts in
release-evidence/renpy/freeze-week/YYYY-MM-DD_gateN.log. - Label or asset renames after Gate 3 require
save_format_versionbump and restart Gate 1. - Pair promotion days with metadata diff.
- Friday Block 5 row until ship:
renpy_freeze_pass Y/N.
Challenge calendar at a glance
| Day | Gate | Primary artifact | Pass signal |
|---|---|---|---|
| Mon | 1 | label_inventory_v1.json |
Every label + menu entry listed |
| Tue | 2 | build_classification_freeze.md |
build.classification + version frozen |
| Wed | 3 | asset_path_map.json |
Every shipped image/audio path mapped |
| Thu | 4 | persistent_schema_v1.json |
Persistent fields documented |
| Fri | 5 | Golden path + save round-trip | Load after quit on standalone |
| Sat | — | Evidence review | No new gates |
| Sun | — | Read-aloud | Seven logs present |
| Mon+1 | 6 | Installed Steam smoke | S4–S6 from smoke article |
| Tue+1 | 7 | renpy_freeze_receipt_v1.json |
Promotion allowed |
Beginner path (read this first)
- Monday — Export a list of story
labelnames you ship in the demo. - Tuesday — Open
options.rpy/ build config; write downbuild.classification. - Wednesday — List every image and audio file the demo references.
- Thursday — Write which
persistentvariables store progress. - Friday — Play to mid-demo, save, quit, relaunch; progress remains.
- Next Monday — Install from Steam (or playtest branch); repeat Friday test.
- Next Tuesday — File
renpy_freeze_receipt_v1.json.
How this differs from engine export tutorials
GameMaker export sanity and Defold collection audit are one-evening pipelines. GDevelop freeze week targets storage APIs. Ren'Py fest failures cluster around narrative rewrites and asset renames—this challenge freezes labels and bundles, not just exe paths.
Pair writing discipline with narrative tools roundup only for workflow—this article owns build and save proof.
Gate 1 (Monday) — Label and menu inventory
Export label_inventory_v1.json:
{
"schema": "label_inventory_v1",
"project_version": "0.6.0-freeze-week",
"demo_entry_label": "start_demo",
"labels": [
{ "name": "start_demo", "purpose": "fest_entry", "reachable": true },
{ "name": "chapter_02_hub", "purpose": "mid_demo_checkpoint", "reachable": true },
{ "name": "debug_skip", "purpose": "dev_only", "reachable": false }
],
"menus": ["main_menu", "save_load_menu"],
"excluded_from_demo": ["debug_skip", "ending_full_game_tease"]
}
Pass: No unlisted jump targets in demo routes; dev-only labels marked reachable: false.
Common Monday failures
| Failure | Fix |
|---|---|
Orphan jump to removed label |
Restore label or update jump |
| Demo includes full-game endings | Exclude in options.rpy or config |
Multiple start labels |
Pick one demo_entry_label |
Gate 2 (Tuesday) — Build classification freeze
Document in build_classification_freeze.md:
# Build classification — frozen 2026-05-26
- build.name: MyVN_Demo
- build.classification: "demo" # not "all" during fest week
- config.version: 0.6.0-freeze-week
- build_label on title: vn-nextfest-2026-05-26-rc1
- Forbidden: promote debug/development classification to public depot
Ren'Py build docs describe how classifications filter files into packages. Fest demos should ship a narrow classification so writer laptops do not bundle gui/development/ skins into the Steam depot.
Pass: Launcher build uses frozen classification; build_label visible on title matches BUILD_RECEIPT row.
Cross-read developer console opinion—VN teams still ship config.developer true by habit.
Classification table (working dev)
| Classification | Fest demo use |
|---|---|
demo |
Shipped routes and assets only |
all |
Avoid for public fest depot |
android / pc |
Platform splits documented |
hidden |
Dev tools, placeholder CG |
Gate 3 (Wednesday) — Asset path map
Create asset_path_map.json:
{
"schema": "asset_path_map_v1",
"rules": {
"rename_policy": "no renames after Gate 3 without save_format_version bump",
"case_sensitive": true
},
"images": [
{ "statement": "image ch03 smile", "path": "images/ch03_smile.png", "demo": true }
],
"audio": [
{ "statement": "define audio.bgm_menu", "path": "audio/bgm_menu.ogg", "demo": true }
]
}
Pass: Every image, define audio, and movie used in demo routes appears; grep shows zero references to deleted files.
Wednesday rename discipline
| Action | Allowed during freeze week? |
|---|---|
| Fix typo in dialogue text | Yes |
| Rename image file on disk | No (restart week) |
Change image statement target |
No without schema bump |
| Add new CG | No (scope creep) |
Align FAQ save claims with demo scope—if FAQ says three chapters, inventory must list three.
Wednesday test script
- Delete
saves/under game directory and per-user persistent path. - Launch standalone; reach mid-demo checkpoint label.
- Save in slot 1; note
persistentkeys in log. - Quit; relaunch; load slot 1.
- Confirm
last_label_seenmatches inventory.
Gate 4 (Thursday) — Persistent schema freeze
Create persistent_schema_v1.json:
{
"schema": "persistent_schema_v1",
"save_format_version": 2,
"fields": [
{ "key": "chapter_id", "type": "int", "demo_max": 2 },
{ "key": "route_flags", "type": "dict", "demo_keys": ["met_a", "met_b"] },
{ "key": "build_label_seen", "type": "str", "required": true }
],
"migration": {
"on_version_mismatch": "wipe_slot_with_message",
"message_label": "save_incompatible"
}
}
Implement in python blocks:
# After init python:
if persistent.save_format_version != 2:
renpy.run_action(Restart())
Pass: Loading old saves either migrates safely or shows save_incompatible—never silent chapter reset.
Ren'Py persistent data survives between sessions; fest demos must not store full-game spoilers in persistent if the SKU is demo-only.
Thursday edge cases
| Edge case | Gate 4 action |
|---|---|
| Writer adds new route flag mid-week | Bump save_format_version; restart Gate 1 |
| Steam Cloud not used | Document local-only in FAQ |
| Multiple language tables | Each language row in inventory |
| Rollback build on branch | build_label_seen mismatch → wipe with message |
Forward-link discipline: if you later publish save-slot case study, attach this schema file to partner packets.
Translation and dub tables (Monday add-on)
If the demo ships multiple languages, extend Gate 1 inventory:
| Surface | Inventory row |
|---|---|
translate blocks |
Language code + label coverage |
| Voice files per language | Path in asset_path_map Wednesday |
| Font substitutions | gui.rpy font per language |
Fail if English label chapter_02_hub exists but Japanese table still points at removed chapter2 slug.
ATL and image definitions (Wednesday add-on)
Ren'Py image statements with ATL transforms reference base files—map both:
{
"statement": "image ch03 smile = Attract",
"base_path": "images/ch03_smile.png",
"transform": "Attract",
"demo": true
}
Renaming only the transform while leaving base file stable is allowed; renaming base file is not.
Gate 2 deep dive — version strings players see
Players screenshot config.version on the about screen. Freeze:
| Field | Shown where | Fest rule |
|---|---|---|
config.version |
About / pause menu | Matches receipt |
build_label |
Title corner | Matches BUILD_RECEIPT |
config.name |
Window title | No internal codenames |
Outbound: Ren'Py build documentation for classification syntax on your launcher version.
Gate 5 (Friday) — Golden path + save round-trip
Define five-step golden path (same discipline as Wednesday smoke):
- Title → Start Demo
- Reach
chapter_02_hub(or documented checkpoint) - Save slot 1
- Quit application
- Relaunch → Load slot 1 → same line of dialogue
Log gate5_pass.log with build_label, OS username hash (optional), and screenshot of save screen.
Pass: Round-trip on standalone exe built Tuesday classification— not launcher “Run Project” only.
Audio spot-check (Friday add-on)
Trailer and menu loudness drift breaks VN trust fast—run Tool 1 from LUFS listicle on menu loop after save test passes. Document integrated LUFS in gate log (optional row).
Gate 6 (Monday+1) — Installed Steam smoke
Install from Steam client or playtest branch—not zip copied from developer folder.
| Check | Pass |
|---|---|
| Installed path launches | Yes |
build_label on title matches receipt |
Yes |
| Save round-trip on installed build | Yes |
| No Ren'Py traceback on first boot | Yes |
| Autosave does not fire before player reaches demo entry | Yes |
Cross-read playtest invite isolation when playtest keys differ from public fest depot—two build_label rows required.
Gate 7 (Tuesday+1) — Freeze receipt
File renpy_freeze_receipt_v1.json:
{
"schema": "renpy_freeze_receipt_v1",
"project": "MyVN",
"freeze_week": "2026-W21",
"build_label": "vn-nextfest-2026-05-26-rc1",
"config_version": "0.6.0-freeze-week",
"build_classification": "demo",
"save_format_version": 2,
"gates": {
"gate1_label_inventory": true,
"gate2_classification": true,
"gate3_asset_map": true,
"gate4_persistent_schema": true,
"gate5_round_trip": true,
"gate6_steam_install": true
},
"freeze_pass": true,
"promotion_allowed": true,
"owner": "producer@studio",
"signed_at": "2026-05-27T18:00:00Z"
}
Attach paths to label_inventory_v1.json, asset_path_map.json, and persistent_schema_v1.json.
Promotion rule: If any gate false, promotion_allowed must be false—no manual override without new freeze week.
Gate 5 deep dive — autosave vs manual slots
| Mode | Fest demo guidance |
|---|---|
| Autosave on first line | Disable until after demo_entry_label |
| Quick save | Hide if demo scope is single-slot |
| Multiple slots | Document max slot in FAQ |
Test both quicksave (if enabled) and slot 1—some VN bugs appear only on quicksave path.
Gate 6 deep dive — depot vs local dist folder
Steam install paths differ from MyVN-1.0-pc/ zip habits:
- Note install directory from Steam client.
- Compare
game/payload size to last BUILD_RECEIPTbytesfield (rough). - Launch with Steam offline mode once—catches missing DLL dependencies.
- Confirm Steam overlay does not block first
menuinteraction.
Log steam_install_path.txt in gate folder—support tickets reference it.
Steamworks integration (optional Gate 6b)
If achievements or stats are enabled:
| Check | Pass |
|---|---|
| Demo scope achievements only | Yes |
| Stats do not write before demo entry | Yes |
| Steam Cloud off unless FAQ promises cloud | Yes |
Read cloud saves parity before enabling Cloud on a fest SKU.
Operating review hook
Four-Friday operating reviews Block 2:
- Freeze weeks completed vs promoted builds
- Top Gate 3 failure (asset rename vs writer jump)
- Save-related refund tag count (qualitative, from dashboard)
Roles on a three-person VN team
| Person | Daily duty |
|---|---|
| Writer / director | Gate 1 label truth; script patch log |
| Programmer | Gate 2–4 build + persistent schema |
| Producer | Sign logs; block promotion without receipt |
Solo dev: still produce seven logs—fest partners ask for paper trail.
Metrics without fake benchmarks
Track internally:
| Metric | Use |
|---|---|
| Gate 3 restart count | Asset discipline |
| Mid-week label changes | Writer protocol health |
| Promotion delays | Cost of unfreeze |
Do not publish invented retention percentages.
Vertical slice honesty
Vertical slice honesty applies: if the SKU is two chapters, persistent.chapter_id must not serialize chapter nine flags.
Truth audit pairing
Run 7-day truth audit the week after freeze week—store copy about chapter count must match label_inventory_v1.json.
Q3 diligence attachment
Q3 diligence reviewers ask what happens to player routes when builds update—freeze receipt plus label inventory answers without fabricated metrics.
Community hook (optional)
Share progress only if your studio already runs devlogs—internal Sunday read-aloud is the minimum bar. Hashtag campaigns do not replace renpy_freeze_receipt_v1.json.
Script patch protocol (writers)
During freeze week, writers may:
- Fix typos inside existing dialogue blocks
- Adjust
menuchoice text without renaming labels - Fix
# charactertags
Writers may not:
- Rename
labelidentifiers - Move
jumptargets - Add endings or routes
- Import new image folders
Use a shared SCRIPT_PATCH_LOG.md one line per change—producers attach to BUILD_RECEIPT upload notes.
BUILD_RECEIPT pairing row
Add to weekly BUILD_RECEIPT:
| Field | Example |
|---|---|
engine |
renpy-8.3.0 |
build_label |
vn-nextfest-2026-05-26-rc1 |
renpy_freeze_pass |
true |
save_format_version |
2 |
receipt_path |
release-evidence/renpy/freeze-week/renpy_freeze_receipt_v1.json |
Cross-engine freeze family
| Engine | Freeze article | Primary risk |
|---|---|---|
| Construct | Sheet order challenge | Event order |
| GDevelop | Save path challenge | Storage API |
| Ren'Py | This challenge | Labels + assets + classification |
| GameMaker | Export sanity | Texture pages |
Playtest and refund signals
After Gate 7, route feedback through 18 playtest tools with mandatory build_label.
Watch refund signal dashboard for tags mentioning “save” or “chapter reset” within 48 hours of promotion—correlate to build_label before blaming store algorithm.
Partner packet crosswalk
Attach to diligence ZIP:
label_inventory_v1.jsonasset_path_map.jsonrenpy_freeze_receipt_v1.json- Optional: 90s screen recording of save round-trip
Common mistakes (seven)
- Launcher-only testing — Gate 5 requires packaged exe.
- Promoting
developmentclassification — Gate 2 fail. - Renaming CG files without schema bump — Gate 3 violation.
- Storing full-game flags in demo
persistent— Gate 4 fail. - Skipping Gate 6 — Steam path differs from dist folder.
- Writer patches without log — Cannot audit mid-week jumps.
- Promotion before receipt — Producers lack proof.
Pro tips (six)
- Print label list for writers—physical checklist beats Slack memory.
- Same
build_labelon title, receipt, BUILD_RECEIPT. - Delete saves folder before each gate test.
- Pair with validate-packet when scripting checks.
- Index logs by ISO week —
2026-W21. - Run fest marketing cap stop on Gate 5 fail.
Snippet-friendly answers
How do I export Ren'Py to Steam?
Freeze labels and assets for seven gates, build with demo classification, upload via SteamPipe, smoke installed build, file renpy_freeze_receipt_v1.json, then promote branch.
Why did my Ren'Py save break after a script patch?
Usually label rename or persistent schema change without migration—Gate 4 prevents silent failure.
Is this the same as GDevelop freeze week?
Same evidence culture; Ren'Py checklist focuses on narrative labels and asset paths, not GDevelop storage APIs.
Key takeaways
- Seven weekday gates end with
renpy_freeze_receipt_v1.json. build.classificationfreeze keeps debug files out of public fest depots.- Gate 3 asset path map stops mid-week CG renames from corrupting saves.
- Gate 4 persistent schema requires explicit migration or wipe messages.
- Standalone exe round-trip before Steam install smoke.
- Pair with BUILD_RECEIPT, metadata diff, and Wednesday demo smoke.
- No fest promotion until
freeze_pass: true. - Writers follow script patch protocol during freeze week.
- Visual novel fest weekly build cadence makes freeze weeks cheaper than save-bug firefights.
- Ren'Py fills the freeze family beside Construct and GDevelop.
- Menu loop loudness optional row ties to LUFS tools.
- Playtest and public fest depots need separate build labels when scopes differ.
save_format_versionsemver is mandatory for any post-Wednesday label change.- Gate 6 on installed Steam build is non-optional for desktop fest demos.
- Partner packets should include inventory + receipt, not marketing adjectives.
Month-one adoption ladder
| Week | Goal |
|---|---|
| 1 | Complete first Ren'Py freeze week |
| 2 | Attach receipt to BUILD_RECEIPT habit |
| 3 | Pair Wednesday smoke on promotion |
| 4 | Archive maps in release-evidence taxonomy |
FAQ
We only ship itch for this fest—skip Steam gates?
Run Gates 1–5 on desktop build; run Gate 6 when a Steam depot exists.
Ren'Py 7.x vs 8.x?
Re-run Gate 2 after launcher upgrade; update config.version.
Does this replace narrative tooling listicles?
No—this is shipping discipline, not writing craft. Use the listicle for tool choice; use this challenge before fest promotion.
Can we patch story endings during freeze week?
No—scope change restarts freeze week.
Conclusion
Ren'Py makes narrative iteration fast—and save-breaking renames fast too.
Freeze labels. Freeze assets. Freeze classification. Promote only after Gate 7.
If your team journals evidence cycles, treat freeze week as the narrative discipline pass before art-heavy trailer weeks—not optional paperwork.
Next reads: BUILD_RECEIPT pipeline, Wednesday demo smoke, GDevelop save-path freeze.