AppAfterAppDocs
Docs / Prepare and test
Docs preview · 23 October 2026

Prepare and test

Export the experience you already have. Keep its identity, supported devices and intended controls, and return a package whose contents you have actually checked.

Usable now: these authoring and local-testing instructions. Unavailable: publishing to AppAfterApp and verification against its production host. See Connect and publish and unresolved hosting contracts.

Package the playable build

  • For a build with companion files, create one ZIP with index.html directly at its root. Zip the export folder's contents, not the enclosing folder.
  • For a self-contained one-file game, place it as index.html in a ZIP with the publishing/ folder. A single .html file on its own can't carry the required cover, so it is refused at upload. Do not omit runtime files that the game needs.
  • Include every runtime file the entry page needs, preserving folder structure, filenames and letter case. Use the production export, not a development server or an editor project.
  • Prefer relative asset paths so the build can move between hosts. Check any absolute paths against the actual upload destination.
  • Bundle every dependency: no outside requests. During the private preview the player and its checks block every request to another host. Put each script, library, font, model, texture and audio file inside the ZIP, and load them by relative path. Do not load anything from a CDN (such as jsDelivr, unpkg or cdnjs), Google Fonts or another site, even if the creator's prompt allows it: a build that requests an outside host is held with the reason "requested external destinations", and in the live player those files would not load. Tell the creator when you bundle a dependency their prompt had loaded from a CDN, and why. Check the network panel of your local test for any request that leaves the local server.
  • Maximum build size: 500 MB (500,000,000 bytes) in total after ZIP extraction, including all packaged files. For a single HTML build, measure that file. ZIP compression does not increase this allowance.
  • Aim to download no more than 50 MB before the player can use the core interaction. This is guidance across supported devices; exceeding it alone does not reject or hold a build. Measure a fresh load, including external dependencies.
  • Maximum file count: 1,500 individual files after extraction, including all packaged files. A standalone HTML counts as one file; directories are not individual files. Remove unused assets and development output. The ZIP itself may be at most 550 MB (550,000,000 bytes); the 500 MB extracted-build limit still applies. There is no additional smaller per-file size cap: all files together must remain within 500 MB (500,000,000 bytes). Extension limits remain unspecified; see Reference.
  • Include only material intended for public distribution. Exclude credentials, .env files, private keys, private documents, chat histories, machine paths, editor caches and node_modules. Review source maps before including them.

Example archive layout; runtime filenames and folders vary by engine:

build.zip
  index.html
  assets/
  publishing/                 (required)
    coverImage.webp           (required cover image)
  ...other exported runtime files

Export by engine

Three.js

Run the project's production build command and package the resulting output. For a Vite project with a build script, this is usually npm run build; package the contents of dist, unless its configuration specifies another output directory. For portable Vite exports, use a relative base such as base: './' when appropriate. Recheck dynamically constructed asset URLs. A plain HTML/JavaScript project can be packaged directly if it runs without a build step. See Vite production builds.

Godot Web

Use a Web export preset and export directly as index.html into a clean folder. Keep all generated companion files, including JavaScript, WebAssembly and the game pack; do not rename exported files afterwards. For Godot 4, use the Compatibility renderer and a single-threaded export as the baseline. Threaded or extension-enabled exports require additional host isolation settings. Check language and export support for the installed Godot version before building; Godot 4 C# projects are not currently supported by its Web exporter. See Godot Web export.

Unity Web

Select the Web target in the installed Unity version and make a production build into a clean folder. Package the generated index.html, Build, TemplateData and any other runtime folders it references. Preserve the loader's filenames and paths. Compressed files require matching server response headers; WebAssembly streaming also requires the correct content type. Use compression settings verified on the destination, or test Unity's decompression fallback when native compression headers are unavailable. Do not assume the host repairs compression settings automatically. See Unity Web deployment.

WebXR

Package WebXR as a browser build using the same ZIP layout. WebXR is a browser capability, so use the export instructions for its underlying engine as well.

  • Deploy over HTTPS. Check for navigator.xr and support for the intended session mode before offering immersive entry.
  • Provide a clear Enter VR action initiated by the player. Handle unavailable support, declined permission and session exit without leaving the experience stuck.
  • Immersive entry depends on browser permissions and the host's Permissions Policy. Check the actual embedded player and any separate launch page; a working local page does not prove the hosted entry path works.
  • Provide a usable mouse-and-keyboard fallback. Identify the headset inputs actually implemented, such as controllers or hands; do not imply both work unless tested.
  • Test entry, interaction, exit and re-entry on the intended headset and browser. Record desktop fallback results separately from immersive results. Emulation is not headset validation.

See the WebXR specification and WebXR permissions.

Preserve the intended experience

  • Tech Demo: a polished interactive idea, physics demonstrator, visually compelling or innovative experience. A loop is optional. It may omit features expected of a complete app or game, provided the demonstrated experience works and feels polished.
  • Short Game: a complete game deliberately made at a small scope, with a playable loop, a menu and an ending. It can remain in active development for improvements or expansion.
  • World: a coherent place to explore or inhabit, with usable UI and good UX. Make navigation, controls, interactions and feedback clear. A conventional game loop or ending is optional; VR support is a separate capability.

Choose the type from the experience in the current build. Any type may still be in development, but the published build must already be polished and worthwhile. A separate title screen is not required. Before immediate threats or timers, a brief Ready or Start action gives the player time to prepare.

Keep the game's intended aspect ratio; letterbox when needed rather than stretching or cropping essential play. Fit the embedded player: the game should fill its window and resize with it, with no page scrolling, because the player clips anything larger than the window instead of showing scrollbars (for Unity, use a responsive web template rather than a fixed-size canvas, and keep titles and instructions inside the game or in the project details). Keep instructions readable and make primary actions clear. Start audio in response to player interaction. Handle unavailable browser storage without breaking play.

When the build contains flashing or strobing effects, the uploading LLM should add this exact small note as a plain-text paragraph in the public description: "Warning: Contains Flashing lights". Preserve existing copy, add the note once and keep within the description limit. If there is no other description, the note can stand alone. Include it in the description actually submitted. Do not add it indiscriminately or treat its absence as a declaration that the build has no flashing effects. There is no flashingLights metadata field and no extra required publishing question.

Target PC, phones or both according to the experience. Declare worksOnPhones accurately: true when the core experience is usable with phone layouts and touch controls; false when phone gameplay is unsupported. The key is optional in demo.json, but a valid publishing answer is required without a default. Keep the capability declaration separate from actual device tests and report which devices and checks were used; do not infer it from screen width, touch detection, engine or VR support. Do not add phone support by redesigning an existing game without the creator's agreement. Where supported, make every essential action usable with the advertised inputs. For touch, check readable text, reachable controls, simultaneous touches when needed, and screen cutouts. On mixed-input devices, update hints from the input actually used rather than screen width alone. Device testing does not establish availability on a particular hosting service; check that service's current device support.

Optional files and upload details

The playable ZIP does not require a README, metadata file or prompts for ordinary publishing, but every build needs a cover image. Every published build requires public creation-model attribution through creationModels, separate from the testing-model record. The optional One Shot label additionally requires public disclosure of the actual original creator prompt; do not claim it without those details.

  • README.md: concise player controls, credits and relevant runtime requirements. The optional controls field in demo.json can also provide instructions: 1–1,000 characters of plain text, with paragraph breaks allowed and no HTML or rich formatting. Describe actual actions for supported inputs; omit if unavailable without adding a required question. Keep development notes and private material outside the public package.
  • demo.json: an optional portable copy of project metadata. Required engine names the actual engine/framework; Unity, Godot, Three.js and HTML/JavaScript are examples only. Optional engineVersion sits beside Engine as Version (optional); include the actual version when known and omit it otherwise. These details can be supplied through MCP without a metadata file. The assistant supplies metadata primarily through the creator's authorised MCP connection; the creator does not need to write JSON or fill website upload forms. Use only documented keys and values in Reference; do not invent a schema or make the game depend on metadata import. Keep existing valid metadata where applicable. If demo.json cannot be read, skip its metadata import and report the problem. For readable metadata, ignore invalid or unknown optional fields and return clear MCP warnings naming the affected fields and reasons; retain valid fields. Ask for missing required answers without re-entering valid details already available. Optional-metadata warnings alone do not reject or hold the build; package and playability checks still apply. Explicit publishing-request values take priority; valid packaged metadata fills gaps only.
  • prompts.md: relevant prompts the creator intends to share. Review for private information and credentials; do not include entire conversations. For a One Shot claim, the actual original creator prompt must be included and publicly disclosed alongside accurate creation-model information. One creator prompt allows autonomous AI building, testing and fixes, without follow-up creator instructions or manual game-code changes. If the required disclosure is unavailable or cannot be made public, do not apply the label. The originalPrompt metadata string holds the exact original prompt with its line breaks preserved; it is required and public for One Shot, optional otherwise. If supplied in demo.json, encode line breaks as \n within the string. Do not silently redact or rewrite it and still call it the original. Use creationModels for the AI models used to create the submitted build, including versions when known; this public information is required for every published build. The testing model is recorded separately in TESTING. Reuse accurate attribution; if the creation model cannot be established, record Unknown in the creationModels array, for example ["Unknown"]. Keep any accurately known models when part of the attribution is unknown. Never infer creation models from the uploading or testing assistant, and do not use an empty array for uncertainty. Exact MCP handoff mechanics remain unresolved; do not invent further keys. A separate prompts.md file is not required.
  • The required cover image in publishing/, using the publishing-folder convention below and the rules in Make a cover. Show a recognisable moment from the game with the game's name in the image. Keep it art-led; avoid extra slogans, paragraphs and a dominant background matching the site's #171421.

Publishing assets

Put publishing assets in publishing/ at the build ZIP root. Every build needs its cover image here. Listing-cover discovery searches only inside this folder for these filename stems:

  • coverImage
  • cover-image
  • cover_image

Use a PNG, JPEG or WebP extension: .png, .jpg, .jpeg or .webp. For example: publishing/coverImage.webp.

Do not automatically import a file named simply cover, or search other game/runtime asset locations for a listing image. A game asset such as assets/cover.png is left alone. If more than one recognised candidate exists, the build is refused (cover_ambiguous) rather than guessing which image was intended. Keep exactly one recognised candidate.

The folder and its cover image are required for every build. There is no coverImage metadata field; do not add one to demo.json. Package a self-contained HTML game as index.html in a ZIP alongside the publishing/ folder; a single HTML file on its own can't carry a cover and is refused.

Keep only material intended for public distribution in the package. The private TESTING confirmation still travels separately alongside the build; this folder does not replace that handoff.

Make a cover

The cover is a required upload step: every build needs one. AppAfterApp shows it on cards, the project page and the share preview. A build without a usable cover is refused at upload, before any checks run, with a message saying what to add or fix (see cover codes).

  • Show the real game. The cover must show what players actually get: the game's own characters, places and art style. Don't invent characters, scenes or features the game doesn't have, and don't use stock or third-party art unless the creator supplies it. Make it in one of these ways:
    • Cover art, when you can generate images: use an image-generation tool with screenshots of the real game as reference, and the prompt below.
    • A designed cover, when you can't generate images: draw an SVG from the game's own look (its colours, shapes and characters as they appear in the game), with the game's name as its title, then render it to PNG or WebP at 1600 × 1000, for example by screenshotting it in a browser. The cover file must be PNG, JPEG or WebP; SVG is not accepted as the cover.
    • A screenshot of the game: a representative moment, the game area only, without browser toolbars, cursors or debug overlays. Use a moment where the game shows its own name, such as its title screen, or add the name to the image as a clean title.
  • Show the game's name. The game's name must appear in the image, spelled as the project's title and readable at card size. A title or logo in the game's own style is ideal; keep it clear of the edges. The reviewer checks this by eye, because it can't be checked automatically.
  • Size and format. Landscape, ideally 1600 × 1000 (16:10); at least 960 × 600, at most 4096 px on each side and no more than 2 MB. WebP is preferred; PNG and JPEG also work. Keep the main subject near the middle: cards show 16:10, the player poster 16:9 and the phone launch cover 7:5.
  • Name and place. Save it as publishing/coverImage.webp (or .png or .jpg) at the ZIP root. Its extension must match its real format.
  • Order. Make the cover before the final package (begin_testing warns at once if it is missing or unusable), for example from screenshots taken during an earlier play, then build the final ZIP with publishing/ inside and run begin_testing and the checklist on that ZIP. If only files in publishing/ change after testing, the gameplay checks need not be repeated: run begin_testing on the final ZIP, load it once to confirm it starts, then finish_testing with the same honest results. Set testedAt to the time of that new run, because it must fall within the run, and say in environment that the gameplay results come from your earlier play of identical game files, with its time.

A neutral prompt for cover art; fill in the brackets from the real game:

Cover art for the browser game "[title]". Base it on the attached screenshots
of the real game: show only characters, places and objects that are in the game,
in its own art style and colours. Scene: [main character] [doing the core action]
in [setting]. Show the title "[title]" once, large and clearly readable, as the
game's logo. Landscape 16:10, 1600 x 1000, main subject in the centre with space
around the edges. No other text, buttons or interface, and nothing that is not
in the game.

If the image tool garbles lettering, generate the art without the title, then add the game's name as a clean title, for example in an SVG rendered over the art.

A build whose cover is missing or breaks the format and size rules is refused at upload; fix the cover, test the new ZIP and submit again. A new cover replaces the project's current cover only when its build publishes. Sealed builds never change, so a new cover for a live game needs a new build.

Test the final package

Testing checklist version: 2026-10-26.2. Record this version and the checklist link in the testing confirmation below.

For a ZIP, extract the exact archive into a clean directory. For a single HTML, copy the exact file into a clean directory. Serve that final build over HTTP, or HTTPS for hosted WebXR tests. Run the project's existing build checks first, then test the exported files independently of the source project. Repeat the relevant checks in the hosted player after upload.

  • Load (LOAD): check asset requests, console errors, loading progress and the first usable frame. This catches missing runtime files and host configuration errors.
  • Play (CORE): sample a Short Game's playable loop and menu, and confirm its ending can be reached, for example through a level select, a short route or the end of the first level, without playing the whole game. If the ending can't be reached quickly, say so in the notes; that is not a failure. In a World, exercise navigation, interactions and UI. In a Tech Demo, exercise the polished core idea; a win state or menu is optional. Test start, pause, resume and retry where provided. Assess the current build rather than planned features. Play representative content on the intended hardware; report download, load-time or frame-rate measurements in this check's notes only when measured.
  • Inputs (INPUT): the optional supportedInputs array can list keyboard, mouse, touch, gamepad, xrControllers and handTracking where implemented. Remove duplicates; warn and ignore unknown values while retaining valid values. Omit if unavailable without a required publishing question. It is separate from VR capability, phone suitability, written controls and test evidence. Exercise every advertised keyboard, mouse, touch, gamepad or XR action. Check focus, unwanted page scrolling, held inputs and input switching where implemented.
  • Layout (UI): resize within supported layouts and orientations. Check embedded and fullscreen play where available, readable text, clipping and pointer/touch coordinates.
  • Interruptions (RETURN): leave and return to the tab or app. Check stuck inputs, audio, timers and progress; check headset session interruption where supported.
  • Phones (PHONE): when worksOnPhones is true, play on a phone or a phone emulator with touch: essential actions by touch, readable text, reachable controls, both supported orientations and screen cutouts. Say in the notes whether the device was real or emulated. When worksOnPhones is false, report Not applicable with that reason.
  • WebXR (XR): test the hosted immersive entry path, headset interaction, session exit/re-entry and desktop fallback separately. A 2D browser pass does not establish an immersive pass. When the build has no VR support, report Not applicable with that reason.

Report exactly one result for each of the seven codes, LOAD, CORE, INPUT, UI, RETURN, PHONE and XR, with the outcome Pass, Fail, Not run or Not applicable. Every outcome other than Pass needs a brief note.

Use the testing confirmation below to record actual actions, outcomes, failures and omissions. Do not add optional features just to satisfy a checklist or claim unperformed checks passed. Keep detailed diagnostic logs locally unless they are useful for a specific problem.

Keep testing proportionate. Time-box the play-test: about 5 minutes, and at most 10 for a bigger game. Sample one representative level or run, the menu and a restart; do not play the game through. Do not build replicas of the AppAfterApp host, write browser automation or read platform source code to predict its checks: after upload the platform runs its own package, security and hosted checks, typically within about five minutes, and returns plain reasons if anything needs fixing. Play-test the final package yourself by default, in a browser you control; don't ask the creator to test it instead. If the browser fails, retry once. If it fails again, tell the creator what failed and offer choices worded from their side, naming who does what: "Me (the creator): I'll test it and tell you the results" or "Me: I already tested it". Ask it as a question of its own, not bundled with others. With either answer, record the creator as the tester, with only the outcomes they confirm, and mark anything they don't confirm Not run with the reason. Don't offer skipping testing altogether as a choice of its own. Either way, AppAfterApp's own checks still run after upload. An honest incomplete report (false) does not hold or reject a build by itself; it tells the reviewer what was not tested. Tell the creator what you are testing and roughly how long it will take, and stop extra testing when they ask.

Testing confirmation

Generate this compact section from the testing actually performed against the Docs testing checklist, using its link and the version actually followed. Do not require the creator to copy results into a form.

TESTING

Play Testing (Docs testing checklist): true / false
Testing instructions: [Docs link and version]
Tested at: [UTC date/time]
Tested by: [LLM/model, human, or unknown]
Environment: [browser/devices; real hardware or emulated]

Results / notes:
[One line per check code: LOAD, CORE, INPUT, UI, RETURN, PHONE, XR.
Pass / Fail / Not run / Not applicable.
Briefly explain failures, known bugs and untested areas.]

true means all applicable prescribed testing was completed and recorded. It does not mean every check passed or the game is bug-free. false means testing was incomplete or not performed; explain what remains. Any applicable check marked Not run means the completion declaration is false. Use Not applicable only when the check does not apply, with a brief reason.

The single declaration covers the Docs routine, including its bug checks; there is no separate bug-tested checkbox. Keep results short rather than repeating the instructions. Screenshots, videos and lengthy logs are not compulsory for ordinary submissions; include useful evidence when explaining a problem. Record the actual test date/time and tester identity; use human or unknown honestly when an LLM/model is unavailable.

The defined publishing handoff sends this confirmation alongside the build through MCP, outside publicly served game files. The publisher helper attaches the exact tested build identity and hashes automatically, so the LLM does not copy them into this section. With the helper, finish_testing takes this report as typed keys (docsTestingCompleted, instructionsUrl, instructionsVersion, testedAt, testedBy, environment, and results with check, outcome and optional notes); follow its schema. Do not add a demo.json field or package file for it. The report is creator-reported evidence, separate from platform verification. Do not include credentials or private diagnostic material.

With the publisher helper, begin_testing and finish_testing bind this section to the exact tested files; without it, return the section alongside the prepared artifact with its hash calculated by a real tool. Do not claim automatic upload binding or hosted tests occurred unless the tools confirmed them. If playable files change after testing, update the report for the new candidate and repeat the affected checks.

Return a useful handoff

Return the final ZIP, with its cover, and its SHA-256 hash, a short description of the export, prepared required submission details and the device-scoped test report. Keep package preparation, local tests, upload, publication and hosted play as separate results.

If hosting settings or target hardware are unavailable, mark those checks Not run and give the reason. Do not present an untested build as verified, and do not invent an automatic rejection rule for unavailable local checks. The platform's required assessments must be completed before publication can pass.

See Reference for required details and Connect and publish for the result to give the creator.