Leap Build Spec: Upgrade Custom Forms to Work Like SignUpGenius + Jotform
We need to upgrade community.givehub.com Custom Forms so they can handle:
-
SignUpGenius-style slot signups
-
Jotform-style conditional logic
-
multi-step forms
-
repeatable sections
-
capacity limits
-
waitlists
-
reminders
-
form-to-workflow automation
-
payment plans from Custom Forms
This should extend the existing Custom Forms system, not replace it.
1. New Form Field Types
Add these field/block types:
type CustomFormFieldType =
| existingFieldTypes
| "signup_slots"
| "repeatable_section"
| "payment_plan"
| "capacity_limit"
| "section_break"
| "page_break";
2. Signup Slots Field
Add a new Custom Form field type:
signup_slots
This allows orgs to create date/time-based signup options with capacity.
Admin builder settings
For each signup slot field, allow admin to configure:
{
title: string;
description?: string;
selectionMode: "single" | "multiple";
showRemainingSpots: boolean;
showRegistrantNames: boolean;
allowWaitlist: boolean;
cancellationAllowed: boolean;
reminderEnabled: boolean;
reminderHoursBefore: number;
slots: Array<{
id?: string;
label: string;
date: string;
startTime: string;
endTime: string;
location?: string;
notes?: string;
capacity: number;
priceCents?: number;
isActive: boolean;
}>;
}
Public form behavior
Show slot choices like:
Saturday, May 2
9:00 AM – 11:00 AM
3 spots left
Saturday, May 2
11:00 AM – 1:00 PM
FULL — Join Waitlist
Rules:
-
Prevent overbooking.
-
If slot is full and waitlist is enabled, allow waitlist signup.
-
If waitlist is disabled, disable the full slot.
-
If selectionMode = single, user can select one slot.
-
If selectionMode = multiple, user can select multiple slots.
-
If showRemainingSpots = true, show spots left.
-
If showRegistrantNames = true, show public-safe names like John S..
3. Database Tables for Slots
Create tables:
CREATE TABLE custom_form_slots (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
org_id UUID NOT NULL REFERENCES organizations(id) ON DELETE CASCADE,
form_id UUID NOT NULL,
field_id UUID NOT NULL,
label TEXT NOT NULL,
slot_date DATE NOT NULL,
start_time TIME NOT NULL,
end_time TIME NOT NULL,
location TEXT NULL,
notes TEXT NULL,
capacity INTEGER NOT NULL,
price_cents INTEGER NOT NULL DEFAULT 0,
is_active BOOLEAN NOT NULL DEFAULT true,
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
CREATE TABLE custom_form_slot_registrations (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
org_id UUID NOT NULL REFERENCES organizations(id) ON DELETE CASCADE,
form_id UUID NOT NULL,
field_id UUID NOT NULL,
slot_id UUID NOT NULL REFERENCES custom_form_slots(id) ON DELETE CASCADE,
submission_id UUID NULL,
person_id UUID NULL,
registrant_name TEXT NOT NULL,
registrant_email TEXT NOT NULL,
registrant_phone TEXT NULL,
status TEXT NOT NULL DEFAULT 'confirmed',
/*
confirmed
waitlisted
canceled
attended
no_show
*/
waitlist_position INTEGER NULL,
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
CREATE INDEX idx_custom_form_slots_form_field
ON custom_form_slots(form_id, field_id);
CREATE INDEX idx_custom_form_slot_registrations_slot_status
ON custom_form_slot_registrations(slot_id, status);
Important: slot availability must be calculated from confirmed registrations only.
4. Slot Availability Logic
Add backend utility:
async function getSlotAvailability(slotId: string): Promise<{
capacity: number;
confirmedCount: number;
waitlistCount: number;
remainingSpots: number;
isFull: boolean;
}>
Availability rules:
remainingSpots = capacity - confirmedCount;
isFull = remainingSpots <= 0;
When submitting a form with selected slots:
-
Start DB transaction.
-
Lock selected slot rows or use transaction-safe count.
-
Check current confirmed count.
-
If spot available:
-
create registration with status = confirmed.
-
-
If full and waitlist enabled:
-
create registration with status = waitlisted.
-
assign next waitlist_position.
-
-
If full and waitlist disabled:
-
reject submission with user-friendly error.
-
-
Commit transaction.
This must be race-condition safe.
5. Waitlist Promotion
When a confirmed registration is canceled:
-
Find earliest waitlisted person for that slot.
-
Promote to confirmed.
-
Clear waitlist position.
-
Send email/SMS notification.
Add admin action:
Promote next waitlisted person
6. Capacity Limits
Add form-level capacity settings.
Admin can configure:
{
maxSubmissionsEnabled: boolean;
maxSubmissions?: number;
closeWhenFull: boolean;
waitlistWhenFull: boolean;
}
Public behavior:
-
If form reaches max submissions and waitlist disabled:
-
show closed/full message.
-
-
If form reaches max submissions and waitlist enabled:
-
allow waitlist-only submission.
-
Add helper:
async function getFormCapacityStatus(formId: string): Promise<{
maxSubmissions?: number;
confirmedSubmissions: number;
remaining: number | null;
isFull: boolean;
}>
7. Repeatable Sections
Add field type:
repeatable_section
Used for:
-
registering multiple kids
-
adding multiple attendees
-
adding household members
-
adding multiple volunteer names
Admin settings:
{
title: string;
minItems: number;
maxItems: number;
buttonLabel: string;
fields: CustomFormField[];
}
Public behavior:
-
User can click “Add another participant.”
-
Each repeated item stores its own field values.
-
Validation runs per repeated item.
-
Payment calculation can optionally multiply by repeat count.
Example:
Participant 1
- First name
- Last name
- Grade
- T-shirt size
[Add another participant]
8. Conditional Logic Engine
Add form-level conditional logic similar to Jotform.
Admin can create rules:
{
id: string;
name: string;
conditions: Array<{
fieldId: string;
operator:
| "equals"
| "not_equals"
| "contains"
| "greater_than"
| "less_than"
| "is_empty"
| "is_not_empty";
value?: any;
}>;
conditionMode: "all" | "any";
actions: Array<{
type:
| "show_field"
| "hide_field"
| "require_field"
| "make_optional"
| "show_page"
| "skip_page"
| "set_value"
| "add_fee"
| "apply_tag";
targetFieldId?: string;
targetPageId?: string;
value?: any;
}>;
}
Public behavior:
-
Logic runs live as user fills out the form.
-
Hidden fields should not be required.
-
Hidden field values should either be cleared or excluded from submission.
-
Fees should update live when logic adds fees.
Examples:
IF “Do you need childcare?” = Yes
SHOW “Child Information”
IF “Ticket Type” = VIP
ADD FEE $50
IF “Volunteer Role” = Kitchen
SHOW “Food Allergy / Safety Questions”
9. Multi-Step Forms
Add page support using:
page_break
Admin builder should allow fields to be grouped into pages.
Public UI:
-
Step indicator
-
Next button
-
Back button
-
Save progress later, future enhancement
-
Validation per step before moving forward
Example:
Step 1: Contact Info
Step 2: Participant Details
Step 3: Slot / Registration
Step 4: Payment
Step 5: Confirmation
10. Payment Plan Integration
Connect this to the Payment Plan system from the previous spec.
Custom Forms should support:
-
Pay in full
-
Payment plan
-
Optional down payment
-
Installments
-
Saved payment method
-
Authorization checkbox
Payment fields should work with:
-
form fees
-
slot prices
-
repeatable participant count
-
add-on fees from conditional logic
Payment total should be calculated from:
baseFormAmount
+ selectedSlotPrices
+ repeatableSectionFees
+ conditionalLogicFees
+ addOns
- discounts
Then user can:
Pay full amount today
or
Enroll in payment plan
11. Form Submission → CRM
On submission:
-
Create or update person by email.
-
Attach form submission to person timeline.
-
Apply selected tags.
-
Save slot registrations.
-
Save payment/payment plan records.
-
Trigger workflows.
Activity timeline example:
Submitted form: Youth Camp Registration
Selected slot: Saturday 9 AM – 11 AM
Payment plan created: $100/month for 6 months
12. Form Submission → Workflow Automation
Add workflow trigger:
form_submitted
Trigger payload:
{
orgId: string;
formId: string;
submissionId: string;
personId?: string;
formName: string;
submittedAt: string;
fields: Record<string, any>;
selectedSlots?: Array<{
slotId: string;
label: string;
date: string;
startTime: string;
endTime: string;
}>;
payment?: {
totalAmountCents: number;
paymentStatus: string;
};
paymentPlan?: {
id: string;
status: string;
totalAmountCents: number;
};
}
Workflow actions should support:
-
Send email
-
Send SMS
-
Create task
-
Apply tag
-
Add to group/list
-
Notify admin
-
Start drip campaign
13. Confirmation Emails
After submission, send confirmation email.
Email should include:
-
Organization name
-
Form name
-
Submission summary
-
Selected slots
-
Payment summary
-
Payment plan schedule, if applicable
-
Cancellation/update link if enabled
Subject example:
Confirmation: {{formName}}
14. Reminder Emails/SMS for Slots
Create scheduled job:
sendSlotReminders
Runs hourly or daily.
Find confirmed slot registrations where:
slot start date/time is within reminder window
AND reminder has not already been sent
Send reminder email/SMS:
Reminder: {{slotLabel}}
Date: {{slotDate}}
Time: {{startTime}} - {{endTime}}
Location: {{location}}
Add reminder tracking table or fields so reminders are not sent twice.
15. Admin Submission Management
Add enhanced form submissions page.
Admin should be able to view:
-
Form submission
-
Person record
-
Selected slots
-
Payment status
-
Payment plan status
-
Tags applied
-
Workflow status
Admin actions:
-
Cancel slot registration
-
Promote waitlist
-
Resend confirmation
-
Export CSV
-
Mark attended/no-show
-
Refund payment, if existing refund flow exists
-
Open person profile
16. Public Update / Cancel Link
Generate secure tokenized link for each submission.
Allows user to:
-
View submission
-
Update basic details
-
Cancel slot if allowed
-
Update payment method for payment plan
Use expiring token or long-lived signed token.
Do not require account login.
17. Templates Library
Add starter templates.
Suggested templates:
-
Volunteer Signup
-
Meal Train / Serve Team Signup
-
Youth Camp Registration
-
Mission Trip Payment Plan
-
School Fee Payment Plan
-
Sponsorship Commitment Form
-
Event RSVP
-
Class Registration
-
Childcare Signup
-
Donation Pledge Form
Each template should preconfigure fields, slots, payment settings, and workflows where possible.
18. Permissions
Add permissions:
forms.view
forms.create
forms.edit
forms.delete
forms.manage_submissions
forms.manage_slots
forms.manage_waitlists
forms.export
forms.manage_templates
forms.manage_logic
Admins should get all permissions by default.
19. Reporting
Add reporting for:
-
Total form submissions
-
Capacity remaining
-
Slot registrations
-
Waitlist count
-
Attendance
-
Form revenue
-
Payment plan revenue
-
Outstanding payment plan balance
-
Failed payment plans
-
Conversion rate by form
-
Abandoned forms, future enhancement
CSV export should include:
-
Contact fields
-
Repeatable section values
-
Selected slots
-
Payment status
-
Payment plan status
-
Tags
-
Submission date
20. Build Order
Please build in this order:
Phase 1: Foundation
-
Add DB tables for slots/registrations.
-
Add signup_slots field type.
-
Add public slot selection UI.
-
Add safe backend submission handling with capacity protection.
Phase 2: Admin + Waitlist
-
Add admin slot configuration UI.
-
Add waitlist support.
-
Add cancel/promote actions.
-
Add enhanced submission view.
Phase 3: Jotform-style form power
-
Add repeatable sections.
-
Add conditional logic.
-
Add multi-step/page-break forms.
Phase 4: GiveHub advantage
-
Integrate payment plans.
-
Add form-to-workflow trigger.
-
Add reminder emails/SMS.
-
Add templates library.
21. Important Requirements
-
Do not break existing Custom Forms.
-
Existing forms must continue working.
-
New field types should be backward-compatible.
-
Public form submission must be transaction-safe.
-
Slot capacity must not overbook.
-
Payment totals must be recalculated server-side.
-
Do not trust frontend fee totals.
-
All payment plan authorization must be stored.
-
Use existing GiveHub payment gateway logic.
-
Use existing People/CRM records when possible.
-
Use existing Messaging system when possible.
-
Use existing Workflow/task system when possible.
-
Use existing permissions pattern.
-
Use production-safe frontend/API URLs from environment config.
Final goal:
GiveHub Custom Forms should become a combination of:
SignUpGenius + Jotform + GiveHub Payments + GiveHub CRM + GiveHub Workflows
This should make Custom Forms useful for registrations, volunteers, events, camps, school fees, sponsorships, mission trips, pledges, tuition, and payment plans.
