DZMM Builder
Overview
Build AI-driven interactive web applications on the DZMM.AI platform using specialized knowledge, complete examples, and reusable code patterns. This skill provides comprehensive support for creating single-file HTML applications that leverage streaming AI conversations, cloud key-value storage, and browser effect systems.
When to Use This Skill
Invoke this skill when users:
- Request creating a new DZMM application ("Build me a DZMM chatbot", "Create an AI story generator", "Make a dating sim game", "Build a social media content generator", "Create a visual novel", "Build an interactive fiction game")
- Ask questions about DZMM API usage ("How do I use dzmm.completions?", "How does KV storage work?", "How to parse structured AI output?", "How to use chat API for branching stories?", "How to implement streaming AI responses?")
- Need help debugging DZMM applications ("My DZMM app returns 400 error", "AI responses are not displaying", "State not persisting", "DZMM API not initializing")
- Want to optimize existing DZMM apps (performance, user experience, architecture improvements, mobile responsiveness, reduce token usage)
- Ask about "fourth wall breaking" effects or browser control from AI
- Need guidance on state management in games (stats, mood, relationships, dynamic UI)
- Want to integrate Markdown rendering or rich text formatting (nested structures, dialogue quotes, options buttons)
- Request configuration/setup UI for applications
- Need branching narrative systems (Galgame save/load, multi-route stories, choice history tracking)
- Ask about available models and their performance characteristics
- Request message management features ("How to add reroll/regenerate?", "How to let users edit messages?", "How to delete conversation branches?")
- Want multi-opening/multi-scenario systems ("How to add multiple starting scenes?", "How to switch between different story routes?")
- Need help migrating from React/Vue to DZMM ("How to migrate my app to DZMM?", "What's the DZMM equivalent of useState?", "Can I use React/TypeScript with DZMM?", "How to build DZMM apps with modern frameworks?", "vite-plugin-singlefile for DZMM", "My DZMM app has sandbox errors", "Form submission blocked in DZMM", "localStorage not working in DZMM", "HTTP 400 error with DZMM API", "maxTokens limit exceeded")
- Ask about resource management ("How to load images/audio in DZMM?", "Should I use URLs or embed resources?")
Core Capabilities
1. Application Generation
Generate complete, single-file HTML applications for the DZMM platform based on user requirements.
Approach:
- Clarify the application type and core features
- Select an appropriate architecture pattern (stateless generator, stateful dialogue, or layered cache platform)
- Use example templates from
assets/examples/as foundation - Customize for specific requirements
- Test the complete flow (initialization → AI call → display)
Architecture Patterns:
Stateless Generator - For one-shot content generation:
- Example: Translator, text summarizer, content creator, social media post generator
- No conversation history or state persistence
- Simplest architecture, fastest development
- Optional: Integrate marked.js for Markdown rendering
- Reference: See
assets/examples/小红书文案.htmlfor minimal implementation - Code snippets:
references/code-snippets.mdsection 2
State Management Game - For interactive games with dynamic variables:
- Example: Dating sims, RPG games, decision-based narratives
- Multiple state variables (stats, mood, time, relationships)
- Structured AI output parsing (###STATE/###END format)
- Configuration UI for game initialization
- State-driven UI updates (progress bars, backgrounds, effects)
- Auto-save with KV storage
- Reference: See
assets/examples/恋爱游戏.htmlfor complete implementation
Stateful Dialogue System - For multi-turn conversations:
- Example: Chatbots, interactive stories, Q&A systems
- Maintains conversation history
- Uses Alpine.store for state management
- Persists state with KV storage
- Reference: See
assets/examples/dungeon-adventure.htmlandassets/examples/horror-story.html
Layered Cache Platform - For content communities:
- Example: Forums, story libraries, content platforms
- Two-tier caching (list cache + detail cache)
- On-demand content generation
- Concurrent request locking
- Reference: See
assets/examples/贴吧.htmlfor full implementation
Visual Novel / Galgame System - For narrative-driven interactive fiction:
- Example: Visual novels, interactive stories, AI-driven narrative games
- Multi-opening scene system with dynamic switching
- Rich text rendering with placeholder technique (handles nested structures)
- Message management (reroll, edit, delete with context preservation)
- Multi-slot save/load system with preview
- Modular prompt system (main prompt + character + guidance + emphasis)
- Responsive mobile design with compressed UI
- Reference: See yoshiwara-chronicles project for complete implementation
- Key features: XML-structured prompts, <last_input> emphasis, streaming AI responses
2. API Integration Guidance
Provide detailed guidance on using DZMM's specialized APIs.
Core APIs:
window.dzmm.completions() - Streaming AI generation:
await window.dzmm.completions(
{
model: 'nalang-turbo-0826' | 'nalang-medium-0826' |
'nalang-max-0826' | 'nalang-xl-0826' |
'nalang-max-0826-16k' | 'nalang-xl-0826-16k',
messages: [{ role: 'user' | 'assistant', content: string }],
maxTokens: number // Optional, 200-3000, default 1000
},
(newContent, done) => {
// newContent is cumulative, not incremental
// done is true when generation completes
}
);
window.dzmm.chat - Tree-structured conversation storage (⭐ NEW):
// Insert messages into conversation tree (supports branching storylines)
const result = await window.dzmm.chat.insert(parentId, [
{ role: 'user', content: 'Player choice' },
{ role: 'assistant', content: 'Story response' }
]);
const newMessageIds = result.ids; // Array of new message IDs
// Get message details (with parent/children relationships)
const messages = await window.dzmm.chat.list(['msg-123', 'msg-124']);
// Returns: [{ id, role, content, timestamp, parent, children }, ...]
// Get complete conversation timeline
const timeline = await window.dzmm.chat.timeline(messageId);
const fullHistory = await window.dzmm.chat.list(timeline);
Use cases: Galgame save/load systems, branching narratives, multi-route stories, interactive fiction with choice history.
window.dzmm.kv - Cloud key-value storage:
// Save (auto-serializes objects)
await window.dzmm.kv.put(key, value);
// Load
const result = await window.dzmm.kv.get(key);
if (result.value) {
const data = result.value;
}
// Delete
await window.dzmm.kv.delete(key);
Limits: Keys ≤256 chars, values ≤1MB recommended. Development mode: data lost on refresh. Production: persistent.
Critical Requirements:
- Must wait for
dzmm:readyevent before any API calls - Only
userandassistantroles supported (nosystem) - Limit conversation history to ≤20 messages to avoid token overflow
- maxTokens range: 200-3000, default 1000
- Concurrent requests: ≤3 recommended
- Use versioned keys for KV storage (e.g.,
app_state_v1)
Reference: Consult references/developer-guide.md sections 2-3 for complete API documentation and references/code-snippets.md sections 1-3 for ready-to-use code patterns.
3. Effect System Implementation
Implement "fourth wall breaking" effects where AI can control the user's browser environment.
Effect Categories:
Visual Effects:
- Light control (dimming, darkness, flickering)
- Screen shake (low/medium/high intensity)
- Glitch effects
- Color filters (blood, blur, etc.)
Audio Effects:
- Programmatic sound generation (beeps, drones, heartbeats)
- Web Audio API without external files
- Ambient and tension-building sounds
Dynamic Elements:
- Particle systems (dust, blood, explosions)
- Jumpscare popups
- Element manipulation
Implementation Pattern:
// 1. AI outputs special instructions
const aiPrompt = `When the user says "turn off lights", output:
###EFFECT
{"action":"lights","params":{"state":"off"}}
###END`;
// 2. Parse and execute
const effectMatch = content.match(/###EFFECT\s*({[\s\S]*?})\s*###END/);
if (effectMatch) {
const effect = JSON.parse(effectMatch[1]);
executeEffect(effect);
// Remove instruction from display
content = content.replace(/###EFFECT[\s\S]*?###END/, '').trim();
}
// 3. Effect executor
function executeEffect(effect) {
switch(effect.action) {
case 'lights':
document.body.classList.add(`lights-${effect.params.state}`);
break;
// ... more effects
}
}
Reference: See assets/examples/horror-story.html for complete effect system with CSS animations, Web Audio, and Canvas particles.
4. Debugging and Optimization
Diagnose and fix common DZMM application issues.
Common Issues:
HTTP 400 Errors:
- Cause: Using
role: 'system'in messages (not supported) - Fix: Convert system prompts to first
usermessage or maintain in frontend variables - Cause: Messages array contains undefined/null values
- Fix: Validate and sanitize messages before sending
No Response from AI:
- Cause: API not ready yet
- Fix: Ensure
dzmm:readyevent is awaited before any API calls
Context Overflow:
- Cause: Too many messages or overly long content
- Fix: Slice messages array to last 10-20 items, truncate individual messages to 2000 chars
State Not Persisting:
- Cause: KV key naming conflicts or version mismatch
- Fix: Use versioned keys with unique identifiers
Form Submission Blocked (Public Release Only):
- Cause: DZMM public release uses iframe sandbox without
allow-formspermission - Error:
Blocked form submission to '' because the form's frame is sandboxed - Fix: Replace
<form>with<div>, use@clickinstead of@submit.prevent - Example:
<!-- ❌ WRONG: Will fail in public release --> <form @submit.prevent="handleSubmit()"> <button type="submit">Submit</button> </form> <!-- ✅ CORRECT: Works in all environments --> <div> <button type="button" @click="handleSubmit()">Submit</button> </div> - Note: This only affects public release, not development mode or workshop preview
Performance Optimization:
- Debounce user input to reduce API calls
- Implement two-tier caching for content-heavy apps
- Use concurrent request locks to prevent duplicate API calls
- Limit conversation history proactively
Reference: Consult references/developer-guide.md section "常见问题" for comprehensive troubleshooting guide.
5. Code Patterns and Snippets
Provide reusable, production-ready code patterns for common DZMM tasks.
Available Patterns:
- Initialization and API readiness (dual detection with timeout)
- AI completions (basic, multi-turn, streaming with real-time display)
- KV storage operations (save, load, delete, multi-slot, batch operations)
- Chat API operations (branching narratives, save/load, timeline retrieval)
- Instruction parsing systems (JSON, XML, ###STATE format)
- Alpine.js state management (local and global stores)
- Visual effect systems (CSS animations, particles, audio)
- Error handling and structured logging (retry with exponential backoff)
- Utility functions (debounce, sanitize, scroll control)
- Prompt templates (structured output, XML hierarchy, emphasis sections)
- Complete application templates
- Rich text rendering (placeholder technique for nested structures)
- Message management (reroll, edit, delete with context preservation)
- Multi-opening system (scene switching with state management)
- Resource management (URL-based asset loading, preloading)
- Modular prompt system (main + character + guidance + emphasis)
- Responsive layout patterns (mobile-first with Tailwind breakpoints)
Usage: Reference references/code-snippets.md for copy-paste ready code snippets organized by category. All snippets are tested and can be used directly or with minimal modifications.
New Visual Novel Patterns (from yoshiwara-chronicles):
- Rich text parser with placeholder technique
- Message reroll/edit/delete functions
- Opening scene switcher with confirmation
- Multi-slot save system with preview extraction
- Streaming AI response with auto-scroll
- XML-structured prompt builder
- Resource manager for external assets
Workflow Guide
For New Applications
-
Clarify Requirements
- Determine application type (chatbot, game, content platform, etc.)
- Identify core features and interactions
- Choose architecture pattern
-
Select Template
- Browse
assets/examples/for similar applications:小红书文案.html- Simple content generator, Markdown rendering恋爱游戏.html- Dating sim, multi-variable state managementhorror-story.html- Effect system, immersive experiencedungeon-adventure.html- Turn-based game, state managementneon-gomoku.html- AI opponent, game logic贴吧.html- Content platform, two-tier caching
- Browse
-
Build Application
- Start with HTML structure and Alpine.js integration
- Implement DZMM API initialization (wait for
dzmm:ready) - Add AI completions with appropriate model selection
- Implement state management and KV storage if needed
- Add visual effects or advanced features as required
-
Test and Refine
- Test initialization and API readiness
- Verify AI responses and parsing
- Check state persistence across page reloads
- Optimize performance (history limits, debouncing)
For Debugging Existing Applications
-
Identify the Issue
- Review error messages and console logs
- Check network requests in browser DevTools
- Verify API readiness timing
-
Diagnose Root Cause
- Cross-reference with common issues in
references/developer-guide.md - Check message format compliance (only
user/assistant) - Validate conversation history length
- Cross-reference with common issues in
-
Apply Fix
- Use code patterns from
references/code-snippets.md - Add error handling if missing
- Implement validation for user inputs and API responses
- Use code patterns from
-
Optimize
- Add performance improvements (caching, debouncing)
- Improve user experience (loading states, error messages)
- Enhance code maintainability (structured logging, modularity)
For Migrating React/Vue Applications to DZMM
Two Approaches Available:
Approach A: Keep React/Vue Framework (Recommended for Large Projects)
Use modern build tools to maintain component-based development, then bundle to single HTML.
Tech Stack: React + TypeScript + Vite + vite-plugin-singlefile
Workflow:
- Setup:
npm create vite@latest my-app -- --template react-ts - Install Plugin:
npm install -D vite-plugin-singlefile - Configure Vite: Add plugin for single-file build mode
- Develop: Keep existing React components structure
- Build:
npm run build:single→ generates standalone HTML - Deploy: Upload to DZMM platform
Key Considerations:
- ✅ Keep TypeScript type safety and component modularity
- ✅ Hot reload during development
- ✅ Rich ecosystem (shadcn/ui, React Router, etc.)
- ⚠️ Handle sandbox restrictions (localStorage, form submission)
- ⚠️ Enforce maxTokens limits (200-3000)
- ⚠️ Prevent consecutive same-role messages in API calls
Critical Fixes:
- localStorage: Implement fallback to memory storage
- Forms: Replace
<form>with<div>+ button onClick - maxTokens: Never exceed 3000 (API returns HTTP 400)
- Messages: Merge emphasis into last user message to avoid consecutive roles
See: Q11 in references/developer-guide.md for complete implementation guide
Approach B: Rewrite to Alpine.js (Lightweight Alternative)
Convert component hierarchy to single HTML with Alpine.js reactive sections.
-
Assessment
- Identify existing resources (images, audio, fonts) - these will be reused via URLs
- Map React/Vue components to Alpine.js x-show pages
- List state variables (useState/Vuex → Alpine data)
- Inventory API calls (fetch → dzmm.completions/kv)
-
Resource Strategy (Critical)
- DO NOT recreate visual assets with CSS - use GitHub Raw URLs
- Collect all image/audio file URLs from original project
- Create resource manager object with base URL
- Use Google Fonts or existing font CDN links
- Goal: 100% visual fidelity, not approximate simulation
-
Structure Migration
- Convert component hierarchy to single HTML with x-show sections
- Convert state management:
useState→ Alpine reactive data propertiesuseEffect→ Alpinex-initor watchersprops→ Alpine function parameters or computed properties
- Convert event handlers:
onClick={fn}→@click="fn"
-
API Migration
- Replace
fetch('/api/chat')withdzmm.completions() - Convert localStorage to
dzmm.kvoperations (or safe storage wrapper) - Add
dzmm:readyevent waiting - Implement streaming callbacks if needed
- Replace
-
Feature Additions (from yoshiwara-chronicles patterns)
- Add message management (reroll, edit, delete)
- Implement rich text rendering with placeholder technique
- Add multi-opening system if applicable
- Implement modular prompt system
- Add responsive mobile optimizations
-
Testing and Refinement
- Verify all resources load correctly (images, audio)
- Test DZMM API initialization
- Check mobile responsiveness (375px, 768px, 1920px)
- Validate state persistence with KV storage
- Test on actual DZMM platform (dev and production modes)
Comparison:
| Factor | React + Vite | Alpine.js |
|---|---|---|
| Type Safety | ✅ TypeScript | ❌ Plain JS |
| Dev Experience | ✅ Hot reload | ⚠️ Manual refresh |
| Ecosystem | ✅ Rich (shadcn/ui, etc.) | ⚠️ Limited |
| File Size | ⚠️ Larger (900KB+) | ✅ Smaller (<100KB) |
| Maintenance | ✅ Component-based | ⚠️ Single file can get messy |
| Learning Curve | ⚠️ Steeper for beginners | ✅ Easier to learn |
Model Selection Guide
Choose the appropriate DZMM AI model based on task complexity:
Standard Models (32K context):
- nalang-turbo-0826: Fastest, most economical. Best for simple tasks, quick responses (maxTokens: 1000-1500)
- nalang-medium-0826: Balanced performance. Good for moderate complexity tasks (maxTokens: 1500-2000)
- nalang-max-0826: Enhanced reasoning and strategy. Best for game AI, complex rules, stable output (maxTokens: 2000-3000)
- nalang-xl-0826: Largest model, strongest comprehension. For complex dialogues, long-form content (maxTokens: 2000-3000)
16K Models (faster, shorter context):
- nalang-max-0826-16k: Fast version of max model with 16K context window
- nalang-xl-0826-16k: Fast version of XL model with 16K context window
Legacy Model Names (may still work in some examples):
nalang-xl→ likely maps tonalang-xl-0826nalang-xl-10→ likely maps tonalang-xl-0826
Selection Tips:
- For prototyping: Start with
nalang-turbo-0826for speed - For production games: Use
nalang-max-0826ornalang-xl-0826for quality - For short conversations: Try 16K variants for faster response
- All models support maxTokens range: 200-3000 (default 1000)
Resources
references/developer-guide.md
Complete DZMM platform developer guide covering:
- Platform introduction and tech stack
- Core API documentation with examples
- Three architecture patterns with full implementations
- Best practices for prompts, error handling, performance
- Comprehensive FAQ and troubleshooting
- Design philosophy and logging strategies
Load this reference when users need in-depth understanding of DZMM concepts, detailed API specifications, or comprehensive architecture guidance.
references/code-snippets.md
Organized library of reusable code patterns:
- 10 categories covering all common DZMM tasks
- Copy-paste ready snippets
- Complete with comments and usage examples
- Tested and production-ready
Load this reference when implementing specific features or need quick access to proven code patterns.
assets/examples/
Seven complete, working DZMM applications:
-
小红书文案.html (~15KB) - Stateless Generator
- Minimal architecture for quick prototyping
- Markdown rendering with marked.js integration
- Input validation with character count
- Modern gradient UI design
- Single-purpose content generation
- Best for: Quick tools, text generators, one-shot tasks
-
恋爱游戏.html (~35KB) - State Management Game
- Multi-variable state system (affection, mood, time, relationship)
- Structured AI output with ###STATE/###END parsing
- Configuration UI for game initialization
- Dynamic UI updates (progress bars, backgrounds)
- Complete save/load system with state filtering
- Responsive mobile design with extensive @media queries
- Best for: Dating sims, stat-based games, visual novels
-
horror-story.html (29KB) - Effect System
- Comprehensive effect system (lights, sounds, particles, visual effects)
- AI-controlled browser environment
- "Fourth wall breaking" implementation
- Web Audio API sound generation
- Canvas particle system
- Best for: Immersive experiences, atmospheric games
-
dungeon-adventure.html (41KB) - Turn-based Game
- Turn-based game with state management
- Character stats and inventory system
- Multi-turn AI dialogue with context
- JSON parsing for game state updates
- Best for: RPG games, adventure games
-
neon-gomoku.html (24KB) - Board Game
- AI opponent for board games
- Game logic and win detection
- Structured AI instruction parsing
- Visual game board rendering
- Best for: Strategy games, puzzle games
-
贴吧.html (26KB) - Content Platform
- Two-tier caching architecture
- List + detail content loading
- Concurrent request locking
- XML parsing for content structure
- Best for: Forums, content communities, social platforms
-
yoshiwara-chronicles-dzmm.html (84KB) - Complete Visual Novel System (Alpine.js) ⭐
- Multi-opening system with dynamic scene switching (Night Chapter, Day Chapter)
- Rich text rendering with placeholder technique (handles nested options, dialogue quotes, italics)
- Message management (reroll/regenerate, edit, delete with context preservation)
- Multi-slot save system (3 slots with preview extraction)
- Modular prompt engineering (XML-structured with main + character + guidance + emphasis sections)
- Advanced prompt techniques (
<last_input>emphasis, token optimization, format rules at bottom) - Streaming AI responses with real-time display and auto-scroll
- Responsive mobile design (compressed navigation, flex-wrap buttons, adaptive spacing)
- Resource reuse pattern (GitHub Raw URLs for background images)
- Complete implementation of all visual novel patterns documented in this skill
- Best for: Visual novels, interactive fiction, narrative-driven games, Galgames
- Reference project: Based on 54-commit development of yoshiwara-chronicles
-
yoshiwara-chronicles-react (893KB, gzip: 473KB) - React Multi-Component Version 🚀
- Same project as #7, but built with React + TypeScript + Vite
- Component-based architecture: 30+ modular TypeScript/TSX files
- Professional codebase structure: services/lib/contexts/types layered design
- Complete DZMM API encapsulation with TypeScript type safety
- Sandbox compatibility layer: localStorage fallback, form submission handling
- Automatic API parameter validation: maxTokens range checking, consecutive role detection
- Production-ready error handling: Detailed logging, validation, graceful degradation
- Modern build pipeline: Vite + vite-plugin-singlefile (hot reload → single HTML)
- All features from Alpine.js version plus improved maintainability
- Best for: Large projects (>5000 lines), team collaboration, TypeScript projects
- Full source code: https://github.com/waylon256yhw/yoshiwara-chronicles/tree/dzmm-version
- Documentation:
assets/react-examples/yoshiwara-chronicles-react.md - Key learning: Q11 (React/Vue migration guide), Q12 (backend integration templates)
Use these as starting templates or reference implementations for specific features.
Best Practices
- Always Initialize Properly
- Wait for
dzmm:readyevent before any API call - Initialize AudioContext on first user interaction (browser requirement)
- Show loading state during initialization
- Use dual detection: check
window.dzmmdirectly + event listener + timeout recheck - Example pattern:
if (window.dzmm) { this.dzmmReady = true; } else { window.addEventListener('dzmm:ready', () => { this.dzmmReady = true; }); setTimeout(() => { if (!this.dzmmReady && window.dzmm) this.dzmmReady = true; }, 2000); } - Wait for
1.5. ⚠️ Resource Reuse Strategy (Critical for Migrations)
- Golden Rule: If resources already exist, ALWAYS reference them by URL instead of recreating with code
- Use GitHub Raw URLs for images, audio, fonts from existing projects
- Never simulate textures with CSS gradients/shadows - use real image files
- 100% visual fidelity vs ≤60% with code simulation
- Benefits: Perfect restoration, time savings, smaller file size, easier maintenance
- Example:
<!-- ✅ CORRECT: Direct URL reference -->
<div style="background-image: url('https://raw.githubusercontent.com/user/repo/main/public/image.jpg')">
<!-- ❌ WRONG: CSS simulation of textures -->
<div style="background: linear-gradient(...); box-shadow: inset ...">
- Resource Manager Pattern:
const ASSET_BASE = 'https://raw.githubusercontent.com/user/repo/main/public';
const assets = {
backgrounds: { welcome: `${ASSET_BASE}/bg1.jpg` },
music: [{ src: `${ASSET_BASE}/music/track1.mp3` }]
};
- Migration Checklist: All images referenced? All audio referenced? Fonts from CDN? Any simulated textures replaceable?
-
Manage Conversation History
- Keep only last 10-20 messages to prevent token overflow
- Truncate individual messages to reasonable lengths (≤2000 chars)
- Use system prompts as first user message, not
role: 'system'
-
Handle Errors Gracefully
- Wrap all API calls in try-catch blocks
- Provide user-friendly error messages
- Log structured context for debugging (model, message count, error)
-
Optimize Performance
- Implement debouncing for user input
- Use two-tier caching for content-heavy apps
- Add concurrent request locks to prevent duplicate calls
- Clean up resources (audio nodes, animation frames, particles)
-
Design Clear Prompts with Format Control
- Use structured output formats (###STATE/###END, XML, or JSON)
- Provide both correct AND incorrect examples in prompts
- Explicitly warn AI what NOT to do (e.g., "❌ Don't put dialogue before STATE")
- Use clear delimiters and validate parsing
- Example from 恋爱游戏.html:
【正确示例】 用户:早上好 回复: ###STATE {"affection":52,"mood":"高兴"} ###END 早上好呀! 【错误示例 - 绝对不要这样】 ❌ 把对话写在STATE前面 ❌ 不写STATE -
Smart State Persistence
- Exclude temporary state from saves (disabled, loading, input)
- Only save game-critical data
- Use Object.assign() for clean state restoration
- Example pattern:
const excludeKeys = ['disabled', 'loading', 'input']; const saveData = {}; Object.keys(this).forEach(key => { if (!excludeKeys.includes(key) && typeof this[key] !== 'function') { saveData[key] = this[key]; } }); -
Responsive Design for Mobile
- Design for touch interactions first
- Use extensive @media queries for layout adjustments
- Test text readability on small screens (14-16px minimum)
- Ensure buttons are finger-friendly (min 44px touch targets)
- Hide non-essential labels on mobile to save space
-
Configuration UI Pattern
- Provide initial setup screen for user customization
- Include game/app instructions in setup
- Validate inputs before allowing start
- Example: name input, difficulty selection, initial parameters
-
Markdown Integration (for content generators)
- Load marked.js before Alpine.js
- Configure marked options once:
marked.setOptions({ breaks: true, gfm: true }) - Render with
x-html="renderMarkdown(content)" - Style rendered HTML with specific CSS selectors (
.post-body h1,.post-body p, etc.)
-
Version Your Data
- Use versioned keys for KV storage (e.g.,
app_state_v1) - Include timestamps for cache expiry checks
- Document data schema changes
- Use versioned keys for KV storage (e.g.,
-
Use Chat API for Branching Narratives
- Perfect for Galgame save/load systems with multiple routes
- Store each player choice and story branch as separate messages
- Use
parentIdto create branching storylines at decision points - Track current position with last message ID
- Load history with
timeline()for save/load functionality - Example pattern:
// Save choice and branch const result = await dzmm.chat.insert(currentNodeId, [ { role: 'user', content: playerChoice }, { role: 'assistant', content: storyResponse } ]); currentNodeId = result.ids[result.ids.length - 1]; localStorage.setItem('savePoint', currentNodeId); // Load save const timeline = await dzmm.chat.timeline(savedNodeId); const history = await dzmm.chat.list(timeline); -
Respect API Limits
- Concurrent requests: Keep ≤3 simultaneous API calls
- Call frequency: Add debouncing to avoid rapid-fire requests
- Message size: Limit individual messages to reasonable lengths
- Development vs Production: Remember data persistence differs between modes
- Use loading states to prevent duplicate requests during processing
-
Rich Text Rendering with Placeholder Technique
- Problem: Nested structures (like
<options>inside AI responses) conflict with regex replacements - Solution: Extract complex structures → process simple text → restore structures
- Pattern:
renderRichText(text) { // 1. Extract options blocks with placeholders const optionsMap = []; let result = text.replace(/<options>([\s\S]*?)<\/options>/g, (match, content) => { const placeholder = '___OPTIONS_' + optionsMap.length + '___'; optionsMap.push(content); return placeholder; }); // 2. Process regular text (italics, quotes, line breaks) result = result .replace(/\*([^*]+)\*/g, '<em>$1</em>') .replace(/「([^」]+)」/g, '<span class="dialogue">「$1」</span>') .replace(/\n/g, '<br>'); // 3. Restore options as HTML buttons optionsMap.forEach((content, i) => { const buttons = /* generate buttons from content */; result = result.replace('___OPTIONS_' + i + '___', buttons); }); return result; }- Use data attributes to avoid HTML quote conflicts:
<button data-option="${escaped}"> - Event delegation for dynamic buttons: Single click handler with
event.target.closest('[data-option]')
- Problem: Nested structures (like
-
Message Management Features
- Reroll (Regenerate): Preserve context before target message, call API with same history
- Edit: Update user message, delete all subsequent messages, auto-trigger AI response
- Delete: Slice array to remove message and everything after it
- Key implementation details:
// Reroll: preserve context const contextMessages = this.messages.slice(0, messageIndex); // Edit: delete subsequent + auto-respond this.messages = this.messages.slice(0, index + 1); await this.getAIResponse(editedContent, false); // Delete: with confirmation if (confirm('Delete this and all following messages?')) { this.messages = this.messages.slice(0, index); }- Use
editingIndexandrerollingIndexfor UI state tracking - Always clean
<options>tags from history to prevent AI format inertia
-
Multi-Opening Scene System
- Configuration: Array of opening objects
[{ id: 'night', label: '夜之章' }] - Content library: Object mapping
{ night: 'content...', day: 'content...' } - State management: Track
selectedOpeningandpreviousOpeningfor cancel support - Pattern:
changeOpening() { if (this.messages.length > 1) { if (!confirm('Switch will clear conversation. Continue?')) { this.selectedOpening = this.previousOpening; // Revert return; } } this.previousOpening = this.selectedOpening; this.messages = []; this.messages.push({ role: 'assistant', content: this.getOpeningGreeting() }); }- Extensible design: Easy to add new openings to array and content object
- Configuration: Array of opening objects
-
Responsive Mobile Design
- Top navigation: Use
flex-col md:flex-rowfor vertical (mobile) → horizontal (desktop) - Button overflow: Add
flex-wrapandgap-1.5to allow wrapping - Text scaling:
text-xs md:text-smfor responsive font sizes - Decorative elements: Hide on mobile with
hidden md:block - Compressed spacing: Reduce padding/margin on mobile (e.g.,
py-4 → py-1.5) - Fixed layout: Use
h-screen+flex-1+flex-shrink-0for header/content/footer - Touch targets: Minimum 44px for buttons on mobile
- Whitespace control:
whitespace-nowrapto prevent button text wrapping - Test at: 375px (iPhone SE), 768px (iPad), 1920px (Desktop)
- Top navigation: Use
-
Advanced Prompt Engineering
- XML Structure: Use tags like
<时代背景>,<创作美学>,<回复规范>for clear hierarchy - Emphasis section: Put critical format rules at BOTTOM of message array (AI remembers recent content better)
- Message construction:
const messages = [ { role: 'user', content: systemPrompt }, // Top: World/character setting ...cleanedHistory, // Middle: Conversation { role: 'user', content: getEmphasis() } // Bottom: Format rules (strongest) ];- <last_input> wrapper: Emphasize most recent user input
for (let i = cleanedMessages.length - 1; i >= 0; i--) { if (cleanedMessages[i].role === 'user') { cleanedMessages[i].content = `<last_input>\n${cleanedMessages[i].content}\n</last_input>`; break; } }- Token optimization: Simplify repeated tags (
<option>→<op>saves ~12 chars × 3) - Clean history: Remove
<options>blocks from history to prevent AI format inertia
- XML Structure: Use tags like
-
KV Storage Advanced Patterns
- Multi-slot saves with preview:
// Save: Full game state await dzmm.kv.put(`game_slot_${slotNumber}`, JSON.stringify({ character, messages, timestamp, ...gameState })); // Preview: Extract metadata only (don't load full messages) const data = JSON.parse(result.value); return { characterName: data.character.name, messageCount: data.messages.length, lastMessage: data.messages[messages.length-1].content.slice(0, 50), timestamp: new Date(data.timestamp).toLocaleString() };- Batch operations: Use
Promise.all()for parallel KV operations - Versioning: Use keys like
${appName}_v2_${dataKey}for schema upgrades - Chunking: Split large data if hitting size limits
- Caching with expiry: Store
{ value, expiresAt }and check timestamp on load
-
Streaming AI Response Optimization
- Real-time display: Update UI in callback with
done === false - Placeholder message: Add empty message to array, update content in callback
- Auto-scroll: Use
$nextTick()to ensure DOM updated before scrolling - Error recovery: Remove placeholder message if API fails
- Retry logic: Implement exponential backoff (1s, 2s, 4s) for failed requests
- Pattern:
this.messages.push({ role: 'assistant', content: '' }); const idx = this.messages.length - 1; await dzmm.completions({ /* ... */ }, (content, done) => { this.messages[idx].content = content; if (done) { this.$nextTick(() => scrollToBottom()); } }); - Real-time display: Update UI in callback with
Writing Style Note
Follow DZMM conventions:
- Use imperative/infinitive verb forms in instructions
- Maintain objective, instructional tone
- Provide concrete examples with actual code
- Reference bundled resources explicitly
- Keep explanations concise and actionable