# Site Content Management System This document explains how to manage site content (modals, rules, etc.) using the new database-driven system. ## Overview The site content management system allows administrators to modify: - Modal content (welcome modal, rules, instructions) - Help text (paint faster, map lagging) - Footer links and contact information - Site title and branding - Any other text content on the site Content is stored in MySQL and can be edited through an admin interface, supporting multiple locales (English, Chinese, etc.). ## Architecture ### Database Schema **Table: `SiteContent`** - `id`: Auto-incrementing primary key - `key`: Unique string identifier (e.g., `modal.rules.title`) - `value`: Text content - `locale`: Language code (en, zh, etc.) - `createdAt`: Creation timestamp - `updatedAt`: Last update timestamp ### Backend API Endpoints **Public Endpoint:** - `GET /api/site-content?locale=en` - Fetch all content for a locale (used by frontend) **Admin Endpoints (require authentication & admin role):** - `GET /api/admin/site-content` - Get all content items - `POST /api/admin/site-content` - Create or update a single item - `POST /api/admin/site-content/bulk` - Bulk update multiple items - `DELETE /api/admin/site-content/:key` - Delete an item - `POST /api/admin/site-content/initialize` - Initialize default content ### Frontend Integration **File: `frontend/_app/info.js`** - Automatically loads content from API on page load - Falls back to hardcoded defaults if API fails - Uses MutationObserver to patch modals when they appear - Supports locale switching ## Setup Instructions ### 1. Database Migration Run the Prisma migration to create the `SiteContent` table: ```bash pnpm db:push ``` ### 2. Initialize Default Content After the database is set up, initialize the default content by making a POST request: ```bash curl -X POST http://localhost:3000/api/admin/site-content/initialize \ -H "Cookie: j=YOUR_ADMIN_JWT_TOKEN" ``` Or use the admin UI (see below). ### 3. Access the Admin UI Navigate to: `http://localhost:3000/_app/admin-content-editor.html` **Note:** You must be logged in as an admin with a valid JWT token in cookies. ## Using the Admin UI ### Interface Features 1. **Locale Selector** - Switch between languages (en, zh) 2. **Reload Button** - Refresh content from database 3. **Add New Item** - Create new content entries 4. **Initialize Defaults** - Populate database with default content 5. **Save All Changes** - Bulk save modified items 6. **Delete Button** - Remove individual items ### Content Keys Content is organized using dot-notation keys: #### Modal Content Keys **Overview Section:** - `modal.overview.title` - "Overview" heading - `modal.overview.videoUrl` - YouTube embed URL **Paint Faster Section:** - `modal.paintFaster.title` - Section heading - `modal.paintFaster.mobile` - Instructions for mobile users - `modal.paintFaster.desktop` - Instructions for desktop users **Map Lagging Section:** - `modal.mapLagging.title` - Section heading - `modal.mapLagging.text` - Help text - `modal.mapLagging.link` - Link to hardware acceleration guide **Rules Section:** - `modal.rules.title` - "Rules" heading - `modal.rules.badge` - Badge text (e.g., "Important") - `modal.rules.item.0` - First rule (with emoji) - `modal.rules.item.1` - Second rule - `modal.rules.item.N` - Additional rules (add as needed) - `modal.rules.footer` - Footer warning text **Footer Section:** - `modal.footer.email` - Contact email - `modal.footer.discord.url` - Discord invite URL - `modal.footer.discord.text` - Discord link text - `modal.footer.github.url` - GitHub organization URL - `modal.footer.github.text` - GitHub link text - `modal.footer.instagram.url` - Instagram URL - `modal.footer.instagram.text` - Instagram link text - `modal.footer.terms.url` - Terms of service URL - `modal.footer.terms.text` - Terms link text - `modal.footer.privacy.url` - Privacy policy URL - `modal.footer.privacy.text` - Privacy link text **Site-wide:** - `site.title` - Site title/branding ### Adding New Rules To add a new rule to the rules modal: 1. Click "Add New Item" 2. Set key to `modal.rules.item.4` (or next available number) 3. Set value to `🚀 Your new rule text here` 4. Click "Add Item" 5. Repeat for other locales (en, zh, etc.) The frontend will automatically display all numbered rules in order. ### Workflow Example 1. **Login as admin** to your FurryPlace instance 2. **Navigate to** `/_app/admin-content-editor.html` 3. **Select locale** (e.g., English) 4. **Click "Initialize Defaults"** (first time only) 5. **Edit content** directly in the text fields 6. **Click "Save All Changes"** to persist to database 7. **Refresh your main site** - changes appear immediately! ## Development Notes ### Adding New Content Fields To add new editable content: 1. Choose a unique key (e.g., `modal.newSection.title`) 2. Add to the initialize defaults in `src/routes/site-content.ts` 3. Update the monkey patch in `frontend/_app/info.js` to use the new key 4. Add documentation to this file ### Locale Support Currently supports: - `en` - English - `zh` - Chinese To add a new locale: 1. Add option to locale selector in admin UI 2. Initialize default content for that locale 3. Update frontend locale detection in `info.js` ### Caching Considerations - Frontend caches API response per page load - No server-side caching (content always fresh from DB) - Consider adding Redis/memory cache for production ## Troubleshooting ### Content Not Updating 1. Check browser console for `[WPLACE_INFO]` logs 2. Verify API endpoint returns data: `GET /api/site-content?locale=en` 3. Clear browser cache and reload 4. Check database for content entries: `SELECT * FROM SiteContent;` ### Admin UI Not Loading 1. Verify you're logged in as admin 2. Check browser cookies for `j` JWT token 3. Verify `role` in User table is set to `admin` 4. Check browser console for authentication errors ### Default Content Missing Run initialization endpoint: ```bash curl -X POST http://localhost:3000/api/admin/site-content/initialize \ -H "Cookie: j=YOUR_JWT_TOKEN" ``` ## Security Notes - Admin endpoints require authentication AND `role='admin'` - Input validation prevents injection attacks - Keys restricted to alphanumeric + dots + underscores - No HTML rendering (XSS protection via text replacement) ## Future Enhancements - [ ] Add wysiwyg editor for formatted text - [ ] Support for images/media uploads - [ ] Version history and rollback - [ ] Multi-tenant support (different content per domain) - [ ] Import/export functionality (JSON/CSV) - [ ] Preview changes before publishing - [ ] Scheduled content changes - [ ] Content approval workflow