A beautiful, multi-tenant SaaS application for displaying team birthdays on digital signage using SignPresenter. Built with React and Supabase.
Live Demo: bdaypresenter.com
This is a serverless web application with the following components:
- Frontend: React SPA hosted on Vercel (auto-deploys from GitHub)
- Backend: Supabase (managed PostgreSQL database, authentication, and file storage)
- Domain: bdaypresenter.com (GoDaddy DNS → Vercel)
- Version Control: GitHub (mbyrdLCS/bdaypresenter)
- User Signs Up → Creates account in Supabase Auth
- Profile Created → Automatic trigger creates user profile with unique display URL slug
- Add Team Members → Stored in Supabase database with photos in Supabase Storage
- Display Page → Public URL at
/display/{slug}shows birthdays in real-time - SignPresenter → Points to the display URL, auto-updates when data changes (no re-configuration needed!)
The beauty of this system: Set it once in SignPresenter, and changes auto-update!
- User adds/edits/deletes birthdays in dashboard
- Changes are saved to Supabase database
- Display page fetches fresh data on each load
- SignPresenter shows updated content automatically
- No need to re-add URLs or refresh anything in SignPresenter
- 🔐 Multi-tenant Authentication - Each organization has their own account
- 👥 Team Management - Add, edit, and delete team members
- 📸 Photo Uploads - Upload profile photos for each team member
- 🎨 Seasonal Themes - Automatically changing themes for each month
- 📅 Monthly View - Shows all birthdays for the current month
- 🎉 Daily Spotlight - Full-screen celebration on actual birthdays
- 🔄 Auto-rotation - Cycles through multiple birthdays on the same day
- 🔗 Unique Display URLs - Each organization gets their own display URL
- 📺 SignPresenter Ready - Optimized for digital signage
- Frontend: React + Vite
- Styling: Tailwind CSS
- Backend: Supabase (PostgreSQL + Auth + Storage)
- Routing: React Router
- Deployment: Vercel (recommended)
- Node.js 20.x or higher
- npm or yarn
- A Supabase account (free tier works great)
cd birthday-celebration-app
npm install- Go to https://supabase.com
- Click "Start your project"
- Create a new project (note: it may take 2-3 minutes to set up)
- In your Supabase dashboard, go to the SQL Editor
- Copy the contents of
database-schema.sql - Paste and run the SQL script
- This will create:
profilestableteam_memberstable- Row Level Security policies
- Automatic profile creation trigger
- In your Supabase dashboard, go to Storage
- Click "New bucket"
- Create a bucket named
profile-photos - Make it public
- Add the following policy for uploads:
- Policy name: "Authenticated users can upload"
- Allowed operation: INSERT
- Target roles: authenticated
- Policy definition:
(bucket_id = 'profile-photos')
- In your Supabase dashboard, go to Project Settings → API
- Copy your Project URL (looks like
https://xxxxx.supabase.co) - Copy your anon/public key (starts with
eyJ...)
Create a .env file in the root directory:
cp .env.example .envEdit .env and add your Supabase credentials:
VITE_SUPABASE_URL=your-supabase-project-url
VITE_SUPABASE_ANON_KEY=your-supabase-anon-keynpm run devThe app will be available at http://localhost:5173
- Sign Up: Create an account with your organization name
- Add Team Members: Go to the dashboard and add team members with:
- Name
- Birthday (month and day)
- Photo (optional)
- Get Your Display URL: Copy the unique URL from your dashboard
- Set Up SignPresenter:
- Add a new website element in SignPresenter
- Paste your display URL
- Set the duration as desired (recommended: 30-60 seconds)
- SignPresenter Website Guide
- Monthly View: Shows all birthdays for the current month in a grid layout
- Birthday Spotlight: On someone's actual birthday, shows a full-screen celebration with their photo
- Multiple Birthdays: If multiple people share a birthday, it rotates between them every 10 seconds
- Seasonal Themes: Each month has a unique color scheme and emoji theme
| Month | Theme | Colors | Emoji |
|---|---|---|---|
| January | Winter Wonderland | Blue & White | ❄️ |
| February | Love & Hearts | Pink & Red | 💝 |
| March | Spring Awakening | Green & Lime | 🌷 |
| April | Spring Blossoms | Pink & Purple | 🌸 |
| May | Sunshine Days | Yellow & Orange | 🌻 |
| June | Summer Vibes | Cyan & Blue | ☀️ |
| July | Summer Fun | Red & Orange | 🎆 |
| August | Beach Days | Teal & Cyan | 🏖️ |
| September | Autumn Begins | Amber & Orange | 🍂 |
| October | Fall Harvest | Orange & Red | 🎃 |
| November | Cozy Season | Brown & Amber | 🍁 |
| December | Winter Holidays | Red & Green | 🎄 |
Live URLs:
- Production: https://bdaypresenter.com
- Vercel URL: https://bdaypresenter.vercel.app
- GitHub Repo: https://github.com/mbyrdLCS/bdaypresenter
Infrastructure:
- Hosting: Vercel (Free tier - auto-deploys from GitHub main branch)
- Database: Supabase (Free tier - hosted PostgreSQL)
- Domain: GoDaddy (bdaypresenter.com)
- DNS: Points to Vercel via A record to 216.198.79.1
Environment Variables in Vercel:
VITE_SUPABASE_URL: Your Supabase project URLVITE_SUPABASE_ANON_KEY: Your Supabase anonymous key
The app uses continuous deployment - it's fully automated!
- Make your changes locally
- Test locally with
npm run dev - Commit and push to GitHub:
git add . git commit -m "Description of changes" git push origin main
- That's it! Vercel automatically:
- Detects the push to main branch
- Runs the build (
npm run build) - Deploys to production
- Updates https://bdaypresenter.com
- Usually takes 1-2 minutes
You can watch the deployment progress at: https://vercel.com/dashboard
This section is for reference - the app is already deployed!
- ✅ Created GitHub repository at
mbyrdLCS/bdaypresenter - ✅ Connected Vercel to GitHub
- ✅ Configured environment variables in Vercel
- ✅ Set up custom domain bdaypresenter.com
- ✅ Configured DNS in GoDaddy:
- A record: @ → 216.198.79.1
- CNAME: www → cname.vercel-dns.com
- ✅ Updated Supabase redirect URLs to include:
- http://localhost:5173/**
- https://bdaypresenter.com/**
- https://*.vercel.app/**
- Fork this repo or create your own
- Set up Supabase project and run
database-schema.sql - Go to vercel.com and import your repo
- Add environment variables in Vercel
- Deploy
- (Optional) Add custom domain in Vercel settings
birthday-celebration-app/
├── src/
│ ├── components/ # Reusable React components
│ ├── contexts/ # React contexts (Auth)
│ ├── pages/ # Page components
│ │ ├── Home.jsx # Landing page
│ │ ├── Login.jsx # Login page
│ │ ├── Signup.jsx # Signup page
│ │ ├── Dashboard.jsx # Admin dashboard
│ │ └── Display.jsx # Public birthday display
│ ├── services/ # External services
│ │ └── supabase.js # Supabase client
│ ├── utils/ # Utility functions
│ ├── App.jsx # Main app component with routing
│ ├── main.jsx # App entry point
│ └── index.css # Global styles with Tailwind
├── database-schema.sql # Supabase database schema
├── .env.example # Example environment variables
└── README.md # This file
- Row Level Security (RLS): Enabled on all tables
- User Isolation: Each user can only access their own data
- Public Display URLs: Display pages are publicly accessible (read-only)
- Authenticated Uploads: Only authenticated users can upload photos
- Secure Storage: Photos stored in Supabase Storage with proper policies
- Create a new branch:
git checkout -b feature/your-feature-name
- Make your changes
- Test locally
- Commit and push:
git add . git commit -m "Add: your feature description" git push origin feature/your-feature-name
- Merge to main when ready (or create PR on GitHub)
- Main styles:
src/index.css(Tailwind utilities and custom classes) - Component styles: Tailwind classes in JSX files
- Color scheme: Edit gradient colors in component files
- Seasonal themes:
src/pages/Display.jsx(line ~100-200)
- Make changes in Supabase dashboard SQL editor
- Update
database-schema.sqlfile to keep it in sync - Document changes in this README
Local development:
- Edit
.envfile - Restart dev server
Production (Vercel):
- Go to Vercel dashboard
- Select bdaypresenter project
- Settings → Environment Variables
- Add/Edit variables
- Redeploy (or push to trigger auto-deploy)
Supabase free tier projects are paused after 7 days of inactivity. To prevent this, we use an external cron service to ping the database daily.
Endpoint: https://bdaypresenter.com/api/keep-alive
Setup:
- The keep-alive endpoint is at
api/keep-alive.js- it makes a simple query to keep the database active - We use cron-job.org (free) to ping this endpoint daily
- Login to cron-job.org to view/edit the scheduled job named "Keep Bday alive"
To modify the cron schedule:
- Go to cron-job.org and log in
- Find the "Keep Bday alive" job
- Adjust the schedule as needed (currently set to daily at 3:00 AM)
Note: Vercel's built-in cron jobs require a Pro plan. That's why we use the free external service instead.
- Make sure your
.envfile exists and has the correct variables - Restart your development server after creating/updating
.env
- Verify you created the
profile-photosbucket in Supabase Storage - Ensure the bucket is set to public
- Check that upload policies are configured correctly
- Verify the database schema was run successfully
- Check that team members were added through the dashboard
- Ensure the correct user ID is in the URL
- Make sure
tailwind.config.jsandpostcss.config.jsexist - Verify
@import "tailwindcss"is insrc/index.css - Try deleting
node_modulesand runningnpm installagain
- Check DNS settings in GoDaddy
- Verify A record points to 216.198.79.1
- Check Vercel domain configuration
- DNS changes can take up to 48 hours (usually 5-30 minutes)
- Check build logs in Vercel dashboard
- Ensure environment variables are set
- Verify
package.jsonscripts are correct - Check for TypeScript/ESLint errors
See database-schema.sql for the complete schema with:
- User profiles with organization names
- Team members with birthdays
- Row Level Security policies
- Automatic triggers
- Storage bucket configuration
This project is licensed under a Non-Commercial License with Attribution Requirement.
Key Points:
- ✅ Free to use for organizations and non-profits
- ✅ Can modify and adapt for your needs
- ✅ Must keep SignPresenter.com references
- ❌ Cannot sell or use commercially
- ❌ Cannot remove attribution
See LICENSE file for full details.
For commercial licensing inquiries, contact: mike@signpresenter.com
Contributions are welcome! Please feel free to submit a Pull Request. For major changes, please open an issue first to discuss what you would like to change.
- Fork the repository
- Create your feature branch (
git checkout -b feature/AmazingFeature) - Test your changes thoroughly
- Commit your changes (
git commit -m 'Add some AmazingFeature') - Push to the branch (
git push origin feature/AmazingFeature) - Open a Pull Request
- Issues: GitHub Issues
- Email: mike@signpresenter.com
- Live Demo: bdaypresenter.com
- SignPresenter Docs: support.signpresenter.com
- Built with ❤️ for organizations celebrating their teams
- Powered by SignPresenter for digital signage displays
- Thanks to all contributors and organizations using this system
- Custom theme builder
- Work anniversary tracking
- Team milestones and achievements
- Photo slideshow mode
- Multiple team support per organization
- Birthday reminder notifications
Made with ❤️ for the SignPresenter community