Itch.io Butler Upload and Store Page Ninety-Minute QA Pass for Unity and Godot PC Teams - 2026
itch.io is where a huge slice of indie PC discovery still happens in 2026, especially during game jams, pay-what-you-want experiments, and dual launches next to Steam. The failure mode is not “itch is hard.” The failure mode is boring: you push the wrong folder with Butler, your store page still mentions last month’s control scheme, or your restricted file channel serves a debug zip to press while retail players get the right one—but nobody wrote that down.
This guide is a ninety-minute QA pass for Unity and Godot 4 teams who already treat Steam store copy like a contract but still upload to itch from muscle memory. You will leave with a timed checklist, a zip layout recipe, and a Butler channel discipline that survives jam night and CI alike.
If you also own Steam depots and default branches, keep one spreadsheet row that names both Steam build id and itch file id for the same semantic version so producers stop answering “which PC zip is holy?” from memory. For install size pressure that hits both storefronts, cross-read reduce install size before store review before you promise disk numbers on either page.

Why this matters now
Jam and event density: Compressed deadlines mean Butler pushes happen minutes before a deadline. That is when relative paths, forgotten .dll folders, and Mac versus Windows zip mix-ups show up.
Dual storefront reality: Many teams ship Steam and itch the same week. Players compare checksums in Discord. If itch still hosts 0.8.1 while Steam default is 0.8.3, you spend a weekend on reputation repair, not gameplay.
CI and secrets: API keys in GitHub Actions or GitLab CI are normal now. A rotated key or wrong game slug in butler push fails silently until someone reads stderr in a log viewer.
Honest scope: this article does not replace itch.io creator documentation or the Butler tool documentation. It is a meeting script for humans who already export builds and need verification, not another “what is itch” essay.
Who this is for and how long it takes
Teams: two-to-fifteen people shipping Windows PC builds (optional macOS or Linux) with Unity or Godot 4, using or planning Butler for uploads.
Roles: whoever runs butler push, whoever edits the itch project page, and whoever signs off on version strings.
Time: ninety minutes once per milestone, fifteen minutes after any hotfix you care about on both Steam and itch.
Direct answer (snippet-sized)
itch.io Butler QA in ninety minutes means you (1) confirm the local zip or folder matches your smoke-tested artifact, (2) verify butler push target (user/project:channel) against a written channel map, (3) diff store page short text and metadata against default features, (4) download your own public or restricted upload in a clean directory and run it once, and (5) log file id or upload version next to semantic version in one row. Success is no silent channel drift and no page copy that outruns the zip.
Beginner quick start - Five itch concepts in one paragraph
A project is your game’s hub on itch. A upload is a file or embed players install or run. Butler is the command-line push tool that sends patches efficiently compared to re-uploading giant zips blindly. A channel is the suffix after the colon in user/my-game:windows-64 that separates Windows retail from mac demos or press builds. Restricted uploads are hidden from the default page but still fetchable with a secret URL or access control you configure—useful for QA and influencers, dangerous when you forget which channel is public.
If those words feel obvious, skip to the timed agenda. If not, read once before you push during a jam.
The ninety-minute agenda (use a literal timer)
Minutes 0-10 - Freeze the artifact
- Write down semantic version (for example
0.9.2), git sha or changelist, and OS targets you intend to ship. - Locate the exact Unity
Build/output folder or Godot export directory you smoke tested. Not “the one we probably built yesterday.”
Minutes 10-25 - Zip and layout honesty
- Build a zip the same way CI does, or document why CI differs.
- Windows: confirm
.exe, data folder, and native dependencies sit at the paths your README describes. - Godot: confirm export templates and GDExtension dll / so siblings match export presets.
- Unity: confirm Mono / IL2CPP player matches what the page claims about .NET and architecture (x64 versus ARM).
Minutes 25-40 - Butler target and credentials
- Print the exact command you will run, for example
butler push .\dist\windows user-slug/game-slug:win-stable --userversion 0.9.2. - Confirm user slug and game slug match the URL you hand to players.
- Confirm API key is valid, not expired, and not committed to a public repo. Rotate if a former contractor had CI access.
Minutes 40-55 - Push, then pull
- Push to a staging channel first if your team uses one (
:win-rc). If you only have one channel, push, then download the result from itch into a clean folder. - Run the downloaded build. If it fails, assume upload or compression issue before you blame players.
Minutes 55-70 - Store page and pricing truth
- Read short description aloud. Mark any sentence that promises multiplayer, saves, controller, or languages you did not test on this zip.
- Confirm pricing tier, sale state, and donation language match what finance expects.
Minutes 70-85 - Dual storefront parity
- If Steam exists, open your Steam QA checklist habits side by side. Align version strings and feature bullets, or add explicit “Steam-only” / “itch-only” notes where platforms diverge on purpose.
Minutes 85-90 - Log
- One spreadsheet row: date, itch channel, butler userversion, file id if your team tracks it, owner. Paste SHA256 of the zip if you have a script handy.
Unity-specific zip discipline
Player name and company fields become folder names and window titles. Mismatch annoys support more than you expect.
Development vs release: strip Development build watermarks from jam builds unless you label the page as such.
Addressables and streaming: if your game expects remote catalogs, either ship offline fallback for itch zips or say so on the page. Silent online-only assumptions create one-star “broken” comments on airplane Wi-Fi.
IL2CPP and plugins: include Visual C++ redist notes in the README or install script expectations the same way you would for Steam.
Godot-specific zip discipline
Export presets should name channels clearly (win_release, linux_steamdeck) and match Butler channel suffixes in your internal map.
PCK embedding versus external pck files: pick one story per channel and document it. Mixed embed states between itch and Steam confuse speedrunners who chase deterministic load times.
.gdextension and DLL load paths: case sensitivity matters on Linux. Test extract into a lowercase path if you claim Linux support.
CI patterns that fail gracefully
Secrets: store BUTLER_API_KEY in secret storage, not plaintext workflow files.
Idempotency: re-running a failed job should not half-push channels. Use atomic steps or verify upload checksum after push.
Artifacts: attach the same zip artifact you push to itch as a CI artifact for 24-48 hours so rollback is a re-push, not a rebuild from memory.
Restricted files and press channels
Press and creator keys are high leverage and high risk. Rules:
- Never reuse public channel names for secret builds.
- Expire old restricted uploads when you promote retail.
- Log who received URLs in a tracker row so NDA confusion does not become accidental leaks.
When page copy outruns the zip
Treat short description edits like code changes. If marketing adds co-op before netcode ships, you created refund risk. The fix is branching copy in a doc first, then syncing store pages after default build truth matches.
If you maintain patch rollback discipline for Steam, mirror the same severity language on itch when a bad zip ships.
Comparison cue - itch versus Steam upload mental models
Steam thinks in depots and packages. itch thinks in files and channels. The shared habit is immutable identity for what players download. Teams that map Steam branches to itch channels on paper survive events. Teams that improvise both at midnight feed forums drama.
Jam night and festival addendum (ten-minute micro-pass)
When the full ninety-minute ritual is impossible, do not skip verification entirely. Run this ten-minute sequence after any Butler push that players will see before a deadline:
- Re-read the upload label on the itch project page. Confirm it still says demo, jam build, or full release the way your rules expect. Jam pages get copied into collections and Discord embeds; a wrong label becomes a moderation thread.
- Download the file you intend to be default for new visitors. Extract to a path with spaces in the folder name once. Many Unity games survive normal paths but break when a jam entrant unzips into
Downloads\My Game (jam)\. - Launch offline or with Wi-Fi disabled if your page implies offline play. itch buyers often test on airplanes and conference hall networks.
- Paste the public URL into a private browser window. Confirm pricing, minimum price, and donation language match what you think you set. Browser cache and logged-in creator views lie sometimes.
This micro-pass does not replace the agenda above. It catches the top failure modes when adrenaline is high.
macOS, Gatekeeper, and “it runs on my machine”
macOS builds on itch frequently fail for reasons that are not Butler bugs. If you ship a zip with a .app bundle, document whether you notarize and staple tickets, or whether players must right-click open the first time. Godot and Unity both export .app layouts that look fine locally but trigger Gatekeeper friction for players who never read your README.
Windows SmartScreen behaves similarly for unsigned exe files. If you choose not to code-sign, say so in the install notes and expect a support spike the first week. The QA pass should include one fresh Windows user account without your developer certificates installed, because that is closer to a jam judge’s laptop than your CI runner.
Classification, content warnings, and system requirements honesty
itch gives you metadata fields that are easy to set once and forget. During the minutes 55-70 block, extend “store page truth” to:
- Genre and tags that match how curators describe you, not how your design doc describes you. Wrong tags attract speedrunners to puzzle games and roguelike purists to linear demos.
- Content warnings and mature flags that match scripted content, not “we might add gore later.” Mismatch here is a trust issue faster than a legal issue, but both hurt.
- System requirements text that matches what you tested. If Linux is best effort, write best effort instead of copying a Steam Deck paragraph that promises Proton behavior you never validated on itch zips.
Players forgive honest narrow support. They rarely forgive silent crashes framed as full platform support.
Spreadsheet row template (itch plus Steam on one line)
Borrow the Steam listing habit: one immutable row per milestone. Extend it so itch cannot drift alone:
| Column | Example | Why it matters |
|---|---|---|
date |
2026-05-02 |
Anchors the verification to a calendar, not memory. |
semantic_version |
0.9.2 |
Should match in-game UI when you show version strings. |
itch_user_game |
teamslug/gameslug |
Prevents butler push typos under stress. |
itch_channel |
win-stable |
Same role as a beta branch name—name it like API. |
butler_userversion |
0.9.2 |
Ties logs to human readable versions. |
steam_build_id |
9876543 or n/a |
Dual-launch teams need both or explicit n/a. |
zip_sha256 |
abc… |
Ends “I got a different file” fights in Discord. |
smoke_owner |
initials |
Forces accountability when the row is empty. |
If a column does not apply, fill it with n/a deliberately. Empty cells invite assumptions.
Social preview, embeds, and Discord reality
itch pages become unfurls in Discord, Slack, and forums. After you edit title, short text, or cover image, paste the URL into a private channel and read the embed like a stranger. Cropped cover art and ambiguous subtitles cause wishlist traffic to bounce.
If you maintain Open Graph images elsewhere, keep itch cover art readable at small thumbnail scale the same way you treat Steam library icons. The habit is identical even when the pipeline differs.
Butler troubleshooting patterns that are not “mystical networking”
When butler push fails, collect four facts before you guess:
- Exact command string, including trailing slashes and relative paths.
- Butler version on the machine that failed versus the CI image.
- Whether the API key was rotated recently and whether secrets were re-saved in the CI provider UI rather than only in a local .env file.
- Whether the game slug changed during a rebrand while scripts still pointed at the old slug.
Path separators differ between Windows agents and Linux containers. A script that works on a developer laptop may still fail in CI because the working directory is not where you think it is. Log pwd and dir or ls at the start of the job once, then delete the noise after you trust the path.
Red-team questions (ask aloud in the last five minutes)
- If a moderator downloads our default upload right now, will they see the same version string we post in release notes?
- If press uses the restricted URL, can they accidentally share a link that expires to an older build than retail?
- Did we delete or hide last month’s jam zip, or does it still rank in search and confuse returning players?
- If Steam default moves tomorrow, is there any sentence on itch that becomes a lie without a matching edit?
- Did we test extract on Windows Defender Controlled Folder Access or another AV suite that blocks unsigned writes beside the exe?
“No” answers are not shameful. They are tickets with owners.
Outbound references
- itch.io creator docs for projects, uploads, and metadata.
- Butler documentation for install, login, push, and patching behavior.
Key takeaways
- Butler channel names are part of your public API to players and press—treat them like branch names, not junk suffixes.
- Download your own upload after push; push success is not play success.
- Align semantic version strings across itch, Steam, and in-game UI when you claim parity.
- Unity Addressables and Godot PCK layout decisions belong in README truth, not Discord lore.
- Restricted uploads need expiry and ownership logs like any beta branch.
- CI keys rotate; verify credentials before jam deadline hour.
- Dual storefront teams should diff copy explicitly, not assume Steam edits flowed to itch.
- Zip layout mistakes are the top itch support tax for PC indie teams.
- Ninety minutes once per milestone prevents weekend fire drills.
- Log file identity next to version strings every time.
FAQ
Do we have to use Butler
No, but manual browser uploads scale poorly for frequent patches. Butler deduplicates blocks and reduces human error once channels are mapped.
Can one itch project host demo and full game
Yes, usually via separate channels or separate upload rows. Document which URL players should use so jam entrants do not buy the wrong file.
We only ship on itch during jams
Run a lighter twenty-minute pull test after push even for jams. Dead downloads hurt ratings fast.
Does itch replace Steam
No. It is another surface with different discovery physics. Many teams use itch for DRM-free fans and Steam for workshop features.
What about HTML5 builds
This guide focuses PC zip discipline. Web embeds need separate hosting and CORS checks. If you ship web demos, add a web row to your ninety-minute pass.
Our Butler push works locally but fails in CI
Check PATH, butler version pin, API key scope, and working directory paths on Linux runners versus Windows paths.
Should we checksum zips
Yes when you can. SHA256 in release notes reduces “ I got a different file ” threads.
Conclusion
itch.io rewards straightforward builds and honest pages. A ninety-minute Butler and metadata pass is cheap compared to debugging why half your jam players extracted an empty folder. Pair this habit with [Steam listing QA](/blog/steam-store-page-capsule-short-description-ninety-minute-qa-unity-godot-pc-2026) when you straddle storefronts, and [install-size discipline](/blog/reduce-indie-game-install-size-store-review-90-minute-team-pass-unity-godot-2026) when disk promises matter.
If this saved you from pushing the wrong channel under stress, bookmark it before your next deadline week.