# Project pack: Rallly @ fc272a5

Facts about **Rallly** for an AI following the [BespokeAI handover guide](https://handoff.bespokeai.software/guide/v2.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.
- Fresh checkout: use the setup below in an empty folder. If you already have this exact source checked out, keep your branch and use the development command instead; do not clone again or reset local changes.
- 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 the pinned source
- Fresh pinned-source setup (skip clone and checkout in an existing worktree):

  ```sh
  git clone https://github.com/lukevella/rallly bespoke-rallly
  cd bespoke-rallly
  git checkout --detach fc272a5094e548462f158e4a90799de7febc98b1
  # Prepare development requirements and local configuration first.
  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
  ```

The commands below are a starting point from the reviewed source. Prepare the listed tools, local configuration and companion services before starting the app. These instructions have not yet been validated in participant sessions.

### Separate trial of the current release
This tries an upstream release, which may differ from the pinned source above. It does not run your source changes. Use only sample data and a separate data directory or volume. Check the upstream documentation before running it.

  ```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/r2/bespoke.yaml) · Hosting options: [hosting.md](https://handoff.bespokeai.software/p/rallly/fc272a5/r2/hosting.md) · Agent skill: [SKILL.md](https://handoff.bespokeai.software/p/rallly/fc272a5/r2/SKILL.md)
