Tech Stack
Briefcase is built with a modern, type-safe stack optimized for cross-platform mobile development and real-time data handling.
Languages
- TypeScript (Frontend & Backend)
- SQL (via Drizzle ORM)
- HTML/CSS (Landing Pages)
Frontend
- React Native
- Expo SDK 54
- React Navigation v7
- TanStack React Query
- React Native Reanimated
Backend
- Node.js
- Express.js v5
- Drizzle ORM
- PostgreSQL (Neon)
Cloud Services
- Replit (Hosting & Deployment)
- RevenueCat (Subscriptions)
- Google Gemini (AI)
Architecture
The application follows a clean client-server architecture with shared type definitions for end-to-end type safety.
Directory Structure
// Project Layout briefcase/ ├── client/ # React Native app │ ├── components/ # Reusable UI components │ ├── screens/ # Screen components │ ├── contexts/ # React contexts (Auth, Theme, Subscription) │ ├── hooks/ # Custom hooks │ └── navigation/ # React Navigation setup ├── server/ # Express.js backend │ ├── routes.ts # API endpoints │ ├── storage.ts # Database operations │ └── templates/ # HTML templates ├── shared/ # Shared types & schemas │ └── schema.ts # Drizzle schema + Zod types └── migrations/ # Database migrations
Data Flow
Authentication Flow
User submits email/password, server creates account with bcrypt-hashed password
24-hour token sent via email, user clicks link to verify
Login generates session token stored in PostgreSQL
Session token sent in headers, validated on each request
Portfolio Data Flow
User searches asset via Finnhub/CoinGecko autocomplete
Current price automatically fetched from market data APIs
Holding saved to PostgreSQL with user association
Dashboard refreshes prices on focus via TanStack Query
External APIs
| Service | Purpose | Rate Limit |
|---|---|---|
| Google Gemini | AI chatbot, portfolio insights, recommendations | 15 RPM (free tier) |
| Finnhub | Stock/ETF prices, search autocomplete | 60 calls/min |
| CoinGecko | Cryptocurrency prices, market data | No key required |
| Alpha Vantage | Backup stock data source | 5 calls/min |
All API integrations are designed to fail gracefully. If Gemini is unavailable, AI features show helpful fallback messages. Price APIs have built-in caching to reduce API calls and improve performance.
RevenueCat Implementation
Briefcase uses RevenueCat for subscription management, providing a unified API across iOS and Android for handling in-app purchases.
Configuration
| Parameter | Value |
|---|---|
| Product ID | monthly_499 |
| Entitlement ID | Briefcase Pro |
| Price | $4.99/month |
| Free Trial | 3 days |
Implementation Flow
RevenueCat configured on app launch with public API key
SubscriptionContext checks for "Briefcase Pro" entitlement
Non-premium users see upgrade prompts for AI features
Native iOS purchase sheet with 3-day trial offer
RevenueCat automatically grants access upon successful purchase
Premium-Gated Features
AI Features
- AI Chat Modal
- Portfolio Recommendations
- AI-Powered Insights
- Smart Alerts
Free Features
- Portfolio Tracking
- Real-time Prices
- Basic Analytics
- Holdings Management
Code Example
// SubscriptionContext.tsx const ENTITLEMENT_ID = "Briefcase Pro"; const checkSubscriptionStatus = async () => { try { const customerInfo = await Purchases.getCustomerInfo(); const isPremium = customerInfo.entitlements.active[ENTITLEMENT_ID] !== undefined; setIsPremium(isPremium); } catch (error) { console.error("Failed to check subscription", error); } }; // Usage in components const { isPremium } = useSubscription(); {isPremium ? ( <AIChatInterface /> ) : ( <UpgradeCard onPress={() => navigation.navigate("Paywall")} /> )}
Security
Authentication
- bcrypt password hashing
- Secure session tokens
- Email verification
- 24-hour token expiry
Data Protection
- Environment secrets for API keys
- PostgreSQL with encrypted connections
- HTTPS-only communication
- User data isolation
All sensitive API keys (Gemini, Finnhub, Session Secret) are stored as encrypted environment variables in Replit's secrets manager. The RevenueCat public API key is safely embedded in the app as it's designed to be client-facing.