Open the app

Language

For players

Tutorial Beta · Founding Creators

Make your first place

Not open to everyone yet. The kit isn't on npm, so step 3 fails today, and the app can't enable a pushed draft yet (step 7). Founding Creators get it first. You can already change your place with the wand.

Become a Founding Creator
Open llms.txt

You'll put code into a room on the HatchWorld map: when someone walks in, the walls turn teal and they get a greeting. About 10 minutes.

You need:

  • The HatchWorld app, and a place of your own in it.
  • Node 22 or newer.
  • A terminal. A coding agent (Claude Code, Codex) is optional: this page works by hand too.

1. Turn on Developer mode

In the app: Settings → For developers → Developer mode.

Walk into your place. A code button appears under the wand. It shows only in your own place.

2. Issue a key

Tap the code button. Code of this place opens. Tap Claude Code / Codex, then Issue a key, then Copy.

You get four lines like these:

HatchWorld place "Corner Café" (S7kQ2xR9mPa). You may edit its code.
Read https://spaces.hatchworld.io/pub/sdk/install.md first and follow it exactly.
Place key (rights: draft, expires 2026-10-17): hwk_…
Keep the key in the env var HATCHWORLD_PLACE_KEY; never write it to files, commits or output.

Two keys are in there:

  • S7kQ2xR9mPa is the place key: the public name of your place. Safe to share.
  • hwk_… is your personal key: it lets code be uploaded to this place. Shown once. Treat it like a password.

The personal key lives 7 days by default and can only upload drafts. You turn drafts on.

Using a coding agent? Paste the four lines to it and skip to step 6. It follows install.md and does steps 3–5 itself.

3. Start the project

In an empty folder:

npm init -y
npm i -D @hatchworld/place-kit@0.1.0
npx place-kit init S7kQ2xR9mPa

Use your own place key. You'll see:

created place.json
created server/index.js
created client/index.js
created jsconfig.json
created .gitignore
created AGENTS.md
created CLAUDE.md
next: put the key in HATCHWORLD_PLACE_KEY, then npx place-kit pull and npx place-kit build

init never overwrites a file that's already there.

Put the personal key in your shell, not in a file:

export HATCHWORLD_PLACE_KEY=hwk_…

4. Write the code

Replace server/index.js with:

import { SpaceScript } from '@hatchworld/space@1';

// Server part: a new instance per event; what must last goes in this.state.
export default class Place extends SpaceScript {
    static capabilities = ['world.write'];
    static texts = {
        welcome: { en: 'Welcome in!', ru: 'Заходи!' }
    };

    /** @param {import('@hatchworld/space@1').PlayerEnterEvent} e */
    onPlayerEnter(e) {
        this.world.look('walls', { colors: ['#00bcd4'], ms: 1500, ease: 'inOut', loop: 'none' });
        this.emit('ui.say', { text: 'welcome' }, { to: e.uid });
    }
}

What each line does:

  • onPlayerEnter runs when someone walks in. A method named on<Event> is all it takes to subscribe.
  • this.world.look('walls', …) fades the walls to a colour. Changing the room needs the world.write capability, so it's declared in static capabilities.
  • this.emit('ui.say', …, { to: e.uid }) shows a plate on that one person's phone.
  • Every text a player sees is a key in static texts, with English and at least one more language.
  • The JSDoc line types e. The kit's check is strict TypeScript over JavaScript, so every parameter needs a type.

Leave client/index.js as init wrote it.

5. Build

npx place-kit pull
npx place-kit build

On a place with no code yet, pull says there is no such version (or no active one) on this place. That's expected; go on. On a place with code, it writes the current code to pulled/ for you to compare.

build bundles each part into dist/ and runs the same type check the server runs:

server dist/server.js: built
client dist/client.js: built
server dist/server.js: ok
client dist/client.js: ok

Any other line is an error as file:line:col TScode: text. Fix it and build again.

6. Push

npx place-kit push
version 1: draft; the owner turns it on in the app
server dist/server.js: ready
client dist/client.js: ready

Your code is now a draft on the server. The server checked it again; nothing runs yet.

7. Enable it and walk in

In the app, open Code of this place and enable version 1.

Walk out of your place and back in. The walls fade to teal and you see "Welcome in!".

You did it: your code runs in a room on the real map, for everyone who walks in.

If something went wrong

You seeDo this
HATCHWORLD_PLACE_KEY is not setStep 3: export HATCHWORLD_PLACE_KEY=hwk_… in the same shell
the key has expired or the key was revokedIssue a new key in the app (step 2) and export it again
place … was not found, or the key's owner does not own itCheck the place key in place.json against the one in your text
too many requestsWait a minute: 60 requests a minute per key, 10 pushes a minute per place
a part is over the place's size limitEach part is 64 KB unless your place got more. See Keys and limits
TS7006 (implicit any)Give the parameter a JSDoc type, as in step 4
Next How a place runs server part, client part, drafts, and why your class is new on every event.

Docs