Skip to content

Pages and templates

Rendering model

main_routers/pages_router.py renders Jinja2 templates from templates/. Shared template context includes asset versions; pages that can initialize VRM also receive the backend-owned lighting defaults.

Use root-relative asset URLs (/static/...). Electron windows and nested routes do not share the same URL depth, and relative asset paths can resolve differently.

Public page routes

RouteTemplatePurpose
/, /{lanlan_name}index.htmlMain UI and avatar renderer
/model_manager, legacy /l2dmodel_manager.htmlLive2D, VRM, MMD, and PNGTuber model management
/live2d_parameter_editorlive2d_parameter_editor.htmlLive2D parameter editing
/live2d_emotion_managerlive2d_emotion_manager.htmlLive2D motion/expression mapping
/vrm_emotion_managervrm_emotion_manager.htmlVRM expression mapping
/mmd_emotion_managermmd_emotion_manager.htmlMMD morph mapping
/character_card_manager, legacy /chara_managercharacter_card_manager.htmlCharacter cards and character settings
/api_keyapi_key_settings.htmlProvider and API-key settings
/voice_clonevoice_clone.htmlVoice-cloning workflow
/cloudsave_managercloudsave_manager.htmlCloud-save management
/memory_browsermemory_browser.htmlRecent conversation memory review and processing settings
/cookies_logincookies_login.htmlCookie-based login flow
/chatchat.htmlCompact standalone React chat surface
/chat_fullchat.htmlFull standalone React chat surface
/web_chat_compactindex.htmlMain-page template forced into compact chat mode
/subtitlesubtitle.htmlStandalone subtitle window
/agenthudagenthud.htmlAgent task HUD
/card_makercard_maker.htmlCharacter-card creation
/jukebox, /jukebox/managerjukebox.html, jukebox_manager.htmlJukebox and its manager
/toasttoast.htmlStandalone toast surface
/soccer_demo, /badminton_demomatching demo templatesMini-game development pages

/chara_manager redirects to /character_card_manager. /l2d is only a compatibility route; it is not a separate Live2D implementation.

The memory browser edits the recent conversation file exposed by the main server. It does not directly edit facts, reflections, persona data, archive shards, or retrieval indexes owned by the memory system.

Chat and subtitle windows

index.html and chat.html both mount the same React chat bundle into #react-chat-window-root. Their remaining hidden DOM nodes exist for compatibility with shared voice, session, and screenshot scripts; they are not a second chat UI.

Electron uses preload-provided APIs for native window behavior. chat.html checks window.nekoChatWindow; subtitle-window.js uses window.nekoSubtitle when present and otherwise remains usable as a web page. Inter-page state uses BroadcastChannel('neko_page_channel') and same-origin postMessage fallbacks. The Electron main process and preload implementation live outside this repository.

Theme

static/theme-manager.js initializes the theme before most page content to avoid a flash. Theme styles are in static/css/dark-mode.css; pages that need dark mode must load both resources and use the shared data attributes/CSS variables.

Static mounts

URL prefixContent
/staticVersioned application JS, CSS, images, bundled libraries, and locale JSON
/user_live2dActive user Live2D directory
/user_live2d_localWritable local shadow when the active Live2D directory differs
/user_vrm, /user_vrm/animationUser VRM models and VRMA animations
/user_mmd, /user_mmd/animationUser MMD models and VMD animations
/user_pngtuberNormalized PNGTuber packages
/user_modsConfigured local mod directory
/workshopSteam Workshop content, mounted during startup when available

Mounts are conditional on their backing directories. API responses already return public URLs; clients must not reconstruct them from local paths.