尚未检测到更新。GitHub 发布版本后会显示在这里。
个人 GitHub 账号下公开仓库的所有者可以登录并验证所有权,自行管理介绍,无需管理员批准。
登录并生成验证文件,在 30 分钟内将其提交到此仓库的默认分支。其他分支或分叉仓库中的文件无效。然后在下方检查文件,即可无需管理员批准直接管理项目。请保留文件以维持管理权限。
如需登录,将前往登录页面。登录后请回到此处,再次点击所选的验证按钮。
在项目文件夹中运行 /nomorevibe verify,即可验证所有权并自行管理介绍。
一分钟完成验证制作者的介绍仅有上面的一句话。 更多详情请阅读仓库 README。 仓库 README ↗
正在加载完整 README。
查看完整 README ↗Sunday service scheduling for Mont Carmel Church: teams and positions (coordinators, worship, sound, ushers…), monthly calendar with auto-fill, coverage and workload checks, double-booking warnings, live Sunday checklists, a live service timer with a full-screen stage screen, confirm/decline and swap requests, and order-of-service templates.
vercel.json)src/ — the app (main.js starts it; domain.js holds the scheduling rules; views/ one file per screen)schema.sql — database setup for a brand-new projectmigrations/ — database updates, run in order after schema.sqltests/ — run with npm test (tests/db/ runs the migrations on a local Postgres)Database updates live in migrations/, numbered in order. For each one: in Supabase open SQL Editor → New query, paste the whole file, click Run, then merge the matching pull request so Vercel publishes the app. Every migration only adds things and is safe to run twice. Until a migration has run, the screens that need it show Database update needed and everything else keeps working.
| # | File | Adds | Notes |
|---|---|---|---|
| 001 | 001-teams-and-positions.sql | Teams, positions, assignments | Run it, then merge soon after: changes made in the old app in between don't carry over. Everyone on the roster becomes a Coordinator. |
| 002 | 002-live-timer.sql | Live service timer | |
| 003 | 003-members-attendance-events.sql | Members, check-in, events | |
| 004 | 004-service-reports.sql | Service reports | |
| 005 | 005-activity-log.sql | Activity log (who changed what) | Starts recording from the moment it runs; earlier changes aren't in the log. |
| 006 | 006-people.sql | Richer people: categories, families, notes timeline, profile fields, saved filters | Each status becomes a category (member/regular → Congregation, newcomer/visitor → Visitors) and the move is written to the category history; the old status column is kept. Notes move to the notes timeline. Everyone on the serving team gets a member record (Volunteers). Check-in keeps working before and after. |
| 007 | 007-messaging.sql | Email and text messages: message log, recipients, opt-out history | Sending also needs the Vercel settings below. |
| 008 | 008-followups.sql | Follow-up flows (Newcomer flow with four steps), board, weekly reminder | From now on, new Visitors join the Newcomer flow automatically. People already in Visitors aren't added; use Add to a follow-up for them. The weekly email also needs CRON_SECRET below. |
| 009 | 009-reports.sql | Attendance & people reports, weekly report emails | Reports read what's already there, so they include history from before 009. Weekly emails need the messaging settings and CRON_SECRET. |
| 010 | 010-admins.sql | Manage administrators in the app (People → Administrators) | Emails are stored lower-case, the last administrator can't be removed, and changes go in the activity log. |
| 011 | 011-service-layout.sql | Printable service layout: names typed for one service | Placeholders themselves live in the templates, so the layout shows and prints before 011; typing a name needs 011. |
| 012 | 012-admin-permissions.sql | Different access for each administrator (including Live service for the timer) | Everyone who is an administrator today keeps full access; narrow it on People → Administrators afterwards. |
| 013 | 013-volunteers-from-members.sql | Add volunteers from the members list | A member added to the serving team is linked to their existing record instead of creating a second one. |
| 014 | 014-hide-admin-list.sql | Only full administrators see who the administrators are | Others see only their own access. |
| 015 | 015-event-services.sql | Calendar events linked to their service plan and printable layout | Until it runs, the calendar still links Sundays and special services to their layouts; only “Plan it as a service” waits for it. |
| 016 | 016-events-on-schedule.sql | Every calendar event is on the Schedule, and the other way round | Upcoming events get a draft Schedule entry; Schedule special events get a calendar entry. Deleting one deletes the other. |
Run npm test to apply schema.sql and every migration to a throwaway local Postgres and check the access rules, without touching Supabase.
People → Everyone is the church directory (the serving team and teams & positions are the other two tabs).
Contact opens the composer from: the people you've ticked (or everyone shown, including a saved filter) on People, a person's profile, a team on Teams & positions, or a service's team on Live. Choose Text (SMS), Email or Both, write the message (Insert first name adds {first_name}), check who won't receive it (opted out, no mobile, no email), review the total, and send. The counter shows characters and text segments as you type.
Setting it up (Vercel → Project → Settings → Environment Variables):
| Variable | What it is |
|---|---|
SUPABASE_DB_URL | Supabase → Project Settings → Database → Connection string, Transaction pooler (port 6543), with your database password filled in |
UNSUBSCRIBE_SECRET | Any long random text (signs the unsubscribe links). For example, the output of openssl rand -hex 32 |
APP_URL | Your site address, e.g. https://servicesync-ruby.vercel.app |
TWILIO_SID, TWILIO_TOKEN | Twilio Console → Account Info |
TWILIO_FROM | Your Twilio number (+1…) or Messaging Service SID (MG…) |
RESEND_API_KEY | Resend → API Keys |
MAIL_FROM | e.g. Mont Carmel <[email protected]> (the domain must be verified in Resend) |
Then in Twilio, set the number's (or Messaging Service's) incoming message webhook to https://<your site>/api/twilio-inbound (HTTP POST). US carriers require registering business texting (A2P 10DLC) in Twilio before bulk texts are delivered; this can take a couple of weeks.
The Follow-ups tab shows one board per flow, with a column for each step. The church starts with a Newcomer flow: Welcome text (1 day), Phone call (3 days), Second visit (7 days), Connect to a group (14 days). Administrators can rename steps, change their due days, give each step a default person, and add new flows.
| Variable | What it is |
|---|---|
CRON_SECRET | Any long random text. Vercel sends it to /api/cron so nobody else can trigger the emails |
Print the order of service before every service, with who leads each part.
Administrators can fill in any service; people on the roster can fill in published Sundays (the same rule as service reports).
Everyone in check-in and the People list is a member. To make one of them a volunteer:
The new serving-team card is linked to the member's record (attendance, notes, follow-ups stay together); it never creates a duplicate. Members already on the serving team are greyed out in the list, and their profile shows On the serving team. This needs the Schedule & teams area (or full access).
Every event added on Events also appears on the Schedule (as a special event, in draft until the month is published), and every special event added on the Schedule appears on the calendar. Plan the serving team on the Schedule like any Sunday: press Serving team on the event (or on its layout) to jump there. Deleting the event in either place removes it from both.
After midnight: an end time earlier than the start counts as the next day, so 7:00 PM – 2:00 AM is one event. It shows as "7:00 PM – 2:00 AM (next day)", and the calendar marks the next day with "↳ Night of worship".
Every event or service can use any layout (order of service):
Every service on the Events calendar links to its layout: click a Sunday to see its English and French services, each with Service layout and Live. Special services from the Schedule appear on the calendar too.
Reports → Attendance & people has these reports. Each one downloads as CSV (it opens in Excel) and works in English and French:
| Report | What it shows |
|---|---|
| Absentees | People who came at least N times, then missed the last N weeks. Tick people to text or email them, or add them to a follow-up |
| Attendance | Charts and tables by service, category and month, with first visits |
| One person's attendance | Every Sunday someone came, for the period you choose |
| People activity | New people, category changes, notes, finished follow-ups and opt-outs |
| No notes lately | People nobody has written a note about in N days |
| Category changes | Who moved between categories, when and by whom |
| Volunteer positions | Who served in which position, how often, and how many times they confirmed or declined |
| Text message log | Every text with its delivery status. Team members see only their own |
| Unsubscribes | Opt-outs and opt-ins by email and text (administrators only) |
Team members see the same people and attendance they can already see in the app. Administrators can also choose Email weekly on a report: pick the weekday, the language and up to 20 addresses. The cron job runs every day at 12:00 UTC and sends the reports that are due that weekday. Each email has the first 50 rows and the full CSV attached, and it's logged under Sent messages.
Reports has a report for every service (English, French and special events), newest first, showing how many notes, how many people were present and how long it ran. Each report has:
Notes save when you click out of the box ("Saved" appears). Two people can write notes on different segments at the same time without overwriting each other. Open a report from the list or from Report & notes on the Live screen. Admins can write any report; people on the roster can write reports for published Sundays.
Reports → Activity log (administrators only) lists every change to the schedule, serving team, members, check-ins, events, templates and reports: who made it, when, and in plain words ("Anna confirmed: Jerry as Coordinator · English Service, Nov 1"). Search it, or filter by area or by person. Bursts such as an import show as one line ("added 120 members") that expands.
The database records the changes itself, so nothing done through the app can skip the log, and nobody can edit or delete entries through the app. Live-timer and checklist ticks aren't logged.
On Live, each service has a Service timer card. Press Start service and it counts down each segment of the order of service (from Templates), in sync on every screen.
Stage screen. Stage screen opens the timer in a new window: segment name, a giant countdown, what's next, the time of day, and whether the service is on time. It turns amber near the end of a segment and red when it runs over. Press Full screen (or F). The French service's screen is in French.
The address looks like …/#stage/2026-11-01/en, so a booth laptop or TV can bookmark it. It needs someone signed in. From a keyboard, Space or → = next, ← = back, P = pause, + = add a minute (for people allowed to run the timer).
Phone remote. Press Remote on the timer card. Scan the QR code with a phone (or copy the link, …/#remote/2026-11-01/en), sign in, and the phone becomes a remote: a big Next button, Back, Pause, −1 / +1 / +5 min, a stage message and End service. Every press updates the stage screen, the Live tab and any other remote within a second (through Supabase Realtime), so the timer can be run from the front row while the stage screen sits on the booth computer. Several remotes can be used at once; the phone stays awake while the remote is open.
Who can run the timer: administrators with Full access or the Live service area (any service, even before it's published), and people on the roster on published Sundays. Others see the countdown without the buttons.
On computers the tabs sit in a bar on the left, with your name, sign-out and the EN | FR switch at the bottom. On phones and tablets, the ☰ button at the top left opens the same list from the left side.
npm install
npm run dev # local preview at http://localhost:5173
npm test # scheduling rules and screens
npm run build # what Vercel runs
servicesync, pick a region near Charlotte (US East), set a database password, and create it.schema.sql, and click Run. Then do the same with each file in migrations/, in order.
[email protected] the administrator. Change it first if you sign in with a different email.https://abcd1234.supabase.co)service_role key here.src/config.js (or set VITE_SUPABASE_URL and VITE_SUPABASE_ANON_KEY in Vercel → Project → Settings → Environment Variables):
export const SUPABASE_URL = ... || 'https://abcd1234.supabase.co';
export const SUPABASE_ANON_KEY = ... || 'eyJhbGciOi...';
The anon key is safe to publish. The access rules in schema.sql decide what each person can see and change.Option A — from your computer (fastest)
cd servicesync-web
npx vercel # log in, accept the defaults
npx vercel --prod # publish
Option B — through GitHub
Push this folder to a GitHub repo, then on vercel.com click Add New → Project, import the repo and click Deploy. vercel.json sets the build for you.
Your app will be at something like servicesync.vercel.app. To use your own domain, add it under Project → Settings → Domains.
In Supabase, open Authentication → URL Configuration:
https://servicesync.vercel.appWithout this step, the sign-in email links point to the wrong place.
Optional — "Continue with Google": in Authentication → Providers → Google, turn it on and paste a Google OAuth client ID and secret (created at console.cloud.google.com). Until then, coordinators use the email sign-in link.
Who can do what
| Administrator | Team member | |
|---|---|---|
| Plan, auto-fill and publish months | ✓ | |
| Edit people, teams, templates, checklists | ✓ | |
| See published schedule | ✓ | ✓ |
| Confirm or decline own assignments | ✓ | ✓ |
| Mark own Sundays off | ✓ | ✓ |
| Request a swap | ✓ | |
| Approve or decline swaps | ✓ | |
| Tick checklists in Live view | ✓ | ✓ |
Go to People → Administrators (administrators only). Pick someone from the serving team, or type any email address, then press Add administrator and choose what they manage. To take someone off the list, press Remove next to their name. They stay on the serving team with a team member's access. The change applies the next time they open or reload the app. The last administrator can't be removed, so the church is never locked out.
Access levels (after migration 012): give an administrator Full access, or tick only the areas they manage:
| Area | What it allows |
|---|---|
| Schedule & teams | Plan and publish months, teams, positions, the serving team, swaps, days off, events |
| Live service | Run the service timer and phone remote for any service, even before it's published |
| People | Edit and remove members, categories, families, import; manage anyone's notes and saved filters |
| Messaging | Text or email anyone; see every sent message and unsubscribe |
| Follow-ups | Edit follow-up flows and steps; delete follow-ups |
| Reports | Activity log and weekly report emails |
| Templates | Order of service, placeholders, checklists |
Every administrator can still see everything, write service reports and check people in. Anyone on the roster can still run the timer on published Sundays. Only administrators with full access see the list of administrators, add or remove them, or change their access, and there is always at least one with full access. The database enforces all of this, not just the screens.
Before migration 010, or if you're ever locked out, you can do the same in the Supabase SQL Editor:
insert into admins (email) values ('[email protected]');
delete from admins where email = '[email protected]';