A private, invite-only bulletin board for trading shifts, giving away shifts, and posting shift requests.
Status: Private internal fork β no ads, no billing, no public registration. Locked to two pre-seeded, invite-only boards. See wdwshiftx.md for the migration plan and checklist.
- Overview
- The Problem
- The Solution
- Tech Stack
- Key Features
- Roles
- Getting Started
- Development
- Database Schema
- Security & Privacy
- Status
- Contributing
- License
WDWShiftX replaces the chaos of Facebook groups with a structured, secure platform organized around invite-only boards. Users join boards with a code, then post and browse shifts scoped to only the boards they belong to.
- Trade shifts with trusted peers on your boards
- Give away shifts you can't work
- Request specific shifts on a request section
- Stay scoped β only see posts from boards you've joined
Built as a Progressive Web App (PWA) for mobile-first access, with board-level moderation to ensure trust and accountability.
Users currently rely on Facebook groups to coordinate shift trades, which creates:
- Noise: Hundreds of unrelated posts make finding relevant shifts difficult
- Security risks: No verification of user status or group membership
- No structure: Posts lack standardized formatting, making filtering impossible
- Ghosting: People claim shifts but don't follow through, with no accountability
WDWShiftX provides:
- Board-Based Access: Users join private boards via invite codes β posts are scoped to your boards only
- The Wall: A unified, filterable feed of all shifts and requests across your boards
- Verification: Email verification ensures only active users can register
- Two-Level Role System: Platform-level Global Roles + per-board Board Roles for layered moderation
- Audit Trails: Soft deletes and flag systems provide accountability
- Frontend: Next.js 14+ (App Router), React, Tailwind CSS
- Backend: Supabase (PostgreSQL, Auth, Row-Level Security)
- Deployment: Vercel (serverless functions for elastic scaling)
- Target: Progressive Web App (installable on iOS, Android, desktop)
- Unified feed of shift offers and requests across all your boards
- Filter by board, date, keyword, or your own posts
- Posts auto-expire before shift start time
- Badges: Trade, Giveaway, Overtime Approved
- Auto-expires 30 minutes before shift start
- Edit/deactivate your own posts
- Post shift requests by date and time preference
- Auto-expires at end of requested date
- Two pre-seeded, private boards, joined via 7-character invite codes at onboarding
- Self-serve board creation is disabled β boards are fixed for this fork
- Leaders manage invite codes (pause/resume, regenerate); Mods/Leaders review pending join requests
- Join attempt rate limiting: 5 attempts/minute, 15 failures/24h β account deactivation
- Flag inappropriate posts or profiles
- Mods/Leaders see flags and manage them per board
- Audit trail for documentation
- Soft deletes preserve accountability
- WCAG 2.1 AA compliant (7:1 contrast, 44Γ44px touch targets)
- Responsive across phones, tablets, desktops
WDWShiftX uses two independent role systems.
Naming note: the labels below are what users see as of 2026-07-18. Internally (DB values, RLS policies, route paths, code) the board "Admin" is still stored as
Leaderand the global "Overlord" asAdminβ the display mapping lives inlib/roles.ts.
| Role | Permissions |
|---|---|
| Guest | View landing page, login, register |
| User | Join boards, view The Wall, post shifts/requests, manage profile |
Overlord (stored as Admin) |
Full platform control β manage users, boards, and global settings |
| Role | Permissions |
|---|---|
| User | View and post on the board |
| Mod | User permissions + moderate posts, manage flags and approvals |
Admin (stored as Leader) |
Mod permissions + manage invite code, rename board, delete board, promote/demote members |
Board roles are independent of Global Roles. A platform User can be a board Admin on one board and a Mod on another.
- Node.js 18+ and npm
- Supabase account
- Vercel account (for deployment)
# Clone the repository
git clone https://github.com/ace-d-baugh/wdwshiftx.git
cd wdwshiftx
# Install dependencies
npm install
# Set up environment variables
cp .env.example .env.local
# Add your Supabase URL and anon key
# Run database migrations
npm run db:migrate
# Start development server
npm run devVisit http://localhost:3000 to see the app.
NEXT_PUBLIC_SUPABASE_URL=your_supabase_url
NEXT_PUBLIC_SUPABASE_ANON_KEY=your_supabase_anon_key
SUPABASE_SERVICE_ROLE_KEY=your_service_role_keywdwshiftx/
βββ app/ # Next.js App Router pages
β βββ (auth)/ # Auth routes (login, register, etc.)
β βββ (dashboard)/ # Protected app routes
β β βββ wall/ # The Wall β main feed + new post forms
β β βββ profile/ # Profile + My Boards management
β β βββ leader/ # Mod/Leader tools (approvals, flags, archive)
β β βββ admin/ # Admin panel (users, boards)
β βββ actions/ # Server actions (boards, shifts, requests)
βββ components/ # React components
β βββ ui/ # Reusable UI primitives
β βββ features/ # Feature-specific components
βββ lib/ # Utilities and helpers
β βββ supabase/ # Supabase client setup
β βββ validations/ # Zod schemas
βββ public/ # Static assets
βββ supabase/ # Database migrations
npm run dev # Start development server
npm run build # Build for production
npm run start # Start production server
npm run lint # Run ESLint
npm run type-check # Run TypeScript compiler
npm run db:migrate # Push migrations to remote Supabase
npm run db:reset # Reset local database (dev only)- users β User accounts with global role (
Guest | User | Admin) and active status - boards β Private boards with name, invite code, and enabled flag
- user_boards β Board membership with per-board role (
User | Mod | Leader) and approval status - board_join_attempts β Rate-limiting log for invite code attempts
- shifts β Shift offers (trades/giveaways), scoped to a board
- requests β Shift requests, scoped to a board
- comments β Comments on shifts and requests
- flags β Moderation flags on posts/profiles, scoped to a board
- Soft Deletes:
is_activeflags preserve audit trails on posts and comments - RLS via SECURITY DEFINER helpers:
is_board_member(),is_board_moderator(),is_board_leader(), andis_any_board_moderator()prevent RLS recursion while enforcing board-scoped access - Invite Code Format: 7-character alphanumeric using an unambiguous charset (no O/0, I/1 confusion)
- Generated Columns:
expires_atauto-calculated for shifts and requests
- Display name, email, phone (optional)
- Board memberships and roles
- Shift/request posts, comments, flags
- Passwords (Supabase Auth handles hashing)
- Email verification required before accessing the app
- Invite code rate limiting (DB-backed, 24-hour rolling window)
- Row-Level Security (RLS) on all tables β board membership enforced at the database level
- HTTPS only
- Server Actions for all mutations (no exposed REST endpoints for writes)
Core product (auth, boards, wall, moderation, notifications, calendar sync, in-app messaging, PWA support) is feature-complete and running as a private internal tool for two pre-seeded teams. See wdwshiftx.md for the full migration checklist from the original multi-tenant product.
This is a solo-maintained internal tool β not open to outside contributions.
MIT License β see LICENSE for details.
- Issues: GitHub Issues
- Discussions: GitHub Discussions
Remember: Always verify shift trades and OT approval on your employer's official scheduling pages. WDWShiftX is a bulletin board only β communication and final execution are your responsibility.