Skip to content

Commit 42b6369

Browse files
Kjubikstronkclaude
andcommitted
Add working notes so a fresh session starts informed
Everything a new session would otherwise re-derive: the privacy model, the couples architecture, the design constraints, the gotchas that have already cost time, and what is deliberately not being built. Deliberately excludes anything the codebase already answers — no file tree, no dependency list, no standard commands. Only npm run rules and npm run ui are listed, because neither is guessable. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
1 parent 10993f2 commit 42b6369

1 file changed

Lines changed: 139 additions & 0 deletions

File tree

‎CLAUDE.md‎

Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
# our dates — working notes
2+
3+
A private date planner for couples. Calendar + Google Map + a list, with each
4+
partner rating a date blind after the fact. Live at
5+
**https://kjubikstronk.github.io/dateideas/** — Firebase project `dates-8910a`.
6+
7+
Two couples use it today: mck097@gmail.com + alice@dates.local (couple
8+
`founders`), and milan@obradovic.at + sarah@hutter.at (couple `milan-sarah`).
9+
10+
---
11+
12+
## The two things that shape everything
13+
14+
**The site is public; the data is not.** GitHub Pages can't restrict access, so
15+
the deployed page is an empty shell — a login box and nothing else. All privacy
16+
is enforced by Firestore rules on Google's servers. The Firebase and Maps keys
17+
are in the bundle deliberately; they're identifiers, not secrets. Sign-up is
18+
disabled in the console, so nobody can self-register.
19+
20+
**Membership is a document, not a rule.** `members/{uid}` holds one field,
21+
`coupleId`; every date carries the same field and the rules compare them.
22+
`firestore.rules` contains no UIDs at all.
23+
24+
To add a person: create the account in Firebase Auth, then create
25+
`members/{their-uid}` with the right `coupleId`. No code, no rules edit, no
26+
deploy. An account with no members doc sees "not paired up yet".
27+
28+
---
29+
30+
## Commands worth knowing
31+
32+
```bash
33+
npm run rules # deploys firestore.rules from the repo — never paste into the console
34+
npm run ui # preview mode: sample data, no Firebase, no login
35+
```
36+
37+
`.env.local` (keys) and the Firebase MCP need `firebase login` once.
38+
39+
---
40+
41+
## Gotchas that have already cost us time
42+
43+
**Firestore rejects any query it can't prove is safe.** An unscoped
44+
`collection(db,'dates')` read is denied outright once the rules scope by
45+
`coupleId` — not filtered, denied. Client query and rules must agree. This is
46+
why the couples migration had to ship in two ordered steps.
47+
48+
**Rules take effect instantly; data doesn't migrate itself.** Deploying rules
49+
that require a field before backfilling that field locks everyone out. Deploy
50+
the app first, then tighten the rules.
51+
52+
**`Map` from `@vis.gl/react-google-maps` shadows the global `Map`.** It's
53+
aliased to `GoogleMap` in DateMap.tsx. Don't un-alias it.
54+
55+
**No hooks after an early return.** This has bitten twice. Lint catches it —
56+
run `npm run lint` before committing.
57+
58+
**`DateCard` is memoised and keyed by id**, so it survives every Firestore
59+
snapshot. Any local state seeded at mount goes stale when the partner writes.
60+
Seed on open, not on mount.
61+
62+
**Dates are `yyyy-MM-dd` strings, never Date objects or timestamps.** They sort
63+
and compare correctly and can't drift by timezone. A date happening *today* is
64+
not past — use `<`, not `<=`.
65+
66+
**One service worker only.** `vite-plugin-pwa` owns it. Adding Firebase
67+
messaging later needs `injectManifest` and a single combined worker, not a
68+
second file at the same scope.
69+
70+
**Places bills by the highest field tier requested.** `rating` is the only
71+
Enterprise-tier field left and buys just the `4.3 ★` on the map candidate card.
72+
Detail lookups are cached per session — don't remove that, every map POI tap is
73+
otherwise billable.
74+
75+
---
76+
77+
## Design constraints — do not violate
78+
79+
Y2K handheld device: 3px ink borders, hard offset shadows with no blur,
80+
`steps()` easing only, `border-radius: 0`.
81+
82+
- ink `#1A1033` · paper `#FFE5F1` · card `#FFFDFE` · hot `#FF5CA8` ·
83+
deep `#B31E67` · lavender `#B8A6FF` · aqua `#5BE0E6` · mute `#6B6480`
84+
- **Hot pink is fills and borders only** — it fails contrast as text. Pink text
85+
uses deep. Everything must pass WCAG AA.
86+
- Mobile-first, 375px primary. Touch targets ≥44px. **Inputs ≥16px** or iOS
87+
zooms the page and won't zoom back.
88+
- **Emoji, not custom pixel art**, for categories and weather. Decided; my
89+
hand-drawn set was rejected and rightly so.
90+
- Google's map colours stay untouched.
91+
- Agenda entries are flat rows; a card lifts only while being worked on. The
92+
device bezel keeps the only 6px shadow.
93+
94+
---
95+
96+
## Verification habits that have paid off
97+
98+
- Probe security live rather than assuming: unauthenticated reads/writes of
99+
`dates`, `members`, `reports` must all return 403.
100+
- The in-app browser **cannot composite** — CSS transitions freeze mid-flight,
101+
`requestAnimationFrame` never fires, and Google Maps tiles never paint. Verify
102+
logic and inline styles, not appearance. Never schedule anything on rAF alone.
103+
- Deployed and local bundle hashes differ legitimately (CI uses `npm install`,
104+
not `npm ci`). Use the Actions status to confirm a deploy, not a hash.
105+
106+
---
107+
108+
## Open work
109+
110+
**Notifications** — planned, not started. Decided: GitHub Actions cron + FCM
111+
(free, no Blaze upgrade). Girlfriend has an iPhone 13, so Web Push is viable,
112+
but on iOS it works **only** from a home-screen install — never in a Safari tab.
113+
Needs: combined service worker, permission asked after scheduling (not on load),
114+
tokens on `members/{uid}` behind a narrow rules exception, daily sender, real
115+
device testing.
116+
117+
**Before any public release** — three product decisions, not bugs:
118+
1. There is no sign-up flow. Every couple is manual work.
119+
2. `reports` are readable by all members — one couple's bug reports are visible
120+
to every other. Fine for people who know each other; a leak with strangers.
121+
3. The Maps budget is €2. It would be exhausted fast at scale, and the map then
122+
silently dies for everyone.
123+
124+
Also note: this is a **web app**. "Release on mobile" means Add to Home Screen.
125+
A store listing would need Capacitor-style wrapping, review, and Apple's
126+
$99/year.
127+
128+
**Dropped deliberately** — couple nameplate, "go again" duplicate button,
129+
inline day-picking on someday cards, calendar `.ics` subscription, JSON export,
130+
surprise-me dice, custom pixel stickers, photos on memories.
131+
132+
---
133+
134+
## Working style that suits this project
135+
136+
The owner is watching a weekly token budget. Prefer Sonnet for routine work and
137+
save Opus for security rules, race conditions and genuine debugging. Be
138+
economical, verify rather than assume, and say plainly when something is
139+
unverified.

0 commit comments

Comments
 (0)