Skip to main content

Knowledge > Products > Pro Website > Admin Features

Pro Website Admin Features

Dashboard Overview​

Pro Website administration happens in the PewSearch admin dashboard at pewsearch.com/admin/[token]. The admin dashboard serves both Premium Page and Pro Website customers, but the WebsiteTab is only visible when premium_churches.plan === 'pro_website'.

The admin token is a unique, per-church secret string stored in premium_churches.admin_token. Churches receive this token via magic link during onboarding. There is no username/password login -- the token IS the authentication.

WebsiteTab Structure​

The WebsiteTab contains 3 sub-tabs that organize all Pro Website editing capabilities:

Sub-Tab 1: Design​

Controls the visual presentation of the Pro Website.

FeatureUI ElementData FieldNotes
Hero VideoPicker grid (12 thumbnails)hero_video_keyClick to select, shows preview
Slideshow BuilderMulti-select video pickerhero_slideshow_keysDrag to reorder, add/remove videos
Transition VideoPicker grid (3 thumbnails)transition_video_keyClick to select
Logo UploadDrag-drop zone + file pickerlogo_urlMax 2MB, PNG/JPG/SVG accepted

Logo Upload Details:

Upload flow:
1. User drags file onto drop zone OR clicks to open file picker
2. Client-side validation:
- File size <= 2MB
- File type: image/png, image/jpeg, image/svg+xml
- If validation fails: show inline error, do not upload
3. POST /api/upload/logo with FormData
4. Server uploads to Supabase Storage (church-logos bucket)
5. Returns public URL
6. UPDATE premium_churches SET logo_url = returned_url
7. Preview updates in real-time

The logo appears in the StickyNav (Section 1) of the Pro Website page. If no logo is uploaded, the church name is displayed as text.

Sub-Tab 2: Content​

Controls the informational content displayed on the Pro Website. This is where churches spend most of their admin time.

Hours Editor​

Structured day/time grid for service and office hours.

Data structure (custom_hours JSONB):
{
"sunday": [
{"label": "Morning Worship", "time": "9:00 AM"},
{"label": "Sunday School", "time": "10:30 AM"},
{"label": "Evening Service", "time": "6:00 PM"}
],
"monday": [],
"tuesday": [
{"label": "Bible Study", "time": "7:00 PM"}
],
...
}

UI: A grid with rows for each day of the week (Sunday through Saturday). Each day has an "Add Time" button to add label/time pairs. Entries can be edited or deleted. The day ordering in the display is always Sunday-first, matching visitor expectations.

Staff Editor​

Manages the staff directory (Section 9).

Data structure (custom_staff JSONB array):
[
{
"name": "Pastor John Smith",
"title": "Senior Pastor",
"bio": "Pastor John has served our church for 15 years...",
"photo_url": "https://...",
"order": 1
}
]

UI features:

  • Add/remove staff members
  • Edit name, title, bio for each
  • Photo upload (drag-drop or file picker, max 2MB, PNG/JPG)
  • Drag-to-reorder (updates order field)
  • Photo upload endpoint: POST /api/upload/staff-photo

Staff photo upload flow:

1. User clicks "Upload Photo" or drags onto staff card
2. Client-side validation: size <= 2MB, image type
3. POST /api/upload/staff-photo with FormData (includes church_id)
4. Server uploads to Supabase Storage (staff-photos bucket)
5. Returns public URL
6. Updates staff entry's photo_url in the JSONB array
7. Preview updates in card

Known gap: Staff photo upload UI needs polish. The drag-drop zone is functional but not as visually polished as the logo upload.

Ministries Editor​

Manages ministry cards (Section 11).

As of 2026-05-31 (PR #682) each category can hold sub-groups, photos, and a contact — all optional, so a flat {name, description} row is still valid and renders unchanged.

Data structure (custom_ministries JSONB array):
[
{
"name": "Children's Ministry",
"description": "Programs for kids nursery through 5th grade.",
"photo_url": "https://.../church-photos/.../ministry-...png",
"gallery_urls": ["https://.../1.png", "https://.../2.png"],
"contact_name": "Sarah Bennett",
"contact_email": "kids@church.org",
"contact_phone": "(616) 555-0142",
"subgroups": [
{
"label": "Nursery (Ages 0-2)",
"description": "Loving care during both services.",
"photo_url": "https://.../church-photos/.../ministry-...png",
"gallery_urls": [],
"contact_name": "Megan Liu",
"contact_email": "nursery@church.org",
"contact_phone": ""
}
]
}
]

UI features (collapsible accordion):

  • Add/remove ministries; each row collapses to name + sub-group count
  • Edit name and description
  • Main photo + up to 3 gallery photos per category (<=3.5MB each, PNG/JPG/WebP) via POST /api/upload/ministry-photo -> church-photos bucket
  • Contact name / email / phone per category
  • Sub-groups (e.g. age ranges): each with label, description, photos, contact
  • Draft-aware (writes draft_custom_ministries; goes live on Publish)

Public render: expandable cards (MinistriesSection) — category cards expand to reveal sub-groups on demand. Spec: knowledge/acceptance/pro-website-ministry-media.md.

Sermons Editor​

Manages sermon video embeds (Section 12).

Data structure (sermons JSONB array):
[
{
"title": "Walking by Faith",
"speaker": "Pastor John Smith",
"date": "2026-03-16",
"video_url": "https://youtube.com/watch?v=...",
"description": "A message about trusting God in uncertain times."
}
]

UI features:

  • Add/remove sermons
  • Edit title, speaker, date, video URL, description
  • Video URL validation (YouTube or Vimeo)
  • Most recent sermon appears as the featured/primary embed

Also supports a standalone featured_video_url field that overrides the first sermon as the primary video embed.

Beliefs Editor​

Manages belief statement cards (Section 5).

Data structure (beliefs JSONB array):
[
{
"title": "The Bible",
"description": "We believe the Bible is the inspired, authoritative Word of God."
}
]

UI features:

  • Add/remove belief statements
  • Edit title and description
  • Reorder

Events Editor​

Manages upcoming events (Section 13).

Data structure (events JSONB array):
[
{
"title": "Easter Sunday Service",
"date": "2026-04-05",
"time": "9:00 AM",
"description": "Special Easter celebration.",
"location": "Main Sanctuary"
}
]

UI features:

  • Add/remove events
  • Edit title, date, time, description, location
  • Date picker for date field

Known gap: No recurring event support. A weekly Bible study must be entered as separate events for each date. This is the most requested improvement from a UX perspective.

What to Expect Editor​

Manages the 10-field first-visit guide (Section 8).

Data structure (what_to_expect JSONB object):
{
"dress_code": "Come as you are! Most people wear casual.",
"parking": "Free parking in our main lot.",
"children": "Nursery and kids programs available.",
"first_visit": "Arrive 10 minutes early.",
"music_style": "Contemporary worship with a full band.",
"service_length": "About 75 minutes.",
"accessibility": "Wheelchair accessible.",
"communion": "First Sunday of each month.",
"coffee": "Free coffee in the lobby!",
"guest_checkin": "Fill out a connection card."
}

UI: 10 text fields, each with a descriptive label and placeholder text suggesting what to write. Fields can be left empty -- only non-empty fields render on the Pro Website page.

FieldLabel in AdminPlaceholder Hint
dress_codeDress CodeWhat should visitors wear?
parkingParkingWhere should visitors park?
childrenChildren's ProgramsWhat's available for kids?
first_visitFirst Visit ExperienceWhat happens when someone walks in?
music_styleMusic StyleWhat kind of worship music?
service_lengthService LengthHow long is a typical service?
accessibilityAccessibilityWheelchair access, hearing assistance?
communionCommunion / Lord's SupperWhen and who can participate?
coffeeCoffee & RefreshmentsIs there coffee? Snacks?
guest_checkinGuest Check-InConnection cards, welcome desk?

Giving URL​

Single text field for the church's online giving link (e.g., Tithe.ly, Planning Center Giving, PayPal).

Data field: premium_churches.giving_url

Contact Email​

Email address that receives contact form submissions from the Pro Website.

Data field: premium_churches.contact_email

Sub-Tab 3: Settings​

Controls routing, identity, and integration settings.

Vanity Slug​

Text field for the church's custom subdomain.

Validation rules:

Regex: /^[a-z0-9][a-z0-9-]{1,28}[a-z0-9]$/
- 3-30 characters total
- Must start and end with a letter or number
- May contain hyphens in the middle
- Lowercase only
- No spaces, underscores, or special characters

UI behavior:

  • Real-time validation as user types
  • Shows preview URL: grace-community.pewsearch.com
  • Uniqueness check against existing vanity_slugs (server-side on save)
  • Error message if slug is taken or invalid

See Vanity URLs for the full routing system.

Contact Email​

Same field as in Content sub-tab (duplicated for convenience in Settings context).

Manages social media profile URLs for the church.

Data structure (custom_social_media JSONB object):
{
"facebook": "https://facebook.com/gracechurch",
"instagram": "https://instagram.com/gracechurch",
"twitter": "https://twitter.com/gracechurch",
"youtube": "https://youtube.com/@gracechurch",
"tiktok": "https://tiktok.com/@gracechurch"
}

UI: 5 text fields with platform-specific icons and URL validation. Empty fields are acceptable -- only populated platforms show social icons on the Pro Website page.

Known gap: Social media editor is minimal. Future improvements could include preview of the linked page, follower count display, or automatic content sync.

Care Settings​

Configuration for pastoral care features (prayer request routing, callback preferences, notification settings). This overlaps with ChurchWiseAI settings for churches that also have a CWA subscription.

Role-Based Access Control​

The admin dashboard uses a 9-role system defined in premium-shared.ts. This controls which tabs are visible and which edit actions are permitted.

Role Definitions​

RoleDisplay NameDashboard TabsEdit Permissions
adminAdministratorAll tabsAll edit permissions, team management
office_adminOffice AdminOverview, Calls, Requests, Care, Training, Website, SettingsBasic info, contact info, website content
prayer_teamPrayer TeamOverview, RequestsView only (prayer requests)
care_teamCare TeamOverview, Requests, CareView only (care cases)
treasurerTreasurerOverviewView only (financial metrics)
volunteer_coordinatorVolunteer CoordinatorOverview, RequestsView only
worship_leaderWorship LeaderOverview, TrainingEdit pastor_pulse only
spiritual_leaderSpiritual LeaderOverview, TrainingView only
care_leaderCare LeaderOverview, TrainingView only

Tab Visibility by Role​

Tab visibility matrix:

admin office_admin prayer care treasurer volunteer worship
Overview Y Y Y Y Y Y Y
Calls Y Y N N N N N
Requests Y Y Y Y N Y N
Care Y Y N Y N N N
Training Y Y N N N N Y
Website Y Y N N N N N
Settings Y Y N N N N N
Upgrade Y N N N N N N

Confidential Content Access​

Sensitive pastoral information is access-controlled by role:

PASTORAL_ROLES = ['admin', 'office_admin']

IF user.role IN PASTORAL_ROLES:
Show full prayer request text
Show full callback request reasons
Show visitor contact details
ELSE:
Show redacted prayer text (first 20 chars + "...")
Show "Callback requested" without reason
Show visitor name only (no phone/email)

This ensures that prayer team members can see that prayer requests exist and pray generally, but cannot access detailed personal information unless they have pastoral-level access.

Team Management​

How It Works​

The admin (token holder) can invite team members by generating an invite link. Each team member gets their own access_token with an assigned role.

Database tables:

TablePurpose
premium_churchesStores the primary admin_token for the church admin
church_team_membersStores team member tokens: access_token, role, church_id, name, email, is_active, last_accessed_at, created_at

Invite flow:

1. Admin clicks "Invite Team Member" in Settings
2. Admin enters: name, email, role (dropdown)
3. System generates unique access_token
4. INSERT into church_team_members (church_id, name, email, role, access_token, is_active=true)
5. Invite link generated: pewsearch.com/admin/{access_token}
6. Admin shares link with team member (email, text, etc.)
7. Team member clicks link → resolveToken validates → dashboard loads with role permissions

Token resolution (resolveToken):

1. Check premium_churches.admin_token first
IF match: role = 'admin', return church data
2. Check church_team_members.access_token
IF match AND is_active = true:
Update last_accessed_at = now()
Return church data with team member's role
3. IF no match: return 401 unauthorized

Team Management UI​

The admin can:

  • View all team members (name, role, last accessed)
  • Edit a team member's role
  • Deactivate a team member (is_active = false)
  • Re-activate a deactivated member
  • Generate a new invite link

Team members CANNOT:

  • Invite other team members
  • Change their own role
  • Access tabs outside their role's permissions
  • See the admin token

Save Behavior​

All editors in WebsiteTab use an auto-save with debounce pattern:

1. User makes an edit (types, selects, reorders)
2. Debounce timer starts (500ms)
3. If user edits again within 500ms, timer resets
4. After 500ms of inactivity:
- PATCH /api/admin/premium-churches (or direct Supabase update)
- UPDATE premium_churches SET [changed_field] = [new_value] WHERE church_id = ...
- Show "Saved" indicator (green checkmark, fades after 2 seconds)
5. If save fails: show error toast, retry button

This means there is no "Save" button. Changes are persisted as the admin types, with a brief debounce to avoid excessive database writes.

API Endpoints​

EndpointMethodPurpose
/api/upload/logoPOSTUpload church logo to Supabase Storage
/api/upload/staff-photoPOSTUpload staff member photo to Supabase Storage
/api/admin/premium-churchesPATCHUpdate premium_churches fields
/api/contactPOSTProcess contact form submissions (public)

File References​

FilePurpose
pewsearch/web/src/app/admin/[token]/components/WebsiteTab.tsxMain WebsiteTab component with all 3 sub-tabs
pewsearch/web/src/lib/premium-shared.tsRole definitions, tab visibility, tier constants (client-safe)
pewsearch/web/src/lib/premium-queries.tsServer-side Supabase queries for premium data
pewsearch/web/src/app/admin/[token]/page.tsxAdmin page entry point, token resolution
pewsearch/web/src/app/api/upload/logo/route.tsLogo upload API
pewsearch/web/src/app/api/upload/staff-photo/route.tsStaff photo upload API

See Also​