founders-break/README.md

110 lines
4.9 KiB
Markdown

# The Founder's Break
Event site for the weekly UF startup pool social at Silver Q, Gainesville.
Hosted by OneTouch Studio at **https://foundersbreak.onetouch.studio**.
Corben EJS site. There is no build step: `deploy_site` copies this repo verbatim.
```
site.config.js all schedule, venue and copy data
views/index.ejs the single page, including the next-date logic
public/css/style.css brand tokens lifted from onetouch.studio
public/js/main.js nav state, scroll reveal, live countdown, RSVP submit
public/assets/ the recurring .ics and the print-resolution QR
public/images/ logo, favicon, RSVP QR
```
## The date is never hard-coded
`views/index.ejs` computes the next occurrence at render time from `weekday` +
`firstEvent` in `site.config.js`. `public/js/main.js` runs the same rule in the
browser, so the countdown ticks and rolls itself over to the following Thursday
once the night ends, with no reload and no redeploy.
## Cancelling a week
Add the ISO date to `cancelled` in `site.config.js` and redeploy:
```js
cancelled: ["2026-11-26"], // Thanksgiving
```
The page then skips that Thursday, shows a notice naming the cancelled date, and
points at the next one that is actually happening. Two other places do **not**
read this list and need the same date added by hand:
- `public/assets/founders-break.ics` is a plain weekly recurrence.
- the `CANCELLED` array in the `founders-break-reminder` Corben function, or it
will email everyone about a Break that is not happening.
## Deploying
```
deploy_site id=4ae63819-3f63-4fea-b0de-eb1e5befe607 repo=gator/founders-break mode=ejs
```
Nothing redeploys itself. Every edit needs the deploy step.
## What happens when somebody RSVPs
The form POSTs to `/forms/rsvp`. The Corben sites renderer stores it in
`site_form_submissions` and fires a `form.submitted` event. From there it is all
plain JavaScript, deliberately: there is no LLM anywhere in the send path.
| Piece | Id |
|---|---|
| Trigger `Founder's Break RSVP` (form.submitted, form_name=rsvp) | `e035fb68-2ecd-452b-bf74-a051c2775423` |
| Function `founders-break-rsvp` | `3d3c4bed-c073-40a4-9a32-9ff6944737dd` |
| Function `founders-break-reminder` | `cf2a1e4c-43f9-4cf4-8fc5-652c494940ae` |
| Cron `Founder's Break weekly reminder` (every 6h) | `84efd815-5426-4952-af88-2f4ed81efc54` |
| Email list `Founder's Break` | `09429866-0005-4260-bf56-2d520eea4db7` |
`founders-break-rsvp` resolves a CRM contact, writes the email address back onto
it (`create_contact` dedupes server-side and can return a record with no address,
which would put an unmailable member on the list), adds them to the list, sends
the HTML confirmation, and sends an internal note to gatordevin@gmail.com.
`founders-break-reminder` runs every 6 hours, works out the Eastern weekday
itself, and only sends on Wednesday between 09:00 and 20:00 ET. A `kv` marker
keyed to the event date makes any repeat run a no-op, which is what makes it safe
to run four times a day.
Both functions authenticate with a scoped `email + crm` key held by the paused
**Founders Break** agent record (`666f7ad0-f546-4fc6-a3c4-14f1384e91a5`). That
agent runs nothing. It exists only because an API key cannot mint another API
key. Deleting it revokes the key and breaks both functions.
## The QR code
`public/images/rsvp-qr.png` and `public/assets/rsvp-qr.svg` both encode
`https://foundersbreak.onetouch.studio/#rsvp`. Deliberately dark-on-white:
inverted QR codes are unreliable on older scanners and these go on flyers.
Regenerate with the `qrcode` npm package if the URL ever changes.
## Tracking
The Corben tracker is injected into every EJS site automatically, so pageviews
(with UTM, referrer, device, browser), clicks on any `a`/`button`/`[data-track]`,
`form_start`, `form_submit`, scroll depth and engagement time all land with no
work from us. Key elements carry a `data-track` label so the click rows are
readable: `rsvp-nav`, `rsvp-hero`, `rsvp-submit`, `add-to-calendar`, `venue-map`,
`details-map`, `venue-instagram`, `hero-what-to-expect`.
`public/js/main.js` adds the three steps the tracker cannot see on its own, via
the same public `/analytics/events` endpoint:
| Event | Means |
|---|---|
| `rsvp_reached` | scrolled the RSVP block into view |
| `rsvp_completed` | submission stored, `event_data.via` is `form` or `reminder-email` |
| `rsvp_failed` | submission rejected, with the reason |
So "reached but did not finish" is `rsvp_reached` minus `rsvp_completed`, and
"started typing then left" is `form_start` minus `form_submit`.
Emails carry a 1x1 open pixel at `GET /analytics/open.gif?s=<site>&k=<kind>&e=<email>&d=<date>`,
landing in `site_events` as `email_open` with kind `confirm-first`,
`confirm-returning` or `reminder`. Apple Mail Privacy Protection and Gmail's
image proxy prefetch images, so treat opens as a ceiling rather than a headcount.
Read any of it with `get_site_analytics`, `get_site_events` or `get_site_click_map`.