.pck and publish it to Summercraft for review. Follow this document top to bottom. Everything in it was verified against the live platform; where a capability is not live yet, this document says so explicitly.
Any page of these docs is fetchable as raw markdown by appending .md to its URL. The full page index is at https://docs.summerengine.com/llms.txt.
1. What Summercraft is
Summercraft (https://summercraft.ai) is the platform where games built against the Summer SDK are published and played. You write a plain Godot 4.5 game in GDScript, extend the SDK base class SummerGame, export a .pck that contains only your game files, and submit it through the publish API. A human reviews every submission before it goes live. There is no auto-publish.
- The publish API lives at
https://summercraft.ai/api/*. - Docs live at
https://docs.summerengine.com. - The Summer SDK classes (
Summer,SummerGame,SummerPlayer,SummerCharacter3D) are provided by the Summercraft runtime when your pack loads. They are not files you ship.
SummerMultiplayerPeer transport (stock @rpc / MultiplayerSynchronizer compatibility) is a published contract still being built in the engine fork.
2. Prerequisites — check all three before writing any code
- Godot 4.5.x. Run
godot --version(or find the binary, e.g./Applications/Godot.app/Contents/MacOS/Godoton macOS). Any 4.5 build works; you only need it for headless export, no export templates required. If it is missing, ask your operator to install Godot 4.5 fromhttps://godotengine.org/downloadbefore continuing. - A Summercraft access token. Check for a
SUMMERCRAFT_ACCESS_TOKENenvironment variable or ask your operator for one. Without it every publish call returns401 sign_in_required. Stop and ask before step 6 if you do not have it — you can build and export everything first. Show your operator this if they do not know how to get one:Sign in at
https://summercraft.ai(create the account yourself — never let an agent handle your password). Then open your browser dev tools on that tab: Application → Cookies →summercraft.ai, and find the cookie whose name ends in-auth-token(it may be split into.0/.1chunks — concatenate their values in order). URL-decode the value; if the result starts withbase64-, base64-decode the rest. Inside the JSON is anaccess_tokenfield: that string is the Bearer token. It expires after about an hour, which is enough for one publish. There is no dedicated token page yet; this manual step is the current path. curland a sha256 tool (shasum -a 256orsha256sum).
Authorization: Bearer <access token> (or a signed-in browser session cookie). A present-but-invalid Bearer token is a hard 401 — it never falls back to a cookie. If you get 401 with a token set, the token has expired: ask your operator for a fresh one.
3. Know the rules before you build
Your.pck must contain only your game. The platform enforces, at review and in the browser submit scanner:
- GDScript only. No
.gdextension,.so,.dll,.dylib,.framework,.resfiles. - No banned APIs anywhere in your scripts, even in dead or conditional branches. The blocklist includes
OS.execute,OS.shell_open,OS.create_process,FileAccess,DirAccess,HTTPRequest,HTTPClient,JavaScriptBridge,ClassDB.instantiate,Thread.new,Expression, raw sockets (StreamPeerTCP,PacketPeerUDP,TCPServer,UDPServer,WebSocketPeer), reflection calls (.call(,.callv(,.call_deferred(,Callable(),Engine.get_singleton,Marshalls.base64_to_variant,ResourceSaver,ProjectSettings.load_resource_pack, and root-tree escapes (get_node("/root,get_tree().root). Full list with rationale:https://docs.summerengine.com/api-reference/summer-sdk/banned-apis-reference.md. Persistence goes throughSummer.data, economy throughSummer.economy— never your own I/O or networking. - No reserved paths in the pack:
res://sdk/,res://core/,res://server/,res://client/,res://official_games/,res://bootstrap.*,res://project.godot,res://summer.cfg,res://test_runner.*. The export preset below keeps them out automatically. manifest.jsonat the pack root with required keysid,name,version,summer_sdk("1.0"),entry_scene,min_players,max_players. The entry scene’s root script mustextends SummerGameor the runtime refuses to load the pack.- Host-authoritative multiplayer is the only mode. All gameplay decisions run on server paths guarded by
Summer.is_server(). Clients render synced state viaset_synced/get_synced; they never decide outcomes.
4. Build the game — multiplayer-native template
Build multiplayer by default:min_players: 1 so it works solo, max_players: 8 so it works with friends, all authority server-side. The template below is a complete king-of-the-hill arena, verified to parse, smoke-run, and export with Godot 4.5.1. Adapt the gameplay; keep the structure.
Create this exact layout in a fresh directory:
sdk/ folder holds local stubs that mirror the real SDK surface so your code parses and smoke-runs without the Summercraft runtime. The export preset excludes sdk/*, so the stubs never ship; on the platform the runtime provides the real classes at the same paths. Do not add behavior to the stubs — they are compile shims, not the SDK.
project.godot:
manifest.json:
id, name, and the descriptive fields for your game. entry_scene and player_scene are relative to the manifest (pack root).
main.gd — the game. Every decision happens on the server path:
main.tscn — entry scene: floor, hill marker, four spawn points, light, camera:
player.tscn — references the runtime’s 3D character template script. The reference is expected; the file itself must never be in your pack:
sdk/summer.gd:
sdk/summer_game.gd:
sdk/summer_player.gd:
sdk/summer_character_3d.gd:
export_presets.cfg — this is what keeps stubs and project config out of the pack:
script_export_mode=0 ships your GDScript as readable text — required so review can read your source. If you add asset folders, they are included automatically (all_resources); add non-resource data files (e.g. extra .json) to include_filter as a comma-separated list.
5. Validate and export
Run all four checks.$GODOT is your Godot 4.5 binary path.
grep exits non-zero when it finds nothing, so do not treat its exit code as a failure. If the smoke run prints SCRIPT ERROR, fix it before exporting — the same error will make the platform runtime refuse your pack.
Then measure the artifact and keep the values for step 6:
6. Publish through the live API
Base URLhttps://summercraft.ai. All requests JSON unless stated. Every step needs Authorization: Bearer $SUMMERCRAFT_ACCESS_TOKEN.
Budget warning: each of the three write steps (create game, upload-url, finalize) has its own limit of 1 request per hour per account. Validation failures (4xx before the limit check) do not spend it, but a successful call does. You get one full publish attempt per hour — do not experiment against these endpoints; get steps 4–5 right first.
6a. Create the game record (once per game, not per version)
201 { "gameId": "<uuid>", "slug": "hold-the-hill", "kind": "engine", "status": "draft", "uploadUrlEndpoint": "/api/games/<uuid>/releases/upload-url" }. Save it:GAME_ID=<gameId from the response>.- Optional body field
"slug": an explicit slug fails with409 slug_takenif taken; without it the server derives one and walks around collisions. 401 sign_in_required→ token missing/expired. (This endpoint’s 401 text mentions only the session cookie — Bearer tokens are accepted here all the same.)429 rate_limited→ body includesretryAt; wait.409 slug_taken→ pick another slug.- Skip this step for updates to an existing game — reuse its
gameId.
6b. Request the presigned upload URL
Declare exactly what you measured in step 5.version must match [A-Za-z0-9][A-Za-z0-9._-]{0,31} with no ..; sha256 is the lowercase hex digest; sizeBytes the exact byte count.
200 { "uploadUrl", "method": "PUT", "headers": { "content-type": "application/octet-stream", "if-none-match": "*" }, "objectKey", "maxBytes", "expiresAt", "finalizeUrl" }.- The URL expires in 1 hour. Both returned headers are folded into the URL’s signature — the PUT must send them exactly, nothing extra that conflicts, or storage answers
403 SignatureDoesNotMatch. - Errors:
404 game_not_found_or_forbidden(wronggameIdor not your game) ·409 not_a_godot_game(thatgameIdis a web game) ·409 version_exists(bumpversion; released versions are immutable) ·413 artifact_too_large·429 rate_limited.
6c. PUT the artifact
- Success is an empty
200. NoAuthorizationheader here — the URL itself is the credential. 412 Precondition Failed→ an object already exists at this key (the key is write-once). If your earlier PUT half-landed, finalize will detect and delete a corrupt one; a clean object under the same (version, sha256) means this exact artifact was already uploaded — just finalize.403 SignatureDoesNotMatch→ your headers differ from the two returned ones.
6d. Finalize — the server verifies your bytes
201 { "releaseId", "gameId", "version", "sha256", "sizeBytes", "pckUrl", "status": "pending_review", "adminNotified", "detail" }— you are done; the release is queued for human review.409 no_upload_intent→ you skipped 6b, or the declaration differs from what 6b recorded.409 artifact_missing→ the PUT never landed; redo 6c.400 checksum_mismatch/400 size_mismatch→ the stored object was corrupt; it has been deleted so the key is free — redo 6c with the same URL if unexpired, then finalize again.429 rate_limited→ finalize has its own hourly budget; wait forretryAt.changelogis optional, max 2000 chars.
7. After submission — what to tell your operator
Report exactly this, no more:- The game record exists at status
draft; release<version>ispending_reviewin the manual review queue. A human reviews every submission; there is no automatic publish and no guaranteed review time. - When approved, the game becomes
publishedand the release goes live; if rejected, the reason appears for the creator onhttps://summercraft.ai/creator. - The owner (and admins) can verify the stored artifact any time — response includes a short-lived (5 min) download URL plus the server-verified
sha256:Other signed-in users can fetch it only after the game is published. - Playing uploaded Godot games in the browser or desktop shell, and hosted game servers, are not live yet — publishing today means entering the catalog pipeline, not instant playability. Do not claim otherwise.
8. Updating the game later
Releases are immutable. To ship a fix: bumpmanifest.json version and use the same new version string in 6b/6d, re-export, and repeat 6b → 6c → 6d with the same gameId. Every update goes through review again. Remember the 1/hour budgets.
9. If something here does not match reality
Error bodies from this API are self-describing:{ "error": "<code>", "detail": "<what to do next>" } — trust the detail text. For anything else, fetch the full reference: https://docs.summerengine.com/api-reference/summer-sdk/exporting-and-uploading-your-game.md and https://docs.summerengine.com/api-reference/summer-sdk/submission-guide.md. Report doc bugs to founders@summerengine.com.
