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).

Data structure (custom_ministries JSONB array):
[
{
"name": "Youth Group",
"description": "For students in grades 6-12. Meets Wednesday evenings.",
"order": 1
}
]

UI features:

  • Add/remove ministries
  • Edit name and description for each
  • Drag-to-reorder
  • No image/icon upload (text-only ministry cards)

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