Skip to content

Commit 34dc55c

Browse files
authored
Merge pull request #379 from DataScience-GT/hotfix-fix-main-review-issues-9d3d
Fix resume preview failing to load in the browser
2 parents bdd4ec6 + d140df2 commit 34dc55c

81 files changed

Lines changed: 5347 additions & 1156 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎.github/workflows/codeql.yml‎

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,10 @@ jobs:
3535
fetch-depth: 0
3636

3737
- name: Setup pnpm
38-
uses: pnpm/action-setup@v3
39-
with:
40-
version: 9
38+
# No version pin: the one in packageManager is the one that reads
39+
# overrides and allowBuilds from pnpm-workspace.yaml. Pinning here
40+
# silently installed an older pnpm that ignores both.
41+
uses: pnpm/action-setup@v5
4142

4243
- name: Setup Node
4344
uses: actions/setup-node@v6

‎.github/workflows/test.yml‎

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,10 @@ jobs:
2020
node-version: "20"
2121

2222
- name: Setup pnpm
23-
uses: pnpm/action-setup@v3
24-
with:
25-
version: 8
23+
# No version pin: the one in packageManager is the one that reads
24+
# overrides and allowBuilds from pnpm-workspace.yaml. Pinning here
25+
# silently installed an older pnpm that ignores both.
26+
uses: pnpm/action-setup@v5
2627

2728
- name: Install dependencies
2829
run: pnpm install

‎README.md‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,12 @@ Two Next.js sites share one Postgres database and four internal packages. Club m
66

77
**Documentation:** start at [`docs/README.md`](./docs/README.md).
88

9+
## Club project
10+
11+
The public website and member portal for Data Science at Georgia Tech, live at [datasciencegt.org](https://datasciencegt.org). This is production club infrastructure (not a greenfield student app).
12+
13+
Member-facing overview — what it is, what members use, current status, and how to help: [`docs/club-project.md`](./docs/club-project.md). Local setup and PR workflow stay in [`docs/getting-started.md`](./docs/getting-started.md) and [`docs/contributing.md`](./docs/contributing.md).
14+
915
## Workspace layout
1016

1117
| Path | Workspace | Role |

‎apphosting.yaml‎

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,16 @@ env:
5959
secret: projects/672446353769/secrets/STRIPE_WEBHOOK_SECRET
6060
- variable: NODE_ENV
6161
value: production
62+
# Cloud Storage bucket holding resume PDFs. Postgres keeps only the metadata
63+
# and the object key — 5000 resumes is 1.5 GB and this database is 0.5 GB.
64+
# The runtime service account needs objectAdmin on it:
65+
# gcloud storage buckets create gs://dsgt-resumes --location=us-central1 \
66+
# --uniform-bucket-level-access --public-access-prevention
67+
# gcloud storage buckets add-iam-policy-binding gs://dsgt-resumes \
68+
# --member=serviceAccount:<app-hosting-runtime-sa> \
69+
# --role=roles/storage.objectAdmin
70+
- variable: RESUME_BUCKET
71+
value: dsgt-resumes
6272
# Consumer Gmail, which caps around 500 recipients a day — shared between
6373
# sign-in codes and every acceptance or announcement send. Acceptance waves
6474
# are capped at 500 for that reason. Moving to a real provider is these three

‎docs/README.md‎

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,11 @@
22

33
This folder is the reference for **query**, the Data Science at Georgia Tech (DSGT) monorepo for club operations and digital infrastructure.
44

5-
Start here, then jump to the page that matches the work you are doing.
5+
Members looking for a club-language overview should start at [Club project](./club-project.md). For local setup and review rules, jump to the page that matches the work you are doing.
66

77
| Document | What it covers |
88
| --- | --- |
9+
| [Club project](./club-project.md) | What the live site is, who uses it, current status, how to help |
910
| [Getting started](./getting-started.md) | Prerequisites, local Postgres, env vars, first `pnpm dev` |
1011
| [Architecture](./architecture.md) | How the two sites and four packages fit together |
1112
| [Contributing](./contributing.md) | Branches, scripts, tests, and review expectations |
@@ -14,6 +15,7 @@ Start here, then jump to the page that matches the work you are doing.
1415
| [CI/CD](./operations/ci-cd.md) | GitHub Actions, Dependabot, branch automation |
1516
| [Security](./operations/security.md) | Auth gates, rate limits, CSP, input scrubbing |
1617
| [Testing](./operations/testing.md) | Vitest, Playwright, and what each suite protects |
18+
| [Resume book](./resume-book.md) | Member uploads, the two staff views, limits, and why files skip tRPC |
1719
| [Glossary](./glossary.md) | Club vs hackathon vocabulary |
1820

1921
## Packages

‎docs/club-project.md‎

Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
# Club project: DS@GT website
2+
3+
This is the member-facing overview of **query**, the live public website and member portal for [Data Science at Georgia Tech](https://datasciencegt.org) (DS@GT / DSGT). <!-- pragma: allowlist secret -->
4+
5+
It is not a setup manual. Local install is [Getting started](./getting-started.md). Pull requests and review rules are [Contributing](./contributing.md). Architecture, packages, and operations stay in the rest of [`docs/`](./README.md).
6+
7+
Aamogh Sawant ([@aamoghS](https://github.com/aamoghS)), club President, owns and ships this repo. There is no separate website lead.
8+
9+
## What this is
10+
11+
The public website visitors see, and the signed-in portal members use to join the club, pay dues, check in at events, follow bootcamp, apply to club projects, and handle Hacklytics interest and registration.
12+
13+
The public pages and the portal are one Next.js app (`sites/mainweb`). Signing in does not take you to a different hostname.
14+
15+
## Live URLs
16+
17+
| Surface | URL |
18+
| -------------------- | ------------------------------------------------------------------------------------------------------------ |
19+
| Public site + portal | [https://datasciencegt.org](https://datasciencegt.org) <!-- pragma: allowlist secret --> |
20+
| Sign in | [https://datasciencegt.org/login](https://datasciencegt.org/login) <!-- pragma: allowlist secret --> |
21+
| Member home | [https://datasciencegt.org/dashboard](https://datasciencegt.org/dashboard) <!-- pragma: allowlist secret --> |
22+
23+
`member.datasciencegt.org` does **not** resolve. Do not send people there, and do not put it in copy or onboarding.
24+
25+
Locally, the same app is [http://localhost:3001](http://localhost:3001). See [Getting started](./getting-started.md).
26+
27+
## What members use it for
28+
29+
After sign-in (Google, GitHub if configured, or email code):
30+
31+
| Need | Where |
32+
| ---------------------------------------- | ----------------------------------------------------------------------------------------------------------------------- |
33+
| Join / pay dues | Portal membership — Stripe **$25** annual membership, **$10** bootcamp add-on (on top of membership, not instead of it) |
34+
| Club events and check-in | Portal events / club pass |
35+
| Bootcamp (term-gated add-on) | `/club/bootcamp` and the public `/bootcamp` page |
36+
| Club projects (pitch + optional resume) | `/initiatives` |
37+
| Staff tools | `/admin` (appointed roles only; there is no public admin signup) |
38+
| Hacklytics interest and registration | Portal `/hacklytics` (the marketing site links here after login) |
39+
40+
Hacklytics participation is open to non-members. A paid membership is not required to register for the hackathon.
41+
42+
Public pages (no login):
43+
44+
| Path | Page |
45+
| ----------- | ------------------ |
46+
| `/` | Home |
47+
| `/team` | Executive board |
48+
| `/events` | Public events |
49+
| `/projects` | Projects |
50+
| `/history` | Club history |
51+
| `/bootcamp` | Bootcamp marketing |
52+
53+
Route-level detail: [Main website](./sites/mainweb.md). Club vs hackathon vocabulary: [Glossary](./glossary.md).
54+
55+
## Club projects (the roster on the site)
56+
57+
`/` and `/projects` read the roster from the `club_project` table, not from a hardcoded array. Editing a card is a row edit, which is why the old list sat five years stale.
58+
59+
| Column | What it does |
60+
| --------------- | ----------------------------------------------------------------------------------------- |
61+
| `status` | `active`, `revived`, `needs_lead`, or `past`. Only `past` drops out of the current roster |
62+
| `lead_name` | Free text, so a lead can be named before they ever sign in |
63+
| `initiative_id` | The portal initiative members apply to, when there is one |
64+
| `join_url` | External destination for projects that recruit elsewhere (ARC) |
65+
| `is_published` | Pull a card off the site without deleting it |
66+
67+
Applying happens in the portal. A card with an `initiative_id` links to `/initiatives`, where a signed-in member says why they want to join and may attach a PDF resume; the leader reads both and accepts or declines from `/lead`. A card with no initiative falls back to `join_url`, then to the shared interest form.
68+
69+
To reset the roster to the checked-in Fall 2026 list:
70+
71+
```bash
72+
pnpm --filter @query/db db:seed:club-projects
73+
```
74+
75+
The seed upserts on `slug` and never deletes, so re-running it republishes the roster without duplicating cards. Removing a project from the site is `is_published = false`, not a deleted row.
76+
77+
## Current status (Fall 2026)
78+
79+
This is **live production infrastructure**, not a greenfield student app and not a class project waiting for a first deploy.
80+
81+
- Serving real members at [datasciencegt.org](https://datasciencegt.org) <!-- pragma: allowlist secret -->
82+
- Hosted on Firebase App Hosting / Cloud Run
83+
- GCP project: `dsgt-website`
84+
- Database: Neon (Postgres)
85+
- Last `main` activity: late August 2026
86+
87+
Treat production as production. A broken PR can take down dues, login, or event check-in.
88+
89+
## How the repo is laid out
90+
91+
High level only. Details live in the linked docs.
92+
93+
| Path | What it is |
94+
| ---------------------- | ---------------------------------------------------- |
95+
| `sites/mainweb` | Public club site **and** the authenticated portal |
96+
| `sites/hacklytics2027` | Hacklytics 2027 marketing site (static; no database) |
97+
| `packages/api` | tRPC, pricing, server logic |
98+
| `packages/auth` | Sign-in (NextAuth) |
99+
| `packages/db` | Schema and membership rules |
100+
| `packages/ui` | Shared React components |
101+
102+
Club operations (membership, club events, bootcamp, club projects) and hackathon editions share one database but are modeled as separate domains. Do not hang club tables off a hackathon row.
103+
104+
Setup, env, and first-admin bootstrap: [Getting started](./getting-started.md). How the pieces connect: [Architecture](./architecture.md). Index of the rest: [Documentation](./README.md).
105+
106+
## Older repos (do not revive)
107+
108+
These are predecessors. The live product is **this** repo (`DataScience-GT/query`). Do not open feature work there, do not migrate traffic back, and do not treat them as the current stack.
109+
110+
| Repo | What it was |
111+
| ----------------------------------------------------------------------------------------------------- | -------------------------------------------------- |
112+
| [DataScience-GT/datascience-gt.github.io](https://github.com/DataScience-GT/datascience-gt.github.io) | Earlier website / portal repo |
113+
| [DataScience-GT/dsgt-member-portal](https://github.com/DataScience-GT/dsgt-member-portal) | Earlier member portal (membership, Stripe, events) |
114+
115+
## How to help
116+
117+
Safe first work — useful, visible, and hard to take production down with:
118+
119+
1. **Public content accuracy** — `/team`, `/projects`, `/events` (and related copy) matching the current board and programs
120+
2. **Onboarding and docs** — this folder, especially anything that helps a new contributor run the app without guessing
121+
3. **Small UI bugs** — layout, dead links, copy, accessibility on pages you can exercise locally
122+
4. **Tests** — fill gaps in existing Vitest suites; see [Testing](./operations/testing.md)
123+
124+
Label anything that touches **payments**, **auth**, or **production deploy** as **needs-exec-review**. Do not merge that class of change on a student PR alone. That includes Stripe amounts and webhooks, NextAuth / OAuth / email-code login, secrets, `apphosting.yaml`, Firebase Hosting, and anything that writes production schema.
125+
126+
Club events and working time are after **6:30 PM ET**. Questions: [hello@datasciencegt.org](mailto:hello@datasciencegt.org) or Aamogh.
127+
128+
## How to join / contribute
129+
130+
1. Read [Contributing](./contributing.md) and [Getting started](./getting-started.md).
131+
2. Branch from `dev` (that is the integration branch). `main` is production.
132+
3. Open the pull request against **this** repo (`DataScience-GT/query`). Feature branches are reviewed into `dev`; `dev` is what ships to `main`.
133+
4. Never commit secrets (`.env`, Stripe keys, OAuth client secrets, SMTP passwords, production `DATABASE_URL`). If a secret was pasted into a PR, say so immediately — do not “fix” it by committing a deletion and moving on.
134+
135+
Code owners: `@aamoghS`.

‎docs/getting-started.md‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,15 @@ This guide gets a local copy of **query** running: Postgres, schema, env, and bo
55
## Prerequisites
66

77
- **Node.js** `>=20.16.0 <24` (`.nvmrc` pins `20`; CI also uses 20 and 22)
8-
- **pnpm** `10.33.2` (see `packageManager` in the root `package.json`)
8+
- **pnpm** `12.3.4` (see `packageManager` in the root `package.json`)
99
- **Docker** (for local Postgres)
1010
- Optional: **gcloud** and **Firebase CLI** if you need production secrets or deploys
1111

1212
Enable Corepack so the repo’s pnpm version is used:
1313

1414
```bash
1515
corepack enable
16-
corepack prepare pnpm@10.33.2 --activate
16+
corepack prepare pnpm@12.3.4 --activate
1717
```
1818

1919
## Install

‎docs/glossary.md‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,16 @@
33
| Term | Meaning in this repo |
44
| --- | --- |
55
| **query** | This monorepo (`package.json` name). Not a search engine. |
6-
| **Club** | Year-round DSGT operations: membership, club events, bootcamp, initiatives. Not keyed by hackathon. |
6+
| **Club** | Year-round DSGT operations: membership, club events, bootcamp, club projects. Not keyed by hackathon. |
77
| **Hackathon / edition** | One `hackathon` row (e.g. Hacklytics 2027) and everything that cascades from it. |
88
| **Hacklytics** | DSGT’s annual data-science hackathon. Marketing site is `sites/hacklytics2027`; operations are the portal. |
99
| **Portal** | Authenticated product UI inside `sites/mainweb` route group `(portal)`. |
1010
| **Member** | A `member` row with a **paid, unexpired** year. A lapsed row still exists but `isMember` is false. |
1111
| **Pass** | `member.pass_code` — rotatable QR for club check-in. Independent of membership dates. |
1212
| **Volunteer** | Weakest `admin.role`. Can scan badges (`isScanner`). Cannot pass `isAdmin`. |
1313
| **Staff** | Active admin whose role is not `volunteer`. |
14-
| **Project leader** | `project_leader` row. Runs club **initiatives**. Not a staff role. |
15-
| **Initiative** | Club project members apply to join. Never judged. Distinct from a hackathon **project**. |
14+
| **Project leader** | `project_leader` row. Runs **club projects**. Not a staff role. |
15+
| **Club project** | `initiative` row. Members apply to join with a pitch and an optional resume. Never judged. Distinct from a hackathon **project**, which is a judged submission. The UI says "club project"; the table is still `initiative`. |
1616
| **Hackathon project** | Team/solo submission (`hackathon_project`). Promoted into `judging_project` for scoring. |
1717
| **Interest** | “Tell me when registration opens” (`hackathon_interest`). Requires a signed-in user. |
1818
| **Current edition** | In-progress hackathon if one exists; otherwise the newest edition that is not `draft` or `announced`. |

‎docs/operations/ci-cd.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ All workflows live in `.github/workflows/`.
77
| Workflow | Trigger | What it does |
88
| --- | --- | --- |
99
| `pnpm-ci.yml` | Push `main`/`dev`, PRs | `pnpm install` + `pnpm turbo run build` (Node 22) |
10-
| `test.yml` | Push `main`/`dev`, PRs | `pnpm test` (Node 20, pnpm 8 in this file — version drift vs root `pnpm@10`) |
10+
| `test.yml` | Push `main`/`dev`, PRs | `pnpm test` (Node 20; pnpm comes from `packageManager`, unpinned in the workflow so it cannot drift) |
1111
| `codeql.yml` | Push/PR `main`/`dev`, daily 02:00 UTC | CodeQL `security-extended,security-and-quality`; PRs also run dependency review (`fail-on-severity: high`) |
1212

1313
## Deploy

‎docs/operations/environment.md‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,12 @@ Without `DATABASE_URL`, `db` is null, sessions fall back to JWT, and tRPC proced
5151
| `DB_POOL_MAX` | `20` |
5252
| `DB_CONNECTION_TIMEOUT_MS` | `3000` |
5353

54+
## Resume book
55+
56+
| Variable | Default / notes |
57+
| --- | --- |
58+
| `RESUME_BUCKET` | Cloud Storage bucket holding resume PDFs (App Hosting sets `dsgt-resumes`). Unset means uploads return 503 rather than failing obscurely. Credentials are ADC — the runtime service account needs `roles/storage.objectAdmin`. See [Resume book](../resume-book.md) |
59+
5460
## Security / proxy
5561

5662
| Variable | Default / notes |

0 commit comments

Comments
 (0)