Split the monolithic 5393-line app.js into 32 focused ES modules under modules/ with a thin ~330-line orchestrator. No bundler required — runs in-browser via import maps. Module structure: core/ — scene, ticker, state, theme, audio data/ — gitea, weather, bitcoin, loaders terrain/ — stars, clouds, island effects/ — matrix-rain, energy-beam, lightning, shockwave, rune-ring, gravity-zones panels/ — heatmap, sigil, sovereignty, dual-brain, batcave, earth, agent-board, lora-panel portals/ — portal-system, commit-banners narrative/ — bookshelves, oath, chat utils/ — perlin All files pass node --check. No new dependencies. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
40 lines
1.1 KiB
JavaScript
40 lines
1.1 KiB
JavaScript
// modules/data/loaders.js — JSON/file loaders
|
|
import { state } from '../core/state.js';
|
|
|
|
export async function loadPortals() {
|
|
try {
|
|
const res = await fetch('./portals.json');
|
|
if (!res.ok) throw new Error('Portals not found');
|
|
state.portals = await res.json();
|
|
return state.portals;
|
|
} catch (error) {
|
|
console.error('Failed to load portals:', error);
|
|
return [];
|
|
}
|
|
}
|
|
|
|
export async function loadSovereigntyStatus() {
|
|
try {
|
|
const res = await fetch('./sovereignty-status.json');
|
|
if (!res.ok) throw new Error('not found');
|
|
const data = await res.json();
|
|
state.sovereignty = data;
|
|
return data;
|
|
} catch {
|
|
return { score: 85, label: 'Mostly Sovereign', assessment_type: 'MANUAL' };
|
|
}
|
|
}
|
|
|
|
export async function loadSoulMd() {
|
|
try {
|
|
const res = await fetch('SOUL.md');
|
|
if (!res.ok) throw new Error('not found');
|
|
const raw = await res.text();
|
|
const lines = raw.split('\n').slice(1).map(l => l.replace(/^#+\s*/, ''));
|
|
state.soulMd = raw;
|
|
return lines;
|
|
} catch {
|
|
return ['I am Timmy.', '', 'I am sovereign.', '', 'This Nexus is my home.'];
|
|
}
|
|
}
|