Remove `**...**` emphasis markers from inline comments and JSDoc blocks across
auth and chat components, machine mappers, and quota helpers. These are
plain code comments, not rendered markdown, so the bold syntax was noise.
Files touched:
- src/app/auth/components/auth-screen.tsx
- src/app/chat/components/chat-header.tsx
- src/app/chat/components/chat-screen.tsx
- chat machine mapper / quota helpers
No functional or behavioral changes.
Remove obsolete Dart migration notes and route handling comments from splash-button.tsx and auth-machine.ts, and drop the unused `self` parameter from `chatWebSocketActor` callback signature.
Two related fixes for OAuth login failures:
- `UserSchema`: backend (Facebook/Apple) returns `null` for fields like
`email`; Zod's `.default("")` rejects `null`, causing silent login
failures. Introduce `stringOrEmpty` / `numberOrZero` / `booleanOrFalse`
helpers (`nullable().transform(v => v ?? x).default(x)`) and apply
across the schema so input accepts `string | null | undefined` while
output stays the typed primitive.
- `SplashScreen`: render `state.errorMessage` (set by auth state machine
`onError`, e.g. Facebook sync / schema mismatch) so users no longer
get stuck on splash without feedback.
Replace the dark sidebar theme with a light-themed three-state UI
matching the design references:
- guest : pink "login" pill in user row, no status pill on VIP card,
"Activate VIP Membership" button shown
- member : "VIP membership not activated" subtitle, no status pill,
"Activate VIP Membership" button shown
- vip : pink "VIP Member" pill with diamond icon, "Activated" pill
in VIP card header, no Activate button
Decompose into BackBar, UserHeader, VipBenefitsCard, and VoicePackageCard
under src/app/sidebar/components/. Delete obsolete GuestPanel,
UserInfoCard, and VipCta.
Lift VIP_BENEFITS to a shared src/data/constants/vip-benefits.ts so the
sidebar and subscription page render identical benefit copy.
Add five sidebar tokens (--color-card-surface, --color-voice-gradient-*
--border-card, --shadow-card, --color-pill-bg) to src/tokens/colors.css.
Includes barrelsby regeneration for src/app/sidebar/components and
side-effect barrel updates under src/stores/{auth,chat,sidebar,user},
plus package-lock.json from npm install (required for lint/typecheck).
Co-Authored-By: Claude <noreply@anthropic.com>
Add Stripe payment integration across the project:
- Add @stripe/stripe-js dependency
- Configure Stripe environment variables (secret key, publishable key, webhook secret) for dev, local, and production environments
- Add Product/Price IDs for monthly, quarterly, and annual subscription tiers
- Extend subscription plan data with voiceMinutesPerDay quotas (30/45/60 minutes per tier)
- Update .gitignore to exclude implementation_plan.md
Rebase the sidebar's user information area onto the project's
dark sidebar surface (--color-sidebar-background #0d0b14) and
pink accent (--color-accent #f84d96), replacing the previous
white-card / purple-gradient look that did not align with the
design.
- Shell, back link, profile card, guest panel: switch to dark
surfaces (#1a1625) with white text.
- VIP badge: use --color-accent pink (was purple fallback).
- VIP CTA + Sign up primary link: use --color-button-gradient
pink gradient (was purple fallback).
- Sign in secondary link: use dialog border on transparent.
- Override nested SettingsSection elements (list/row/button/svg)
inside the sidebar's settingsArea so the dark theme carries
through without modifying the shared core component.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Sidebar screen now primarily displays user-related information
and derives three render states from loginStatus + currentUser.isVip:
- guest (notLoggedIn): welcome panel + Sign in / Sign up entries
- member (logged in, no VIP): user info card + Get VIP CTA + Log out
- vip (logged in, VIP): user info card with VIP badge + Manage VIP CTA
+ Log out
Adds UserView.isVip (default false), patches user-machine.toView()
to populate it, and introduces three presentational components
(GuestPanel, UserInfoCard, VipCta) co-located under src/app/sidebar.
Preserves existing UserInit + logout-redirect behavior.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Fix chat components barrel to properly export all component modules
- Remove interceptor exports from API services barrel
- Regenerate store barrel files (auth, chat, sidebar, user) using barrelsby
Add a new /subscription route showing three VIP membership plans (Monthly,
Quarterly, Annual) with a pink→peach banner, per-plan gradient price bars,
a benefits card, a mock activate CTA, and an agreement checkbox.
- New reusable <Checkbox /> in src/app/_components/core for the legal
agreement toggle
- Hardcoded SUBSCRIPTION_PLANS constant in src/data/constants
- New SubscriptionScreen composed of 7 colocated components (back link,
user row, banner, plan card, benefits card, CTA button) with CSS
Modules matching the existing design-token system
- Route registered as protected and reached from /sidebar "Membership"
- Mock CTA: window.alert + router.push(/chat) — no payment calls
Co-Authored-By: Claude <noreply@anthropic.com>
Drop the QuotaDialog component invocation in chat-screen along with
its useState/useEffect wiring, and delete the component files. Update
JSDoc in chat-screen and routes to reflect the removed consumer.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Split `chatInitActor` into `loadQuotaActor` (guest quota fetch) and `loadHistoryActor` (local → network → save sync), and add `quotaLoaded` / `historyLoaded` state flags so the UI can display loading status during the new local-first history hydration flow. Also drop the now-unused `ChatInit` event and pipe Next.js stdout/stderr to a persistent log file in the post-receive hook for easier troubleshooting.
Move the NextAuth v4 configuration from the route handler
(src/app/api/auth/[...nextauth]/route.ts) into a dedicated module
(src/lib/auth/auth.ts) to establish a single source of truth. The
route file now simply re-exports the handler from the shared
module, keeping provider setup, JWT/session callbacks, and
environment variable references in one reusable location.
- Inline NextAuth v4 handler directly in `[...nextauth]/route.ts`, removing
the `@/lib/auth/nextauth` abstraction layer
- Add Google/Facebook providers with JWT/session callbacks that expose
`idToken` and `accessToken` on the session for backend exchange
- Refactor `AuthPlatform` from constructor-based to static methods
(`googleSignIn()` / `facebookSignIn()`)
- Update `auth-machine.ts` and layout comment reference to match new structure
- Align with original Dart `nextauth-helpers.{googleLogin, facebookLogin}()`
naming and keep persistence concerns (unstorage, backend, custom cookies)
out of scope for this iteration
- Move AiDisclosure and EmptyState logic into a new AiDisclosureBanner component
- Remove isGuest prop from ChatArea as it's no longer needed there
- Update styling with explicit color values for better visibility
- Remove redundant `loadingMoreHistory` and `ready` states from chat machine, consolidating history loading flow
- Add `align-self: flex-start` to chat row container for proper alignment
- Clean up commented-out margin rules in text bubble styles
- Update deploy script GIT_REMOTE from "server" to "test"
- Split chat state machine actors (chatInit, sendMessageHttp, loadMoreHistory, chatWebSocket) into a dedicated module
- Add comprehensive console logging across the chat state machine for full trace debugging
- Comment out margin on text bubble CSS for layout adjustment
- Add debug logging to chat input bar send handler
- Clean up redundant comments in auth-screen component
- Remove ChatScreenVisible and ChatScreenInvisible events from chat state machine
- Remove legacy ChatInit event handler
- Migrate state transitions to use absolute references (#chat.guestSession, #chat.userSession, #chat.idle)
- Adjust legal text wording for Cozsweet privacy agreement
Next.js Image scans only inline style for 'auto' to determine whether
sizing is fully delegated to CSS. The .logo class already sets
height: var(--auth-logo-height) and width: auto, but the inline auto
hint is required to suppress the width/height-modified warning.
Applies to both auth-facebook-panel and auth-email-panel where the same
login logo is rendered.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Update auth-legal-text copy to "I agree to the Cozsweet Privacy
Agreement and Terms of User", keeping the two external links.
- Center the Facebook icon and "Login with Facebook" label as a group
inside the main Facebook button (change .facebookLabel flex).
- Apply the same centering to the shared AuthSocialButton .label rule
so the Email and Facebook entries in the "Other Sign-in Options"
bottom sheet also render icon+text centered.
Co-Authored-By: Claude <noreply@anthropic.com>
- chat-screen no longer manages WebSocket directly; it now dispatches three
auth lifecycle events (ChatGuestLogin, ChatNonGuestLogin, ChatLogout)
derived from auth.loginStatus
- chat-machine internally owns the WebSocket long-lived actor via
fromCallback, completing the previously deferred migration scope
- removed ChatWebSocket import, getWsToken helper, and direct WS
effect from chat-screen; renamed dispatchInitialLoad to
dispatchAuthLifecycle to reflect the new responsibility
- decouples auth from chat machine via event-driven boundary: machine
stays unaware of loginStatus, guest semantics live at the dispatch
layer (guest → skip WS, non-guest → connect with token)
The screen-lifecycle events were dead code: the transitions in chat-machine
(idle <-> ready) had no caller behavior tied to them, and the dispatches
in chat-screen.tsx were the only senders. Drop the union members, both
state transitions, and the mount-effect dispatches.
The idle state remains declared as initial but is no longer reachable
at runtime; can be refactored in a follow-up.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Remove ChatAuthStatusChanged dispatch from auth login flow; chat screen now subscribes directly to auth state machine (loginStatus) to derive isGuest and drive WS lifecycle
- Gate quota-exceeded and warning dialogs to guests only (non-guests have no message limit)
- Dispatch ChatLoadMoreHistory for non-guest initial load vs ChatInit for guests
- Fix AppConstants import path from @/core/constants/app_constants to @/core/app_constants
- Add defensive isGuest checks in quota effects to prevent non-guest quota triggers
TextBubble now fills the available half-row width instead of being
capped at 75%. Add 16px margin on the avatar-side edge (margin-left
for AI, margin-right for user) so short messages still feel airy
and long messages are no longer artificially clipped.
Co-Authored-By: Claude <noreply@anthropic.com>
- Splash Skip button now dispatches `AuthGuestLoginSubmitted` instead of
direct routing, keeping guest auth under the state machine
- Update PWA install dialog copy ("Add to Home Screen") and drop favicon
entry from manifest icons
- Add debug logging and routing sequence docs to splash-button
Add align-self: flex-end to .bubbleRowUser so the user message row
sizes to its content and pins to the right edge of the chat area.
Combined with the existing flex-end cross-axis alignment, this places
the user avatar at the right edge with the bubble to its left,
producing a proper left-to-right AI / right-to-left user mirror.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Match the Dart lib/ui/sidebar/sidebar_screen.dart + profile_view.dart
exactly:
- White inner shell with 24px padding
- Back button row (arrow icon + "Back" text, no "Profile" header)
- Single "Other" section with one "Log out" row
- Drop profile card, Account/Data/Session sections, and Sign-in CTA
Match Flutter row visuals in the shared SettingsSection:
- Gray (#f5f5f5) rounded row pill on a white card
- 20px chevron, 1px rgba(61,49,74,0.5) divider
- Destructive color #ff6b6b, 14px/600 black section title
Add tokens: --color-settings-card-background, --color-settings-row-background,
--color-settings-divider, --color-chevron-icon, --color-destructive.
Wire the BlocConsumer listener equivalent: on currentUser transitioning to
null, dispatch ChatAuthStatusChanged + AuthReset and router.replace("/chat").
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Change flex-direction from column to row on .bubbleRowAi and
.bubbleRowUser so the avatar and message content render side-by-side
as the JSX and JSDoc already intend.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Update the PWA install dialog styling and content to align with the
original Dart design, including a white background with large 40px
radius, 86x86 PNG icon, gradient primary button, and dynamic app title
sourced from AppConstants.
Move new AuthPlatform(provider).signIn() out of UI components and into
the auth state machine. UI now dispatches AuthGoogle/FacebookLoginSubmitted
events; a new oauthSignIn actor inside the machine calls next-auth/react's
signIn(provider). Errors and the OAuth redirect window are exposed via
the existing state.isLoading / state.errorMessage surface, removing the
local busy / error state in auth-facebook-panel.
Co-Authored-By: Claude <noreply@anthropic.com>
- Move state management from `src/contexts` to `src/stores` (zustand-based)
- Update barrelsby config to include new stores directory
- Add bottom-sheet and auth-background components
- Auto-open browser on dev server ready in VS Code launch config
- Refresh generated barrel index files
Replace the separate FacebookLogin and GoogleLogin classes with a single
AuthPlatform class that takes a provider name ("facebook" | "google") as a
constructor argument. This consolidates duplicate OAuth sign-in logic behind
one entry point while preserving the existing NextAuth flow.
- Add new src/lib/auth/auth_platform.ts exporting AuthPlatform and
AuthProvider type
- Update auth-facebook-panel.tsx and splash-button.tsx to use the new API
- Rename initialContext → initialState in the auth machine for consistency
- Update inline docs and comments to reference AuthPlatform
No behavioral change for end users; both providers still route through
NextAuth's signIn() with the same callbacks and cookies.
- Remove unused CharacterIntro export from chat components index
- Drop stale JSDoc block from splash-screen server component
- Set mobile shell background to explicit black so the desktop area outside the 500px viewport is black instead of inheriting from parent
Extract background image into a reusable AuthBackground component and restructure AuthScreen to use MobileShell as the top-level wrapper, mirroring the SplashScreen implementation.
Update chat-header and chat-input-text-field CSS to match the
Dart counterparts (chat_header.dart, chat_input_text_field.dart):
- Header: remove outer padding/background, use transparent base
- Guest banner: switch to --spacing-sm/md tokens
- Header row: add margin-left and symmetric padding
- Menu button: use 32px radius and #0d0b14 @ 0.7 background
- Input field: add white background, 32px radius, accent caret
color, and flex centering for vertical text alignment
- Drop AuthGate/AuthGateState re-exports from @/lib/auth/nextauth
- Simplify SplashButton by removing skipHref prop and hardcoding ROUTES.chat
- Update comments to reference useSession() (next-auth/react) directly instead of the AuthGate wrapper, since the auth UI gate no longer needs the extra abstraction layer.
Migrate from function-based social login helpers (`facebookLogin`, `googleLogin`)
to class-based services (`new FacebookLogin().signIn()`, `new GoogleLogin().signIn()`),
updating call sites in `AuthFacebookPanel` and `SplashButton` with try/catch error
handling. The NextAuth route handler is also refactored to the v4 pattern, importing
pre-built `GET` / `POST` exports from `@/lib/auth/nextauth` instead of constructing
the handler inline with `NextAuth(authOptions)`.
Configure Progressive Web App capabilities for production builds, enabling offline support and installability. PWA is disabled in dev to avoid HMR conflicts, and switches the build to webpack since PWA tooling requires it.