<% /* ---- Next occurrence ------------------------------------------------- All arithmetic happens on a UTC Date that carries the *Eastern calendar date*, never a wall-clock instant. That keeps day-of-week and day-adding correct across DST without needing a timezone library. public/js/main.js runs the same rule so the live countdown agrees with this render and can roll itself over without a reload. */ const TZ = site.timezone || "America/New_York"; const now = new Date(); const V = site.venue; const todayISO = new Intl.DateTimeFormat("en-CA", { timeZone: TZ, year: "numeric", month: "2-digit", day: "2-digit", }).format(now); const hourET = Number( new Intl.DateTimeFormat("en-US", { timeZone: TZ, hour: "2-digit", hourCycle: "h23" }).format(now) ) % 24; const toDate = (iso) => { const [y, m, d] = iso.split("-").map(Number); return new Date(Date.UTC(y, m - 1, d)); }; const isoOf = (dt) => dt.toISOString().slice(0, 10); let next = toDate(todayISO); const first = toDate(site.firstEvent); if (next < first) next = first; while (next.getUTCDay() !== site.weekday) next.setUTCDate(next.getUTCDate() + 1); if (isoOf(next) === todayISO && hourET >= (site.endHour24 || 21)) next.setUTCDate(next.getUTCDate() + 7); // Keep the FIRST skipped date: with two cancellations in a row the notice // should name the soonest one people were expecting, not the last one. const cancelled = site.cancelled || []; let skippedWeek = null; while (cancelled.includes(isoOf(next))) { if (!skippedWeek) skippedWeek = isoOf(next); next.setUTCDate(next.getUTCDate() + 7); } const nextISO = isoOf(next); const isTonight = nextISO === todayISO; const fmtDate = (opts) => new Intl.DateTimeFormat("en-US", Object.assign({ timeZone: "UTC" }, opts)).format(next); const nextLong = fmtDate({ weekday: "long", month: "long", day: "numeric" }); const nextShort = fmtDate({ weekday: "short", month: "short", day: "numeric" }); const weekdayName = new Intl.DateTimeFormat("en-US", { timeZone: "UTC", weekday: "long" }).format(next); // Eastern UTC offset on the event date, so the countdown target is a real instant. const offLabel = new Intl.DateTimeFormat("en-US", { timeZone: TZ, timeZoneName: "shortOffset" }) .format(new Date(`${nextISO}T12:00:00Z`)); const offHours = Number((offLabel.match(/GMT([+-]?\d{1,2})/) || [, "-5"])[1]); const pad = (n) => String(n).padStart(2, "0"); const offStr = `${offHours < 0 ? "-" : "+"}${pad(Math.abs(offHours))}:00`; const startISO = `${nextISO}T${pad(site.startHour24)}:00:00${offStr}`; const endISO = `${nextISO}T${pad(site.endHour24)}:00:00${offStr}`; const heroLine = isTonight ? `Tonight at ${V.name}, ${site.startTime} to ${site.endTime}. Grab a cue and meet the people building things in ${V.city}.` : `Every ${weekdayName} at ${V.name}, ${site.startTime} to ${site.endTime}. The next one is ${nextLong}.`; const details = [ { label: "When", value: `Every ${weekdayName}` }, { label: "Time", value: `${site.startTime} to ${site.endTime}` }, { label: "Where", value: `${V.name}, ${V.street}`, href: V.mapUrl }, { label: "Entry", value: site.entry }, ]; %> <%= site.name %> | <%= site.tagline %>

<%= site.tagline %>

<%= site.name %>

<%= heroLine %>

Four people talking beside a lit pool table in a dark bar.

<%= isTonight ? "The Break is tonight" : "Until the next Break" %>

-days
-hours
-min
-sec

<%= nextLong %>, <%= site.startTime %> at <%= V.name %>

<% if (skippedWeek) { %>

No Break on <%= new Intl.DateTimeFormat("en-US", { timeZone: "UTC", month: "long", day: "numeric" }).format(toDate(skippedWeek)) %>. Back on <%= nextLong %>.

<% } %>
<% details.forEach(function (d) { %>
<%= d.label %>
<% if (d.href) { %><%= d.value %><% } else { %><%= d.value %><% } %>
<% }) %>

class="is-live"<% } %>><%= isTonight ? "Happening tonight" : `Next: ${nextShort}` %> Add the whole series to your calendar

We are building Gainesville's startup culture, one terrible pool shot at a time.

Whether you are an engineer, a designer, a business strategist, or just an ambitious person driven to build things from the ground up, this is your crowd.

Zero pool skills required. Seriously. We are here to build startups, not run the table.

What to expect

Three students laughing over a napkin sketch at the rail of a pool table.
<% site.expect.forEach(function (item, i) { %>
<%= i === 1 ? " cell-tint" : "" %> reveal">

<%= item.title %>

<%= item.body %>

<% }) %>

We play at <%= V.name %>.

<%= V.note %>

<%= V.street %>
<%= V.city %>, <%= V.state %> <%= V.zip %>

@<%= V.instagram %> Pouring since <%= V.established %>

The Silver Q storefront on West University Avenue at dusk.
Look for the sign on West University Avenue.

RSVP for <%= isTonight ? "tonight" : nextLong %>

Not required, but it helps us know how many tables to hold. We will email you a reminder the day before.

For the weekly reminder. Nothing else.

A few words is plenty. It helps us introduce you to the right people.

One email a week at most. Unsubscribe any time.

Point a phone at this.

It opens straight to the RSVP. Screenshot it and send it to whoever should be there.