Quick Start
Create Your Project
npx @sharpee/sharpee init my-adventurecd my-adventurenpm installThe scaffolded project gives you a single starting room. Let’s expand it into a two-region story.
Build a Region
Create src/regions/house.ts with a few connected rooms and objects:
import { WorldModel, IFEntity, EntityType, IdentityTrait, RoomTrait, Direction,} from '@sharpee/world-model';
export function createHouse(world: WorldModel) { // Rooms const foyer = world.createEntity('foyer', EntityType.ROOM); foyer.add(new IdentityTrait({ name: 'Foyer', description: 'A grand entrance hall with marble floors. A doorway leads north to the library. The front door is to the south.', })); foyer.add(new RoomTrait());
const library = world.createEntity('library', EntityType.ROOM); library.add(new IdentityTrait({ name: 'Library', description: 'Dusty bookshelves line every wall. A reading desk sits beneath a window. The foyer is south.', })); library.add(new RoomTrait());
// Connect rooms via RoomTrait exits const foyerTrait = foyer.get(RoomTrait); if (foyerTrait) { foyerTrait.exits[Direction.NORTH] = { destination: library.id }; } const libraryTrait = library.get(RoomTrait); if (libraryTrait) { libraryTrait.exits[Direction.SOUTH] = { destination: foyer.id }; }
// Objects in this region const book = world.createEntity('dusty-book', EntityType.OBJECT); book.add(new IdentityTrait({ name: 'dusty book', description: 'An ancient tome with faded gold lettering. The title reads "A History of the Valley".', })); world.moveEntity(book.id, library.id);
const key = world.createEntity('brass-key', EntityType.OBJECT); key.add(new IdentityTrait({ name: 'brass key', description: 'A small brass key with an ornate handle.', })); world.moveEntity(key.id, foyer.id);
return { foyer, library };}Everything for the house — rooms, connections, objects — lives in one file.
Wire It Into Your Story
Update src/index.ts to use the region:
import { Story, StoryConfig, GameEngine } from '@sharpee/engine';import { WorldModel, IFEntity, EntityType, IdentityTrait, ActorTrait, ContainerTrait,} from '@sharpee/world-model';import { createHouse } from './regions/house';
export const config: StoryConfig = { id: 'my-adventure', title: 'My Adventure', author: 'Your Name', version: '1.0.0', description: 'A short adventure in a mysterious house.',};
export class MyAdventure implements Story { config = config;
initializeWorld(world: WorldModel): void { const house = createHouse(world);
// Place the player in the foyer const player = world.getPlayer(); if (player) { world.moveEntity(player.id, house.foyer.id); } }
createPlayer(world: WorldModel): IFEntity { const player = world.createEntity('yourself', EntityType.ACTOR); player.add(new IdentityTrait({ name: 'yourself', aliases: ['self', 'me'], description: 'As good-looking as ever.', properName: false, })); player.add(new ActorTrait({ isPlayer: true })); player.add(new ContainerTrait({ capacity: 100 })); return player; }}
export const story = new MyAdventure();export default story;Using AuthorModel for Setup
When placing items inside closed containers during world setup, normal game rules block the action (“the chest is closed”). Use AuthorModel to bypass validation:
import { WorldModel, EntityType, IdentityTrait, ContainerTrait, OpenableTrait, AuthorModel,} from '@sharpee/world-model';
export function createHouse(world: WorldModel) { // ... rooms ...
const chest = world.createEntity('chest', EntityType.OBJECT); chest.add(new IdentityTrait({ name: 'wooden chest', description: 'A sturdy wooden chest with iron bands.', })); chest.add(new ContainerTrait({ capacity: 10 })); chest.add(new OpenableTrait({ isOpen: false })); world.moveEntity(chest.id, library.id);
const gem = world.createEntity('gem', EntityType.OBJECT); gem.add(new IdentityTrait({ name: 'sparkling gem', description: 'A gem that catches the light.', })); // AuthorModel skips "container is closed" validation const author = new AuthorModel(world.getDataStore(), world); author.moveEntity(gem.id, chest.id);
// ...}Build Your Story
Build the .sharpee bundle and browser client:
npx @sharpee/sharpee buildThis produces:
dist/my-adventure.sharpee— Story bundle for the Zifmia desktop runnerdist/web/— Browser client you can host anywhere
To play, open dist/web/index.html in your browser — no server needed.
Try these commands in the game:
look— describe the current roomnorthorn— move northexamine book— look at somethingtake key— pick up an iteminventory— see what you’re carrying
Next Steps
- Learn about Rooms and Regions in the Author Guide
- Add Objects and Traits for interactive items
- Create NPCs with conversations
- Explore the Design Patterns map for IF design inspiration