JavaScript/MJS Mode for kidlisp.com - Feasibility Report #
Executive Summary #
Building a JavaScript/MJS editing mode for kidlisp.com is highly feasible and can reuse 70-80% of existing code. The kidlisp.com editor already uses Monaco (the VS Code editor), which has excellent built-in JavaScript/TypeScript support. The main work involves:
- Language mode switching (KidLisp ↔ JavaScript)
- Piece lifecycle integration (
boot,sim,paint,act) - File save/load via aesthetic.computer APIs
- Module resolution for imports
Current kidlisp.com Stack Analysis #
Monaco Editor (v0.52.0) #
- Already loaded: CDN from jsDelivr
- KidLisp language: Custom registration with syntax highlighting, bracket matching
- Built-in JS/TS support: Monaco has first-class JavaScript support including:
- Full IntelliSense and autocompletion
- Error checking (via TS compiler in web worker)
- Hover documentation
- Go to definition (within same file)
- Refactoring tools
Reusable Components (~70-80%) #
| Component | Status | Reuse Level |
|---|---|---|
| Monaco setup | ✅ | 90% - just add language toggle |
| Theme system (light/dark) | ✅ | 100% - works for any language |
| Keyboard shortcuts | ✅ | 95% - extend for JS-specific |
| Preview iframe | ✅ | 80% - needs piece loader |
| Play/Stop/Pause controls | ✅ | 90% - different execution model |
| Tab system (Learn/List) | ✅ | 70% - need JS docs |
| History/Recent | ✅ | 60% - different file format |
| Console output | ✅ | 100% - already logs JS errors |
| Auth (Auth0) | ✅ | 100% - same authentication |
| Mobile UI/responsive | ✅ | 100% - layout unchanged |
| URL routing | ✅ | 80% - different path scheme |
| Context menu | ✅ | 50% - need JS docs |
New Components Needed #
| Component | Complexity | Notes |
|---|---|---|
| Language switcher UI | Low | Tab or dropdown toggle |
| JS documentation | Medium | Can use TypeScript inference |
| Piece loader/runner | Medium | Load .mjs in iframe context |
| File save/load API | Medium | Save to user's disk storage |
| Module bundler | High | For imports like "../lib/..." |
| LSP integration (optional) | High | Full IDE experience |
AC Piece Architecture Analysis #
Piece Lifecycle Functions #
Every AC piece exports these optional functions:
// 📦 Boot - Called once when piece loads
export function boot(api) {
// api contains: wipe, resolution, store, params, colon, net, ...
}
// 🎨 Paint - Called every frame for rendering
export function paint(api) {
// api contains: wipe, ink, line, box, circle, screen, ...
}
// 🧮 Sim - Called every frame for logic (before paint)
export function sim(api) {
// api contains: num, store, sound, ...
}
// 🎬 Act - Called on user input events
export function act(api) {
// api.event contains: { is, pointer, key, ... }
}
The API Object #
The api object provides 200+ functions. Key categories:
- Drawing:
wipe,ink,line,box,circle,plot,paste - Screen:
resolution,screen.width,screen.height - Sound:
sound.synth,sound.play,sound.sample - Input:
pen,keyboard,gamepad - State:
store,params,colon - Network:
net.socket,net.udp - System:
jump,alias,download
Module Imports #
Pieces can import from the AC library:
import { getNoteColorWithOctave } from "../lib/note-colors.mjs";
import { drawMiniControllerDiagram } from "../lib/gamepad-diagram.mjs";
import * as graph from "./lib/graph.mjs";
This is the main complexity - we need import resolution.
Implementation Approaches #
Option A: In-iframe Editing (Simpler) #
Use the aesthetic.computer iframe as both editor and runtime:
kidlisp.com
├── Monaco Editor (left)
├── Preview iframe: aesthetic.computer/{piece} (right)
└── Live reload on code change
Pros:
- Full AC runtime available
- All imports work naturally
- Real piece execution
Cons:
- Slower feedback loop (full page reload)
- Harder to show errors inline
- Can't use AC's worker architecture
Option B: Sandboxed Execution (More Complex, Better UX) #
Run piece code in a controlled environment:
kidlisp.com
├── Monaco Editor (left)
├── Canvas preview (right)
├── Minimal AC runtime
├── Import map for modules
└── HMR-style updates
Pros:
- Instant preview updates
- Better error handling
- Could work offline
Cons:
- Need to bundle/mock AC runtime
- Import resolution complexity
- Subset of full functionality
Option C: Hybrid (Recommended) #
Start with Option A for full compatibility, add Option B features incrementally:
- Phase 1: Monaco + iframe reload (1-2 weeks)
- Phase 2: Live preview for simple pieces (2-3 weeks)
- Phase 3: Full import resolution via importmap (3-4 weeks)
Shared Module Architecture #
To make this reusable, extract a shared editor module:
system/public/aesthetic.computer/
├── lib/
│ └── ac-editor/
│ ├── editor-core.mjs # Monaco setup, themes
│ ├── language-kidlisp.mjs # KidLisp syntax
│ ├── language-js.mjs # JS/piece syntax extras
│ ├── preview-runner.mjs # Piece execution
│ ├── file-ops.mjs # Save/load/history
│ └── documentation.mjs # Docs for both languages
Usage:
// kidlisp.com
import { createEditor } from "/aesthetic.computer/lib/ac-editor/editor-core.mjs";
createEditor({ language: "kidlisp" });
// code.aesthetic.computer (future)
import { createEditor } from "/aesthetic.computer/lib/ac-editor/editor-core.mjs";
createEditor({ language: "javascript", pieceMode: true });
Technical Challenges #
1. Module Resolution #
Problem: Pieces use relative imports like "../lib/note-colors.mjs"
Solutions:
- Import maps: Native browser feature for module aliasing
- Service worker: Intercept module requests, rewrite URLs
- Bundler: Use esbuild-wasm to bundle on-the-fly
2. Piece API Injection #
Problem: Pieces expect api parameter with 200+ functions
Solutions:
- Build minimal runtime that provides drawing API
- Proxy to full AC runtime in iframe
- Use web workers for non-DOM operations
3. File Storage #
Problem: Where to save .mjs files?
Solutions:
- User's handle storage:
/api/user/{handle}/pieces/{name}.mjs - Local storage with cloud sync
- GitHub integration (oauth)
4. Error Display #
Problem: JS errors happen at runtime, not parse time
Solutions:
- Monaco's TypeScript checker catches many errors
- Window.onerror capture in preview iframe
- postMessage error events back to editor
Development Estimate #
| Phase | Work | Time |
|---|---|---|
| Phase 1: Language toggle + basic editing | 1 week | |
| Phase 2: Preview iframe integration | 1 week | |
| Phase 3: File save/load API | 1 week | |
| Phase 4: JS documentation in Learn tab | 1 week | |
| Phase 5: Import resolution (importmaps) | 2 weeks | |
| Phase 6: Polish + testing | 1 week | |
| Total | 8 weeks |
For an MVP (edit + preview + save):
- 3-4 weeks to functional editor
- +4 weeks for full IDE experience
Recommendations #
-
Start with language toggle: Add "KidLisp | JavaScript" tabs, let Monaco handle JS syntax natively.
-
Reuse preview iframe: Point to
aesthetic.computer/previewwith posted source code. This leverages existing piece loader. -
Build import map generator: Analyze imports, generate browser importmap for AC libraries.
-
Consider code.aesthetic.computer: A dedicated subdomain for the full IDE, separate from kidlisp.com's simpler focus.
-
API documentation: Auto-generate from JSDoc in AC source files, similar to KIDLISP_DOCS.
Conclusion #
The kidlisp.com architecture is well-suited for JavaScript mode extension. Monaco already supports JS, the preview infrastructure exists, and the UI patterns are proven. The main complexity is module resolution for imports - recommend using browser import maps as the cleanest solution.
A working prototype could be built in 2-3 weeks, with full IDE features in 8 weeks.