Skip to content

Build and Publish

Learn how to build your Encounters story and publish it to a server.

Building Your Story

The build process compiles your Ink scripts, packages assets, and creates a deployable archive.

Build Command

bash
npm run build:story

What Happens During Build

  1. Finds Ink Files - Scans src/ directory for all .ink files
  2. Compiles Ink to JSON - Converts Ink scripts to JSON format using inkjs or inklecate
  3. Copies Assets - Copies all assets from src/ to build directory (excluding .ink files)
  4. Generates Manifests - Creates manifest files listing all compiled Ink scripts
  5. Creates Archive - Packages everything into dist/story-build.zip
  6. Cleanup - Removes temporary build directory

Build Output

After a successful build:

dist/
└── story-build.zip    # Your packaged story

The archive contains:

  • Compiled Ink scripts (.json files)
  • All assets (images, avatars)
  • Contact definitions
  • Conversation configurations
  • Story metadata
  • Manifest files

Build Logs

The build script provides detailed output:

bash
Found 3 .ink files:
  - src/ink/alex.ink
  - src/ink/mum.ink
  - src/ink/family-group.ink

Compiling src/ink/alex.ink -> dist/build/ink/alex.json
 Successfully compiled alex.ink
Compiling src/ink/mum.ink -> dist/build/ink/mum.json
 Successfully compiled mum.ink
Compiling src/ink/family-group.ink -> dist/build/ink/family-group.json
 Successfully compiled family-group.ink

🎉 Ink compile: 3/3 files compiled successfully
🗂️  Wrote root manifest: dist/build/manifest.json
🗜️  Zipped build to dist/story-build.zip
🧹 Removed temporary build directory: dist/build

 Build complete. Archive located at: dist/story-build.zip

Testing Your Story Locally

Before publishing, you can test your story in a browser using the local development server:

bash
npm run run:story

This will:

  • Start a local development server
  • Open your story in your browser at https://localhost:3000
  • Automatically deploy changes when you save files
  • Allow you to interactively test conversations and player choices

How Local Testing Works

  1. Start the server - Run npm run run:story
  2. Browser opens - Navigate to https://localhost:3000
  3. Make changes - Edit your Ink files, contacts, or conversations
  4. Save files - Changes are automatically deployed
  5. Restart story - Restart the story in the browser to see your changes

Development Workflow

Use npm run run:story for interactive testing, then use npm run build:story when you're ready to create the production build.

::: note Restart Required After saving changes, you'll need to restart the story session in the browser to see updates. The changes are deployed automatically, but each story session needs to be restarted to load the new version. :::

Watch Mode

For active development, use watch mode to automatically rebuild when files change:

bash
npm run build:story -- --watch

This will:

  • Build your story initially
  • Watch the src/ directory for changes
  • Automatically rebuild when you save files
  • Keep running until you press Ctrl+C

Development Workflow Options

  • Interactive Testing: Use npm run run:story to test in browser
  • Watch Mode: Use npm run build:story -- --watch for automatic rebuilds
  • Both: Run watch mode in one terminal and run:story in another for the best development experience

Ink Compilation

Compiler Options

The build script tries multiple compilers in order:

  1. inkjs (preferred) - JavaScript-based Ink compiler
  2. inklecate (fallback) - Official Ink compiler
  3. Basic JSON (last resort) - Creates simple JSON structure

Installing Compilers

inkjs (included in dependencies):

bash
npm install

inklecate (optional, for better compatibility):

bash
npm install -g inklecate

Compilation Errors

If your Ink has syntax errors, the build will fail with error messages:

bash
 Failed to compile src/ink/alex.ink:
Error: Expected '->' or 'END' but got 'invalid'
Line 42: invalid syntax here

Common Issues:

  • Missing -> END at the end of knots
  • Undefined knot references
  • Syntax errors in conditions
  • Unclosed brackets or quotes

Debugging Ink Scripts

Best Practice: Use Visual Studio Code with the Ink extension for writing:

  • Install the Ink extension in VS Code (search "Ink" by inkle in Extensions)
  • Get syntax highlighting and error detection as you type
  • Catch errors before building

Alternative: Use the Inky editor to test your Ink scripts before building.

Publishing to Server

Once your story is built, you can publish it to an Encounters server.

Prerequisites

Before you can publish, you need to set up your story and get your credentials.

Step 1: Create Your Story on the Server

  1. Visit the Stories Management Page
  2. Click the button to create a new story
  3. Fill in your story information:
    • Story name
    • Description
    • Age rating
    • Difficulty settings
  4. After creating the story, look at your browser's URL bar
  5. Copy the UUID (the long string of letters and numbers at the end)
    • Example URL: https://encounters.andyh.app/authors/test/stories/abc123-def456-ghi789
    • The UUID is: abc123-def456-ghi789
    • This is your STORY_ID

Step 2: Get Your API Key

  1. Visit the Manage Passport Tokens Page
  2. Create a new API token
    • Give it a descriptive name (e.g., "My Story Publishing Key")
  3. Copy the API key immediately - you won't be able to see it again!
  4. This is your API_KEY

Save Your API Key!

Make sure to copy and save your API key somewhere safe. If you lose it, you'll need to create a new one.

Step 3: Configure Your Environment File

  1. In your project folder, copy the example file:

    bash
    cp .env.example .env
  2. Open the .env file in any text editor (Notepad, VS Code, etc.)

  3. Fill in your credentials:

    env
    BASE_URL=https://encounters.andyh.app
    STORY_ID=paste-your-uuid-here
    API_KEY=paste-your-api-key-here
  4. Save the file

Security Warning

Never commit .env to version control! It contains sensitive API keys. Make sure .env is in your .gitignore file.

For Non-Technical Users

Think of the .env file as your personal login credentials for publishing. Keep it safe and don't share it with anyone!

Publish Command

bash
npm run publish:story

What Happens During Publish

  1. Builds Story - Runs npm run build:story automatically
  2. Validates Archive - Checks that dist/story-build.zip exists
  3. Reads Credentials - Loads BASE_URL, API_KEY, and STORY_ID from .env
  4. Uploads Archive - Sends zip file to server via HTTP POST
  5. Shows Response - Displays server response with version information

Publish Output

Successful publish:

bash
🔨 Building story...
[build output...]
 Build complete. Archive located at: dist/story-build.zip

📤 Uploading dist/story-build.zip -> https://server.com/api/stories/my-story/versions

 Upload complete. Server response:
{
  "id": "my-story-v2",
  "version": "1.1.0",
  "storyId": "my-story",
  "createdAt": "2025-10-18T14:30:00Z"
}

Publish Errors

Missing Environment Variables:

bash
Missing environment variable: API_KEY

Solution: Check your .env file has all required variables.

Build Failed:

bash
Build artifact not found: dist/story-build.zip

Solution: Fix build errors before publishing.

Upload Failed:

bash
 Upload failed: 401 Unauthorized

Solution: Check your API key is correct.

Server Error:

bash
 Upload failed: 400 Bad Request
Invalid story format

Solution: Ensure your story structure is correct.

Version Management

Story Versions

Each time you publish, a new version is created on the server. The server tracks:

  • Version number (e.g., "1.0.0", "1.1.0")
  • Upload timestamp
  • Story content (the zip file)

Updating Your Story

To release an update:

  1. Make Changes - Edit your Ink files, assets, or conversation configurations
  2. Test Locally - Build and verify everything works
  3. Publish - Run npm run publish:story

Each time you publish, a new version is automatically created on the server with an incremented version number.

Build Script Details

Script Location

The build script is at scripts/build-story.cjs.

Key Functions

findInkFiles(dir) - Recursively finds all .ink files

compileInkFile(inkPath) - Compiles a single Ink file to JSON

copyDirSync(src, dest) - Copies directory contents (excluding .ink files)

zipDirectory(sourceDir, outPath) - Creates zip archive

removeInkFiles(dir) - Removes .ink files from build (keeps only compiled JSON)

buildAllStories() - Main build function

Customizing the Build

You can modify scripts/build-story.cjs to:

  • Change output directory
  • Add custom validation
  • Include additional files
  • Modify manifest generation

Publish Script Details

Script Location

The publish script is at scripts/publish-story.cjs.

Key Functions

loadDotEnv(envPath) - Loads environment variables from .env

requireEnv(name) - Validates required environment variable exists

main() - Main publish function

API Endpoint

The script uploads to:

POST {BASE_URL}/api/stories/{STORY_ID}/versions

Headers:

  • Authorization: Bearer {API_KEY}
  • Accept: application/json

Body:

  • Multipart form data with file field containing the zip

Customizing the Publish

You can modify scripts/publish-story.cjs to:

  • Add custom headers
  • Change upload endpoint
  • Add pre-publish validation
  • Implement retry logic

Troubleshooting

Build Issues

"No .ink files found"

  • Check that .ink files are in src/ink/ directory
  • Verify file extensions are .ink not .txt

"Failed to compile"

  • Check Ink syntax in the failing file
  • Test in Inky editor
  • Look for missing -> END statements

"Failed to zip directory"

  • Ensure zip command is available on your system
  • Check disk space
  • Verify write permissions on dist/ directory

Publish Issues

"Missing environment variable"

  • Create .env file from .env.example
  • Fill in all required values
  • Check for typos in variable names

"curl is required"

  • Install curl: sudo apt install curl (Linux) or brew install curl (macOS)
  • Or modify script to use Node.js HTTP client

"401 Unauthorized"

  • Verify API key is correct
  • Check API key hasn't expired
  • Ensure API key has permission to upload stories

"404 Not Found"

  • Verify BASE_URL is correct
  • Check STORY_ID exists on the server
  • Ensure story was created on server first

Best Practices

Development Workflow

  1. Edit - Make changes to your story files
  2. Test Locally - Run npm run run:story to test in browser (optional but recommended)
  3. Build - Run npm run build:story to test compilation
  4. Verify - Check for errors and test the build
  5. Iterate - Fix any issues and rebuild
  6. Publish - When ready, run npm run publish:story

Use Watch Mode

During active development:

bash
# Terminal 1: Watch mode
npm run build:story -- --watch

# Terminal 2: Edit your files
# Builds happen automatically on save

Version Control

Commit to Git:

  • Source files (src/)
  • Scripts (scripts/)
  • Configuration (package.json, .env.example)

Don't Commit:

  • Build output (dist/)
  • Environment variables (.env)
  • Dependencies (node_modules/)

.gitignore example:

.env
node_modules/
dist/

Testing Before Publishing

  1. Build locally - Ensure no compilation errors
  2. Check file size - Large zips may fail to upload
  3. Verify assets - All images and files are included
  4. Test story flow - Walk through the narrative
  5. Update version - Increment version number
  6. Publish - Upload to server

Automated Deployment with GitHub Actions

Want to automatically build and publish your story every time you push to GitHub?

See the GitHub Actions Guide for step-by-step instructions on setting up automatic deployment.

Benefits:

  • ⚡ Automatic builds on every push
  • 🔒 Secure credential storage
  • 📝 Deployment history tracking
  • 🤝 Team collaboration without sharing API keys

Next Steps

Released under the MIT License.