Account & Billing
Routes
Section titled “Routes”| Route | Purpose |
|---|---|
/account | Account settings |
/billing | Billing management (placeholder) |
/upgrade | Plan selection and purchase |
Account Settings (/account)
Section titled “Account Settings (/account)”Personal Information
Section titled “Personal Information”| Field | Type | Required | Notes |
|---|---|---|---|
| Display Name | text | Yes | |
| Username | text | Yes | Rate-limited: 3 changes per 30 days |
| Language | dropdown | Yes | 100+ languages |
| Timezone | dropdown | Yes | 150+ timezones |
| Country | dropdown | Yes | 249+ countries |
Username Rate Limiting:
- Limit: 3 changes per 30-day rolling window
- Tracking:
lastUsernameChangeDate(Timestamp) +usernameChangeCount(number) - Reset: After 30 days pass since last change
- Uniqueness checked against Firestore before update
- Confirmation dialog shows remaining changes
Password Change
Section titled “Password Change”| Field | Required |
|---|---|
| Current Password | Yes |
| New Password | Yes |
| Confirm Password | Yes (must match) |
Strength Indicator (5 bars, 0-100 score):
| Criteria | Points |
|---|---|
| Length >= 8 chars | +20 |
| Lowercase letters | +20 |
| Uppercase letters | +20 |
| Numbers | +20 |
| Special chars (`!@#$%^&*(),.?”:{} | <>`) |
| Score | Level | Bars |
|---|---|---|
| 0-20 | Weak | 1 (red) |
| 21-40 | Weak | 2 (red) |
| 41-60 | Medium | 3 (yellow) |
| 61-80 | Medium | 4 (yellow) |
| 81-100 | Strong | 5 (green) |
Auto-logout: 5 seconds after successful password change, redirect to /sign-in.
Email Change
Section titled “Email Change”- Requires valid email format (
/^[^\s@]+@[^\s@]+\.[^\s@]+$/) - Cannot be same as current email
- Not available for Google/OAuth accounts
- Auto-logout: 4.5 seconds after change
Sessions
Section titled “Sessions”Data tracked per session:
- Status: online / away / offline
- Browser name and OS
- Timezone
- Last seen timestamp
Source: Firebase Realtime Database at presence/{userId}/sessions
Actions:
- View session details in dialog
- Revoke All Sessions: Calls
revokeAllUserSessionsCallable, signs out user, redirects to/sign-in
Work Hours
Section titled “Work Hours”Default schedule: Monday-Friday, 9:00 AM - 4:00 PM
Custom schedule:
- Set per day (Mon-Sun)
- Multiple time slots per day
- Format:
{ start: "HH:MM", end: "HH:MM" } - “Unavailable” = 0 slots for that day
Account Deletion
Section titled “Account Deletion”- Click “Delete my account” (red button in Danger Zone)
- Confirmation dialog appears
- Non-OAuth: Enter password (required)
- OAuth: Session check, may need re-authentication
- Calls
firekitAuth.deleteAccount(password?) - Permanent and irreversible
- Redirect to
/sign-in
Current Subscription Display
Section titled “Current Subscription Display”Paid plan shows: Plan name, storage limit, monthly price, billing period start/end, status badge, Stripe Portal link.
Free plan shows: “Free Plan”, 100 MB storage, $0, “active” status, upgrade link.
Stripe Portal: Via ext-firestore-stripe-payments-createPortalLink Cloud Function.
Upgrade Page (/upgrade)
Section titled “Upgrade Page (/upgrade)”Pricing Plans
Section titled “Pricing Plans”| Feature | Free | Standard | Elite |
|---|---|---|---|
| Monthly | $0 | $32.99 | $97.99 |
| Annual | $0 | $359.99 | $1,019.99 |
| Storage | 10GB | 100GB | 500GB |
| Hubs | Unlimited | Unlimited | Unlimited |
| Templates | Basic | Advanced | All |
| Theming | No | Yes | Yes |
| Custom Domain | No | No | Yes |
| Kickbacks | 5% | 10% | 20% |
| Commission | 12% | 6% | 3% |
| Support | Basic | Basic + Discord | Premium + Elite Discord |
| Beta Access | No | No | Yes |
Monthly/Annual Toggle
Section titled “Monthly/Annual Toggle”- Annual shows savings badge: “Save $XX”
- Annual price shown as monthly equivalent (annual / 12)
Purchase Flow
Section titled “Purchase Flow”- Select plan and billing period
- Click “Purchase [Plan]”
CheckoutService.createCheckoutSessionCustom()called with:mode: 'subscription'success_url: /checkout-successcancel_url: /checkout-cancel- Metadata: priceId, price, planId, planName, planStorage, planKickback, planDiscount
- Watches for Stripe checkout URL
- Redirects to Stripe Checkout
- Returns to success/cancel URL
Feature Comparison Table
Section titled “Feature Comparison Table”Organized by: Storage & Hubs, Templates & Customization, Revenue & Commissions, Support & Access.
Billing Page (/billing)
Section titled “Billing Page (/billing)”Status: Placeholder only (“Billing management will go here”).
Billing Components (Built but not wired to page)
Section titled “Billing Components (Built but not wired to page)”| Component | Features |
|---|---|
| Current Plan | Plan name, status, renewal date, price, manage seats, cancel/upgrade |
| Payment Methods | Top 2 cards shown, manage all cards dialog, add new card form |
| Billing History | Invoice table (number, date, amount, tax, plan, status), download/view |
| Gift Dialog | Send plan to recipient via email, monthly/yearly, 20% extra on yearly |
Card Form Fields
Section titled “Card Form Fields”Cardholder name, card number (disabled for edit), expiry month/year, CVV, billing address (country, street, apt, city, state, ZIP).
Notifications
Section titled “Notifications”Page: /notifications - Placeholder only.
Notification Toggle (Bell Icon)
Section titled “Notification Toggle (Bell Icon)”- Purple badge with unread count
- Dropdown with notification list (max 350px height)
- Per notification: avatar, title (truncated), description (2-line), timestamp, type badge
Type badges:
updates→ purpleassignee→ bluestatus→ green
Actions:
- Click notification: marks as read + navigates to link
- “Mark all as read”: batch update removing user from
unreadByarrays
Notification source: notificationManager.unreadNotifications (max 60, ordered by createdAt desc).