Memory Palace: A Narrative Interface for Macroscope
Memory Palace: A Narrative Interface for Macroscope
Document ID: CNL-SP-2026-001
Version: 0.1
Date: February 5, 2026
Author: Michael P. Hamilton, Ph.D.
AI Assistance Disclosure: This specification was developed collaboratively with Claude (Anthropic, Claude Opus 4.5). The AI contributed to architecture design, schema definition, and document drafting based on existing NodeWorlds codebase analysis and iterative discussion with the author. The author takes full responsibility for the content, accuracy, and design decisions.
Abstract
Memory Palace is a narrative interface layer for the Macroscope environmental monitoring platform. It transforms sensor data, geographic locations, and personal media into explorable text-based environments—interactive spaces where users navigate through memories, places, and time using natural language commands. The system combines the text adventure game paradigm with live environmental data, enabling users to create "palaces" that respond to real-world conditions: weather, bird activity, air quality, and seasonal change. This specification defines the architecture, data model, user interfaces, and integration points for Memory Palace within the Macroscope ecosystem. The initial implementation migrates the standalone NodeWorlds prototype into Macroscope, establishing Canemah (the Blue Heron Mill site) as the reference palace, then extends the platform with a Studio authoring environment and AI-assisted palace creation wizard.
1. Introduction
1.1 Background
NodeWorlds is a prototype text adventure engine developed in 2026 that integrates live sensor data into narrative descriptions. Players explore locations whose descriptions dynamically incorporate real-time weather, bird detections, and environmental conditions from the Macroscope sensor network. The prototype, currently available at https://michaelphamilton.com/nodeworlds/, demonstrated the viability of "living" interactive fiction—stories that breathe with the actual world.
Memory Palace generalizes this concept into a multi-tenant authoring platform. Any Macroscope user can create a palace—a navigable collection of locations, objects, and narrative text—and optionally bind locations to real places with live sensor feeds. Palaces can represent:
- Physical sites with environmental sensors (the Canemah model)
- Travel memories assembled from geotagged photographs
- Fictional worlds that borrow real-world weather
- Educational environments where students explore ecosystems
- Personal archives where objects contain journal entries
1.2 Objectives
- Migrate NodeWorlds functionality into Macroscope without breaking the existing demo
- Establish a multi-palace data model supporting independent worlds
- Integrate with existing Macroscope sensor APIs and place hierarchy
- Create a Studio interface for palace authoring
- Design an AI-assisted wizard for photograph-based palace creation
- Maintain the narrative quality established in the Canemah prototype
1.3 Scope
This specification covers:
- Database schema extensions to the Macroscope database
- Palace player (game engine) architecture
- Palace Studio (authoring interface) design
- Wizard workflow for AI-assisted creation
- API endpoints for palace operations
- Integration with Mapbox for geographic authoring
- Integration with Claude API for narrative generation
Out of scope:
- Mobile-native applications (web-responsive only)
- Multiplayer/synchronous experiences
- Monetization or subscription systems
- Export to other interactive fiction formats (Twine, Inform)
2. System Architecture
2.1 Component Overview
┌─────────────────────────────────────────────────────────────────┐
│ Macroscope │
├─────────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────────────┐ │
│ │ Palace │ │ Palace │ │ Existing │ │
│ │ Player │ │ Studio │ │ Macroscope UIs │ │
│ │ /palace/ │ │ /studio/ │ │ /domains/, etc. │ │
│ └──────┬──────┘ └──────┬──────┘ └─────────────────────┘ │
│ │ │ │
│ ▼ ▼ │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ Palace API │ │
│ │ /api/palace/ │ │
│ └──────────────────────────┬──────────────────────────────┘ │
│ │ │
│ ┌───────────────────┼───────────────────┐ │
│ ▼ ▼ ▼ │
│ ┌─────────────┐ ┌──────────────┐ ┌─────────────────┐ │
│ │ Palace │ │ Sensor │ │ Claude API │ │
│ │ Tables │ │ APIs │ │ (Wizard) │ │
│ │ │ │ (existing) │ │ │ │
│ └─────────────┘ └──────────────┘ └─────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────┘
2.2 Directory Structure
[MACROSCOPE_ROOT]/
├── palace/
│ ├── index.php # Palace directory/selection
│ ├── play.php # Game engine (player interface)
│ ├── parse.php # Command parser
│ ├── resolver.php # Sensor data resolver
│ └── assets/
│ ├── css/
│ │ └── palace.css # Player styles
│ └── js/
│ └── game.js # Player JavaScript
│
├── studio/
│ ├── index.php # Studio dashboard
│ ├── locations.php # Location editor
│ ├── objects.php # Object editor
│ ├── sensors.php # Sensor assignment
│ ├── wizard.php # AI creation wizard
│ ├── upload.php # Photo upload handler
│ └── assets/
│ ├── css/
│ │ └── studio.css
│ └── js/
│ ├── studio.js
│ ├── wizard.js
│ └── mapbox.js # Map interaction
│
├── api/palace/
│ ├── palaces.php # List, create, update palaces
│ ├── locations.php # CRUD for palace locations
│ ├── objects.php # CRUD for palace objects
│ ├── game.php # Game state, commands
│ ├── upload.php # Photo upload API
│ └── wizard.php # Wizard conversation API
2.3 Integration Points
| Component | Integration Method |
|---|---|
| Sensor Data | Existing Macroscope sensor APIs (/api/sensors/) |
| Places | Macroscope places table via place_id foreign key |
| Users | Macroscope users table, existing auth system |
| Images | New palace_images table or shared Macroscope assets |
| Maps | Mapbox GL JS, user-provided API key |
| AI Wizard | Claude API via server-side proxy |
3. Data Model
3.1 New Tables
3.1.1 palaces
Primary table for palace definitions.
CREATE TABLE `palaces` (
`id` INT NOT NULL AUTO_INCREMENT,
`slug` VARCHAR(50) NOT NULL UNIQUE,
`name` VARCHAR(100) NOT NULL,
`description` TEXT,
`owner_id` INT NOT NULL,
`starting_location_id` VARCHAR(50),
`cover_image_id` INT DEFAULT NULL,
`visibility` ENUM('public', 'private', 'unlisted') DEFAULT 'private',
`created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
`updated_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
KEY `idx_owner` (`owner_id`),
KEY `idx_visibility` (`visibility`),
CONSTRAINT `fk_palace_owner` FOREIGN KEY (`owner_id`)
REFERENCES `users` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
3.1.2 palace_locations
Locations within a palace. Each location may optionally link to a Macroscope place for sensor data.
CREATE TABLE `palace_locations` (
`id` INT NOT NULL AUTO_INCREMENT,
`palace_id` INT NOT NULL,
`location_id` VARCHAR(50) NOT NULL,
`name` VARCHAR(100) NOT NULL,
`description` TEXT,
`brief_description` TEXT,
`exits` JSON DEFAULT '{}',
`objects` JSON DEFAULT '[]',
`place_id` INT DEFAULT NULL,
`image_id` INT DEFAULT NULL,
`map_x` INT DEFAULT 0,
`map_y` INT DEFAULT 0,
`latitude` DECIMAL(10,8) DEFAULT NULL,
`longitude` DECIMAL(11,8) DEFAULT NULL,
`created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
UNIQUE KEY `idx_palace_location` (`palace_id`, `location_id`),
KEY `idx_place` (`place_id`),
CONSTRAINT `fk_location_palace` FOREIGN KEY (`palace_id`)
REFERENCES `palaces` (`id`) ON DELETE CASCADE,
CONSTRAINT `fk_location_place` FOREIGN KEY (`place_id`)
REFERENCES `places` (`id`) ON DELETE SET NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
3.1.3 palace_objects
Examinable and interactive objects.
CREATE TABLE `palace_objects` (
`id` INT NOT NULL AUTO_INCREMENT,
`palace_id` INT NOT NULL,
`object_id` VARCHAR(50) NOT NULL,
`name` VARCHAR(100) NOT NULL,
`examination` TEXT,
`portable` TINYINT(1) DEFAULT 0,
`image_id` INT DEFAULT NULL,
`created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
UNIQUE KEY `idx_palace_object` (`palace_id`, `object_id`),
CONSTRAINT `fk_object_palace` FOREIGN KEY (`palace_id`)
REFERENCES `palaces` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
3.1.4 palace_sensor_assignments
Binds available sensors to palace locations.
CREATE TABLE `palace_sensor_assignments` (
`id` INT NOT NULL AUTO_INCREMENT,
`palace_id` INT NOT NULL,
`sensor_id` INT NOT NULL,
`target_type` ENUM('location', 'object') NOT NULL,
`target_id` VARCHAR(50) NOT NULL,
`template_var` VARCHAR(50) NOT NULL,
`active` TINYINT(1) DEFAULT 1,
`created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
KEY `idx_palace_target` (`palace_id`, `target_type`, `target_id`),
CONSTRAINT `fk_sensor_palace` FOREIGN KEY (`palace_id`)
REFERENCES `palaces` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
3.1.5 palace_sessions
Player session state.
CREATE TABLE `palace_sessions` (
`id` INT NOT NULL AUTO_INCREMENT,
`palace_id` INT NOT NULL,
`session_id` VARCHAR(64) NOT NULL,
`current_location` VARCHAR(50) NOT NULL,
`inventory` JSON DEFAULT '[]',
`visited` JSON DEFAULT '[]',
`created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
`updated_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
UNIQUE KEY `idx_session` (`palace_id`, `session_id`),
CONSTRAINT `fk_session_palace` FOREIGN KEY (`palace_id`)
REFERENCES `palaces` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
3.1.6 palace_images
Image assets for palaces.
CREATE TABLE `palace_images` (
`id` INT NOT NULL AUTO_INCREMENT,
`palace_id` INT NOT NULL,
`filename` VARCHAR(255) NOT NULL,
`original_filename` VARCHAR(255),
`title` VARCHAR(100),
`alt_text` VARCHAR(255),
`description` TEXT,
`file_size` INT,
`width` INT,
`height` INT,
`latitude` DECIMAL(10,8) DEFAULT NULL,
`longitude` DECIMAL(11,8) DEFAULT NULL,
`taken_at` DATETIME DEFAULT NULL,
`upload_date` TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
KEY `idx_palace` (`palace_id`),
KEY `idx_coords` (`latitude`, `longitude`),
CONSTRAINT `fk_image_palace` FOREIGN KEY (`palace_id`)
REFERENCES `palaces` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
3.1.7 palace_command_log
Analytics for player behavior.
CREATE TABLE `palace_command_log` (
`id` BIGINT NOT NULL AUTO_INCREMENT,
`palace_id` INT NOT NULL,
`session_id` VARCHAR(64) NOT NULL,
`raw_input` VARCHAR(500),
`parsed_action` VARCHAR(50),
`parsed_target` VARCHAR(100),
`success` TINYINT(1),
`created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
KEY `idx_palace_session` (`palace_id`, `session_id`),
KEY `idx_created` (`created_at`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
3.2 Relationship to Existing Tables
| New Table | References | Relationship |
|---|---|---|
palaces |
users |
Owner of palace |
palace_locations |
places |
Optional link to Macroscope place for sensors |
palace_sensor_assignments |
Macroscope sensor infrastructure | Reuses available_sensors pattern |
3.3 Migration Strategy
The NodeWorlds tables (locations, objects, sensor_bindings, available_sensors, sensor_assignments, sessions, images, command_log) will be migrated to the new palace-scoped schema. Canemah becomes palace_id = 1.
4. Palace Player
4.1 Game Engine
The player is a web-based text interface that accepts natural language commands and returns narrative responses. Core mechanics:
| Command | Action |
|---|---|
| LOOK | Display current location description |
| GO/MOVE/ENTER [direction] | Navigate via exits |
| EXAMINE/LOOK AT [object] | Inspect objects |
| TAKE/PICK UP [object] | Add portable objects to inventory |
| INVENTORY | List carried items |
| MAP | Display node-graph map |
| HELP | Show available commands |
| RESTART | Reset session |
4.2 Sensor Resolution
Template variables in descriptions ({{temperature}}, {{bird_activity}}) are resolved at render time:
- Parse description for
{{variable}}patterns - Look up
palace_sensor_assignmentsfor matchingtemplate_var - Query appropriate Macroscope sensor API
- Apply staleness check (fallback text if data too old)
- Format and substitute into description
4.3 Visit Tracking
- First visit to a location: show
description - Return visit: show
brief_description(if defined) - LOOK command: always show full
description
4.4 Map Interface
A modal SVG/canvas map showing:
- Nodes for each location
- Edges for exits
- Current location highlighted
- Visited locations distinguished from unvisited
- Click-to-teleport for visited locations
5. Palace Studio
5.1 Dashboard
The Studio home displays:
- List of user's palaces
- Create new palace button
- Quick stats (locations, objects, sessions played)
- Link to wizard for AI-assisted creation
5.2 Palace Editor
Tabbed interface for editing a palace:
| Tab | Function |
|---|---|
| Settings | Name, slug, description, visibility, starting location |
| Locations | CRUD for locations, exits editor, map position |
| Objects | CRUD for objects, portability, images |
| Sensors | Assign sensors to locations/objects |
| Images | Upload and manage palace images |
| Preview | Playtest the palace |
| Analytics | Command logs, session stats |
5.3 Location Editor
- Rich text description editor with
{{variable}}insertion helper - Exits manager (keyword → destination dropdown)
- Objects picker (multi-select from palace objects)
- Optional link to Macroscope place (enables sensor binding)
- Geographic coordinates (manual entry or Mapbox picker)
- Node map position (drag on schematic view)
- Image assignment
5.4 Sensor Assignment
When a location is linked to a Macroscope place, available sensors for that place's platforms are shown. User can:
- Select a sensor
- Name the template variable
- Preview current sensor value
- Test resolution in context
6. Creation Wizard
6.1 Overview
The wizard transforms a collection of geotagged photographs into a palace through AI-assisted interview. It leverages Claude's vision and conversation capabilities to extract narrative from the user.
6.2 Workflow
┌─────────────────────────────────────────────────────────────────┐
│ 1. UPLOAD │
│ User drags photos → EXIF extraction → pins on Mapbox map │
└─────────────────────────────────┬───────────────────────────────┘
▼
┌─────────────────────────────────────────────────────────────────┐
│ 2. CLUSTER │
│ Photos grouped by proximity/time → user names clusters │
│ Clusters become candidate locations │
└─────────────────────────────────┬───────────────────────────────┘
▼
┌─────────────────────────────────────────────────────────────────┐
│ 3. INTERVIEW │
│ For each location, Claude asks: │
│ - What happened here? │
│ - What did you see/hear/feel? │
│ - Any objects of significance? │
│ Vision: Claude sees the photos, asks specific questions │
└─────────────────────────────────┬───────────────────────────────┘
▼
┌─────────────────────────────────────────────────────────────────┐
│ 4. GENERATE │
│ Claude produces: │
│ - Location descriptions (in user's voice) │
│ - Brief descriptions for return visits │
│ - Objects with examination text │
│ - Suggested exits based on chronology │
└─────────────────────────────────┬───────────────────────────────┘
▼
┌─────────────────────────────────────────────────────────────────┐
│ 5. REFINE │
│ User reviews in Studio editor │
│ Edit descriptions, adjust exits, add sensors │
│ Playtest and iterate │
└─────────────────────────────────┬───────────────────────────────┘
▼
┌─────────────────────────────────────────────────────────────────┐
│ 6. PUBLISH │
│ Set visibility: private / unlisted / public │
│ Share link: macroscope.nexus/palace/[slug] │
└─────────────────────────────────────────────────────────────────┘
6.3 EXIF Extraction
PHP's exif_read_data() extracts:
- GPS coordinates (latitude, longitude)
- Timestamp (date taken)
- Camera/device info
- Orientation
Photos without GPS data can be manually placed on the map.
6.4 Claude Integration
The wizard maintains a conversation with Claude via API:
{
"model": "claude-sonnet-4-20250514",
"max_tokens": 4096,
"system": "You are helping create a Memory Palace...",
"messages": [
{
"role": "user",
"content": [
{"type": "image", "source": {"type": "base64", "data": "..."}},
{"type": "text", "text": "This is stop 3: Lime Kiln Point..."}
]
}
]
}
6.5 Privacy Considerations
- Photos are processed server-side, not sent to external services except Claude API
- Users can exclude photos from AI processing
- EXIF stripping option before storage
- Private palaces visible only to owner
7. API Endpoints
7.1 Palace Management
| Endpoint | Method | Function |
|---|---|---|
/api/palace/palaces.php |
GET | List user's palaces |
/api/palace/palaces.php |
POST | Create new palace |
/api/palace/palaces.php?id=N |
PUT | Update palace |
/api/palace/palaces.php?id=N |
DELETE | Delete palace |
7.2 Game Engine
| Endpoint | Method | Function |
|---|---|---|
/api/palace/game.php |
POST | action=init — Start/resume session |
/api/palace/game.php |
POST | action=command — Process player command |
/api/palace/game.php |
POST | action=map — Get map data |
7.3 Studio Operations
| Endpoint | Method | Function |
|---|---|---|
/api/palace/locations.php |
GET/POST/PUT/DELETE | Location CRUD |
/api/palace/objects.php |
GET/POST/PUT/DELETE | Object CRUD |
/api/palace/upload.php |
POST | Image upload with EXIF |
/api/palace/wizard.php |
POST | Wizard conversation |
8. Implementation Phases
Phase 1: Migration (Week 1-2)
- [ ] Create palace schema in Macroscope database
- [ ] Migrate NodeWorlds data to
palace_id = 1(Canemah) - [ ] Port game engine to
/palace/play.php - [ ] Port sensor resolver to use Macroscope sensor APIs
- [ ] Verify Canemah plays correctly at new location (
macroscope.nexus/palace/canemah) - [ ] Maintain existing demo at
michaelphamilton.com/nodeworlds/(redirect or keep as legacy)
Phase 2: Multi-Palace (Week 3-4)
- [ ] Palace selection interface (
/palace/index.php) - [ ] Create palace flow
- [ ] Palace-scoped game sessions
- [ ] Basic Studio: settings, locations, objects
- [ ] Sensor assignment UI
Phase 3: Studio Polish (Week 5-6)
- [ ] Exits editor with visual map
- [ ] Image management
- [ ] Preview/playtest mode
- [ ] Analytics dashboard
- [ ] Public palace directory
Phase 4: Wizard (Week 7-10)
- [ ] Photo upload with EXIF extraction
- [ ] Mapbox clustering interface
- [ ] Claude API integration
- [ ] Interview conversation flow
- [ ] Content generation pipeline
- [ ] Review and refinement workflow
Phase 5: Launch (Week 11-12)
- [ ] Documentation
- [ ] User testing
- [ ] Performance optimization
- [ ] Public announcement
9. Technical Requirements
9.1 Server
- PHP 8.3+
- MySQL 8.4+
- Apache with mod_rewrite
- SSL certificate (HTTPS required)
9.2 External Services
| Service | Purpose | Requirement |
|---|---|---|
| Mapbox | Geographic authoring interface | API key (user-provided or platform) |
| Claude API | Wizard interview and generation | API key (platform-provided) |
9.3 Browser Support
- Chrome/Edge (current - 2)
- Firefox (current - 2)
- Safari (current - 2)
- Mobile browsers (iOS Safari, Chrome Android)
10. Future Considerations
10.1 Potential Extensions
- Collaborative editing — Multiple authors on one palace
- Branching narratives — State-dependent descriptions
- Time-based events — Descriptions that change by hour/season
- Audio integration — Ambient soundscapes, spoken narration
- Export formats — Twine, Inform, ePub
- Embedding — Palace player as iframe widget
10.2 Scaling Considerations
- Image CDN for high-traffic public palaces
- Read replicas for session queries
- Rate limiting on wizard API
- Caching for sensor resolution
11. References
[1] NodeWorlds prototype (2026). Live demo: https://michaelphamilton.com/nodeworlds/
[2] Macroscope platform (2025-2026). https://macroscope.nexus/
[3] Yates, F. A. (1966). The Art of Memory. University of Chicago Press.
[4] Mapbox GL JS Documentation. https://docs.mapbox.com/mapbox-gl-js/
[5] Anthropic Claude API Documentation. https://docs.anthropic.com/
Document History
| Version | Date | Changes |
|---|---|---|
| 0.1 | 2026-02-05 | Initial draft |
End of Specification
Cite This Document
BibTeX
Permanent URL: https://canemah.org/archive/document.php?id=CNL-SP-2026-016