An open-source text-based multi-user dungeon (MUD) built with Next.js, Supabase, and AI. Create immersive worlds where players explore interconnected regions, interact with intelligent NPCs, and shape emergent narratives through collaborative gameplay.
🎮 Try the Live Demo - Experience a fully customized world built with Arkyv Engine!
📚 Visit Arkyv.org - Includes a web-based setup manual and a basic demo game!
This is the Supabase Edition - the stable, production-ready version of Arkyv Engine.
🚀 SpacetimeDB Edition (Experimental) - A rewrite using SpacetimeDB with enhanced real-time multiplayer features. The goal is to make Arkyv Engine fully open source without requiring cloud-based hosting providers - everything containerized and self-hostable with true persistent world state.
| Feature | Supabase Edition | SpacetimeDB Edition |
|---|---|---|
| Status | ✅ Stable | |
| Setup | Easy (cloud) | Moderate (self-host) |
| Hosting | Supabase + Vercel | Fully containerized |
| Real-time | Good | Excellent |
| Tech Stack | TypeScript/Next.js | Rust + TypeScript |
| Best For | Quick start, production | Advanced users, full control |
I grew up playing MUDs and always wondered where they all went. I guess hosting was expensive and people moved on to graphical games, but as a huge reader and fan of sci-fi and fantasy, I've always loved the power of text-based storytelling and imagination.
So I built Arkyv Engine—a modern MUD system that's actually easy to host. With free tiers on Supabase and Vercel, and AI to help generate content, anyone can now create and run their own text-based world without breaking the bank or needing a CS degree.
This is for the dreamers, the storytellers, and anyone who believes that the best graphics are the ones in your mind.
- 🎮 Real-time Multiplayer - Explore worlds with other players in real-time
- 🤖 AI-Powered NPCs - Dynamic conversations with intelligent characters
- 🗺️ Visual World Builder - Admin panel for creating and managing rooms
- 💬 Region Chat - Communicate with players in the same area
- 🎵 Dynamic Soundscapes - Ambient audio that changes with location
- 🎨 AI Image Generation - Generate pixel art for rooms and NPCs
- 🔐 Secure Authentication - Supabase Auth with Row Level Security
- Frontend: Next.js 15, React 19, Tailwind CSS
- Backend: Supabase (PostgreSQL, Auth, Realtime, Edge Functions)
- AI Providers: OpenAI or Grok (your choice)
- Image Generation: RetroDiffusion API
- Deployment: Vercel (recommended)
Before you begin, you'll need accounts with the following services:
- Node.js (v18 or higher)
- Supabase - Free tier available
- OpenAI OR Grok - Choose one
- RetroDiffusion (optional, for AI image generation)
- Vercel (optional, for deployment)
For a comprehensive interactive setup guide, visit /setup in your local or deployed app!
The rest of this README provides the same instructions in text format.
Whether you use Docker or deploy to Vercel, you must complete these steps in order:
- ✅ Supabase Setup - Create project, run migration, enable realtime, create storage buckets
- ✅ Get API Keys - Choose OpenAI or Grok for AI (required for NPCs)
- ✅ Deploy Edge Functions - Deploy command processor to Supabase
- ✅ Choose Deployment - Either Docker (self-host) OR Vercel (cloud)
Docker does NOT replace Supabase! It only runs the Next.js app. You still need Supabase (free tier) for database, auth, and realtime features.
git clone https://github.com/SeloSlav/arkyv-engine.git
cd arkyv-enginenpm install- Go to supabase.com and sign up/login
- Click "New Project"
- Fill in project details:
- Name:
arkyv-engine(or your preferred name) - Database Password: Choose a strong password (save this!)
- Region: Select closest to you
- Name:
- Click "Create new project" and wait for it to initialize (~2 minutes)
- In your Supabase project, go to the SQL Editor (left sidebar)
- Click "New query"
- Open
supabase/sql/migrate.sqlfrom this repository - Copy the entire contents and paste into the SQL Editor
- Click "Run" to execute the migration
- You should see: "Success. No rows returned"
This creates all necessary tables: regions, rooms, characters, profiles, npcs, exits, commands, room_messages, and region_chats.
The migration automatically enables realtime for the 5 critical tables. You can verify this in Supabase:
- Go to Table Editor (left sidebar)
- Check that these tables have realtime enabled (paper plane icon
✈️ should be highlighted):room_messages- For terminal messagesregion_chats- For region chatcharacters- For player movementsnpcs- For NPC interactionsprofiles- For profile mode
Note: If for some reason realtime wasn't automatically enabled, you can manually enable it by clicking the "Enable Realtime" button on each table.
- Click Storage in the left sidebar
- Click "New bucket"
- Create first bucket:
- Name:
room-images - Public bucket: ✅ Check this box
- Click "Create bucket"
- Name:
- Create second bucket:
- Name:
npc-portraits - Public bucket: ✅ Check this box
- Click "Create bucket"
- Name:
These are required for AI image generation to work.
- Go to Project Settings → API
- Copy these values (you'll need them for
.env.local):- Project URL (e.g.,
https://xxxxx.supabase.co) - anon public key
- service_role key (keep this secret!)
- Project URL (e.g.,
You only need ONE of these:
- Go to openai.com/api
- Sign up or login
- Navigate to API Keys
- Click "Create new secret key"
- Copy the key (starts with
sk-...)
- Go to x.ai/api
- Sign up or login
- Get your API key from the dashboard
- Copy the key
Copy the example file:
cp .env.example .env.localOpen .env.local and add your keys:
# Supabase Configuration
NEXT_PUBLIC_SUPABASE_URL=https://xxxxx.supabase.co
NEXT_PUBLIC_SUPABASE_ANON_KEY=your_anon_key_here
SUPABASE_SERVICE_ROLE_KEY=your_service_role_key_here
# AI Provider Configuration
# Set to "openai" or "grok" depending on which you're using
AI_PROVIDER=openai
# OpenAI API Key (if using OpenAI)
OPENAI_API_KEY=sk-your_key_here
# Grok API Key (if using Grok)
GROK_API_KEY=your_grok_key_here
# RetroDiffusion (optional - for AI image generation)
RETRO_DIFFUSION_API_KEY=your_retro_key_hereImportant: You only need to fill in the API key for the provider you're using!
The command processor runs as a Supabase Edge Function to handle game commands.
npm install -g supabasesupabase loginsupabase link --project-ref your-project-refFind your project ref in your Supabase project URL: https://supabase.com/dashboard/project/YOUR-PROJECT-REF
CRITICAL: Edge Functions need their own environment variables, separate from your local .env.local file!
📍 Find Your Supabase URL: Click the "Connect" button in the top header of your Supabase Dashboard to copy your project URL.
Method 1: Using Supabase Dashboard (Recommended)
- Go to Project Settings → Edge Functions (in left sidebar)
- Scroll down to "Secrets" section
- Click "Add new secret" for each variable below
All 10 Required Secrets:
| Secret Name | Value | Notes |
|---|---|---|
SUPABASE_URL |
Auto-provided ✓ | Your project URL |
EDGE_SUPABASE_URL |
https://xxxxx.supabase.co | MUST ADD! |
SUPABASE_ANON_KEY |
Auto-provided ✓ | Public anon key |
SUPABASE_SERVICE_ROLE_KEY |
Auto-provided ✓ | Service role key |
EDGE_SERVICE_ROLE_KEY |
your_service_role_key | MUST ADD! |
SUPABASE_DB_URL |
Auto-provided ✓ | Database URL |
AI_PROVIDER |
openai or grok | MUST ADD! |
OPENAI_API_KEY |
sk-your_key | MUST ADD (if using OpenAI) |
GROK_API_KEY |
your_grok_key | MUST ADD (if using Grok) |
RETRO_DIFFUSION_API_KEY |
your_retro_key | Optional - for AI images |
🚨 CRITICAL: You MUST add all secrets marked "MUST ADD!" AND at least ONE AI provider key (OpenAI or Grok) for NPCs to work!
Method 2: Using CLI (Alternative)
If you prefer command line:
# Set the EDGE_ prefixed versions (REQUIRED!)
supabase secrets set EDGE_SUPABASE_URL=https://xxxxx.supabase.co
supabase secrets set EDGE_SERVICE_ROLE_KEY=your_service_role_key
# Set your AI provider and key
supabase secrets set AI_PROVIDER=openai
supabase secrets set OPENAI_API_KEY=sk-your_key_here
# OR for Grok:
# supabase secrets set GROK_API_KEY=your_grok_key_here
# Optional: For AI image generation
supabase secrets set RETRO_DIFFUSION_API_KEY=your_key_hereEDGE_SUPABASE_URL matches your project URL exactly!
supabase functions deploy command-processorYou should see: "Deployed Function command-processor"
The admin panel uses a database column to control who has admin access.
- Start the dev server:
npm run dev - Go to
http://localhost:3000 - Click "Sign In to Try Demo" → "Need an account? Sign Up"
- Create your admin account
- Go to your Supabase project
- Navigate to Authentication → Users (left sidebar)
- Find your newly created user
- Copy the UUID (looks like:
e00d825e-cf13-45ad-a886-c7ff9721da0b)
After running the migration, you need to manually grant yourself admin access. Choose one method:
Option A: Using SQL (Recommended)
- In Supabase, go to SQL Editor
- Click "New query"
- Run this query (replace with your copied UUID):
UPDATE public.profiles
SET is_admin = true
WHERE user_id = 'your-uuid-here';- Click "Run"
- You should see: "Success. 1 rows affected"
Option B: Using Table Editor
- Go to Table Editor → profiles
- Find your user row
- Click the is_admin checkbox to set it to
true - Changes save automatically
Start the development server (if not already running):
npm run devOpen http://localhost:3000 in your browser.
Now that you have admin access, you can create your first rooms!
Navigate to http://localhost:3000/admin - you should now have access to the world builder!
- Scroll down to "Regions Management"
- Click "Create New Region"
- Fill in:
- Name:
Mystical Forest(the system auto-normalizes to lowercase with hyphens) - Description: A brief description of the region's theme
- Name:
- Click "Create Region"
- In the map area at the top, right-click on empty space
- Select "Create new room here"
- Fill in:
- Name:
Forest Clearing - Description: A vibrant description of the location
- Region: Select
Mystical Forest
- Name:
- Click "Create Room"
Tip: You can use the AI assistance buttons to generate names and descriptions!
- Click on your room node to open the room editor
- In the "Exits" section, click a direction (e.g., North)
- Choose "Generate New Room (AI)" or "Create Blank Room"
- Fill in details and click "Create Room"
- Scroll to "NPCs Management"
- Click "Create New NPC"
- Fill in details and assign to a room
- NPCs will respond to the
talkcommand!
- Navigate to
http://localhost:3000/play - Click "Create a new character"
- Enter a name and click "Enter Arkyv as [name]"
- Use commands to explore:
look- View current roomnorth- Move north (or any direction)who- See who's in the roomtalk [npc]- Talk to an NPChelp- See all commands
Using Table Editor (Easiest):
- Go to Table Editor → profiles
- Find the user row
- Click the
is_admincheckbox to toggle it - Changes save automatically
Using SQL (Alternative):
-- Add admin access
UPDATE public.profiles
SET is_admin = true
WHERE user_id = 'another-user-uuid';
-- Remove admin access
UPDATE public.profiles
SET is_admin = false
WHERE user_id = 'user-uuid-to-demote';Prerequisites: You must complete the Supabase Setup and Edge Functions deployment sections first. Docker only runs the Next.js app - Supabase is external.
Quick Start with Docker:
# 1. Clone the repo
git clone https://github.com/SeloSlav/arkyv-engine.git
cd arkyv-engine
# 2. Complete Supabase setup (see sections 3.1 - 3.4 below)
# - Create Supabase project
# - Run migration SQL (supabase/sql/migrate.sql)
# - Create storage buckets
# - Deploy edge functions
# 3. Create .env.local with your keys
cp .env.example .env.local
# Edit .env.local with your Supabase URL, keys, and AI provider key
# 4. Build and run with Docker Compose
docker-compose up -d
# Your MUD is now running at http://localhost:3000Manual Docker Build:
# Build the image
docker build -t arkyv-engine .
# Run the container
docker run -p 3000:3000 --env-file .env.local arkyv-engineWhat Docker Handles:
- ✅ Next.js application (frontend & API routes)
- ✅ Consistent Node.js environment
- ✅ Easy updates and restarts
- ✅ Works on any platform (Windows, Mac, Linux)
What You Still Need to Set Up:
⚠️ Supabase project (database, auth, storage, realtime) - Free tier available⚠️ Supabase Edge Functions deployment (command processor)⚠️ AI provider API key (OpenAI or Grok) - Required for NPCs⚠️ RetroDiffusion API key (optional, for images)
Why? Supabase and AI APIs are external services that can't be containerized. Docker makes the app setup trivial, but you'll always need these external services (which offer free tiers).
git init
git add .
git commit -m "Initial commit"
git remote add origin https://github.com/yourusername/your-repo.git
git push -u origin main- Go to vercel.com
- Click "Add New" → "Project"
- Import your GitHub repository
- In "Environment Variables", add:
NEXT_PUBLIC_SUPABASE_URL=https://xxxxx.supabase.co
NEXT_PUBLIC_SUPABASE_ANON_KEY=your_anon_key
SUPABASE_SERVICE_ROLE_KEY=your_service_role_key
AI_PROVIDER=openai
OPENAI_API_KEY=sk-your_key
RETRO_DIFFUSION_API_KEY=your_key
- Click "Deploy"
Note: Admin access is now managed via the database is_admin column, so no admin-specific environment variables are needed!
- In Supabase, go to Authentication → URL Configuration
- Add your Vercel URL to "Site URL"
- Add
https://your-app.vercel.app/**to "Redirect URLs"
arkyv-engine/
├── pages/
│ ├── index.js # Landing page
│ ├── play.js # Main game interface
│ ├── admin.js # World builder
│ ├── auth.js # Authentication
│ ├── profile.js # User settings
│ └── api/ # Next.js API routes
├── components/
│ ├── ArkyvTerminal.js # Game terminal
│ ├── RoomChatWindow.js # Region chat
│ ├── ArkyvAudioManager.js # Sound system
│ └── ...
├── supabase/
│ ├── sql/
│ │ └── migrate.sql # Database schema
│ └── functions/
│ └── command-processor/
│ ├── index.ts # Command handler
│ └── aiProvider.ts # AI integration
├── lib/
│ ├── supabaseClient.js # Supabase client
│ └── aiProvider.js # AI provider helper
└── styles/
└── global.css # Global styles
Arkyv Engine supports background music for each region. Here's how to add it:
Create a folder in public/audio/ matching your region name (lowercase with hyphens):
mkdir public/audio/my-region-namePlace your .mp3 files in the folder:
public/audio/my-region-name/
├── track1.mp3
├── track2.mp3
└── track3.mp3
Open components/ArkyvAudioManager.js and add your region to STATIC_PLAYLISTS:
const STATIC_PLAYLISTS = {
'my-region-name': [
'/audio/my-region-name/track1.mp3',
'/audio/my-region-name/track2.mp3',
'/audio/my-region-name/track3.mp3',
],
};That's it! Music will automatically play when players enter rooms in that region.
Want specific rooms to have different music than their region? Use room overrides!
💡 Example Use Case: Imagine you have a "Forest Region" with ambient nature sounds playing throughout. Most forest rooms use that regional playlist, but when players enter "The Tavern" room, you want lively medieval music instead. That's where room overrides shine! (Think Elwynn Forest ambient music vs Goldshire Inn tavern music if you're a WoW fan.)
1. Create override folder:
mkdir public/audio/override2. Get the room UUID:
- Open the Admin Panel (
/admin) - Click on the room you want to customize
- Copy the UUID from the URL or room editor
3. Add to data/roomAudioOverrides.js:
const ROOM_AUDIO_OVERRIDES = {
'room-uuid-here': [
'/audio/override/special-track.mp3',
'/audio/override/another-track.mp3',
],
};Priority: Room overrides take precedence over region playlists.
Why Static Files? We use static audio files for simplicity and performance. Audio files are large, and serving them statically from the CDN is much faster than database storage. In the future, we may add a UI to manage these mappings in the admin panel, but the actual audio files will remain static for optimal delivery.
north,south,east,west(orn,s,e,w)up,down(oru,d)northeast,northwest,southeast,southwest(orne,nw,se,sw)
say <message>- Speak to everyone in the roomwhisper <character> <message>- Private message to a characterlook- Examine current locationwho- See who's in the roominspect <name>- View character/NPC detailsset handle <name>- Set your display name (profile mode only)
talk <npc> <message>- Start conversation with NPCexit- End current conversation
help- Show all commandsexits- View available exits
npm install -D tailwindcss postcss autoprefixer @tailwindcss/postcssMake sure .env.local has all required Supabase keys.
- Check your
AI_PROVIDERis set to"openai"or"grok" - Verify your API key is correct
- Ensure you have API credits/quota available
# Check function logs
supabase functions serve command-processor
# Redeploy
supabase functions deploy command-processorIf commands process but you don't see NPC responses or messages:
- Go to Table Editor in Supabase Dashboard
- For each table, click the "Enable Realtime" button (paper plane icon
✈️ ) at top right - Enable for these 5 tables:
room_messages,region_chats,characters,npcs,profiles - Refresh your browser
If commands aren't being processed at all:
- Check Edge Function URL - In Supabase Dashboard → Edge Functions → Logs, look for "URL: https://..." in the logs. It MUST match your project URL exactly (find your URL by clicking "Connect" in the dashboard header).
- Update the secrets (set BOTH):
supabase secrets set SUPABASE_URL=https://your-correct-url.supabase.co supabase secrets set EDGE_SUPABASE_URL=https://your-correct-url.supabase.co supabase secrets set SUPABASE_SERVICE_ROLE_KEY=your_service_role_key supabase secrets set EDGE_SERVICE_ROLE_KEY=your_service_role_key
- Redeploy:
supabase functions deploy command-processor
- Verify Edge Function has ALL required environment variables set:
You should see 10+ secrets including both EDGE_ prefixed and non-prefixed versions.
supabase secrets list
Contributions are welcome! Please feel free to submit a Pull Request.
- Fork the repository
- Create your feature branch (
git checkout -b feature/AmazingFeature) - Commit your changes (
git commit -m 'Add some AmazingFeature') - Push to the branch (
git push origin feature/AmazingFeature) - Open a Pull Request
This project is open source and available under the MIT License.
- GitHub Issues: Report bugs or request features
- Documentation: Check this README and code comments
- Community: Star the repo to show support!
- Built with Next.js
- Powered by Supabase
- AI by OpenAI / Grok
- Images by RetroDiffusion
Happy world building! 🎮✨
