Two issues prevented 0003_circles.sql from running:
1. Missing -->statement-breakpoint markers (Drizzle splits SQL by these)
2. migrate.ts used DATABASE_URL (tia_app, no DDL privileges) instead of
DATABASE_URL_SUPERUSER — now prefers superuser URL with fallback to
DATABASE_URL for local dev
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The SQL file existed but was missing from _journal.json so the
migrator skipped it on deploy. Adding the journal entry ensures
the circles tables are created on next container boot.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds full circle functionality — private social groups for trusted families
to share milestones, memories, and posts with reactions and comments.
- 7-table DB migration: circles, members, invites, posts, comments, reactions, reports
- 11 API routes: create/list circles, posts feed, comments, emoji reactions, invite tokens, join flow, member management, reporting
- 3 new pages: /circle (list), /circle/[id] (feed + PostCard + CreatePostModal), /circle/join/[token]
- Copy-on-share for memory photos (independent R2 objects, never references originals)
- Admin controls: invite generation, member promote/demote/remove, last-admin guard
- C9 privacy consent screen before first post
- Menu entry added
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- New PATCH /api/children/[id] — updates image_url in children table
- New POST /api/children/[id] — returns presigned R2 URL for profile
photos (stored under profiles/{childId}/ prefix, no memories row)
- FamilyProvider: expose updateChildImage() so UI updates instantly
without a full re-fetch after upload
- Home page baby card: photo avatar is now a separate tap target from
the growth link. Tap photo → file picker → upload to R2 → save URL.
Camera overlay (📷) appears on hover/tap; ⏳ shown while uploading.
Tapping name/age/arrow still navigates to growth as before.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Each row in a day chip is now its own button. Tapping 🍼×2 on Thursday
opens a sheet scoped to feeds on Thursday only — not all logs for that day.
Sheet shows entries for that specific type, with edit/delete per entry and
a single focused "+ Add [type]" CTA at the bottom.
Rows showing ×0 render dimmed so missing entries stand out at a glance.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Moved guidelines row ABOVE the 4-day strip (correct order)
- 4-day strip: each chip is now tappable
→ opens a day-detail bottom sheet showing all logs for that day
→ each log row has ‹ › arrow; tap opens edit/delete action sheet
→ empty state tells mama to use Generate sample history to pre-fill
→ quick-add row at bottom (+ Feed / + Sleep / + Diaper) for fast logging
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Remove redundant daily summary bar (Today chip in 4-day strip covers it)
- 4-day strip: reversed to oldest→newest order (Wed→Thu→Yest.→Today)
- 4-day strip: switched from flex to grid grid-cols-4 so all 4 chips
fill the full row width evenly instead of floating left
- Today chip highlighted in rose-400 to stand out from past days
- Guidelines: corrected 9-12 mo (feeds 3→4, sleep 12→14h, diapers 3→4)
per AAP; 12-18 mo sleep 11→13h, diapers 3→4; 18-24 mo sleep 11→12h,
diapers 2→3; all now match mid-range AAP recommendations
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- FAB raised to bottom-20 to clear fixed bottom nav
- Branded loading: bouncing 🍼😴🚼 emojis
- Back button: white pill with shadow (matches other pages)
- Generate History moved to ⋯ overflow menu (keeps header clean)
- Filter pills: emoji labels (🍼 Feed / 😴 Sleep / 🚼 Diaper) + scrollbar-hide
- Daily summary bar: today's feed/diaper/sleep counts at a glance
- 4-day overview strip: quick multi-day snapshot above timeline
- Collapsible guidelines card: collapsed shows x/target fractions,
expands to progress bars with actual/target display
- Today/Yesterday/weekday labels in timeline; Today styled in rose
- Better empty state with emoji and "Tap + to start logging" CTA
- Tap any log row → action sheet with Edit and Delete
Edit: pre-fills LogModal with same values, deletes old log on save
Delete: inline confirmation (no browser confirm()), then refresh
- New DELETE + PATCH handlers at /api/logs/[id] with family ownership check
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Reverted fixed viewport positioning back to absolute — the parent cards
no longer have overflow-hidden so absolute works correctly now. Both
dropdowns (profile share and per-product share) appear directly below/above
their trigger button instead of floating at a random screen corner.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Root cause: parent div had overflow-hidden which clipped absolute-positioned
dropdowns, making them render but be invisible (looked like click did nothing).
- Removed overflow-hidden from profile card container
- Share dropdowns now use fixed positioning to escape any parent overflow
- Merged chevron into the expand button so the whole left area is one tap target
- Per-product share sheet also changed to fixed bottom-28 right-4
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Each product row now has an ↗ share button (product URL shared, not profile)
WhatsApp message: "Found this for our baby — [title]: [url]"
- Only one product share sheet open at a time; closes on backdrop tap
- Profile page share (↗) moved to the profile card header row where it
contextually belongs — shares the /m/slug link, not a product
- Removed the share button that was on the Products section header
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Collapsible profile card:
- Starts collapsed if profile already exists (shows name + URL slug)
- Expands/collapses via chevron toggle row
- Auto-collapses after Save Profile succeeds
Share sheet on Product Recommendations:
- ↗ Share button appears once a valid slug is set
- Options: Copy link (clipboard, shows ✅ feedback), WhatsApp deep link,
and native Web Share API ("More options") when browser supports it
- Backdrop click closes the sheet
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Settings/Sign Out used absolute bottom-0, overlapping the bottom of the
menu items list on shorter screens. Converted to normal flow with mt-4
and added pb-28 so the list clears the bottom nav bar.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add persistent bottom navigation bar (Home / Activity / AI / Menu)
- Fix TodaySummary bug: last-log times now show today's events only
- Replace 6 hardcoded AI chips with 3 AI-generated context-aware chips
- Show child's real profile photo in baby card (fallback to 👶 emoji)
- Recent Activity limited to 3 items with "See all →" link to /activity
- "Suggested now" promoted to prominent amber banner with "Log it →" CTA
- Offline pending banner is now a tappable retry button
- Branded loading state with bouncing emoji (🍼😴🚼👶)
- Remove unused Button import from page.tsx
- Expose image_url via /api/children and Child type/FamilyProvider
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Convert Quick Log from grid-cols-4 to horizontal scroll strip so
it scales to any number of actions without layout breakage
- Add Wardrobe 👗 shortcut linking directly to /wardrobe/add,
saving mama the Menu → Wardrobe → Add Garment 3-tap journey
- Fix: replace non-existent `no-scrollbar` class with `scrollbar-hide`
across page.tsx, wardrobe pages, memories page, and TabBar component
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Production runs Postgres 18; the dev compose file pinned pg16. A pg_dump
from prod (v18) cannot be restored by a v16 pg_restore — the dump header
is rejected. Matching the major version fixes restores and removes a
latent source of dev/prod behaviour drift.
Also adopts the pg18 image's data-directory convention: the volume now
mounts at /var/lib/postgresql (the image places data in a version
subdirectory), and drops the obsolete compose 'version' key.
Makes schema changes deploy automatically: edit schema -> db:generate ->
commit -> push -> Dokploy redeploys -> migrations apply on container start.
No more Dokploy database terminal.
Components:
- src/db/migrate.ts: standalone migrator (single short-lived connection,
fails loud on error so a bad migration crashes the container instead of
letting the app serve a half-migrated schema)
- scripts/build-migrator.mjs: esbuild bundles migrate.ts -> dist/migrate.mjs
with drizzle-orm + postgres inlined. Needed because Next.js standalone
output keeps neither as a separate node_modules package.
- Dockerfile: builder runs db:build-migrator; runner copies migrate.mjs +
drizzle/; CMD is 'node migrate.mjs && node server.js'
- package.json: db:generate / db:migrate / db:studio / db:pull /
db:build-migrator scripts; esbuild promoted to an explicit devDependency
- pnpm-lock.yaml resynced
BUG FIX: .dockerignore had 'drizzle/' — migration SQL was excluded from the
build context, so even a correct Dockerfile COPY would have found nothing.
This was the second half (with the .gitignore bug in commit 1) of why the
migration pipeline never worked. Now only _archived/_introspected are
excluded.
Verified: full docker build succeeds; runner image contains migrate.mjs +
drizzle baseline; migrator tested end-to-end against a scratch DB (35
tables created, __drizzle_migrations populated, idempotent on rerun).
drizzle-kit generate against the now-prod-aligned schema produces a
single baseline migration covering all 35 tables.
VERIFIED: 0000_baseline_prod_2026_05_19.sql was compared column-for-column
and type-for-type against the drizzle-kit pull introspection of tia_prod.
Table sets identical, all columns and types match. The baseline is a
faithful representation of production.
This baseline will be marked as already-applied in prod's
__drizzle_migrations table (done out-of-band, not in git), so the migrator
runs nothing on the next deploy. It exists purely as the reference point
for future schema diffs.
Adds drizzle/README.md documenting the baseline reset and the migration
workflow going forward.
The drizzle/ folder was in .gitignore (line 34) — likely confused with
the build 'out/' dir. Effect: migration SQL never reached the server on
deploy, so the migration pipeline could never have worked. Only 7 of 18
files were ever force-tracked; 0000-0010 + most of manual/ were untracked.
- Remove drizzle/ from .gitignore; document why it must be tracked
- Archive legacy hand-rolled migrations 0000-0015 + manual/ to
_archived_pre_baseline_2026-05-19/ (kept on disk; history retains old copies)
- Archive stale meta/ (knew of only 3 of 16 migrations)
- Baseline regeneration follows in subsequent commits
- Remove 📥 export button from growth page header (less clutter)
- Add "Export Growth Data" row in settings with child name and CSV download
- Fetches growth records on demand, shows loading state while exporting
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add Measurement form now appears directly below the header (not buried
after WHO card) so it's immediately visible when + Add is tapped
- Removed `&& latest` guard — form now works even with zero records
- Goals and Add are mutually exclusive: opening one closes the other
- 3-column grid for measurement inputs (weight / height / head on one row)
- Sticky header with backdrop-blur, smaller title (text-sm), icon-style
export and goals buttons
- All cards use rounded-2xl + shadow-sm for consistent look
- "Add First Measurement" in empty state scrolls to top and opens the form
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- grid-cols-4 (~40% smaller than 3-col) with gap-1 and rounded-xl corners
- Hover: scale-110 image + dark overlay + expand icon (⤢)
- Subtle shadow + ring border on each tile
- Folder emoji + name shown below each tile (when assigned)
- Filter out tiles with no URL and remove tiles that fail to load (onError → null)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Header title reduced to text-xs (~50% smaller)
- Tap image in viewer to zoom 2x; tap again to zoom out
- Tap outside image area to toggle UI chrome (top bar / captions)
- "New folder" pill at end of folder row and in upload picker
- Custom folders saved to localStorage (tia_custom_folders)
- Custom folders appear in folder pills, upload picker, and move-to-folder sheet
- Emoji picker (15 options) + name input for new folders
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Direct PUT to R2 presigned URL is cross-origin, causing "Failed to fetch"
in browsers without R2 CORS configured. Use the existing PUT /api/upload
proxy handler instead — file goes client → Next.js → R2 server-side.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Extract offline queue to src/lib/offline-queue.ts
- Extract shared LogModal with time presets (Just now/5/15/30min/Custom)
and smart default pre-fill from last log of same type
- Replace ActivityScroller with TodaySummary (today's counts + last time)
- Fix activity page: GET /api/logs without type param now returns all logs merged
- Fix field naming: log.loggedAt / log.amount (camelCase throughout)
- Add FAB to activity page for zero-navigation quick logging
- Recent Activity shows 5 most recent entries with correct field names
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Swap 👶 → 🚼 (baby-changing symbol) in all four diaper-specific spots:
activity page getIcon(), homepage ActivityScroller, quick log button,
and recent activity list. Other 👶 usages (child profiles, onboarding,
admin children nav) are left unchanged as they represent babies, not diapers.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Month grid with Su–Sa columns, colored activity dots per day (rose=feed,
blue=sleep, amber=diaper). Tapping a day opens a detail panel below the
grid with the full log list for that day. Month navigation with prev/next
arrows; future months are disabled. Filter pills apply to both views.
Limit raised to 200 entries so calendar data spans multiple months.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Three bugs fixed:
1. GET /api/logs required a `type` param; activity page calls without one,
always receiving {error} → empty list. Fixed: when type is omitted,
merge feeds + diapers_logs + sleeps, sort by time, return camelCase
fields (loggedAt, subType, amount) matching the activity page interface.
2. Type-specific queries (used by homepage) still return raw snake_case
rows unchanged so the homepage "Recent Activity" section is unaffected.
3. LogModal initialised subType as "breast_milk" regardless of log type.
Adding a useEffect to reset it (breast_milk / wet / nap) when type
changes prevents bad enum values from being sent for diaper/sleep logs.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Rose gradient background instead of flat gray
- Header with ← back link and child name subtitle
- Active filter/category pills use bg-rose-400 instead of purple
- Progress bar gradient updated to rose-to-pink
- Full-width px-4 layout (removed max-w-2xl wrapper)
- Date picker uses design system Input + Button components
- Empty state with icon, consistent with other pages
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Replace raw <input>/<button>/<select> elements with Button, Card, Input,
Select, Modal, Badge, and ConfirmDialog from @/components/ui in all
non-admin and admin pages. Removes ~550 lines of inline Tailwind utility
classes from form elements while keeping all business logic intact.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Wire Resend to /api/auth/reset-request with fallback for dev
- Install: sharp, recharts, next-pwa, resend, @react-pdf/renderer, @types/sharp
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- Add auth to /api/ai via requireFamily middleware
- Remove /api/ai and /api/auth/debug from public routes
- Delete debug/test routes that expose internal state
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- Fix handleSubmit to properly wait for API response before closing
- Change diaper icon from 🧷 to 👶
- Update activity scroller diaper icon
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- Add form now appears between Latest Reading and WHO card
- Remove duplicate form below WHO card
- Similar pattern to Goals card
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- WHO card shows icons + values when collapsed (⚖️📏⭕)
- Chart is collapsible inside expanded WHO view
- History is collapsible with scroll for many records
- Add formatAge to history items
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>