This is the Dungeon Masters Club development roadmap. Items are sorted by complexity (Fibonacci points) so the easiest work appears first. Status and priority determine ordering within the same point value.
Unverified users (signed up via email/password) must be blocked from creating any content on the site β blog posts, comments, direct messages, RSVPs, event replies, forum posts, and any other UGC β until they confirm their email address. The account is effectively read-only until verified. Verified badge/status is the single gate.
Ready3 pts
authsecuritycontent
Acceptance criteria
- Identify every RLS policy and application-level gate that allows content creation (INSERT/UPDATE by non-admin users)
- Gated content types: blog posts, comments, DMs, RSVPs, event replies, forum/community posts, media uploads
- RLS policies on all content tables check profiles.email_verified before allowing INSERT or UPDATE
- Application-level checks prevent unverified users from seeing create/edit forms or submitting data
- APIs return clear error message: 'Verify your email before creating content'
- Existing verified users are unaffected
- Google OAuth users are auto-verified and unaffected
Evaluate free/open-source content moderation options for avatar uploads: NSFW JS, LAION Safety Checker, Amazon Rekognition, Google Cloud Vision SafeSearch, PhotoDNA. Choose approach and implement pre-upload scanning.
Backlog3 pts
safetyresearch
Acceptance criteria
- Research report with options compared
- Recommendation for DMC approach
When a date header (.chat-date-header) appears in the same .message-row as an image message, the date pill stretches vertically to match the image bubble height. Fix: render date separators outside individual message rows with their own container, and use inline badge element so the pill only takes the height of its text.
Backlog3 pts
communicationmessagesuibug
Acceptance criteria
- Date separators render as their own row outside individual .message-row elements
- Date pills (.chat-date-badge) only take the height of their text content
- A date before an image message remains a small pill, not the height of the image
- .chat-date-header has transparent background, no pill styling β that goes on the inner .chat-date-badge
Complete the threaded comment reply flow end-to-end. Schema already has comments.parent_id and the UI has reply controls. Ensure event authors see pending comments on their events, authors see their own pending replies, approved replies render nested for everyone, and the moderation panel correctly surfaces event comments awaiting approval.
Backlog3 pts
commentsrepliesmoderationevents
Acceptance criteria
- Authors can see their own pending replies
- Approved replies render nested correctly
- Event authors see pending comments on their events
- Moderation panel shows event comments awaiting approval
- Approved event comments render correctly for all viewers
- Moderation flow works for replies
Blog post hero images (public/images/blog/*.svg) use CSS variables (var(--card-bg), var(--accent)) but are loaded via <img> tags, which prevents them from inheriting page CSS variables in dark mode. Fix by inlining SVG content so CSS variables resolve against the page context.
Backlog3 pts
uidark-modesvgimages
Acceptance criteria
- Hero images respond to dark/light theme on blog detail pages
- Hero images respond to dark/light theme on homepage cards
- No regressions in SVG rendering in light mode
- Still works without JavaScript (SSG-safe)
Investigate and plan the effort required to add emoji reactions (π, β€οΈ, π, π’, π‘, etc.) to the moderator mail / ticket conversation system (DMC-050). Covers: data model (new reaction table vs storing in existing messages), realtime propagation, UI/UX on mobile vs desktop, PWA offline compatibility, existing RLS policies, and migration path. Deliver a research artifact with findings and proposed approach.
Backlog3 pts
researchmessagesmoderationemojireactionsux
Acceptance criteria
- Research covers data model options (new reactions table, JSONB on messages, or client-side)
- Research covers realtime propagation requirements for live reaction updates
- Research covers UI/UX considerations for mobile and desktop
- Research covers PWA offline compatibility for reactions
- Research covers RLS policy requirements for reaction data access
- Research artifact delivered at docs/project/spikes/emoji-reactions-for-dm.md
Create the club's first official event on the website. A session-0 / location building day where members create characters, build the shared world, and set expectations for campaign play.
Proposed3 pts
eventsfirst-sessioncontent
Acceptance criteria
- Event page exists on the website with date, time, venue, description, and RSVP button
- Event description explains what attendees should bring (dice, character sheet ideas)
- RSVP is open and collecting responses
- Event appears on the /events page and in search results
Establish and publish the club's recurring meeting schedule (e.g., every other Saturday, monthly). Allows members to plan ahead and reduces the per-event coordination burden.
Proposed3 pts
eventsfirst-sessionlogisticscommunity
Acceptance criteria
- Recurring schedule is published on the website (club info page or events page)
- Schedule accounts for venue availability and organizer availability
- Members can see upcoming dates at a glance
Create a test event, run through the full RSVP β check-in β attendance pipeline to verify everything works end-to-end. Catch bugs and UX issues before the real first session.
Proposed3 pts
eventstestingfirst-sessionqa
Acceptance criteria
- Test event is created with all required fields
- RSVP from test accounts works correctly
- Attendance marking and walk-in flow work for the test event
- Any bugs or UX issues found are logged as roadmap items or fixed
Display the number of verified events a user has attended on their profile. Count only events where attendance was confirmed by the event author or a moderator. Requires DMC-076 (verified badge) and DMC-077 (attendance table) as prerequisites.
Proposed3 pts
profileseventsattendance
Acceptance criteria
- Non-attendees or users with 0 confirmed attendances show 0 or no count
Move the 'shake-to-energize' checkbox from the admin dice background settings panel to the user account page under a new 'Fun Features' section. Per-device (localStorage), not saved to database. When toggled on, users can shake their phone to energize the homepage dice background animation. The admin panel toggle should also continue working.
Proposed3 pts@candyapplecorn
diceuxaccountfrontend
Acceptance criteria
- Toggle appears on account page under a 'Fun Features' section
- Toggle controls shakeEnabled in dice-settings localStorage
- DiceBackground component respects the toggle (already listens for settings events)
- Admin panel toggle at /admin/dice-background still works alongside account page toggle
- Toggling on requests motion permission from browser (iOS permission gate)
- No database changes β all localStorage
Configure and enable email confirmation for new users signing up with email/password. Wire Resend as the email provider for Supabase Auth so that verification emails are actually delivered. On sign-up, users receive a unique confirmation link in their inbox β they must click it to complete account creation. Unverified accounts should have restricted access (cannot comment, RSVP, or message). Includes testing the full flow end-to-end.
In Progress5 pts
authemailsecurityinfrastructure
Acceptance criteria
- Resend API key is configured in Supabase Auth settings (email provider)
- Supabase Auth has email confirmation enabled for email/password sign-ups
- Sign-up sends a confirmation email with a clickable verification link
- Unverified users are restricted from posting comments, RSVPing to events, or sending messages
- Verified badge/status is tracked and gated correctly in RLS policies
- Existing users are not affected β only new sign-ups require verification
- Admin debug tools page has a 'Send Test Email' feature to verify Resend/SMTP config
- End-to-end test: sign up, receive email, click link, verify account works
Investigate and implement iOS-native-like page transition animations when navigating between tabs in the mobile bottom nav bar. Target: when switching HomeβBlog, the Blog page should feel like it swoops in from the right (like Apple Health / liquid glass iOS 26). Home is the leftmost tab; navigating rightward should animate rightβleft, navigating leftward should animate leftβright. Excludes the Me/Account sheet (already animated). Also investigate animating the active-indicator pill/background on the tab bar itself so focus smoothly transitions between selected tabs.
In Progress5 ptshermes
pwamobileanimationtransitionsux
Acceptance criteria
- Research View Transitions API, Framer Motion, and CSS-only approaches for static-export Next.js PWA
- Implement a working page transition (slide left/right) for mobile bottom-nav navigation
- Animation respects navigation direction β rightward nav slides in from right, leftward from left
- No animation for the Me/Account sheet or external links
- Maintains existing PWA behavior β no regressions in static export, offline mode, or build
- Deliver a research artifact at docs/project/spikes/page-transition-animations.md with findings, alternatives considered, and chosen approach
Sent image messages currently show blue message-bubble background above and below the photo, creating blue bars at the top and bottom. Fix: create a separate image bubble variant (no padding, transparent bg), make the image fill edge-to-edge, and overlay timestamp/checkmark on the bottom-right of the image with a translucent pill.
Backlog5 pts
communicationmessagesuibug
Acceptance criteria
- Sent image messages have no blue top/bottom bands β padding: 0, background: transparent
- The image itself touches the rounded bubble boundary (border-radius on img, not wrapper padding)
- Timestamp/checkmark overlays bottom-right of image on a dark translucent pill
- Text messages continue using normal blue bubble styling unaffected
- Image messages with captions show the caption text below the image, but timestamp alone does not force a blue footer bar
Emoji reactions are currently rendered inside the message bubble flow, causing the bubble to expand vertically and wrap reactions in a large oval/rounded area. Fix: make reactions a sibling of the bubble (not inside it) using absolute positioning. Reactions float half-over the bottom edge of the bubble as separate small chips.
Backlog5 pts
communicationmessagesuibug
Acceptance criteria
- Reactions are rendered as siblings of the bubble, not inside it
- Reactions float half-over the bottom edge of the message bubble via absolute positioning
- The message bubble contains only the actual message text/content β no reaction height increase
- Reactions appear as separate small chips (32x32 circles), not a single oval container
- Reactions do not overlap the next message (margin-bottom added to the row/stack)
- Received reactions float over left side, sent reactions float over right side
Pick a maintained open-source React editor that supports Markdown-compatible bold, italic, links, and preview/output sanitation. Keep storage format simple and sanitize rendered output.
Backlog5 pts
commentseditorui
Acceptance criteria
- Rich editor replaces textarea in CommentForm
- Supports bold, italic, links
- Output is sanitized and safe
- Mobile-friendly
Generate unique URLs with tracking slugs for print materials. Each URL is unique so you can tell which placement drove traffic. Tool to generate URL strings and/or QR code images (CLI or web tool).
Backlog5 pts
analyticsqrmarketing
Acceptance criteria
- Unique tracking URLs can be generated
- Each URL maps to a specific placement
- QR code images can be generated for URLs
- Analytics integration shows traffic from each placement
Add Mermaid.js chart/diagram rendering to blog posts, event details, and development updates. Lazy-load the renderer only when page content contains a mermaid embed. Use next/dynamic with ssr: false.
Backlog5 pts
contentchartsstatic-export
Acceptance criteria
- Mermaid charts render in blog post bodies
- Mermaid charts render in event descriptions
- Mermaid library is only loaded when content contains a mermaid block
- No bundle size impact on pages without mermaid content
Research and plan the push notification delivery system so that notifications appear on phone lock screens even when the device is asleep. The plan must cover: (1) Service Worker push event handling with notification payload formatting for lock-screen display on iOS and Android (via PWA/Web Push API). (2) Deep-link navigation β when a user taps a notification, the PWA should open to the correct sub-page of the app (e.g., a specific event page, message thread, blog post, or profile). (3) Auth-aware redirect β if the user taps a notification while signed out, the PWA should redirect them to the notification's target page after they complete sign-in. Research must evaluate Web Push API limitations (iOS PWA push support, notification_click handlers), Vapid key setup for Supabase push, and the deep-link/redirect-after-login flow.
Backlog5 pts
pwanotificationspushresearchdeep-linking
Acceptance criteria
- Service Worker push event displays notification on phone lock screen on iOS PWA and Android Chrome PWA even when device is asleep
- Tapping the notification navigates to the correct sub-page of the app (event detail, message thread, blog post, profile, etc.)
- Tapping a notification while signed out redirects to the target page after sign-in completes
- Existing push infrastructure (badging, notification bell, SW handlers) continues working without regression
- Research artifact delivered at docs/project/spikes/lock-screen-push-notifications.md with findings, approach comparison, and edge cases
Users can assign custom names to their direct message conversations, making them easier to identify in the DM list. Helpful for users who manage many conversations.
Backlog5 pts
communicationmessagesux
Acceptance criteria
- Users can set a custom display name for any DM conversation via the conversation header or settings
- Custom names appear in the DM list in place of or alongside the other user name
- Names are persisted server-side per-user (not shared between participants)
- Clearing the name reverts to the default display (other user name)
During group events (like workshops, games), replace 'drawing straws' with a dice rolling feature that randomly pairs participants. This adds a fun TTRPG-adjacent mechanic to regular club activities. Integrates the dice rolling system with event check-in data.
Proposed5 pts@candyapplecorn
diceeventspairingsocial
Acceptance criteria
- Event moderators can trigger a random pairing from the event page
- Pairing uses dice rolling animation for visual flair
- Works with checked-in attendees
- Results displayed clearly to all participants
The moderator inbox at /admin/messages has no admin navigation sidebar or cards. Moderators must go back to /admin to access Events, Blog, Users, or other admin sections. Add admin nav to the inbox page so moderators can navigate between admin sections without leaving the inbox.
Proposed5 pts@candyapplecorn
adminmoderationnavigation
Acceptance criteria
- Admin navigation cards/sidebar present on /admin/messages page
- Navigation matches the existing card pattern from /admin dashboard
- Moderator auth-gated
- Works with static export constraint
- Home, Events, Blog, Users, Media, AI Images, Forum, Dice links
The /admin/media?asset=... page doesn't render images created by the AI worker. The media admin page likely only handles user-uploaded media with specific variant patterns. Fix the display to show any media_asset regardless of upload source.
Proposed5 pts@candyapplecorn
aiimage-generationmediaadminbug
Acceptance criteria
- /admin/media?asset=<ai-asset-id> displays the generated image
- The 'View in Media Gallery' link from the ai-images page works
- Image metadata (size, dimensions, timestamp) is visible
Research, visit, and secure a physical venue for the club's first in-person session. Needs to accommodate 8-20 people, have table space for D&D, be accessible, and ideally free or low-cost (library, community center, game store).
Proposed5 pts
eventsfirst-sessionvenuelogistics
Acceptance criteria
- Venue is identified with contact info, capacity, hours, and cost confirmed
- Venue is booked for at least one recurring date/time slot
- Venue has adequate table/seating space for D&D gameplay
- Venue logistics are documented (parking, entrance, power, Wi-Fi)
The worker broadcasts intermediate ComfyUI preview frames via Supabase Realtime during generation, but the UI (/admin/ai-images) doesn't subscribe to the preview channel. Add a Realtime subscription to show a blurred/loading preview as the image is being generated step by step.
Proposed5 pts@candyapplecorn
aiimage-generationcomfyuiadminuxbug
Acceptance criteria
- UI subscribes to Realtime channel preview:{jobId} during active generation
- Preview frames appear progressively showing intermediate generation state
- Graceful degradation if no preview available (normal progress bar continues)
- Preview stops when job completes or fails
Add a scrollable list of recent generation jobs (last 20) on /admin/ai-images showing status, prompt preview, generation time, and links to completed images. Lets moderators see what was generated, retry failed jobs, and browse results.
Proposed5 pts@candyapplecorn
aiimage-generationadminux
Acceptance criteria
- Page shows the last 20 jobs sorted by created_at desc
- Each entry shows: prompt preview (truncated), status, elapsed time, image thumbnail if complete
- Failed/abandoned jobs show retry button
- Works with existing polling β no new server endpoints needed
Determine if waivers or liability forms are needed for in-person sessions. If so, create digital waiver forms that attendees can sign via the website before the first session. Research requirements for the chosen venue (library/game store policies).
Proposed5 pts
legalfirst-sessionlogistics
Acceptance criteria
- Waiver requirement is determined based on venue policy and local laws
- If needed: digital waiver form is implemented on the website
- Signed waivers are stored and accessible to organizers
- Waiver flow is integrated with the RSVP process
Handle attendees who show up to an event without RSVPing. Allow hosts to add walk-ins to the attendance roster and mark them separately from RSVP'd attendees. Supports overflow/waitlist scenarios.
Proposed5 pts
eventsattendancefeatures
Acceptance criteria
- Host can add a walk-in attendee from the attendance management UI
- Walk-ins are recorded with a walk_in flag in the attendance table
- Capacity check accounts for walk-ins (combined RSVP + walk-ins β€ capacity)
- Walk-ins can be marked showed_up or no_show like RSVP'd attendees
Add a verified_at column to profiles, settable by moderators. Show a β
badge on profiles, comments, and RSVPs. No new tables or special permissions β pure trust signal.
Proposed5 pts
profilestrustmoderation
Acceptance criteria
- Non-verified users see no badge
Create flyers to promote the club and first session. Physical flyers for posting at the venue, local game stores, libraries, and community boards. Digital versions for social media, email, and the website event page.
Proposed5 pts
marketingfirst-sessionpromotion
Acceptance criteria
- Physical flyer template is designed with club name, date/time, venue, QR code to website
- Digital flyer version is shareable on social media and Discord
- Flyers are posted on the website event page as downloadable PDF
- Submission process for members to request flyers to post locally
Albums can contain sub-albums for hierarchical organization of media collections.
Proposed5 pts
R2 event notifications enqueue processing jobs via Cloudflare Queues. Worker generates variants with retries/dead-letter.
Ready8 pts
Button in BlogEditor/EventEditor opens a media library modal for selecting and inserting images.
In Progress8 pts
When the user navigates from the DM list page (/my/dms or /my/messages) to a DM chat thread, async image loading causes the message list to jump/flicker as images resolve. Fix: preload the last ~10-20 messages (including image blobs) for the top ~10 most recent conversations while the user is still on the DM list page. Sort by most recent unread activity so chats with new messages are prioritized. Images should be prefetched so they render immediately when the thread page loads, preventing layout shift.
Backlog8 pts
communicationmessagesperformanceux
Acceptance criteria
- DM list page fetches the last ~10 messages for the top ~10 most recent conversations
- Conversations sorted by most recent activity (unread/newest-first)
- Image URLs in preloaded messages are prefetched (browser cache) so they render instantly on thread load
- Navigating to a chat thread shows zero layout shift β no content jumping upward when images resolve
- Preloading runs client-side after the DM list renders, does not block page load
- Only active DMs (not archived/blocked) are preloaded
- Implementation avoids redundant fetches β already-loaded conversations are skipped
- Works on both /my/dms and /my/messages/thread entry points
Add the ability for the DMC system to send outgoing transactional emails. Currently the site has contact-form submission handling (DMC-050) but cannot send emails to users β no welcome emails, no password-reset notifications (beyond Supabase auth defaults), no notification digests, no moderator notification emails. Requires integrating an email-sending service (Resend, SendGrid, AWS SES, or similar) and setting up an API endpoint or Supabase Edge Function to trigger sends on relevant events (new user signup, comment approval, event reminders, etc.).
Backlog8 pts
emailnotificationsinfrastructureauth
Acceptance criteria
- Email sending service integrated and configured (Resend, SendGrid, or similar)
- Transactional email triggered on key events: new user signup, comment approval, event RSVP confirmation, upcoming event reminder
- Server-side API endpoint or Edge Function for sending emails (no client-side API key exposure)
- HTML email templates for each email type
- Email preferences page where users can opt in/out of different email categories
- Moderators receive email notifications for new bug reports / contact submissions
- All email sending respects user opt-in preferences
- Supabase Auth emails (password reset, magic link) continue working unchanged
Prevent duplicate rapid-fire comments and repeated inserts using database constraints, RPC, or trigger-based rate limiting. Enforcement should live behind Supabase RLS, not only in frontend JavaScript.
Backlog8 pts
commentssecuritysupabase
Acceptance criteria
- Rate limiting enforced at the DB level (not just client-side)
- Duplicate rapid-fire comments are rejected
- Legitimate comment flow is unaffected
Integrate the reusable ErrorAlert component (with clipboard copy + one-click bug report) into all user-facing error-prone areas: ProfileForm field submissions, bug report/contact form, comment submission, event creation/editing, blog post composer, media upload, auth flows (login/signup/password reset), and DM chat. Each integration surfaces actual server error responses to the user with copy and report actions.
Backlog8 pts
uxerror-handlingfrontend
Acceptance criteria
- ErrorAlert replaces all inline <p className="rebuild-status-error"> patterns on user-facing pages
- Every API error (from Cloudflare Functions and Supabase) shows the actual server error message, not a generic placeholder
- Clipboard copy works on every ErrorAlert instance
- One-click bug report sends formatted error with page, component, and environment context
- No code quality regressions from the rollout
Allow users to roll dice directly within their comments on the site. The specific UI/UX is TBD β it could render the rolled dice visually inline, show results as text, or embed a small dice animation. The key constraint is that dice results shouldn't cover up or overlap the user's written comment text.
Proposed8 pts@candyapplecorn
dicecommentsinteractive
Acceptance criteria
- Users can initiate a dice roll from the comment editor
- Results are displayed inline without overlapping comment text
- Works on both desktop and mobile
Build the core attendance tracking system: event_attendance database table, host-facing UI to mark RSVP'd attendees as 'showed up' or 'no-show', and attendance count RPCs for future profile display. Supports manual post-event check-in and future QR-based check-in.
Proposed8 pts
eventsattendancefeatures
Acceptance criteria
- Event_attendance table exists with composite FK to event_rsvps
- Host can view RSVP'd attendees and mark each as showed_up or no_show
- Attendance counts are queryable per event and per user
- Non-RSVP'd users cannot be marked (enforced by DB constraint)
- UI is accessible from the event admin management page
Display user avatars (approved profile photos) everywhere a username appears in the UI. Use the existing ProfileAvatar component β small circular thumbnails. Targeted locations: AuthStatus nav bar (next to username), CommentThread (blog/event comments), blog posts (author byline), events (author/organizer), DM chat message list, and any other user-name display. Reuse the existing ProfileAvatar component pattern consistently.
Proposed8 pts
profilesavatarsuxcommentsblogevents
Acceptance criteria
- AuthStatus nav bar shows small circular avatar next to username when user has approved avatar
- CommentThread shows avatar next to comment author name on blog posts and events
- Blog post pages show author avatar next to author name in byline
- Event pages show organizer/author avatar next to name
- Uses existing ProfileAvatar component (or equivalent small circular pattern)
- Falls back to initial letter when no approved avatar exists
- Consistent size (~24-32px) across all locations
- Approved avatar_url is fetched alongside username in all relevant data queries
Build the complete RSVP β attendance pipeline: track who RSVP'd 'going', reconcile against actual attendance at the event, show attendance conversion metrics. Includes RSVP reminders, check-in suggestions for the host, and post-event attendance summary.
Proposed8 pts
eventsattendancefeatures
Acceptance criteria
- Host dashboard shows RSVP list alongside attendance for same-session comparison
- Attendance conversion rate (showed_up / going) is computed per event
- Host can send RSVP reminders from the event management page
- Post-event summary shows: who RSVP'd, who came, who no-showed
- Design accounts for future QR-based check-in as alternative to manual marking
Add an event_attendance table separate from RSVPs. Event authors/moderators can mark attendees as confirmed (showed up) or no-show. Tracks attendance history per user per event.
Proposed8 pts
eventsattendanceprofiles
Acceptance criteria
- Moderators can also confirm/mark attendance
Highlight text in content, create anchored comment threads, side panel lists all threads.
Proposed8 pts
User profiles have their own posts/events/albums feeds separate from the curated public DMC blog.
Proposed8 pts
Allow users to leave comments on individual photos within albums. Initial implementation: logged-in users can comment on any photo, and comments are publicly visible. Permissions model (who can comment, who can view comments, per-album or per-photo controls) to be designed during implementation β this item is a placeholder for the feature intent with the understanding that the permission model will be hashed out before coding begins.
Proposed8 pts
commentsphotosmediapermissions
Acceptance criteria
- Logged-in users can leave comments on individual photos
- Comments are publicly visible
- Permissions model designed and documented before implementation
- Reuses existing comment infrastructure (comment_threads table, moderation, notifications)
Events have attached albums. Hosts check in attendees who can then upload. Retroactive check-in by host only.
Ready13 pts
Mac Mini claims pending media_processing_jobs, downloads from R2, uses Sharp to generate variants, uploads back to R2.
Ready13 pts
Add visitor analytics to the site. Requires cookie consent banner (compliant with privacy regs). Research PostHog vs alternatives before implementing. Only track if consented.
Backlog13 pts
analyticsprivacyconsent
Acceptance criteria
- Cookie consent banner displays on first visit
- Analytics only track when consented
- Consent preference is remembered
- Analytics provider chosen (research complete)
Workflow for location building day events where a moderator creates multiple subgroup documents (private/invite-only blog posts), each accessible only by the subgroup assigned to it. Subgroups collaborate on their document in real-time. After the session, the moderator can view all subgroup documents side-by-side and synthesize them into one published article (potentially AI-assisted). Each subgroup document reuses the existing collaborative content infrastructure (audience=invite_only, content_permissions for subgroup members). Requires a moderator tool to batch-create subgroup docs with templates, and a synthesis dashboard to view/merge them.
Backlog13 pts
collaborationlocation-buildingeventsmoderation
Acceptance criteria
- Moderator can create multiple subgroup documents at once from a template
- Each subgroup document is invite_only with its members as the audience
- Subgroup members can view/edit only their assigned document
- Moderator has a synthesis dashboard showing all subgroup documents for an event
- Moderator can select content from subgroup docs to merge into a single draft article
- AI-assisted synthesis option available (proposed, not required)
- Reuses existing audience, content_permissions, and collaborative editing infrastructure
Turn the /admin/messages moderator inbox into a unified moderation dashboard that aggregates ALL pending moderation items: modmail conversations (already there), pending comment approvals, pending avatar submissions, and pending profile field submissions. Regular users must not see the moderator inbox at all. Profile field submissions currently have no moderation queue β this adds that. The inbox becomes the single place moderators go to review and act on anything needing attention.
Proposed13 pts
moderationadminprofilesavatarscommentsux
Acceptance criteria
- Regular (non-moderator) users cannot see the moderator inbox β no nav link, no route access, proper auth gating
- Pending comment approvals appear in the moderator inbox alongside modmail conversations
- Pending avatar submissions appear in the moderator inbox
- Pending profile field submissions appear in the moderator inbox
- Each pending item shows relevant info (user, timestamp, type, preview of content)
- Moderator can approve/reject/dismiss each item directly from the inbox (or link to detail action page)
- Existing /moderation and /admin/avatars pages still work (or redirect to inbox)
- Badge count on moderator inbox reflects ALL pending item types, not just modmail
- Push notifications fire when ANY new pending item type enters any queue
Create a central moderation dashboard that aggregates pending profile field submissions (display_name, bio, location, website, TTRPG preferences) alongside existing comment and avatar moderation queues. Currently moderators must visit each user's /admin/users/[userId] page individually to review profile field changes. This item delivers a single page to show all pending profile field submissions with approve/reject actions, push notifications to mobile when new items appear, and badging on the moderator inbox to show pending counts.
Proposed13 pts
moderationprofilesadminux
Acceptance criteria
- Single page lists ALL pending profile field submissions across all users
- Each submission shows: user, field name, submitted value, current value, timestamp
- Moderator can approve (writes to profiles table + marks approved) or reject (with reason) each submission
- Approved submissions update the corresponding column in profiles immediately
- Rejected submissions show the rejection reason to the user on their account page
- Page uses moderator-only auth check (existing is_moderator pattern)
- Push notification fires when a new profile field submission is created (via existing moderation_queue notification producer)
- Push notifications also fire for new avatar submissions pending review
- Moderator inbox badge count (mobile sheet and desktop) includes pending profile field + avatar submission counts
- Existing comment moderation and avatar moderation are still accessible from the same admin area
Introduce a first-class club/chapter model so Dungeon Masters Club can support Omaha, Kansas City, and future local chapters. Clubs partition events, content, media, roles, and applications by geography while preserving global site-owner authority.
Proposed13 pts
clubschapterspermissionsrbaceventsprofiles
Acceptance criteria
- The roadmap/design note explicitly avoids building a full Meetup clone in one pass and defines a staged implementation path
A public splash/landing page designed for offline promotion via QR codes and flyers. Messaging like 'We want to start a DMC chapter in your area β need initial members.' Visitors can create an account to express interest, install the site as a PWA to receive push alerts, and optionally subscribe with email for updates. The page acts as the front door for chapter recruitment, feeding into the multi-club chapter architecture (DMC-074).
Proposed13 pts
chaptersrecruitmentlanding-pagepwaemailmarketingqr
Acceptance criteria
- Public landing page at /join or /start-a-chapter with 'interested in starting/joining a DMC chapter' messaging
- Account creation or interest-form submission on the landing page
- PWA install prompt / banner encouraging install for push notifications (detect not-yet-installed)
- Email capture field with opt-in for email notifications about chapter progress
- QR code can be generated pointing to the landing page (reuses DMC-037 infrastructure)
- Landing page works offline (cached via SW) so QR scans always load even on slow venues
- Submitted interest entries stored in a DB table for moderator/admin review
- Moderator dashboard to view interest submissions per location/area
- No full chapter CRUD on this page β it's pure recruitment; chapter creation is a separate admin flow (DMC-074)
Upload original videos, encode HLS/DASH variants at multiple bitrates, segment chunks in R2 for adaptive playback.
Proposed13 pts
Wire up the existing conversations/participants/messages schema (built for DMC-050) for direct user-to-user messaging. Users can start a private conversation with another registered user, send messages, and view their message history. Threads are one-to-one initially (group DMs deferred). Builds on the existing DM-style infrastructure β no new DB tables needed.
Proposed13 pts
communicationmessagesdmsocial
Acceptance criteria
- Users can start a private conversation from another user's profile page
- Users see their conversation list with latest message previews
- Users can send and receive messages within a conversation thread
- Notifications (push + in-app badge) for new messages
- Existing contact-moderator flow continues working unchanged
- Conversations respect privacy β only participants can see the thread
- RLS policies prevent unauthorized access to conversation data
Add voice message support to user-to-user DMs and moderator mail conversations. Users can record audio from their device mic, send it as a message, and recipients can play it back inline. Audio files need persistent storage β evaluate R2 as the primary store (natural fit with existing media pipeline) vs Supabase Storage (simpler integration). Requires: mic permission UX, audio capture/encoding (Web Audio API or MediaRecorder), upload to storage bucket, playback UI with wave form or progress bar, and mobile-friendly recording UX.
Proposed13 pts
communicationmessagesaudior2media
Acceptance criteria
- Users can record audio from the browser/device mic in a conversation thread
- Recorded audio is uploaded to persistent storage (R2 or Supabase Storage)
- Recipients see a playable voice message inline in the conversation
- Playback works on mobile PWA (iOS Safari + Android Chrome)
- Mic permission prompt is clear, cancellable, and handles denied state gracefully
- Recording UX shows duration, allows cancel/retry before sending
- Voice messages appear with the same RLS and privacy constraints as text messages
- Reuses or extends the existing conversations/messages schema and media storage infrastructure
Cloudflare R2 stores images, Supabase stores metadata. Admin can create albums and upload photos. Browser generates thumb/display variants. Public album pages
In Progress21 pts
Convert the Dungeon Masters Club PWA into a native iOS app using Capacitor (Ionic). Wraps the Next.js SSG static export in a native WebView with native plugins for auth, push notifications, haptics, share, camera, and deep linking. Requires auth rewiring from Supabase SSR PKCE to Capacitor adapter with custom URL scheme, and push notification migration from VAPID web push to APNs via @capacitor/push-notifications.
Proposed21 pts@candyapplecorn
capacitoriosnativepwa-to-nativeepic
Acceptance criteria
- App builds and runs via Xcode on iOS simulator and physical device
- Supabase auth works with custom dmc:// URL scheme (PKCE via Capacitor Browser plugin)
- Push notifications delivered via APNs and @capacitor/push-notifications
- Native share sheet via @capacitor/share replaces Web Share API
- Native haptics via @capacitor/haptics replaces navigator.vibrate()
- Camera/gallery media upload via @capacitor/camera
- Persistent preferences via @capacitor/preferences
- Status bar styled correctly (dark background, light icons)
- Splash screen loads and transitions smoothly
- Keyboard handles properly for chat input (no overlap)
- Deep linking / universal links open correct in-app routes
- App icon and all iOS splash screen sizes generated and configured
- Info.plist has proper privacy descriptions (camera, photo library, microphone)
- Offline drafts continue working via IndexedDB in WebView
- Safe area insets respected on all screen sizes (notch, Dynamic Island, home indicator)
Add moderator-only AI image generation to the DMC website. Moderators submit prompts via /admin/ai-images. A Mac mini worker claims the job, runs ComfyUI locally with SDXL, uploads the result to R2, and registers it in the media gallery under an AI Generated album. No LLM tokens used for generation β ComfyUI runs locally on Apple Silicon via PyTorch MPS.
Proposed21 pts@candyapplecorn
aiimage-generationcomfyuiadminmediamac-mini
Acceptance criteria
- Moderator can open /admin/ai-images and submit a prompt without invoking an LLM
- A job row appears in ai_image_generation_jobs table with queued status
- Mac mini worker claims the job, runs ComfyUI locally, generates an image
- Worker uploads the generated image to Cloudflare R2
- Supabase media records created linking to the R2 image
- Job marked complete and image visible in DMC gallery under AI Generated album
- Non-moderators cannot access the page or API
- ComfyUI and worker run as LaunchAgent services surviving reboot
- Failure modes produce understandable job status and errors
- No public ComfyUI endpoint exposed β all traffic is localhost+outbound Supabase/R2
Potential feature: host video playlists with multiple codec encodings chunked for adaptive streaming so browsers can dynamically request the right encoding. May be overkill β posting on YouTube may be sufficient. Parked as a future consideration; not for active implementation.
Proposed21 pts
videoideafuture