# Project pack: Rallly @ fc272a5

Facts about **Rallly** for an AI following the [BespokeAI handover guide](https://handoff.bespokeai.software/guide/v1.md). This pack is pinned to one version and never changes after publication.

> Rallly helps a group agree on when to meet. Suggest a few dates or times, share one link, and everyone ticks yes, if need be, or no. Nobody needs an account to vote. You see the best option at a glance, pick it, and Rallly emails everyone the final date with a calendar invite. Good for book clubs, committees, family get-togethers and team meetings.

## Version and source
- Repository: https://github.com/lukevella/rallly
- Pinned commit: `fc272a5094e548462f158e4a90799de7febc98b1`. Use exactly this version.
- Get it: `git clone https://github.com/lukevella/rallly rallly && cd rallly && git checkout fc272a5094e548462f158e4a90799de7febc98b1`
- Or download a zip: https://github.com/lukevella/rallly/archive/fc272a5094e548462f158e4a90799de7febc98b1.zip
- Official docs: https://support.rallly.co
- Licence: **AGPL-3.0-or-later**. Free to use and change. If you run a changed version that other people use over the internet, you must offer them your source code under the same licence. Self-hosting is free for one registered user (anyone can vote without an account); the author asks groups with more registered users to buy a one-off licence key, on an honour system.

## Running it
- Easiest:

  ```sh
  # On a server with Docker, a domain name and an SMTP email account:
  curl -fsSL https://get.rallly.co | bash
  # The official installer sets up Rallly, PostgreSQL, storage and HTTPS in /opt/rallly and asks for your domain and email settings.
  # Then sign up with the INITIAL_ADMIN_EMAIL address and open /control-panel to claim admin rights.
  ```

- Needs: A server with 2 GB RAM, Docker 19.03+ with Compose v2, ports 80 and 443 and a domain name, An SMTP email provider (sign-in uses emailed codes), For development, Node (version in .nvmrc), pnpm and Docker
- Develop: `pnpm install && cp apps/web/.env.sample apps/web/.env && cp packages/database/.env.sample packages/database/.env && pnpm db:generate && pnpm docker:up && pnpm db:reset && pnpm dev`
- Test: `pnpm test:unit`
- Check/lint: `pnpm check && pnpm lint && pnpm type-check`
- Build: `pnpm build`
- Stack: typescript (Next.js 16, React 19, tRPC, Prisma, Better Auth, Tailwind CSS, Base UI, Turborepo). Difficulty for a non-developer with an AI: **moderate**. One TypeScript monorepo with a thorough CLAUDE.md. Branding, sign-up rules, email and video-call links are settings. Code is organised by feature in apps/web/src/features/; data lives in a Prisma schema split across files; emails are React templates. Strict conventions (Intl date formatting, Base UI only, structure checks) need care.

## The project's own AI instructions
Read these in the repository before changing code: `CLAUDE.md`, `CONTRIBUTING.md`.

## Customisation points (settings → extend → code)
- **control-panel** [settings]: Manage users, who can register and the licence key. → `/control-panel (apps/web/src/features/instance-settings/, instance-policy/, licensing/)`
- **branding** [settings]: App name, colours and logos. Upstream says this needs an Enterprise licence with the white-label add-on. → `/control-panel/branding or APP_NAME, PRIMARY_COLOR, LOGO_URL, HIDE_ATTRIBUTION (apps/web/src/features/branding/)`
- **sign-in-and-access** [settings]: Limit sign-up to your club's or company's email addresses, or use Google/Microsoft/OIDC login. → `ALLOWED_EMAILS, REGISTRATION_ENABLED, EMAIL_LOGIN_ENABLED and SSO variables (apps/docs/self-hosting/configuration.mdx, single-sign-on.mdx)`
- **conferencing** [settings]: Add Zoom, Google Meet, Teams or Webex links automatically when a date is fixed. → `CONFERENCING_PROVIDERS and provider variables (apps/docs/self-hosting/conferencing.mdx)`
- **api-and-webhooks** [extend]: Create polls from your own tools and get told when someone votes. Upstream marks these as Pro features and webhooks as beta. → `Settings → API keys / Webhooks (apps/web/src/features/api-keys/, webhook/; docs in apps/docs/api-reference/)`
- **poll-ui** [code]: How polls look and behave for organisers and voters. → `apps/web/src/features/poll/ and apps/web/src/components/`
- **emails** [code]: The wording and look of invitation and confirmation emails (React email templates). → `packages/emails/src/templates/`
- **text** [code]: Change words in the interface, e.g. call polls "gatherings". → `apps/web/public/locales/en/app.json (other languages come from Crowdin)`

## Must keep working
- Poll links already shared. Existing participant and admin URLs must keep working.
- Votes and comments. Back up the database before upgrades or code changes.
- Voting without an account. Guests must still be able to respond.
- Database changes need a Prisma migration in packages/database/prisma/migrations/.
- Follow CLAUDE.md conventions (Intl-based date formatting, Base UI primitives, pnpm check:structure).

## Staying updatable
Settings, sign-in rules, conferencing and webhooks cover most needs. Upstream welcomes contributions but asks you to open an issue or discussion first. Rallly is AGPL, so you may change licence or white-label checks in your own copy, but the author funds the project through licence keys; please buy one if your group uses several accounts.

## Data, costs and safety
- Personal data: **yes**. Stored in: PostgreSQL database (bundled container or your own), plus S3-compatible storage for images. Names and email addresses of organisers and voters, their availability and comments. Back up the database before upgrades or code changes; the installer's /opt/rallly folder holds the configuration and secrets.
- Service: Email (SMTP), e.g. Resend, Postmark, Mailgun or Brevo (required, free tiers available): Sign-in codes, invitations and the "date is fixed" emails with calendar invites.
- Service: S3-compatible storage (optional, free (bundled by the installer) or pay-per-use): Uploaded logos and profile pictures.
- Service: Google, Microsoft or OIDC sign-in (optional, free): Log in with an existing account instead of emailed codes.
- Service: Zoom, Google Meet, Microsoft Teams or Webex (optional, free with your own account): Creates a video-call link automatically when you pick the final date.
- Service: Rallly licence key (optional, one-off, from $49 for up to 5 users): Asked for when more than one person has a registered account; checked with licensing.rallly.co.
- Setting `NEXT_PUBLIC_BASE_URL`: The address people open Rallly at. Links in emails use it.
- Setting `SECRET_PASSWORD` (**secret**: the person enters it themselves, never in chat): A long random string used to encrypt sessions. The installer generates it. Never paste it into an AI chat.
- Setting `DATABASE_URL` (**secret**: the person enters it themselves, never in chat): PostgreSQL connection string (set for you when you use the bundled database).
- Setting `SUPPORT_EMAIL`: The contact address shown to users.
- Setting `INITIAL_ADMIN_EMAIL`: The email of the person allowed to claim admin rights in /control-panel.
- Setting `SMTP_HOST`: Your email provider's server. SMTP_PORT, SMTP_USER and SMTP_SECURE go with it.
- Setting `SMTP_PWD` (**secret**: the person enters it themselves, never in chat): Password for the email server.
- Setting `ALLOWED_EMAILS`: Only these email addresses (wildcards allowed, e.g. *@ourclub.org) can register.
- Setting `REGISTRATION_ENABLED`: Set to false to stop new people signing up.
- Anyone with a poll link can see the names and choices of everyone who voted. Share links only with the group.
- Rallly must be reachable from the internet for voters, so use HTTPS (the installer sets it up) and keep it updated.
- Restrict sign-up with ALLOWED_EMAILS or REGISTRATION_ENABLED=false so strangers can't use your server to send emails.
- Keep SECRET_PASSWORD, SMTP passwords and API keys out of AI chats.
- Licence activation contacts licensing.rallly.co.

---

# Customising Rallly

Rallly is one TypeScript (Next.js) monorepo. **Most group needs are settings in the Control Panel or environment variables.** Upstream ships a detailed `CLAUDE.md` for code changes.

## Level 1: Settings (no code)
- **Control Panel** (`/control-panel`, admin only): users, licence key, instance settings. The person whose email matches `INITIAL_ADMIN_EMAIL` claims admin there first.
- **Who can sign up:** `ALLOWED_EMAILS` (e.g. `*@ourclub.org`), `REGISTRATION_ENABLED=false`, `EMAIL_LOGIN_ENABLED`, and Google, Microsoft or OIDC single sign-on. Voters never need an account.
- **Email:** `SMTP_HOST`, `SMTP_PORT`, `SMTP_USER`, `SMTP_PWD`, `NOREPLY_EMAIL`, `SUPPORT_EMAIL`. Use a transactional email provider.
- **Video calls:** `CONFERENCING_PROVIDERS=zoom,google-meet,…` plus each provider's OAuth app (see `apps/docs/self-hosting/conferencing.mdx`). Organisers connect their account in Settings → Conferencing.
- **Branding:** app name, colours, logos and "Powered by" text in `/control-panel/branding` or `APP_NAME`, `PRIMARY_COLOR`, `LOGO_URL`, `HIDE_ATTRIBUTION`. Upstream documents this as an Enterprise white-label feature.
- **Your account:** language, time zone, date and time format in Preferences.

## Level 2: Extend (no fork)
- **REST API** (docs in `apps/docs/api-reference/`; the cloud version uses `https://api.rallly.co/v1`): create polls, read options, results and participants. Keys from Settings → API keys (space owner).
- **Webhooks** (Settings → Webhooks, beta): a signed POST when a poll or response changes. There is an n8n guide in `apps/docs/api-reference/webhooks/guides/n8n.mdx`.
- Upstream marks the API and webhooks as Pro features.

## Level 3: Code
Read upstream `CLAUDE.md` first. Summary:

| Change | Where |
|---|---|
| Poll pages and voting | `apps/web/src/features/poll/`, shared UI in `apps/web/src/components/` and `packages/ui` (Base UI only) |
| Other features (spaces, notifications, branding, webhooks…) | `apps/web/src/features/<feature>/` |
| API (tRPC) | `apps/web/src/trpc/routers/` |
| Emails | `packages/emails/src/templates/` |
| Data | `packages/database/prisma/models/` + `pnpm db:migrate` |
| Interface text | `apps/web/public/locales/en/app.json` (other languages via Crowdin) |
| Dates and times | always through `apps/web/src/lib/datetime/` (Intl); never add dayjs |

## Running locally
- **Run it for real:** on a server with Docker and a domain, `curl -fsSL https://get.rallly.co | bash`. The installer asks for your domain and email settings, generates secrets and sets up HTTPS.
- **Develop:**
  1. `pnpm install`
  2. Copy `apps/web/.env.sample` to `apps/web/.env` and `packages/database/.env.sample` to `packages/database/.env`.
  3. `pnpm db:generate`, `pnpm docker:up`, `pnpm db:reset`
  4. `pnpm dev` (served through a local HTTPS proxy, e.g. https://web.rallly.localhost)
- **Check:** `pnpm check`, `pnpm lint`, `pnpm type-check`, `pnpm check:structure`, `pnpm test:unit`.

## Pitfalls
- Back up the database before upgrades or code changes.
- Sign-in depends on email. Test SMTP first; consumer inboxes like Gmail often block automated sign-in emails.
- Don't break existing poll links; people may have them in old messages.
- Never format dates with dayjs or `toLocaleString` directly; use the Intl wrappers so time zones stay right.
- More than one registered user is meant to be covered by a licence key (honour system). Removing the checks is allowed by the AGPL but works against the person who funds the project.

---
Machine-readable: [bespoke.yaml](https://handoff.bespokeai.software/p/rallly/fc272a5/bespoke.yaml) · Agent skill: [SKILL.md](https://handoff.bespokeai.software/p/rallly/fc272a5/SKILL.md)
