π asarOS β Build Dashboard
Complete status tracker: Web App β Mobile App β Monetized SaaS
β
Tasks Done
calculatingβ¦
β
To Do
remaining items
β
Total Tasks
across all phases
4
Active Phase
Mobile Build
π€
Are We Ready for Mobile?
Not quite yet. Here's what must happen first before starting Capacitor:
β
Feature flags bug fixed (Feature Flags page renders inside AppShell)
The admin feature-flags page currently imports AppShell and renders the main app inside admin. Fixed in today's delivery.
β
Google Drive persistence fixed across logout/login
Drive tokens must survive logout. Fixed: authStore.logout() no longer clears Drive tokens. Only deleteAccount wipes them.
β
PRO feature gating applied to mini-apps (ProGate component)
ProGate.tsx exists. Still need to wrap 15+ page.tsx files with it. See PRO Feature Gates section.
β
Feature flag bulk-update admin endpoint wired in worker
The /api/admin/flags/bulk PUT endpoint exists in featureFlags.ts but needs to be added to admin.ts routes.
β
Razorpay live keys set in production worker
Currently using test keys. Must switch to live keys before publishing.
π Database & Migrations
Cloudflare D1 (SQLite) β asaros-db
π
Migrations
β
0001_init.sql β users, oauth_accounts tables
β
0002_auth_payments.sql β password_hash, refresh_tokens, subscriptions
β
0003_password_reset.sql β password_reset_tokens
β
0004_admin.sql β admin_logs, payment_events, is_banned column
β
0005_feature_flags.sql β feature_flags table
π Auth System (Worker)
Routes & Middleware
β
Google OAuth β /api/auth/google + /callback
β
Email/password β /api/auth/register + /login
β
JWT refresh β /api/auth/refresh
β
Logout β /api/auth/logout (revokes refresh token)
β
Forgot/reset password β /api/auth/forgot-password + /reset-password
β
Delete account β DELETE /api/auth/account (App Store required)
β
requireAuth middleware (JWT verification)
β
Ban check middleware (blocks banned users at every API call)
β
Forgot password email sending (currently returns token in dev mode only)
Wire up Resend / SendGrid to send the actual reset email. Currently dev mode only returns debug_token.
// In emailAuth.ts POST /forgot-password:
// await sendEmail({ to: emailLower,
// subject: 'Reset your asarOS password',
// html: resetLink })
π³ Payments (Razorpay)
Payment Routes
β
POST /api/payments/order β create Razorpay order
β
POST /api/payments/verify β verify signature + activate plan
β
GET /api/payments/status β check current plan
β
POST /api/payments/admin/override β manual plan grant/revoke
β
payment_events table logging (revenue tracking)
β
Switch from Razorpay test keys to LIVE keys
Currently using test keys in .dev.vars. Deploy live keys via wrangler secrets.
cd asaros-worker
npx wrangler secret put RAZORPAY_KEY_ID # rzp_live_xxx
npx wrangler secret put RAZORPAY_KEY_SECRET # live secret
β
USD pricing support for international users
Add USD plan options to PLANS config in payments.ts and upgrade page.
β
Razorpay webhook endpoint for subscription renewal/failure
POST /api/payments/webhook β handles subscription.charged, payment.failed events from Razorpay servers.
β
Post-payment welcome email
Send confirmation/receipt after successful payment. Wire up email provider (Resend recommended).
βοΈ Admin API
Admin Routes (X-Admin-Key protected)
β
GET /api/admin/stats β KPI dashboard
β
GET/PUT /api/admin/users β user list, plan change, ban
β
GET /api/admin/subscriptions + revenue + logs
β
GET /api/flags β public feature flags endpoint
β
PUT /api/admin/flags/bulk β bulk feature flag update
The route is defined in featureFlags.ts but needs to be mounted in admin.ts or index.ts.
// In asaros-worker/src/routes/admin.ts, add:
admin.put('/flags/:id', async (c) => { ... });
admin.put('/flags/bulk', async (c) => { ... });
// Already defined in featureFlags.ts β copy or import.
π Auth UI (Frontend)
Auth Components & Flow
β
AuthModal.tsx β sign in / register / forgot password
β
AccountDropdown.tsx β topbar dropdown for signed-in users
β
app/auth/callback β Google OAuth callback handler
β
app/auth/reset β password reset page
β
authStore.ts β login/register/logout/deleteAccount + JWT refresh
β
App opens without login (local mode default β no friction)
β
Logout clears auth session only (Drive tokens persist)
β
Delete account wipes everything (App Store requirement)
β
Microsoft login (placeholder β real implementation)
Currently shows "Coming Soon" in AuthModal. Wire up Microsoft OAuth when ready.
π Trial System
7-Day Trial + Plan Logic
β
trialStore.ts β firstSeenAt, isTrialActive(), daysRemaining()
β
TrialBanner.tsx β shows countdown in last 2 days + after expiry
β
Topbar plan badge β shows "Trial Β· Xd" or "Free" pill
β
featureFlagStore.canAccess() respects trial/free/pro hierarchy
β
Phase 2: Backend device fingerprint tracking (anti-abuse)
Currently trial is purely client-side (localStorage). Phase 2 will add device fingerprint + backend tracking to prevent resetting trial by clearing localStorage.
β‘ Upgrade & Payments (Frontend)
Upgrade Flow
β
app/system/upgrade/page.tsx β plan cards + Razorpay checkout
β
Shows auth modal if not signed in before payment
β
Pro plan badge shown in topbar + AccountDropdown after payment
β
Single payment page β used by all CTAs (sidebar, banner, ProGate)
β
USD pricing option for international users
Add currency toggle (INR / USD) to upgrade page. Backend already supports different amounts.
π¦ Admin Dashboard
Admin UI Pages (at /admin)
β
Admin login gate (ADMIN_KEY entered in browser, validated against /api/admin/stats)
β
/admin β KPI dashboard (users, revenue, conversion)
β
/admin/users β user search, plan change, ban, delete
β
/admin/subscriptions, /revenue, /logs, /settings pages
β
/admin/feature-flags β FIXED (was rendering inside AppShell)
Fixed in today's delivery. The page was importing AppShell from the main app causing the whole app to render inside admin. Now uses only admin-style components.
β
Wire /api/admin/flags/bulk PUT endpoint in worker
Feature flags save button calls this endpoint but it's not yet mounted in the worker routes.
// In asaros-worker/src/routes/admin.ts:
// Add these routes (from featureFlags.ts):
admin.put('/flags/bulk', async (c) => {
// ... update multiple flags
});
admin.put('/flags/:id', async (c) => {
// ... update single flag
});
βοΈ Google Drive & Cloud Sync
Drive Token Persistence
β
useDriveToken.ts β URL param stashing, token apply, restore from localStorage
β
Drive token survives logout β only clears on manual disconnect or account delete
β
resetDriveTokenBridge() resets memory state only (not localStorage)
β
disconnectDriveForUser() β manual disconnect, clears localStorage + mode
β
backup/page.tsx uses authStore userId (not old userStore)
β
Google Drive access_token refresh (token expires in ~1 hour)
Current tokens are short-lived. Need to store refresh_token and auto-refresh when access_token expires. The callback route already returns refresh_token β needs to be stored and used.
β
Dropbox + OneDrive token persistence (same pattern as GDrive)
π PRO Feature Gates
Apply ProGate component to each page β 2 lines per file
How to gate any page (2 lines)
// 1. Add import at top of page.tsx:
import ProGate from '@/components/layout/ProGate';
// 2. Wrap the return in AppShell:
export default function FinancePage() {
return (
<ProGate feature="Finance Tracker" flagId="app_finance">
<AppShell> ... </AppShell>
</ProGate>
);
}
Free β always accessible
β
Dashboard β no gate needed
β
Pomodoro Timer β no gate needed
Trial β available during 7-day trial + Pro
β
Habit Tracker β flagId: app_habits
β
Mood Journal β flagId: app_journal
β
My Diary β flagId: app_diary
β
Smart Notes β flagId: app_notes
β
Personal Growth β flagId: app_growth
β
Daily Standup β flagId: app_standup
β
Study & Learning β flagId: app_study
β
Search β flagId: app_search
β
Time Budget β flagId: app_time_budget
β
Archive β flagId: app_archive
Pro β Pro subscribers only
β
Finance Tracker β flagId: app_finance
β
Password Manager β flagId: app_passwords
β
Health Monitor β flagId: app_health
β
Life Goals β flagId: app_life_goals
β
Work Goals β flagId: app_work_goals
β
Life Kanban β flagId: app_life_kanban
β
Work Kanban β flagId: app_work_kanban
β
Project Manager β flagId: app_projects
β
Book Reader β flagId: app_book_reader
β
Career Plan β flagId: app_career
β
Relationships / Contacts β flagId: app_contacts
π± Mobile UI & Polish
Mobile Optimizations
β
App Drawer β mobile sidebar as full-width drawer with dark header
β
Font size Aβ/A+ controls in drawer header
β
Bottom nav β 5 tabs: Menu, Home, Notes, Search, Vault
β
44px touch targets, 16px inputs (no iOS zoom)
β
Safe area insets (iPhone notch / Dynamic Island)
β
Swipe to open drawer (left edge only, ignores vertical scroll)
β
Themes & Fonts page (theme, font size, font family, density)
β
Anti-flash script for theme (no white flash on dark theme)
β
InstallPrompt floating bubble removed (topbar button handles it)
β
Test all pages on real Android device (Chrome DevTools mobile view β real device)
π¦ Capacitor Setup
Install & Configure Capacitor
β
capacitor.config.ts created (appId: com.asaros.app)
β
next.config.ts: static export mode for BUILD_TARGET=capacitor
β
Package.json scripts: build:cap, cap:sync, cap:android, cap:ios
β
Install Capacitor packages
cd asaros-app
npm install @capacitor/core @capacitor/cli @capacitor/android @capacitor/ios
npm install @capacitor/status-bar @capacitor/splash-screen @capacitor/haptics @capacitor/keyboard
β
Run setup script
chmod +x scripts/setup-mobile.sh
./scripts/setup-mobile.sh
# This installs Capacitor, builds static export, adds platforms, syncs
β
Add deep link redirect URI for Google OAuth in Capacitor
Google OAuth redirect flow breaks in WebView. Add deep link handler or use custom tab.
// In Google Cloud Console β Credentials β Your OAuth Client:
// Add: asaros://auth/callback
// In capacitor.config.ts add: server: { androidScheme: 'asaros' }
// In AndroidManifest.xml add intent-filter for asaros:// scheme
β
Fix Razorpay payment in WebView (Capacitor)
Razorpay web SDK loads in WebView. Test payment flow in Android emulator and real device before release.
π€ Android Build
Android Studio + Play Store
β
Install Android Studio (if not already installed)
Download from developer.android.com/studio. Install with default SDK settings.
β
Open Android project and run on emulator
npx cap open android
# Android Studio opens
# Run β Run 'app' on Emulator (create Pixel 7 API 34 emulator if needed)
β
Generate release keystore (one-time, keep forever)
cd android
keytool -genkeypair -v -keystore release.keystore \
-alias asaros -keyalg RSA -keysize 2048 -validity 10000
# BACK UP release.keystore + passwords securely
β
Build signed AAB for Play Store
./scripts/build-android-release.sh
# Output: android/app/build/outputs/bundle/release/app-release.aab
β
Create app in Google Play Console
play.google.com/console β Create app β Fill details β Internal testing β Upload AAB
β
Play Store assets
Required: 512Γ512 icon PNG, 1024Γ500 feature graphic, 2+ screenshots (1080Γ1920), privacy policy URL, content rating questionnaire, short/full description.
π iOS Build
Xcode + App Store Connect
β
Mac with Xcode 15+ (required β no workaround)
β
Apple Developer Program ($99/year)
β
Open iOS project in Xcode and configure signing
npx cap open ios
# Xcode β Select project β Signing & Capabilities
# Set Team: your Apple Developer account
# Bundle ID: com.asaros.app
β
App Store Connect β create new app record
appstoreconnect.apple.com β My Apps β + New App β iOS β Bundle ID: com.asaros.app
β
iOS App Store assets
Required: 1024Γ1024 icon (no transparency), 6.7" screenshots (1290Γ2796) β MANDATORY, 5.5" optional, description, keywords (100 chars), support URL, privacy policy URL.
β
iOS IAP decision β web-only payments or Apple IAP
Apple takes 15β30% of in-app purchases. Recommended for MVP: web-only payments. Show "Subscribe at asaros.app" β legal per App Store guidelines (Section 3.1.3a).
β
Archive & upload to App Store Connect via Xcode
// Xcode: Product β Archive β Distribute App
// β App Store Connect β Upload β Submit for Review
π Environment & Secrets
Worker Secrets (via wrangler secret put)
β
GOOGLE_CLIENT_ID + GOOGLE_CLIENT_SECRET β Google OAuth
β
JWT_SECRET β token signing (64-char hex)
β
ADMIN_SECRET β admin dashboard key
β
RAZORPAY_KEY_ID + RAZORPAY_KEY_SECRET β LIVE keys
Currently test keys. Must switch to live keys (rzp_live_xxx) before launch.
npx wrangler secret put RAZORPAY_KEY_ID
npx wrangler secret put RAZORPAY_KEY_SECRET
β
GOOGLE_DRIVE_CLIENT_ID + GOOGLE_DRIVE_CLIENT_SECRET + REDIRECT_URI β Drive OAuth
β
App env: NEXT_PUBLIC_WORKER_URL set correctly in Pages
Verify in Cloudflare Pages dashboard β Settings β Environment variables.
π Domain Migration
aos.documateo.com β asaros.app
β
Register asaros.app domain
β
Update wrangler.toml routes to asaros.app
routes = [
{ pattern = "asaros.app/api/*", zone_name = "asaros.app" }
]
β
Update ALLOWED_ORIGINS in wrangler.toml
β
Update Google OAuth authorized redirect URIs
In Google Cloud Console β Credentials β Your OAuth Client β Add: https://asaros.app/api/auth/google/callback
β
Update NEXT_PUBLIC_WORKER_URL in Cloudflare Pages to https://asaros.app
β
Privacy policy & Terms of Service pages at asaros.app/privacy and /terms
Required for App Store and Play Store review. Simple HTML pages are sufficient.
π§ͺ Testing Checklist
Manual Test β Auth Flows
β
Register new email account β verify JWT returned β verify logged in
β
Login with email β logout β login again β app opens correctly
β
Connect Google Drive β logout β login β verify Drive still connected
β
Forgot password flow β receive reset email β reset β login with new pw
β
Delete account β verify all data wiped β verify can re-register
Manual Test β Payments
β
Complete test payment β verify Pro badge appears in topbar
β
Verify payment logged in payment_events table
β
Admin override (grant Pro manually) β verify plan updates
Manual Test β Feature Gates
β
Free user sees upgrade prompt on Pro-gated page
β
Trial user (day 1) can access trial-gated features
β
Admin feature flag toggle takes effect after page refresh