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
npm run build:storyWhat Happens During Build
- Finds Ink Files - Scans
src/directory for all.inkfiles - Compiles Ink to JSON - Converts Ink scripts to JSON format using inkjs or inklecate
- Copies Assets - Copies all assets from
src/to build directory (excluding.inkfiles) - Generates Manifests - Creates manifest files listing all compiled Ink scripts
- Creates Archive - Packages everything into
dist/story-build.zip - Cleanup - Removes temporary build directory
Build Output
After a successful build:
dist/
└── story-build.zip # Your packaged storyThe archive contains:
- Compiled Ink scripts (
.jsonfiles) - All assets (images, avatars)
- Contact definitions
- Conversation configurations
- Story metadata
- Manifest files
Build Logs
The build script provides detailed output:
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.zipTesting Your Story Locally
Before publishing, you can test your story in a browser using the local development server:
npm run run:storyThis 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
- Start the server - Run
npm run run:story - Browser opens - Navigate to
https://localhost:3000 - Make changes - Edit your Ink files, contacts, or conversations
- Save files - Changes are automatically deployed
- 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:
npm run build:story -- --watchThis 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:storyto test in browser - Watch Mode: Use
npm run build:story -- --watchfor automatic rebuilds - Both: Run watch mode in one terminal and
run:storyin another for the best development experience
Ink Compilation
Compiler Options
The build script tries multiple compilers in order:
- inkjs (preferred) - JavaScript-based Ink compiler
- inklecate (fallback) - Official Ink compiler
- Basic JSON (last resort) - Creates simple JSON structure
Installing Compilers
inkjs (included in dependencies):
npm installinklecate (optional, for better compatibility):
npm install -g inklecateCompilation Errors
If your Ink has syntax errors, the build will fail with error messages:
❌ Failed to compile src/ink/alex.ink:
Error: Expected '->' or 'END' but got 'invalid'
Line 42: invalid syntax hereCommon Issues:
- Missing
-> ENDat 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
- Visit the Stories Management Page
- Click the button to create a new story
- Fill in your story information:
- Story name
- Description
- Age rating
- Difficulty settings
- After creating the story, look at your browser's URL bar
- 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
- Example URL:
Step 2: Get Your API Key
- Visit the Manage Passport Tokens Page
- Create a new API token
- Give it a descriptive name (e.g., "My Story Publishing Key")
- Copy the API key immediately - you won't be able to see it again!
- 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
In your project folder, copy the example file:
bashcp .env.example .envOpen the
.envfile in any text editor (Notepad, VS Code, etc.)Fill in your credentials:
envBASE_URL=https://encounters.andyh.app STORY_ID=paste-your-uuid-here API_KEY=paste-your-api-key-hereSave 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
npm run publish:storyWhat Happens During Publish
- Builds Story - Runs
npm run build:storyautomatically - Validates Archive - Checks that
dist/story-build.zipexists - Reads Credentials - Loads
BASE_URL,API_KEY, andSTORY_IDfrom.env - Uploads Archive - Sends zip file to server via HTTP POST
- Shows Response - Displays server response with version information
Publish Output
Successful publish:
🔨 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:
Missing environment variable: API_KEYSolution: Check your .env file has all required variables.
Build Failed:
Build artifact not found: dist/story-build.zipSolution: Fix build errors before publishing.
Upload Failed:
❌ Upload failed: 401 UnauthorizedSolution: Check your API key is correct.
Server Error:
❌ Upload failed: 400 Bad Request
Invalid story formatSolution: 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:
- Make Changes - Edit your Ink files, assets, or conversation configurations
- Test Locally - Build and verify everything works
- 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}/versionsHeaders:
Authorization: Bearer {API_KEY}Accept: application/json
Body:
- Multipart form data with
filefield 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
.inkfiles are insrc/ink/directory - Verify file extensions are
.inknot.txt
"Failed to compile"
- Check Ink syntax in the failing file
- Test in Inky editor
- Look for missing
-> ENDstatements
"Failed to zip directory"
- Ensure
zipcommand is available on your system - Check disk space
- Verify write permissions on
dist/directory
Publish Issues
"Missing environment variable"
- Create
.envfile from.env.example - Fill in all required values
- Check for typos in variable names
"curl is required"
- Install curl:
sudo apt install curl(Linux) orbrew 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_URLis correct - Check
STORY_IDexists on the server - Ensure story was created on server first
Best Practices
Development Workflow
- Edit - Make changes to your story files
- Test Locally - Run
npm run run:storyto test in browser (optional but recommended) - Build - Run
npm run build:storyto test compilation - Verify - Check for errors and test the build
- Iterate - Fix any issues and rebuild
- Publish - When ready, run
npm run publish:story
Use Watch Mode
During active development:
# Terminal 1: Watch mode
npm run build:story -- --watch
# Terminal 2: Edit your files
# Builds happen automatically on saveVersion 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
- Build locally - Ensure no compilation errors
- Check file size - Large zips may fail to upload
- Verify assets - All images and files are included
- Test story flow - Walk through the narrative
- Update version - Increment version number
- 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
- Set up GitHub Actions for automatic deployment
- Review the Ink Scripting Guide for advanced techniques
- Check the Tag Reference for all available features