TECHNICAL HANDOFF
Developer Guide
Architecture, access control, deployment, data flows, and recovery notes for technically experienced maintainers of the Sunset Lake Ward website.
Architecture
| Frontend | Static HTML, CSS, and browser JavaScript hosted by Netlify. |
|---|---|
| Production domain | https://sunsetlakeward.com |
| Netlify fallback | https://sunsetlakeward.netlify.app |
| Database and authentication | Supabase project nftyhqoxdicwqddnowyv. |
| DNS | Cloudflare routes the apex and www domain to Netlify. |
| Identity provider | Google OAuth through Supabase Auth, with email magic links retained as a fallback. |
The browser uses only the Supabase publishable key. Authorization is enforced in PostgreSQL Row Level Security, not by hiding interface elements.
Deployed file map
| File | Purpose |
|---|---|
index.html, app.js | Homepage announcements, organizations, and compact event list. |
calendar.html, calendar.js | Month/list calendar, filters, details, and subscription links. |
editor.html, editor.js | Authentication and core events, announcements, reviews, and editor management. |
editor-content.js | Managed pages, signup sheets, choices, and private roster tools. |
signup-permissions.js | Roster Viewer and Signup Coordinator assignment and scoped interface behavior. |
page.html, page.js | Public managed-page rendering. |
signup.html, signup.js | Public signup rendering, submission, and cancellation. |
embed.html, embed.js | Embeddable events view for the stake website. |
config.js | Public Supabase URL, publishable key, and public endpoint configuration. |
_headers | Netlify security and frame-embedding headers. |
Database model
| Table | Responsibility |
|---|---|
auxiliaries | Organization directory and display order. |
events | Ward, imported sheet, and Church-calendar events plus source metadata and editor overrides. |
announcements | Published and draft announcements. |
site_pages | Editor-managed public resource pages. |
signup_sheets | Signup settings, scheduling, privacy choices, and organizer-only notes. |
signup_slots | Times, items, volunteer positions, and capacity. |
signup_entries | Participant names, selections, private contact details, notes, and cancellation state. |
signup_access_grants | Per-signup Roster Viewer and Signup Coordinator assignments. |
site_members | Active editor identity and ward-wide or auxiliary role. |
pending_site_members | Email-based editor invitations awaiting or linked to an Auth user. |
Every public-schema table uses RLS. Schema changes are recorded in Supabase migrations; do not make undocumented production-only changes.
Authentication and roles
Google redirects to Supabase, and Supabase redirects the authenticated browser back to the editor.
Google authorized redirect URI: https://nftyhqoxdicwqddnowyv.supabase.co/auth/v1/callback Application redirect URLs: https://sunsetlakeward.com/editor.html https://sunsetlakeward.netlify.app/editor.html
The Google OAuth Client ID and secret live in the Supabase Google provider configuration. The secret must never be placed in config.js, committed to a repository, included in a ZIP, or pasted into client-side code.
| Role | Server-enforced scope |
|---|---|
editor | One auxiliary; drafts and submissions, plus grants for that auxiliary’s signup sheets. |
publisher | All organizations; review and publish authority. |
admin | All content and editor administration. |
signup_delegate | Only signup sheets listed in active signup_access_grants. |
Security model
- Use the publishable key in the browser; never expose a Supabase secret or service-role key.
- RLS checks the authenticated user, active role, auxiliary, signup ID, and permission level.
- Signup contact information, age information, notes, cancellation tokens, and organizer notes are not available through anonymous table reads.
- The public signup Edge Function returns an explicit safe-field response rather than raw database rows.
- Removing a signup grant deactivates signup-specific access when no active grants remain.
- Interface visibility is convenience only; database policies remain the authority.
Calendar data flow
- Organization calendar tabs are imported as canonical event rows. Combined Monthly and Weekly tabs are not imported as separate sources.
- The
church-calendarEdge Function reads the connected Church iCalendar feed. - Source identifiers and payloads support matching and duplicate handling.
- Editor overrides preserve locally improved details when an external source refreshes.
- The calendar page and combined ICS feed expose published public events for browser and calendar clients.
Edge Function church-calendar is intentionally public because calendar applications cannot attach a Supabase user session. Keep its output limited to published public event information.
Signup data flow
- An authorized editor creates a sheet and optional slots.
- The public page loads a sanitized response from the
public-signupsEdge Function. - A participant submits through that function; capacity and validation are enforced server-side.
- The participant receives a private cancellation URL.
- Authorized editors or assigned signup delegates read the private roster through authenticated, RLS-protected requests.
The public-signups function does not require a user JWT because visitors must be able to volunteer. It must continue to perform its own validation and return only intentionally public fields.
Deployment runbook
- Make changes in the deployable
dist/directory or rebuild the source project when full source is available. - Run JavaScript syntax checks and verify required HTML references.
- Test the homepage, calendar, editor login, role-restricted views, public signup, cancellation, and stake embed.
- Zip the
distdirectory so the archive containsdist/index.htmland the other site files. - Deploy the ZIP through Netlify and wait for the production deployment to complete.
- Open both the Netlify address and
sunsetlakeward.com. Test in a private browser window and on a phone.
Database migrations and Edge Functions are deployed through Supabase, separately from the Netlify ZIP. Coordinate database-first changes so the existing frontend remains compatible during deployment.
Release checklist
- Homepage loads announcements and only the compact initial event list.
- Calendar month/list switching and organization filtering work.
- Google, Outlook, Apple, and calendar-file subscription links open correctly.
- Google OAuth returns to
/editor.htmlon desktop and mobile. - Auxiliary Editors cannot edit another organization.
- Roster Viewers cannot edit a signup or grant permissions.
- Signup Coordinators see only assigned signup sheets.
- Anonymous requests cannot read private signup columns.
- Public signups enforce capacity and return a cancellation link.
- The stake embed remains frameable while the editor remains protected from framing.
Troubleshooting and recovery
OAuth redirect mismatch
Confirm the error’s requested redirect URI exactly matches the Supabase callback registered on the same Google OAuth Client ID configured in Supabase. Confirm both custom-domain and Netlify editor URLs are in Supabase Auth redirect URLs.
Editor returns to sign-in
Confirm the Auth session is stored under sunset_lake_editor_session, the user has an active site_members record, and the browser is not using a stale embedded webview.
Content disappears
Check status, visibility, publish/expiration dates, organization filters, and RLS before changing data. External calendar refreshes should preserve editor overrides.
Bad deployment
Use Netlify’s prior deploy history to restore the previous frontend. Database rollback requires a deliberate reverse migration; do not delete tables or reset the project to repair a display problem.
Handoff
Transfer access to Netlify, Supabase, Cloudflare, and the Google Cloud OAuth project separately. Rotate secrets when maintainers change, but do not rotate the public publishable key unless necessary.
Participation, bulletin, and email additions
participate.html submits bulletin announcements, sacrament-meeting offers, ideas, ward-needs offers, and appointment requests through the constrained submit_ward_request database function. Direct public table access is denied. bulletin.html reads only published editions and items; planning and review editions remain authenticated.
Reviewer access uses get_ward_requests_for_editor, which masks anonymous submitters from Ward Publishers while preserving identity for Site Administrators. Site Administrators may block an abusive submitter through block_ward_submitter.
Resend is verified for sunsetlakeward.com with sending enabled and receiving disabled. Store the future Resend API key as a server-side Supabase secret; never place it in config.js or browser code.