# Build brief: APNC conference registration app

Build a web app that handles registration for the APNC Spring Conference, 19–22 April 2027\. People book for themselves or for named attendees at member or nonmember prices, pay by card or check, and log back in to manage their booking. Organizers manage members, prices, codes, corrections and reports.

This is a test build, so use made-up data only. Everything is in USD and English. Date cutoffs use America/New\_York, and a price stays valid until the end of its listed date.

## The app has 3 areas

1. **Booking flow:** public, works on mobile, and needs no account to start.  
2. **My booking:** login for purchasers and attendees to see only their own records.  
3. **Organizer admin:** restricted to organizers.

## Core concepts

- **Purchaser:** pays and manages the order. They may or may not attend.  
- **Attendee:** a named person with exactly 1 registration for the event. Later purchases, payers and roles attach to that registration.  
- **Order:** one purchase by one purchaser, covering one or more attendees.  
- **Member:** a person in the imported member list, matched by email. Matching trims spaces and ignores case. Blank expiry means no expiry. A dated membership is valid through that day.  
- **Role:** primary speaker, additional speaker, sponsor or exhibitor. A role changes one person's price or allowance. It never changes the ticket type, and it is separate from membership.

Keep purchaser and attendee as separate records, even when they are the same person.

## Booking flow

1. **Enter.** One public link, plus optional private speaker and sponsor/exhibitor links. A private link only labels the journey and asks for a code. Everyone can also enter a code on the public link. A forwarded link or typed email grants no benefit by itself.  
2. **Who's booking.** Capture the purchaser's details. Ask if they are booking for themselves, another person or a group, and if they are attending. A purchaser who isn't attending gets no attendee place.  
3. **For each attendee, repeat:**  
   - Collect name, designation, email, company, job title, mobile, dietary needs, accessibility needs and CHES/MCHES ID.  
   - Set the price from that attendee's own membership, never the purchaser's. Don't reveal the member list.  
   - Choose products and optionally enter a code. Check the choices against what the attendee already holds.  
   - Let the purchaser add another attendee.  
4. **Review.** Show every attendee, product, benefit and the final total. Recheck everything on the server. If the total changed, ask the purchaser to reconfirm. If any item is invalid, keep the entered details and charge nothing. Never confirm part of a group.  
5. **Pay.** One payment covers the whole order:  
   - **Card:** pay with Stripe. The booking confirms once payment succeeds.  
   - **Check:** confirm the booking straight away with the amount due, and show placeholder mailing instructions.  
   - **Zero balance:** confirm with no charge.  
6. **Confirm.** Show the recorded result. The purchaser gets an email with the order, amounts and any check instructions. Each attendee gets an email with only their own registration and a link to return. Other group members get nothing about each other.  
7. **Return.** Attendees and purchasers log in to My booking. Attendees see their own items and status, never the purchaser's receipt. Purchasers see their orders and receipts, never another attendee's private answers after confirmation.

**Policies:** link a Code of Conduct and a Media Release, using placeholder text. Record who accepted, for whom, which version and when. The purchaser can't accept for someone else. Each attendee accepts through their own link after booking, and the organizer can see who is outstanding.

## Products and prices

Display in this order: Full Conference Registration, Day 1, Day 2, Day 3, then the others. The full ticket keeps the same name in every date band, and only the price changes.

| Full Conference Registration, if booked by | Member | Nonmember |
| :---- | :---- | :---- |
| 31 Dec 2026 | \$305 | \$405 |
| 12 Feb 2027 | \$375 | \$475 |
| 3 Apr 2027 | \$425 | \$525 |
| 22 Apr 2027 | \$485 | \$585 |

&nbsp;

| Product | Member | Nonmember | Notes |
| :---- | :---- | :---- | :---- |
| Day 1 pass (Tue 20 Apr) | \$245 | \$285 | Same price in all date bands |
| Day 2 pass (Wed 21 Apr) | \$245 | \$285 | Same price in all date bands |
| Day 3 pass (Thu 22 Apr) | \$245 | \$285 | Same price in all date bands |
| Preconference only (Mon 19 Apr) | \$80 | \$80 | Standalone ticket, 3-hour HIV session |
| Preconference add-on | \$80 | \$80 | For conference-day attendees |
| Bonfire Night | \$0 | \$0 | Quantity can exceed 1 for family guests |
| Welcome Reception | \$0 | \$0 | Quantity can exceed 1 for family guests |

Rules, applied per attendee across all their purchases:

- 1 full ticket or 1 day pass, plus compatible add-ons.  
- 1 preconference entitlement only, whether through the ticket or the add-on.  
- Guest quantities on free events never create attendees.  
- There are no capacity limits, sold-out states or waitlists.  
- A completed purchase keeps its price. Later price or membership changes never rewrite it.

## Discount codes

- Types: fixed price, percentage and fixed amount. Each code has applicable products, an expiry and an overall redemption limit.  
- Allow 1 code per attendee's purchase. Each benefiting attendee uses 1 redemption.  
- Percentage codes apply per eligible line, rounded half-up to cents.  
- Fixed-price codes set each eligible unit to that price and never raise it.  
- Fixed-amount codes reduce each attendee's eligible subtotal once, capped at that subtotal and split proportionally across lines.  
- Reserve redemptions during a pending payment. Consume them once on confirmation. Release them if payment fails.  
- If too few redemptions remain for a group, send the purchaser back to review a revised order.

Test case: 2 attendees each pick \$100 and \$80 items with a \$50 fixed-amount code. Each pays \$130, with \$27.78 and \$22.22 off the lines. The total is \$260, using 2 redemptions.

## Organizer admin

- Registrations list with search, filter, sort and pagination.  
- Order view with ordered, paid and due amounts.  
- Record a check receipt against the original order.  
- Manage members, prices and codes.  
- Export all matching rows to CSV, not only the visible page. Additional purchases must not inflate attendee counts. Exports must treat formula-like text as plain data.

## Changes and operations

- **Personal edits:** attendees edit their own fields, except name and email, which go through an organizer.  
- **Add-ons:** buy later through the same payment flow.  
- **Upgrades:** charge the current replacement price less the amount paid for the old ticket, by card. \$245 paid moving to \$425 is \$180. A failed payment leaves existing access unchanged.  
- **Substitution:** the purchaser moves a place to a new person, who gives their own details and policy acceptance. Reprice using the original purchase's date band and show a separate \$25 fee after 20 Mar 2027\. A lower price gives no automatic refund. Notify the purchaser, former attendee and replacement.  
- **Speaker and exhibitor benefits:** placeholder rates and allowances. Example: an exhibitor package with 2 included places and a paid third at \$100. Zero-price places still use up the allowance.  
- **Refund records:** organizers refund outside the app, then record amount, status, reference and notes. Due \= max(0, amount owed − gross payments). Net collected \= gross payments − completed refunds. \$400 paid with \$100 refunded shows \$0 due and \$300 net.  
- **Member import:** upload a spreadsheet with First\_Name, Last\_Name, Email\_1:Work and Membership\_Expiration. Preview changes and flag missing emails and duplicate conflicts. Never guess a merge, and hold conflicts out of the import. Importing creates no registration.  
- **Assisted booking:** organizers book for someone through the same flow and rules.  
- **Help route:** a contact link from entry, error and return screens, usable without logging in.  
- **Attendee export:** an outbound webhook or export of confirmed attendees for a separate event app. Exclude purchasers who aren't attending and guest quantities.

## Security and quality

- Enforce permissions on the server, not only in screens. Changing a URL or ID must never reach another person's booking or receipt.  
- Restrict dietary, accessibility and financial data to organizers who need it.  
- Keep secrets out of client code and URLs.  
- Refresh, session expiry and network loss must not lose saved work or committed purchases.  
- Nobody is charged twice, and a booking is never confirmed twice.  
- Completing one registration must not block another from the same browser.  
- Target WCAG 2.2 AA, with keyboard use, labelled fields, accessible error summaries and mobile layouts.  
- Design for about 400 attendees.

## Branding

Match the look of [https\://apnc.org/](https://apnc.org/).

- **Headings:** DM Serif Text, regular weight (Google Fonts).  
- **Body text:** Nunito Sans at 18px, with 400 and 600 weights (Google Fonts).  
- **Colors:** red \#E92E1F for buttons, links and highlighted words. Black \#000000 text on white \#FFFFFF. Soft blush \#F1E6E5 for banners and panels.  
- **Buttons:** fully rounded pills in DM Serif Text at 20px, with white text on red and generous padding (about 15px 35px).  
- **Feel:** clean, spacious pages with plenty of white space and a slim blush announcement bar at the top.  
- **Contrast:** white on \#E92E1F is about 4.3:1, just under AA at this size. Darken the red slightly on buttons if needed.  
- I'll upload the logo files.

## Seed data

Create made-up data only, with example.com emails:

- Members covering: blank expiry, valid dated, expired, 2 rows sharing an email with different names, and a row with no email.  
- 1 organizer account.  
- Test codes for each type, including one with only 2 redemptions left.  
- 1 speaker role and 1 exhibitor role, with placeholder rates.

## Don't build

Public website pages, PDF invoices, waitlists, capacity limits, attendee cancellation, downgrades, refunds started in the app, hotel or transport booking, unnamed advance purchases, sponsorship checkout, form or report designers, scheduled reports, bulk code generation, multi-language or multi-currency support, event app screens, attendance scanning, surveys or certificates.