- Refill a queue of 5 AI prompts in the background on page load
- Track in-flight fetches with pendingFetches ref so we never over-request
- fetchPrompt() is now synchronous: pops from queue or instantly returns a
shuffled built-in (LOCAL_PROMPTS, 12 entries, no-repeat cycling)
- Source badge replaced with a small emoji in the top-right corner of the
popover: 🤖 for AI prompts, 📚 for built-ins
- Removed promptLoading state and spinner entirely
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Notes: per-story rich-text notes panel (right drawer) with TipTap
editor, image support, autosave, and full CRUD API
- Font picker: 15 Google Fonts selectable from a floating Aa button,
persisted to localStorage via --font-body CSS variable
- Sticky toolbar: pulled formatting bar out of overflow:hidden wrapper
so it sticks below the topbar while scrolling
- Prompts: 100 additional built-in prompts (120 total) in a shuffled
no-repeat queue; pre-fetch on page load so the AI has time to respond;
timeout raised to 45s; error logging + /api/prompts/test debug endpoint;
source badge shows whether prompt came from AI or built-in list
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Wrap button labels in spans so the existing hide-on-mobile rule fires.
Hide all topbar text labels and save status on small screens, leaving
only icons. Add overflow-x: hidden to html as a safety net.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Login now uses username instead of email
- DB migration renames email -> username on existing databases
- Users can change their own password from the Stories page
- Admin can reset any user's password from the admin panel
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The resolver 127.0.0.11 directive caused ECONNREFUSED errors in this
network setup. Direct proxy_pass resolves server at startup which is
sufficient since depends_on ensures server is running first.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>