Files
WebForm-mw/README.md
T
Joel Brock 6e7df382c9 AWS Amplify Hosting deploy prep
- amplify.yml: build spec (preBuild npm ci with offline cache, build
  next build, artifacts at .next/**, cache node_modules/.next-cache/.npm).
- .nvmrc: pin Node 20 so Amplify uses the same runtime as local.
- AMPLIFY_DEPLOY.md: first-time walkthrough covering AWS-side setup
  (create app, connect GitHub via OAuth/App, branch/auto-detect),
  environment variable table with secret-flag guidance, smoke-test via
  /healthz and /api/health, optional custom domain + per-PR previews,
  cost estimate, and operational notes (cold starts, no static
  egress IPs, CloudWatch logs, secret rotation).
- README deploy section: now points at both AMPLIFY_DEPLOY.md and the
  existing DEPLOYMENT.md (Render).
2026-05-19 16:48:38 -07:00

137 lines
6.1 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Co-op Check-in
A tokenized, mobile-friendly web form that lets external co-op contacts
update their organization's tracking data on CiviCRM, plus a read-only
activity report showing every value the co-op has shared over time. Built
to wrap CiviCRM's existing custom-field schema without modifying it.
## How it works
Each co-op has a designated **Primary Contact** (the individual) linked
to the **Organization** record in CiviCRM. Staff send that contact a
personalized link generated against the contact's CiviCRM checksum:
- `https://check-in.fci.coop/?cid=<contactId>&cs=<checksum>` — the form
- `https://check-in.fci.coop/report?cid=<contactId>&cs=<checksum>` — the report
When the link is opened, the app verifies the checksum against CiviCRM,
resolves the organization through the Primary Contact relationship, and
loads the right view.
**Form.** Sections are organized by the co-op development stages
(Inquiry → Convene & Prepare → Grow & Plan → Connect & Gather → Excite &
Build → Fulfill & Stabilize). The org's current stage controls which
sections are editable; past and current stages are open for editing,
future stages render as previews with their fields locked so the co-op
can see the framework ahead. Fields prefill with each value's most
recent non-empty entry from past check-ins. On submit, a new
"Check-in (organizing)" activity is created; nothing is overwritten.
**Stage authority.** The current stage is derived from the most recent
"Check-in (organizing)" activity whose Stage field is set. Staff own
stage transitions by manually setting Stage on a check-in activity they
create; the form itself never writes Stage, so org self-submissions
can't override a staff transition. Orgs with no stage-bearing activity
default to "Inquiry."
**Report.** A read-only view of every field that has ever held a value,
grouped by stage. Each row shows the most recent value prominently; an
"N earlier entries" disclosure expands a chronological list of prior
values with their dates. Empty stages and untouched fields are hidden so
the page stays calm.
## Visual & UX details
- **Field Almanac** aesthetic: warm cream paper, deep botanical green
ink, a sparing terracotta accent. Fraunces (display) and DM Sans
(body) at variable weights. Subtle paper-grain texture via layered
CSS gradients.
- **Journey rail** runs down the left side on desktop, with a marker
per stage and a "Now" pill at the current stage. Past stages are
filled with a checkmark, future stages are dashed and locked. A small
inter-card stem stands in for the rail on mobile.
- **Draft auto-save** to `localStorage` (30-day TTL) so partial answers
survive page refreshes; a "Draft restored" banner appears on return.
- **Successful submit** lands on a destination screen instead of a
reloaded form, preventing accidental duplicate submits from
back-button or autofill replay.
- **Currency live preview**, date min/max bounds (19002100), and
thousands-separator formatting on numeric fields.
- **Hand-drawn stage icons** for each of the six stages; FCI brand logo
in the header.
## Accessibility
- Real `<label htmlFor>` on every control; help text and inline errors
linked via `aria-describedby`.
- Required fields use `aria-required`, a visible `*` with
`aria-label="required"`, and typed error messages.
- Failed-validation submit auto-expands the section containing the
first error, scrolls it into view, and focuses the field.
- Accordion sections follow the disclosure pattern: `<button>` headers
with `aria-expanded` + `aria-controls`, `role="region"` panels.
- All animations honour `prefers-reduced-motion`.
- Skip-to-content link present for keyboard users.
- iOS safe-area inset respected on the sticky submit bar.
## Environment variables
The app runs in **stub mode** when any of the CiviCRM variables below
are missing — the UI is fully exercisable against synthesized data with
no live CRM calls. Production startup will refuse to boot in stub mode.
| Variable | Required? | Purpose |
|---|---|---|
| `CIVI_BASE_URL` | yes | CiviCRM root, e.g. `https://crm.fci.coop` |
| `CIVI_API_KEY` | yes | API key of a Civi user with permission to read contacts/activities and create activities |
| `CIVI_SITE_KEY` | yes | The `site_key` from `civicrm.settings.php` |
| `CIVI_HTTP_AUTH_USER` | optional | Username, if CiviCRM sits behind HTTP Basic Auth at the webserver layer |
| `CIVI_HTTP_AUTH_PASS` | optional | Password for the above |
| `HEALTH_TOKEN` | optional | If set, `/api/health` requires `?token=…` in production |
| `PREVIEW_ADMIN_TOKEN` | optional | If set, `/api/preview-link` requires a matching `Authorization: Bearer …` header (admin convenience endpoint for minting form links) |
| `NODE_ENV` | — | Set to `production` for the production build |
Copy `.env.example` to `.env.local` for local development.
## Run locally
```
npm install
npm run dev
```
Open `http://localhost:3000/?cid=1&cs=anything` — any non-empty `cs`
works while in stub mode. The report is at `/report?cid=1&cs=anything`.
## Deploy
The repo ships with `amplify.yml` for [AWS Amplify Hosting](https://aws.amazon.com/amplify/)
(see `AMPLIFY_DEPLOY.md` for a first-time walkthrough) and `render.yaml`
for [Render](https://render.com) (see `DEPLOYMENT.md`). The app is a
standard Next.js 16 App Router project and runs anywhere Node 20+ can
run `next start` — Vercel, App Runner, Fly, self-hosted, etc.
Build + start:
```
npm run build
npm start
```
Set all three required CiviCRM variables in the host's secret store;
the app auto-leaves stub mode the moment they're all present.
A `/healthz` route returns a lightweight 200 for platform health checks;
`/api/health` returns a richer diagnostic payload (gated by
`HEALTH_TOKEN` in production).
## Editing the form
The form definition lives in `config/form.ts` — one TypeScript file
declaring sections, fields, types, visibility rules, and matrix groups
(used for compact M1M12 / Q1Q4 layouts in Stage 5). Each field
references its CiviCRM custom field via APIv4's `<group_name>.<field_name>`
syntax. Edit the file, restart `npm run dev`, you're done.
A browser-based form builder is out of scope for this version.