πŸ“Š CE Tracking SaaS

Comprehensive overnight research brief β€” competitors, product, marketing, niches, tech, business model

Generated: 2026-06-11 | Ready to build tomorrow
πŸ”­

Competitor Intelligence

# Competitive Landscape Report: CE Tracking Market
### Based on Available Search Data

---

> ⚠️ Data Limitations Disclosure
> The search results returned substantive data on only one competitor (CE Broker/Propelus). MyCE Planner, ProTracker, CPA tools, and nurse-specific tools returned zero results. This report is transparent about what is known vs. inferred. Recommendations are flagged accordingly.

---

## 1. COMPETITOR MATRIX

### CE Broker (by Propelus)
*The only competitor with extractable data*

| Attribute | Detail |
|---|---|
| Full Name | CE Broker by Propelus |
| Website | cebroker.com |
| Pricing | Multiple account plans (specific dollar amounts not returned in search data). New "Pro+" subscription tier recently launched. Free tier likely exists based on plan structure language. |
| Target Professions | Healthcare-heavy: Nurses (explicitly mentioned), electricians (Michigan Electric referenced), broad health licensing boards across multiple states |
| Geographic Focus | US-based, state-by-state compliance model. Known state partnerships: Florida, South Carolina, DC, Georgia, Michigan |
| Star Rating | 1.8/5 on Trustpilot β€” critically low |
| Regulatory Relationships | Official tracking system for Florida Dept. of Health, SC Dept. of Labor, DC/Georgia Boards of Nursing, Michigan Electrical boards |

#### Key Features (as marketed):
- Find β€” Course discovery within the platform
- Take β€” Course consumption (or redirect to course)
- Track β€” CE hour logging and compliance status dashboard
- Report β€” Direct reporting to licensing boards
- Compliance Status Visibility β€” Shows requirement gaps vs. completed hours
- Board-direct Reporting β€” Automatic submission to participating boards
- Renewal-ready Course Filtering β€” Courses pre-validated for specific board requirements
- Pro+ Subscription β€” Premium tier (launched recently, details sparse)

#### Known Strengths:
- Official/mandated status in multiple states (captive user base)
- Brand recognition as category leader
- Integrated course marketplace
- Multi-profession and multi-state coverage
- Regulatory relationships create high switching costs at institutional level

#### Known Weaknesses / User Complaints:
- 1.8/5 Trustpilot score β€” among the worst possible ratings, indicating systemic user experience failure
- Review language references "complaints" explicitly in search snippet
- Pricing friction noted (review headline asks "when you actually need it" β€” suggests users feel forced/confused about value)
- The fact that an independent "honest review" exists analyzing its complaints signals significant dissatisfaction
- Likely suffers from mandatory-use resentment β€” users who are forced to use it by their state don't choose it, and dissatisfaction follows

---

### All Other Searched Competitors

| Competitor | Search Result | Status |
|---|---|---|
| MyCE Planner | No results | Unknown / low market presence |
| ProTracker | No results | Unknown / low market presence |
| CPA-specific tools | No results | Gap in data |
| Nurse-specific tools | No results | Gap in data |
| "Other tools" category | No results | Gap in data |

---

## 2. MARKET GAPS
*What nobody appears to be doing well*

### Gap #1: User Experience That People Actually Choose
The biggest gap in the market is a CE tracker people WANT to use.
CE Broker's 1.8 Trustpilot score on a platform people are often *required* to use reveals a massive white space: a CE tracking product with genuine UX quality. The bar is shockingly low. Any app that scores a 3.5+ on experience will feel like a revolution.

Actionable implication: Invest disproportionately in onboarding, UI clarity, and mobile experience. Make the first 5 minutes delightful.

---

### Gap #2: Profession-Agnostic Flexibility
CE Broker's search data shows it skews heavily toward healthcare. The zero-result searches for CPA tools and other professions suggest either:
- The market is fragmented with profession-specific tools that lack visibility, OR
- There is genuine underservice of non-healthcare licensed professions

Professions likely underserved: CPAs, attorneys (CLE), real estate agents, financial advisors, teachers, social workers, engineers (PDH credits)

Actionable implication: Build a multi-profession architecture from day one. Don't hard-code healthcare. Let compliance requirements be configurable by profession + state.

---

### Gap #3: Transparent, Confusion-Free Pricing
The search snippet for CE Broker's review explicitly frames pricing as a question ("what it costs") and "when you actually need it" β€” indicating pricing confusion is a real pain point. When state boards mandate a tool, users don't understand what's free vs. paid.

Actionable implication: Radical pricing transparency. One-page pricing, no hidden tiers, clear free vs. paid delineation on the homepage.

---

### Gap #4: Portable Credential Wallet (Not Board-Locked)
CE Broker's value proposition is tied to board reporting relationships. If your board isn't a partner, the value collapses. This creates a platform dependency problem β€” professionals who move states, change professions, or work across multiple licenses are poorly served.

Actionable implication: Build a license-agnostic CE portfolio β€” a personal record that travels with the professional regardless of which boards you report to. Think "LinkedIn for compliance credentials."

---

### Gap #5: Proactive Compliance Intelligence
Nothing in the search data mentions predictive alerts, deadline forecasting, or personalized compliance timelines. Current tools appear reactive (show current status) rather than proactive (warn you 90 days out, tell you exactly what to take).

Actionable implication: Build smart deadline alerts, "you need X hours in Y category by Z date" personalized feeds, and recommended course paths based on remaining requirements.

---

### Gap #6: Employer/Team View
All search data focuses on individual professionals. No mention of employer dashboards, HR integration, or team compliance management β€” despite the fact that hospitals, accounting firms, and law firms have compliance liability for entire staff populations.

Actionable implication: B2B tier with team dashboards, manager views, and bulk compliance reporting could be a significant revenue and retention driver.

---

## 3. PRICING INTELLIGENCE

### What We Know:
| Data Point | Source |
|---|---|
| CE Broker has multiple "Account Plans" | CE Broker account plans page |
| CE Broker recently launched "Pro+" as a new premium tier | Newswire announcement |
| Pricing is confusing enough that independent reviewers explain "what it costs" | Trustpilot/review site |
| Free tier likely exists | Implied by plan structure |

### What We Can Reasonably Infer:
*(Based on SaaS patterns in compliance/professional tools β€” not confirmed by search data)*

- Free tier: Basic tracking, manual entry, limited features
- Individual paid: Estimated $35–$75/year range typical for this category
- Pro/Pro+: Likely $75–$150/year with premium features (board reporting, course access, alerts)
- Institutional/board partnerships: B2B contracts, not consumer-priced

### What the Market Will Bear:
- Individual professionals typically pay $50–$150/year for compliance tools they are motivated (or required) to use
- Mandatory-use tools can charge more but face backlash (see: CE Broker's 1.8 stars)
- Voluntary-use tools must demonstrate clear ROI vs. the cost β€” lower price + better UX is the winning formula against a mandatory competitor

### Pricing Recommendations:
1. Freemium model: Free forever for basic tracking (single profession, single state). This directly undercuts CE Broker's confusion around "do I need to pay?"
2. Pro tier at $4.99–$9.99/month or $49/year: All professions, all states, smart alerts, deadline forecasting
3. Teams tier: Per-seat pricing starting at $8–$15/seat/month for employer accounts
4. Transparent, no-surprise billing: Publish all pricing publicly. No "contact sales for pricing."

---

## 4. POSITIONING OPPORTUNITY

### CE Broker's Positioning:
*"Official. Trusted by regulators. Comprehensive."*
β†’ Translation: Institutional, mandatory, government-adjacent, B2B-first, user experience secondary.

### The Positioning White Space:
CE Broker owns the regulators. You can own the professionals.

#### Recommended Positioning Framework:

> "The CE tracker built for you β€” not your board."

| Dimension | CE Broker | Your App |
|---|---|---|
| Built for | Regulators and boards | Individual professionals |
| Tone | Institutional, compliance-heavy | Empowering, career-focused |
| Experience | Mandatory/transactional | Chosen/delightful |
| Scope | Healthcare + select professions | Any licensed profession |
| Value frame | Compliance avoidance (don't get penalized) | Career advancement (grow your credentials) |
| Data ownership | Board-locked | Professional-portable |
| Pricing clarity | Confusing | Radically transparent |

### Positioning Statement Options:

Option A (Simplicity angle):
*"CE tracking so simple you'll actually stay compliant."*

Option B (Professional ownership angle):
*"Your license, your record, your career. CE tracking that works for you."*

Option C (Anti-institutional angle):
*"Built for professionals, not bureaucrats."*

Option D (Multi-profession angle):
*"One place for every license you'll ever hold."*

---

## 5. FEATURES TO STEAL
*Best ideas worth implementing, improved*

| Feature (from CE Broker) | Why It's Valuable | How to Do It Better |
|---|---|---|
| Requirement mapping by state + profession | Eliminates user research burden | Make it self-updating, crowdsourced + verified. Add a "requirements changed" notification system. |
| Course marketplace integration | One-stop-shop increases stickiness | Don't lock to proprietary courses. Integrate third-party providers. Let users log external courses freely. |
| Board-direct reporting | Removes manual submission step | Pursue board API partnerships, but don't make value *dependent* on them. Offer PDF/CSV export as fallback. |
| Compliance status dashboard | Clear visual of where you stand | Make it mobile-first, widget-capable, at-a-glance. Think Duolingo streak energy applied to compliance. |
| Renewal-ready course filtering | Reduces choice paralysis | Add quality ratings, peer reviews, and price comparison across providers. |
| Multi-plan account structure | Serves different user types | Simplify to 3 tiers max. Name them clearly (Free / Pro / Teams). |

---

## 6. FEATURES TO AVOID
*What competitors do that users demonstrably hate*

### ❌ Mandatory Paywall for Basic Functionality
What CE Broker does: Appears to require payment for features users feel should be basic (based on pricing confusion complaints).
Why users hate it: Licensed professionals already pay for licenses, renewals, and CE courses. Another paywall on *tracking* feels extractive.
Avoid by: Keeping a genuinely useful free tier. Don't bait-and-switch.

---

### ❌ Board-Dependency as Core Value Prop
What CE Broker does: Value is tied to official board relationships β€” if your board isn't a partner, you're a second-class user.
Why users hate it: Professionals in non-partner states or professions get a degraded experience despite paying the same price.
Avoid by: Making the tool fully valuable *without* any board integration. Board reporting is a bonus, not the product.

---

### ❌ Confusing Plan Structure
What CE Broker does: Multiple account plans + new Pro+ tier = pricing confusion significant enough that external reviewers write explainer articles about it.
Why users hate it: Time-pressed professionals don't want to decode pricing. Confusion = distrust.
Avoid by: Maximum 3 tiers. One-sentence description of each. Monthly and annual toggle. No asterisks.

---

### ❌ Institutional UX Applied to Consumer Product
What CE Broker does: Designed to satisfy board and regulator requirements first, professional UX second (inferred from 1.8/5 score).
Why users hate it: Clunky, form-heavy, bureaucratic interfaces in 2024 are unacceptable when users have Duolingo, Notion, and Linear as their UX reference points.
Avoid by: Consumer-grade design. Mobile-first. Minimal required fields. Progressive onboarding.

---

### ❌ Forcing Course Consumption Within Platform
What CE Broker does: Course marketplace integration creates pressure to take courses within their ecosystem.
Why users hate it: Professionals already have preferred providers, employers pre-approve specific courses, and CE content libraries outside CE Broker may be cheaper or better.
Avoid by: Be provider-agnostic by default. Let users log any course from anywhere. Course marketplace = optional add-on revenue, not core architecture.

---

## STRATEGIC SUMMARY: THE ONE-PAGE BRIEF

```
THE OPPORTUNITY:
CE Broker has a monopoly on regulatory relationships
but a 1.8-star user experience. Every other competitor
is invisible in search. The market has a dominant player
that users hate and are sometimes forced to use.

THE MOVE:
Build the CE tracker professionals CHOOSE β€”
not the one their board assigns them.

WIN ON:
βœ“ UX quality (consumer-grade, mobile-first)
βœ“ Multi-profession flexibility (not just healthcare)
βœ“ Radical pricing transparency (freemium done right)
βœ“ Portable credentials (not board-locked)
βœ“ Proactive compliance intelligence (predictive, not reactive)
βœ“ B2B team tier (underserved employer market)

AVOID:
βœ— Paywall confusion
βœ— Board-dependency as core value
βœ— Institutional UX
βœ— Provider lock-in

POSITIONING:
"Built for professionals, not regulators."
```

---

*Note: This report should be supplemented with direct competitor research, user interviews with CE Broker users (especially those who left 1-2 star reviews), and pricing verification through direct product trials before making final product decisions.*
🎨

Product Design & UX

# CE/CPD Tracking Application β€” Comprehensive Product Design Brief

---

## EXECUTIVE SUMMARY

Product Name Suggestion: *Continuum* (tagline: "Your license, protected.")

Core Problem Being Solved: Licensed professionals (CPAs, nurses, engineers, teachers, lawyers, etc.) face license revocation risk from poor CE/CPD tracking. Current solutions are either employer-mandated clunky portals, messy spreadsheets, or expensive enterprise tools. There is no clean, affordable, consumer-grade app designed around the individual professional's anxiety about compliance.

Core Emotion to Design For: Relief. The user should feel *safe* every time they open the app.

---

## 1. MVP FEATURE LIST (Weeks 1–6)

Philosophy: Build the smallest thing that eliminates the core fear β€” "Am I going to lose my license?"

### 1.1 Authentication & Account
- Email/password signup with email verification
- Google OAuth (single priority social login β€” reduces friction by ~40% based on general SaaS patterns)
- Password reset flow
- Account deletion (GDPR/trust signal)
- No social login with Facebook/Twitter β€” unnecessary complexity

### 1.2 Professional Profile Setup
Single-screen setup collecting:
- License type (dropdown: CPA, RN, LPN, PE, Attorney, Teacher, Social Worker, Other)
- License number (optional, stored for user reference only)
- Licensing state/jurisdiction (US state dropdown + "Non-US")
- Renewal period end date (the most critical field in the entire app)
- Total CE hours required for current period (pre-filled suggestions per license type, editable)
- Subcategory requirements if any (e.g., "4 hours Ethics required" β€” free-text entry in MVP, structured in Phase 2)

### 1.3 CE Activity Logging
The core action of the entire product. Must be frictionless.

Fields per activity:
- Activity title (text, required)
- Provider/sponsor (text, optional)
- Date completed (date picker, defaults to today)
- Credit hours earned (decimal number, e.g., 1.5)
- Credit category (dropdown populated from their license type defaults + "Other")
- Format (dropdown: In-person, Webinar, Online self-study, College course, Conference, Reading/Publication, Other)
- Certificate uploaded? (yes/no toggle in MVP β€” actual file upload in Phase 2)
- Notes (text area, optional)

Entry methods:
- Manual form (required for MVP)
- CSV import (required for MVP β€” this is the killer migration tool)

### 1.4 Dashboard (The "Home Screen")
See Section 5 for full UI description. MVP dashboard shows:
- Days until license renewal deadline (giant, prominent number)
- Hours completed vs. hours required (progress ring)
- Subcategory progress (simple list, not chart)
- Last 5 activities logged
- Quick-add button (always visible)

### 1.5 Reports
- Single exportable PDF report of all activities in current period
- Fields: date, activity name, provider, hours, category, format
- User's name and license number on header
- "Suitable for audit" language in footer
- Generate with one click, download immediately

### 1.6 Basic Email Notifications
- 90-day warning before renewal deadline
- 60-day warning
- 30-day warning
- 7-day warning
- Weekly digest (every Monday): "You've logged X hours. Y hours to go."
- All notifications include one-click link to log an activity

### 1.7 Billing & Subscription
- Stripe Checkout for subscription ($7.99/month or $69.99/year β€” offer both)
- 14-day free trial, no credit card required
- Stripe Customer Portal for self-serve cancellation, payment update
- Graceful degradation on cancellation: read-only access to data for 30 days, then data export offered before deletion

### 1.8 Data Export
- Export all activities as CSV
- Export current period as PDF
- Available even after cancellation (for 30 days)
- This is a trust feature. Users won't subscribe if they fear lock-in.

---

What is explicitly NOT in MVP:
- Mobile app (PWA only)
- Document storage/certificate uploads
- Team/employer features
- Integrations with CE providers
- AI features
- Social features
- Multiple license tracking
- Calendar sync

---

## 2. PHASE 2 FEATURES (Months 2–4, After First 50 Users)

Philosophy: Listen to what the 50 users are actually struggling with, then build for the top 3 pain points. The features below are educated predictions β€” validate before building all of them.

### 2.1 Certificate & Document Storage
- Upload PDF/JPG/PNG certificates per activity (S3-compatible storage, 1GB per user)
- Documents tied to activity record
- "Missing certificate" flag on activities
- Bulk certificate export (ZIP download) β€” critical for audit scenarios
- Why Phase 2: Storage infrastructure adds complexity. Validate users will pay before building it.

### 2.2 Structured Subcategory Tracking
Replace the free-text subcategory fields with:
- Pre-built requirement templates per license type per state
- E.g., "California CPA: 80 hours total, 4 Ethics, 24 Technical"
- Visual progress per subcategory requirement
- Alert if a subcategory is at risk of being unfulfilled even if total hours are fine
- This is a major value-add β€” the spreadsheet cannot do this easily

### 2.3 Multiple License/Renewal Period Tracking
- Users can have multiple active licenses (e.g., RN with two state licenses)
- Each license has its own requirements, deadline, category rules
- Dashboard shows summary card per license
- Why Phase 2: You'll hear this from users within the first week

### 2.4 Mobile PWA Optimization
- Fully responsive, install-to-homescreen PWA
- Offline activity entry (sync when connection restored)
- Camera-based certificate capture (take photo of paper certificate)
- Why Phase 2: Get validation on desktop first, then optimize mobile

### 2.5 CE Provider Directory
- Curated list of approved CE providers per license type
- Links to external providers (not a marketplace yet)
- Users can suggest providers
- Business angle: Foundation for future affiliate revenue

### 2.6 Activity Templates
- Save frequently used activity types (e.g., "Monthly hospital in-service, 1 credit, Category: Clinical")
- Quick-log from template in 2 taps
- Why valuable: Nurses doing recurring monthly training will love this

### 2.7 Renewal Period History
- Archive of past renewal periods with all logged activities
- "I survived my last audit because I had this" is a retention story
- Historical PDF reports

---

## 3. PHASE 3 FEATURES (Month 4+, Retention & Growth)

Philosophy: These are the features that make users impossible to churn and willing to pay more.

### 3.1 AI-Powered CE Recommendations
- Based on license type, location, and credit gaps, suggest specific courses
- "You need 3 more Ethics hours by March 15. Here are 4 options under $50."
- Affiliate revenue opportunity (tasteful, opt-in)

### 3.2 Audit Defense Pack
- One-click generation of a complete audit response package
- Organized by requirement category
- Includes activity log + all certificates in one PDF
- Cover letter template
- Pricing: Could be a one-time add-on ($9.99) or premium tier feature

### 3.3 Calendar Integration
- Sync renewal deadline to Google Calendar / Apple Calendar / Outlook
- Upcoming scheduled CE shows in calendar
- ICS file export as MVP of this feature

### 3.4 Team/Group Accounts
- Employer or study group invites team members
- Admin sees aggregate compliance status (not individual details unless permitted)
- Volume pricing: $5/seat/month at 10+ seats
- This is your B2B pivot path β€” don't build prematurely

### 3.5 License Verification Reminders
- Separate from CE: remind user to actually submit renewal paperwork
- Checklist: "Have you paid renewal fee? Updated your address? Submitted CE proof?"
- State-specific renewal portal links

### 3.6 Public Compliance Badge
- Shareable URL showing "Current with CE requirements as of [date]"
- Opt-in only
- Professional use: LinkedIn, email signature
- Trust signal for independent contractors

### 3.7 Stripe Revenue Expansion
- Annual plan upsell (already in MVP but promote heavily in Phase 3)
- Premium tier at $14.99/month (unlimited storage, audit pack, AI features)
- Employer/team billing

---

## 4. DATABASE SCHEMA

Stack assumption: PostgreSQL, Python/FastAPI, SQLAlchemy ORM

```sql
-- ============================================================
-- USERS
-- ============================================================
CREATE TABLE users (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
email VARCHAR(255) UNIQUE NOT NULL,
password_hash VARCHAR(255), -- NULL if OAuth only
full_name VARCHAR(255),
created_at TIMESTAMPTZ DEFAULT NOW(),
updated_at TIMESTAMPTZ DEFAULT NOW(),
email_verified BOOLEAN DEFAULT FALSE,
email_verified_at TIMESTAMPTZ,
is_active BOOLEAN DEFAULT TRUE,
timezone VARCHAR(64) DEFAULT 'America/New_York',
notification_prefs JSONB DEFAULT '{}', -- granular opt-in/out
last_login_at TIMESTAMPTZ,
deleted_at TIMESTAMPTZ -- soft delete
);

-- ============================================================
-- OAUTH PROVIDERS (for Google login)
-- ============================================================
CREATE TABLE oauth_accounts (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
provider VARCHAR(64) NOT NULL, -- 'google'
provider_user_id VARCHAR(255) NOT NULL,
access_token TEXT,
refresh_token TEXT,
token_expires_at TIMESTAMPTZ,
created_at TIMESTAMPTZ DEFAULT NOW(),
UNIQUE(provider, provider_user_id)
);

-- ============================================================
-- SUBSCRIPTIONS (Stripe state mirrored locally)
-- ============================================================
CREATE TABLE subscriptions (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
stripe_customer_id VARCHAR(255) UNIQUE,
stripe_subscription_id VARCHAR(255) UNIQUE,
stripe_price_id VARCHAR(255),
plan_type VARCHAR(32), -- 'monthly', 'annual', 'trial'
status VARCHAR(32), -- 'active','trialing','past_due','canceled','paused'
trial_ends_at TIMESTAMPTZ,
current_period_start TIMESTAMPTZ,
current_period_end TIMESTAMPTZ,
canceled_at TIMESTAMPTZ,
created_at TIMESTAMPTZ DEFAULT NOW(),
updated_at TIMESTAMPTZ DEFAULT NOW()
);

-- ============================================================
-- LICENSE PROFILES
-- (One user may have multiple licenses β€” Phase 2)
-- (MVP: enforce one per user via application logic, schema ready)
-- ============================================================
CREATE TABLE license_profiles (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
license_type VARCHAR(128) NOT NULL, -- 'CPA', 'RN', 'PE', etc.
license_type_code VARCHAR(32), -- normalized code for logic
display_name VARCHAR(255), -- user's custom label
license_number VARCHAR(128), -- stored, never validated externally
jurisdiction VARCHAR(128), -- state/country
is_primary BOOLEAN DEFAULT TRUE,
is_active BOOLEAN DEFAULT TRUE,
created_at TIMESTAMPTZ DEFAULT NOW(),
updated_at TIMESTAMPTZ DEFAULT NOW()
);

-- ============================================================
-- RENEWAL PERIODS
-- Each period has its own requirements and deadline
-- ============================================================
CREATE TABLE renewal_periods (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
license_profile_id UUID NOT NULL REFERENCES license_profiles(id) ON DELETE CASCADE,
period_label VARCHAR(128), -- e.g., "2023-2025 Renewal Cycle"
start_date DATE NOT NULL,
end_date DATE NOT NULL, -- THE critical deadline
total_hours_required DECIMAL(6,2) NOT NULL,
is_current BOOLEAN DEFAULT TRUE,
is_archived BOOLEAN DEFAULT FALSE,
created_at TIMESTAMPTZ DEFAULT NOW(),
updated_at TIMESTAMPTZ DEFAULT NOW()
);

-- ============================================================
-- CE REQUIREMENTS (subcategories within a renewal period)
-- ============================================================
CREATE TABLE ce_requirements (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
renewal_period_id UUID NOT NULL REFERENCES renewal_periods(id) ON DELETE CASCADE,
category_name VARCHAR(128) NOT NULL, -- e.g., "Ethics", "Technical", "Any"
hours_required DECIMAL(6,2) NOT NULL,
hours_can_overlap BOOLEAN DEFAULT FALSE, -- can count toward total?
display_order INT DEFAULT 0,
notes TEXT,
created_at TIMESTAMPTZ DEFAULT NOW()
);

-- ============================================================
-- CE ACTIVITIES (the core data)
-- ============================================================
CREATE TABLE ce_activities (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
renewal_period_id UUID NOT NULL REFERENCES renewal_periods(id) ON DELETE CASCADE,
ce_requirement_id UUID REFERENCES ce_requirements(id) ON DELETE SET NULL,

title VARCHAR(512) NOT NULL,
provider VARCHAR(255),
completed_date DATE NOT NULL,
credit_hours DECIMAL(6,2) NOT NULL CHECK (credit_hours > 0),

-- Category/format
category VARCHAR(128), -- matches ce_requirements.category_name
format VARCHAR(64), -- 'in-person','webinar','self-study','conference','other'

-- Certificate
has_certificate BOOLEAN DEFAULT FALSE,
certificate_url VARCHAR(1024), -- S3 key (Phase 2)
certificate_uploaded_at TIMESTAMPTZ,

-- Metadata
notes TEXT,
source VARCHAR(32) DEFAULT 'manual', -- 'manual', 'csv_import', 'api'
is_deleted BOOLEAN DEFAULT FALSE, -- soft delete
created_at TIMESTAMPTZ DEFAULT NOW(),
updated_at TIMESTAMPTZ DEFAULT NOW()
);

-- ============================================================
-- NOTIFICATION LOG
-- Track what was sent, prevent duplicate sends
-- ============================================================
CREATE TABLE notification_log (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
notification_type VARCHAR(128) NOT NULL, -- 'deadline_90d', 'weekly_digest', etc.
channel VARCHAR(32) DEFAULT 'email',
sent_at TIMESTAMPTZ DEFAULT NOW(),
metadata JSONB DEFAULT '{}', -- e.g., days remaining at time of send
opened_at TIMESTAMPTZ, -- if tracking email opens
clicked_at TIMESTAMPTZ
);

-- ============================================================
-- ACTIVITY TEMPLATES (Phase 2, schema ready now)
-- ============================================================
CREATE TABLE activity_templates (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
template_name VARCHAR(255) NOT NULL,
title VARCHAR(512),
provider VARCHAR(255),
credit_hours DECIMAL(6,2),
category VARCHAR(128),
format VARCHAR(64),
notes TEXT,
use_count INT DEFAULT 0,
created_at TIMESTAMPTZ DEFAULT NOW()
);

-- ============================================================
-- USEFUL INDEXES
-- ============================================================
CREATE INDEX idx_ce_activities_user_id ON ce_activities(user_id);
CREATE INDEX idx_ce_activities_renewal_period ON ce_activities(renewal_period_id);
CREATE INDEX idx_ce_activities_completed_date ON ce_activities(completed_date);
CREATE INDEX idx_ce_activities_deleted ON ce_activities(is_deleted) WHERE is_deleted = FALSE;
CREATE INDEX idx_renewal_periods_current ON renewal_periods(is_current) WHERE is_current = TRUE;
CREATE INDEX idx_notification_log_user_type ON notification_log(user_id, notification_type);
CREATE INDEX idx_subscriptions_status ON subscriptions(status);
```

Key Design Decisions:
- UUIDs everywhere (no sequential IDs exposed in URLs β€” prevents scraping/enumeration)
- Soft deletes on activities (users panic when they delete something accidentally)
- JSONB for notification prefs (avoids premature schema decisions)
- Renewal periods are separate from license profiles (enables historical archiving)
- CE requirements are per-period (requirements change cycle to cycle)

---

## 5. USER INTERFACE

### 5.1 Design System

Visual Language:
- Color palette: Deep navy primary (#1B2A4A), clean white backgrounds, accent in calm green (#2ECC71) for "good standing" states, amber (#F39C12) for warnings, red (#E74C3C) for danger/overdue
- Typography: Inter for UI chrome, system font stack for content β€” do not use custom fonts (performance matters on mobile)
- Tone: Professional without being corporate. Calm. Like TurboTax crossed with a good to-do app.
- Iconography: Lucide icons (React) or Heroicons β€” consistent, clean, free

The Guiding UX Principle: Every screen should answer "Am I okay?" within 3 seconds of loading.

---

### 5.2 Dashboard (Primary Screen)

Layout: Single-column on mobile, two-column on desktop

```
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ CONTINUUM [+ Log Activity] πŸ‘€ β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ β”‚
β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚
β”‚ β”‚ 🟒 YOU'RE ON TRACK β”‚ β”‚
β”‚ β”‚ β”‚ β”‚
β”‚ β”‚ [β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘] 32 / 40 hours β”‚ β”‚
β”‚ β”‚ β”‚ β”‚
β”‚ β”‚ 128 days until renewal Β· March 31, 2025 β”‚ β”‚
β”‚ β”‚ β”‚ β”‚
β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚
β”‚ β”‚
β”‚ REQUIREMENTS BREAKDOWN β”‚
β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚
β”‚ β”‚ Ethics β–ˆβ–ˆβ–ˆβ–ˆβ–‘β–‘ 3 / 4 hrs β”‚ ⚠️ Needs 1 more β”‚
β”‚ β”‚ Technical β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ 8 / 8 hrs β”‚ βœ… Complete β”‚
β”‚ β”‚ General β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ 21/28 β”‚ In progress β”‚
β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚
β”‚ β”‚
β”‚ RECENT ACTIVITY [View All β†’] β”‚
β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚
β”‚ β”‚ Dec 12 Annual Ethics Update 1.0 hr Ethics β”‚ β”‚
β”‚ β”‚ Dec 3 Tax Law Changes Webinar 2.0 hrs Tech β”‚ β”‚
β”‚ β”‚ Nov 28 State Conference 8.0 hrs Gen β”‚ β”‚
β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚
β”‚ β”‚
β”‚ [
πŸ“£

Marketing & Automation Plan

# Complete Marketing Plan: CE/CPD Tracking App
## Launch to 100 Paying Subscribers in 4 Months

---

# EXECUTIVE SUMMARY

The Core Strategy: Start with warm network activation (your accountant and real estate agent friends), layer in community-based marketing on Reddit and LinkedIn, automate ruthlessly, and use referral mechanics to compound growth. Every tactic is chosen because a solo operator can execute it in under 2 hours/day.

Revenue Math:
- 100 paying subscribers Γ— $7.99/month = $799 MRR
- To get 100 paid, need ~300 trial signups (assuming 33% trial-to-paid conversion)
- Timeline: 16 weeks
- Weekly signup target: ~19 trials/week by Week 8

---

# SECTION 1: WEEK 1 LAUNCH PLAYBOOK
## Days 1–7: Exact Step-by-Step Actions

---

### DAY 1 β€” FOUNDATION (3 hours)

Morning (60 min): Set up your tracking infrastructure first

1. Create a free Notion page titled "Launch Tracker" with columns: Channel | Action | Date | Leads Generated | Signups
2. Set up a free Mailchimp account (or Brevo/Sendinblue β€” free up to 300 emails/day) and import your personal contacts
3. Create a Bitly account β€” you'll use shortened tracked links everywhere so you know what's converting
4. Create your referral tracking spreadsheet: Name | Email | Referred By | Date | Status

Afternoon (60 min): Optimize your LinkedIn profile BEFORE posting anything

Your LinkedIn profile is a landing page. Fix it now:

- Headline: Change from whatever it is to: *"Building the simplest CE/CPD tracker for accounting & finance professionals | CGMA, CPA, Nurses, Real Estate"*
- About section: Write this exact copy (customize slightly):

> *"I built [App Name] because I spent years watching professionals scramble to track continuing education hours at renewal time β€” digging through emails, old receipts, and half-finished spreadsheets.*
>
> *There had to be a better way.*
>
> *[App Name] is a dead-simple CPD/CE tracker for CGMA holders, CPAs, nurses, and real estate agents. Log a course in 30 seconds. Get deadline reminders. Never panic at renewal again.*
>
> *Try it free for 30 days β€” no credit card required: [your link]*
>
> *If you're a CGMA holder, CPA, nurse, or real estate agent β€” I'd love your honest feedback. DM me."*

- Add your app's URL to your featured section
- Add "Founder" or "Creator" at your current company

Evening (60 min): Prepare your personal email blast

Go through your phone contacts, email contacts, and LinkedIn connections. Create a list of:
- Everyone you know who is an accountant, CGMA, CPA
- Everyone you know in real estate
- Anyone in nursing or healthcare
- Anyone who knows people in those fields

Target: 50–100 people. This is your Day 3 email list.

---

### DAY 2 β€” REDDIT SETUP (2 hours)

Step 1: Create or warm up your Reddit account

> ⚠️ Critical: If your Reddit account is less than 30 days old, you will be auto-filtered or banned from most subreddits. If you have an old account, use it. If not, create one now and spend 30 minutes leaving genuine comments on non-marketing posts in r/Accounting, r/personalfinance, and r/productivity. This "warms" the account.

Step 2: Join these subreddits (subscribe and read the rules for each)

| Subreddit | Members | Purpose |
|-----------|---------|---------|
| r/Accounting | 250k+ | Primary CGMA/CPA target |
| r/CGMAExam | smaller | Highly targeted |
| r/CPA | 80k+ | Future expansion |
| r/RealEstate | 1.4M | Real estate CE |
| r/realtors | 50k+ | Real estate agents |
| r/nursing | 400k+ | Future expansion |
| r/productivity | 1M+ | Cross-professional tool |
| r/Entrepreneur | 1.5M+ | Founder story posts |
| r/SideProject | 200k+ | Launch posts welcome |
| r/IMadeThis | 100k+ | Product launches |

Step 3: Leave 5 genuine comments today (No promotion β€” just be helpful)

Go to r/Accounting and r/RealEstate, find posts about professional development, licensing, or career questions, and leave actually useful comments. Examples:

- On a post about CGMA renewal: *"The CGMA renewal portal can be clunky β€” one tip: screenshot every course completion page immediately, even if the credits are supposed to auto-populate. Saved me twice."*
- On a post about real estate CE: *"Most states require it but almost no one tracks it properly until 30 days before renewal. Spreadsheet works okay but gets messy fast once you have 5+ courses logged."*

This builds karma and establishes you as a real community member, not a spammer.

---

### DAY 3 β€” PERSONAL NETWORK BLAST (2 hours)

Send this email to your personal list of 50–100 people:

---

Subject: I built something β€” want to be my first users?

Body:

Hey [First Name],

I'm doing something slightly terrifying β€” I just launched an app.

It's called [App Name], and it solves a problem I kept seeing: professionals who need to track continuing education hours (CGMA, CPA, real estate agents, nurses) spending way too much time digging through old receipts and emails at renewal time.

[App Name] makes it dead simple. Log a course in 30 seconds. Get deadline reminders. See your progress in one dashboard. That's it.

I'd love for you to be one of my first users.

Here's the deal:
- 30 days completely free, no credit card required
- If you find it useful after 30 days, it's $7.99/month
- If you tell a colleague and they sign up, you both get an extra 30 days free

Try it here: [your tracking link]

And honestly β€” even if CE tracking isn't relevant to you personally, if you know anyone who is a CGMA holder, CPA, real estate agent, or nurse, I'd be incredibly grateful if you forwarded this.

One favor: reply to this email and tell me what you think. Good, bad, or indifferent β€” I'm building this in public and real feedback is everything right now.

Thank you,
[Your name]

P.S. If you're a real estate agent or accountant specifically, I'm looking for 5 "founding users" to give me detailed feedback in exchange for 3 months free. Reply and I'll set you up.

---

Why this works:
- Personal tone, not a marketing blast
- Clear ask
- Gives them something to forward
- Creates a "founding user" category that feels exclusive
- P.S. targets your exact audience

---

### DAY 4 β€” APPROACH YOUR ACCOUNTANT AND REAL ESTATE AGENT FRIENDS

*(Full detail in Section 6, but here's the Day 4 action)*

Text your accountant friend:

> "Hey [name] β€” I finally launched that app I've been building. It's a CE tracker for CGMA holders and accountants. Would you be willing to be my first real user and give me brutally honest feedback? I'll give you 3 months free and I genuinely want to know what sucks about it. Could also use your help connecting me with 2-3 other CGMA people who might want to try it. No pressure either way β€” just thought of you first."

Text your real estate agent friend:

> "Hey [name] β€” launched my app finally! It tracks CE hours for real estate agents so you never scramble at license renewal time. Would mean a lot if you'd try it and tell me what you think. 3 months free on me. And if you know a couple agents who might want in on the free trial, I'd love an intro. You'd be helping me more than you know."

Key: These are texts, not emails. Texts feel personal. Emails from founders feel like marketing.

---

### DAY 5 β€” FIRST LINKEDIN POST (45 min)

Post this on your personal LinkedIn:

---

*πŸš€ I launched something today.*

*For the last [X months], I've been building [App Name] β€” a CE/CPD tracking app for professionals who have mandatory continuing education requirements.*

*CGMA holders. CPAs. Real estate agents. Nurses.*

*The problem I kept seeing: professionals are great at their jobs and terrible at paperwork. Come renewal time, they're scrambling through email folders and PDF certificates trying to prove they did the hours.*

*I built the simplest possible solution:*
*βœ… Log a course in 30 seconds*
*βœ… See your total hours at a glance*
*βœ… Get reminders before deadlines*

*That's it. No bloat. No upsells. No enterprise pricing.*

*$7.99/month after a 30-day free trial. No credit card required to start.*

*If you're a CGMA holder, CPA, real estate agent, or nurse β€” I'd love for you to be an early user. Link in the comments.*

*And if you know someone who fits that description, a share would genuinely mean the world to a solo founder right now. πŸ™*

*What's the most annoying part of tracking your CE hours? I want to hear.*

---

Immediately after posting:
- Comment your app link in the first comment (this keeps the link out of the post itself, which LinkedIn's algorithm prefers)
- Share the post to your personal feed story
- Send the post link to your accountant and real estate agent friends and ask them to like/comment

---

### DAY 6 β€” FIRST REDDIT POST (45 min)

Post in r/SideProject:

Title: *I built a CE/CPD tracker for accountants and professionals who hate losing track of continuing education hours*

Body:

> Hey r/SideProject,
>
> Long-time lurker, first-time poster. I just launched [App Name].
>
> The problem: Professionals with mandatory CE requirements (CGMA, CPA, real estate agents, nurses) often have no good system for tracking their hours. The official portals are clunky, spreadsheets get abandoned, and every renewal cycle involves a mini panic attack.
>
> What I built: A dead-simple CPD tracker. Log a course in 30 seconds, see your hours in one dashboard, get deadline reminders.
>
> Stack: [mention your stack β€” this community loves this]
>
> Business model: 30-day free trial (no credit card), $7.99/month after.
>
> Current status: Just launched. Zero paying users. Trying to get to 100 in 4 months.
>
> Would love feedback, especially from anyone in accounting, real estate, or healthcare. What would make you actually use this vs. a spreadsheet?
>
> Happy to answer any questions about the build or the launch.

---

Also post in r/IMadeThis with a shorter version.

---

### DAY 7 β€” REVIEW, RESPOND, AND PLAN (2 hours)

Morning:
- Respond to every comment on your LinkedIn post and Reddit posts (every reply extends reach)
- Follow up by text with your accountant and real estate agent friends if they haven't responded
- Check Bitly to see which links got clicks

Afternoon:
- Count total signups from Week 1
- Document what worked: which message got responses, which channel drove clicks
- Set up your Week 2 schedule

Week 1 Success Benchmark:
- βœ… 10–20 trial signups
- βœ… 2 "founding user" commitments from friends
- βœ… At least 1 organic referral
- βœ… LinkedIn post with 20+ reactions
- βœ… Reddit posts with net-positive karma (not removed)

---

# SECTION 2: LINKEDIN STRATEGY
## Content Calendar, Outreach Templates, and Automation

---

## LinkedIn Content Calendar: 4 Weeks of Posts

Posting rhythm: 3x/week (Monday, Wednesday, Friday)
Format mix: 40% personal stories, 30% educational, 20% social proof/milestones, 10% direct CTAs

---

### WEEK 1 POSTS

Monday Post β€” The Origin Story

Hook: *"I watched a senior accountant fail her CGMA renewal because of a spreadsheet."*

Body:
> She had done every hour. Every course. But when the renewal portal asked for documentation, she couldn't find half of it. Her email had the certificates. Her spreadsheet had some of the hours. Neither matched the portal.
>
> She had to re-do two courses under deadline pressure. It cost her 40 hours and real money.
>
> That's why I built [App Name].
>
> It's a CPD tracker for CGMA holders, CPAs, real estate agents, and nurses β€” the professionals who have mandatory continuing education but no great tool to track it.
>
> 30-day free trial. No credit card. $7.99/month after.
>
> Link in comments. Would love your thoughts if you've experienced this.

---

Wednesday Post β€” Educational

Hook: *"CGMA holders: here's what AICPA actually requires for CPD compliance (and where most people mess up)"*

Body:
> [Research the actual CGMA CPD requirements and lay them out clearly]
>
> Most common mistake: [specific mistake]
>
> Second most common: [specific mistake]
>
> I spent a while going through the official CIMA/CGMA documentation so you don't have to. Here's the quick version:
>
> [3-5 bullet points of actual requirements]
>
> Saving the full breakdown for a blog post β€” follow me to catch it when it drops.
>
> Question for CGMA holders: do you find the official portal sufficient for tracking, or are you supplementing with something else?

---

Friday Post β€” Relatable/Humor

Hook: *"The 4 stages of CE tracking (and which stage you're currently in)"*

Body:
> Stage 1 β€” The Optimist: "I'll log every course immediately. I'll be so organized this year."
>
> Stage 2 β€” The Avoider: "I'll do it at the end of the month. It's fine."
>
> Stage 3 β€” The Scrambler: "Renewal is in 6 weeks. WHERE ARE MY CERTIFICATES."
>
> Stage 4 β€” The Survivor: "I made it. I'm never doing that again." *[Does it again next year]*
>
> I'm building something to get professionals out of Stage 3 permanently.
>
> [App Name] β€” 30-day free trial, no credit card. Link in comments.
>
> Which stage are you usually in? πŸ‘‡

---

### WEEK 2 POSTS

Monday β€” Social Proof/Milestone

Hook: *"Day 7 of launching my app. Here's exactly what happened."*

Body:
> Raw numbers:
> πŸ“§ Personal emails sent: [X]
> πŸ”— LinkedIn impressions: [X]
> πŸ“ Trial signups: [X]
> πŸ’¬ Conversations started: [X]
>
> What surprised me: [genuine insight]
>
> What didn't work: [genuine miss]
>
> What I'm changing: [what you're adjusting]
>
> Building in public is uncomfortable. But the feedback from real users in week 1 already changed [specific thing] about the product.
>
> If you're building something solo, what's your biggest distribution challenge right now?

*(This "building in public" style generates massive engagement and attracts other founders + potential users)*

---

Wednesday β€” Educational for Target Audience

Hook: *"Real estate agents: your CE requirements vary WILDLY by state. Here's a quick breakdown."*

Body:
> [Research 5-6 states with different requirements and lay them out]
>
> Key point: [insight]
>
> The problem with state variation: [problem]
>
> [App Name] handles this by letting you set your own renewal period and hour requirements β€” it doesn't assume anything.
>
> Real estate agents: what state are you in, and do you find your CE requirements confusing or pretty straightforward?

---

Friday β€” Engagement/Community

Hook: *"What's the dumbest way you've tracked CE hours? I'll go first."*

Body:
> Me: A Notes app on my phone labeled "CE stuff" that I never opened after creating it.
>
> Followed by a Gmail folder I searched desperately every renewal cycle.
>
> Followed by a spreadsheet that had three different versions with conflicting numbers.
>
> This is why I built [App Name].
>
> Yours? πŸ‘‡
>
> (Best answer gets a free year of the app β€” genuinely)

---

### WEEK 3 POSTS

Monday β€” Case Study / User Story

Hook: *"How [first name, job title] went from renewal panic to 10 minutes of CE admin per month"*

Body:
> [Use your founding user β€” get their permission β€” and tell their story]
>
> Before [App Name]: [their pain]
> After: [their result]
> Favorite feature: [specific feature]
> Time saved per month: [estimate]
>
> [Approximate quote from them]
>
> This is exactly who I built it for. If this sounds like you, link in comments.

---

Wednesday β€” Contrarian Take

Hook: *"Your employer's LMS is not good enough for tracking your personal CPD. Here's why."*

Body:
> Your company's learning management system tracks what they want you to learn.
>
> Your professional license requires YOU to prove what YOU learned.
>
> These are different things.
>
> [3 specific reasons the employer LMS fails for personal CPD compliance]
>
> The professional is ultimately responsible β€” not the employer. Your name is on the license.
>
> This is why I built [App Name] as a personal tool, not an enterprise product.
>
> Thoughts? Do you rely on your employer's system or do you track independently?

---

Friday β€” Specific Audience Callout

Hook: *"CGMA holders: I have a question about your CPD experience"*

Body:
> I'm building a CE tracker specifically with CGMA requirements in mind, and I want to make sure I'm solving the right problems.
>
> Quick poll:
>
> πŸ”΅ I use the CIMA online portal and it's fine
> 🟒 I use a spreadsheet to supplement
> 🟑 I use email folders / certificates
> πŸ”΄ I wing it and panic at renewal
>
> Comment your answer β€” and if you have more to say, I'm all ears. Every piece of feedback directly shapes what I build next.

---

### WEEK 4 POSTS

Monday β€” Product Update

Hook: *"New feature in [App Name] this week β€” built because a user asked for it"*

Body:
> [Real feature update or improvement]
>
> The request: [paraphrase user feedback]
> The solution: [what you built]
> Time it took: [honest answer]
>
> This is the part of building solo that I love β€” feedback to shipped in days, not quarters.
>
> If you're in the trial and want something changed, just reply to any email from me. I read every one.

---

Wednesday β€” Month 1 Milestone Post

Hook: *"30 days in. Here are my real numbers."*

Body:
> [Your actual numbers β€” be honest, even if they're small]
>
> Trial signups: [X]
> Paid conversions: [X]
> MRR: $[X]
> Churn: [X]
> NPS from users who responded: [X]
>
> Most surprising thing I learned: [genuine insight]
>
> Biggest mistake I made: [honest miss]
>
> What I'm doubling down on in Month 2: [strategy]
>
> If you're building in public, share your numbers below. We're all figuring this out.

---

Friday β€” Direct CTA (once a month maximum)

Hook: *"If you're a CGMA holder, CPA, real estate agent, or nurse β€” this is for you"*

Body:
> 30 days free. No credit card.
>
> [App Name] tracks your CE/CPD hours so you never scramble at renewal time.
>
> One dashboard. Deadline reminders. Log a course in 30 seconds.
>
> After 30 days: $7.99/month. Cancel anytime.
>
> I'm a solo developer and every signup genuinely matters. If this solves a problem you have β€” or you know someone it would help β€” link in comments.
>
> Referral: share your link and both of you get an extra 30 days free.

---

## LinkedIn Outreach Templates for CGMA Holders

How to find them:
1. LinkedIn search: "CGMA" in title or credentials
2. Filter: 2nd connections, your country/region first
3. Target: people who post about accounting, professional development, career growth
4. Look for: people who've recently mentioned "renewal," "CPD," "continuing education" in posts

Connection Request (under 200 characters):

> "Hi [Name] β€” saw your post about [specific thing]. Fellow finance/accounting person here. Building something for CGMA CPD tracking and would love to connect."

*(Always reference something specific from their profile or a post. Generic requests get ignored.)*

First Message After Connection (send 2–3 days after they accept):

> Hi [Name],
>
> Thanks for connecting.
>
> I'm building a CPD tracker specifically for CGMA holders β€” born out of watching colleagues (and honestly myself) scramble at renewal time.
>
> It's in early launch and I'm talking to CGMA professionals to make sure I'm solving the right problems.
>
> Would you be open to a 15-minute chat β€” or if time is tight, even just answering one question: what's your current system for tracking CPD hours?
>
> Either way, no sales pitch β€” genuinely trying to build something useful.
>
> [Your name]

Follow-up if no response in 7 days:

> Hey [Name] β€” just following up on my last message. No worries if it's not relevant.
>
> Short version: I launched a 30-day free trial of [App Name] this week β€” CPD tracking for CGMA holders.
>
> If you want to try it, here's the link: [link]. If not, totally fine.
>
> Either way β€” good luck with your CPD cycle this year. πŸ‘‹

Message to someone who posted about CPD/CE stress:

> [Name] β€” your post about [CPD renewal/tracking struggle] hit home. I just launched a CPD tracker specifically for CGMA holders that addresses exactly this.
>
> Would it be okay if I shared a free trial link? 30 days, no card needed. If it doesn't solve your problem, I genuinely want to know why β€” I'm building this thing and feedback is gold.

---

## LinkedIn Automation Tools

| Tool | Purpose | Cost | Notes |
|------|---------|------|-------|
| Taplio | Schedule LinkedIn posts, analytics | $39/mo | Best LinkedIn-specific tool |
| Buffer | Free scheduling (3 channels) | Free | Good starting point |
| Phantombuster | Profile scraping, auto-connection (use carefully) | $56/mo | Use within LinkedIn limits: max 20 connections/day |
| Dux-Soup | LinkedIn automation for outreach | $11.25/mo | Cheaper Phantombuster alternative |
| Shield Analytics | LinkedIn post analytics | $8/mo | Track what content performs |

⚠️ LinkedIn Automation Rules:
- Never send more than 20 connection requests per day
- Never use fully automated generic messages β€” always personalize at least the first line
- Take weekends off (LinkedIn flags unusual patterns)
- If you get a warning, stop automation for 2 weeks

---

# SECTION 3: REDDIT STRATEGY
## Subreddits, Post Titles, Comment Strategy, Rules

---

## The 3 Types of Reddit Posts That Work for SaaS

Type 1: The Launch Post β€” works in r/SideProject, r/IMadeThis, r/Entrepreneur
Type 2: The Problem Discussion β€” works in professional subreddits
Type 3: The Resource Post β€” works everywhere, no direct promotion
🎯

Niche Deep Dives

# CE Tracking SaaS: Market Analysis Report
## 5 Niche Deep-Dive Analysis

---

# NICHE 1: CGMA HOLDERS (Chartered Global Management Accountants)

## 1. EXACT CE REQUIREMENTS

Annual CPD Requirement: 120 hours over a rolling 3-year period (minimum 20 hours per year)

Category Breakdown:
- No strict category minimums by default, BUT members must self-assess relevance to their role
- AICPA/CIMA joint credential β€” governed by CIMA's CPD policy (the "Professional Development" framework)
- CIMA uses a reflective learning model β€” not purely hour-based. Members log:
- Learning need identified
- Activity undertaken
- Hours spent
- What was learned
- How it was applied
- Some activities require verifiable CPD (third-party confirmation), others are non-verifiable (self-directed reading, reflection)

Renewal/Submission:
- Annual declaration via CIMA's online portal (My CPD)
- Subject to audit β€” random selection of members must submit evidence
- No universal proof submission unless audited; honor system with audit risk
- US-side (AICPA): CPAs holding CGMA must *also* comply with their state CPA board requirements (which vary dramatically by state β€” 40 hours/year in most states, with ethics minimums of 2-4 hours)

Critical Complexity: A CGMA holder who is also a licensed CPA faces dual tracking obligations β€” CIMA's reflective model AND their state board's hour-based model. This is a genuine pain point.

---

## 2. MARKET SIZE

- Global CGMA holders: ~300,000 worldwide
- US CGMA holders: Approximately 40,000–50,000 (AICPA members who have added CGMA designation)
- Australian CGMA holders: Estimated 5,000–8,000 (CIMA has ~7,000 members in Australia)
- Geographic concentration (AU): Sydney, Melbourne, Brisbane β€” heavily CBD-based, finance/corporate sector
- NSW specifically: Estimated 2,000–3,000 CGMA holders

Operator relevance: The accountant friend is more likely a CPA/CA (Chartered Accountant under CA ANZ) than a CGMA holder specifically. CGMA is less common in Australia than CA or CPA Australia designations.

---

## 3. PAIN SCORE: 6/10

Reasoning:
- CIMA's reflective model is genuinely confusing β€” it's not just "log hours," it requires narrative documentation
- Dual-credential holders (CGMA + state CPA) have real complexity
- However, CIMA's own portal (My CPD) exists and is functional, reducing pain somewhat
- The honor-system-until-audited model means many members simply don't track carefully β€” low urgency until audit notice arrives
- Pain is moderate but real, especially for dual-credential holders

---

## 4. WILLINGNESS TO PAY: 7/10

Evidence:
- CGMAs are management accountants in corporate/finance roles β€” above-average income ($80K–$180K+ range)
- Already paying CIMA membership fees (~$400–600 AUD/year) plus AICPA fees
- Corporate environment means expense reimbursement is common β€” employer may pay for tools
- B2B angle strong: CFOs and finance teams buying tools for compliance is normal behavior
- However, the "free CIMA portal exists" objection is real

---

## 5. COMMUNITY LOCATIONS

Associations:
- CIMA Australia (cima.me/en/australia) β€” local chapter events
- AICPA (US-focused)
- CPA Australia (separate credential but overlapping community)
- CA ANZ (Chartered Accountants Australia and New Zealand)

Online Communities:
- Reddit: r/Accounting (330K+ members), r/CPA, r/AusFinance
- LinkedIn Groups: "CIMA Members Network" (~15,000 members), "CGMA Professionals" (~8,000 members), "Management Accountants Australia"
- Facebook: "CIMA Australia Members" (small, ~500), "Australian Accountants Network"
- Slack: Various accounting firm internal channels
- Most active professional community: LinkedIn, not Reddit or Facebook

---

## 6. ACQUISITION STRATEGY

Primary Channel: LinkedIn content marketing + direct outreach

Message:
> "CGMA renewal coming up? If you're also a licensed CPA, you're tracking two different CPD frameworks simultaneously. Most accountants cobble this together in spreadsheets. Here's a better way."

Tactics:
- Partner with CIMA Australia for member communications (association partnership)
- Target Finance Directors/CFOs with team licenses (B2B angle)
- Content: "The difference between CIMA's reflective CPD model and your state board's hour requirements β€” and how not to get caught in an audit"
- The accountant friend connection is directly relevant here β€” ask for introduction to their CIMA network

Warm Lead Activation:
> The operator's accountant friend likely knows other accountants with CGMA or CA designations. This is a direct referral pathway into a trusted professional community.

---

## 7. PRODUCT CUSTOMIZATION NEEDED

- Dual-framework tracking: Must handle both CIMA reflective model AND state CPA board hours simultaneously, with one input feeding two different output formats
- Narrative fields: CIMA requires "what did you learn, how did you apply it" β€” not just hours
- Audit preparation mode: One-click export of all evidence in CIMA audit-ready format
- Verifiable vs. non-verifiable classification: Activity tagging must distinguish these
- Multi-credential dashboard: Show compliance status across ALL credentials a user holds

---

## 8. COMPETITIVE THREAT

- CIMA's own My CPD portal β€” free, functional, but basic. No dual-tracking, no reminders, no reporting
- MyCPE (US-focused) β€” sells CPE credits AND has basic tracking, dominant in US CPA space
- CPE tracking within state board portals β€” fragmented, state by state
- Excel/Google Sheets β€” the dominant "competitor" currently
- Specific threat: If CIMA upgrades their portal, your tool loses differentiation. Monitor their product roadmap.

---

## 9. RECOMMENDATION: CONDITIONAL GO

Rationale:
- Strong operator connection (accountant friend as warm lead into community)
- Real dual-tracking pain that free tools don't solve
- Good WTP in corporate finance environment
- Condition: Validate that the accountant friend (and their network) actually finds the dual-tracking problem painful enough to pay for. If they're using spreadsheets happily, pain may be lower than expected. B2B angle (team licenses for finance departments) may be stronger than individual licenses.

---
---

# NICHE 2: NSW/AU REAL ESTATE AGENTS

## 1. EXACT CE REQUIREMENTS

Governing Body: NSW Fair Trading (for NSW); each state has its own regulator

NSW Specifically (most relevant to operator):

Class 1 Licence (Agent in Charge/Principal):
- 9 CPD points per year
- Structured component: Minimum 3 points from Structured CPD (approved courses only)
- Elective component: Remaining points from approved elective activities
- Compliance period: 1 September – 31 August annually
- Mandatory topics rotate each year β€” Fair Trading announces the mandatory topic annually (e.g., "Underquoting" was a mandatory topic in recent years)

Class 2 Licence (Salesperson/Property Manager):
- 3 CPD points per year
- Must include the annual mandatory topic

Certificate of Registration (Entry level):
- Different requirements β€” working toward full licence

Where they submit:
- CPD is logged with the course provider (who reports to NSW Fair Trading)
- Agents must keep their own records
- NSW Fair Trading can audit β€” agents need evidence of completion
- No central agent-facing submission portal β€” this is a gap

Key Complexity:
- Mandatory topic changes annually β€” agents must track WHICH topic is mandatory for the current cycle
- Points from different categories (structured vs. elective) must be balanced correctly
- Agents working across multiple states (especially ACT/NSW border, VIC/NSW border) face dual-state requirements

---

## 2. MARKET SIZE

NSW Licensed Real Estate Agents:
- Approximately 60,000–70,000 licensed real estate agents in NSW (Class 1 + Class 2 combined)
- Certificates of Registration add another ~15,000–20,000
- Total NSW addressable market: ~75,000–90,000 individuals

National (Australian) Real Estate Agents:
- Approximately 200,000–250,000 licensed agents nationally
- VIC: ~50,000, QLD: ~40,000, WA: ~25,000, SA: ~15,000, others smaller

Geographic concentration:
- Sydney Metro: ~40,000–45,000 agents (heavily concentrated in Inner West, North Shore, Eastern Suburbs, South-West growth corridors)
- Major agencies: Ray White, LJ Hooker, McGrath, Belle Property, Domain-affiliated independents

---

## 3. PAIN SCORE: 8/10

Reasoning:
- No central tracking portal β€” agents are entirely responsible for their own records
- The mandatory topic changes annually, creating confusion ("what's mandatory THIS year?")
- Points system (not just hours) adds calculation complexity
- Property managers vs. sales agents have different day-to-day schedules, making structured CPD hard to schedule
- Common pattern: agents scrambling to complete CPD in August (end of cycle) β€” classic procrastination + last-minute problem
- Many agents working for larger agencies may get some training through their agency BUT it's not tracked centrally for licence purposes
- High pain, well-documented in industry forums

---

## 4. WILLINGNESS TO PAY: 7/10

Evidence:
- Real estate agents in NSW typically earn commission-based income; top performers earn $150K–$500K+
- BUT: many agents are mid-tier earners ($60K–$120K), making price sensitivity real
- Agents are accustomed to paying for tools: CRM software (Rex, VaultRE), listing portals (Domain, REA Group), marketing tools
- However, cultural norm in real estate is "my agency provides tools" β€” individual payment behavior is less consistent
- Key insight: Principal/licensee-in-charge (Class 1) who runs an office has both personal compliance AND staff compliance to manage β†’ higher WTP for team solution
- Franchise head offices (Ray White corporate, LJ Hooker corporate) would pay for a white-labeled compliance tool for their network β€” B2B opportunity

---

## 5. COMMUNITY LOCATIONS

Associations:
- Real Estate Institute of NSW (REINSW) β€” primary professional body, ~3,000 members (smaller than you'd expect; membership not mandatory)
- Real Estate Institute of Australia (REIA) β€” national body
- Property Council of Australia β€” larger commercial/development focus

Online Communities:
- Reddit: r/AusProperty (100K+ but mostly buyer/investor focused), r/ausrealestate (smaller, ~5K, more agent-relevant)
- Facebook Groups: "Real Estate Agents Australia" (~15,000 members, highly active), "Real Estate Agents NSW" (~5,000), "Property Management Professionals Australia" (~12,000), "Real Estate Career Network Australia" (~8,000)
- LinkedIn Groups: "Real Estate Professionals Australia" (~20,000), "Real Estate Network – Australia/NZ"
- Most active: Facebook groups are THE primary social channel for Australian real estate agents β€” more than LinkedIn or Reddit
- Industry events: REINSW Annual Conference, Various agency-specific events

---

## 6. ACQUISITION STRATEGY

Primary Channel: Facebook Groups + Direct agency partnerships

Message (for individual agents):
> "NSW CPD compliance period ends August 31. Do you know exactly how many structured points you've completed this year β€” and whether you've done the mandatory topic? Most agents find out they're behind in July. Here's a tool that tells you exactly where you stand, 365 days a year."

Message (for principals/LIC):
> "You're responsible for ensuring everyone at your office is CPD compliant. How are you tracking it? A spreadsheet? Relying on agents to tell you? One non-compliant agent is a Fair Trading audit risk for your whole business."

Tactics:
- The operator's real estate agent friend is the single most important asset β€” use them as a beta tester, case study, and referral source
- Ask the friend to post in their agency's internal group or at their next office meeting
- Approach REINSW about a partnership or member benefit
- Run targeted Facebook ads to NSW-based real estate agent job titles
- Create content: "NSW CPD mandatory topic for [current year] β€” what you need to know"
- Agency partnership play: Approach 3–5 mid-size independent agencies to offer team dashboards; if principal sees value, they push adoption to all agents

Warm Lead Activation:
> Direct: The operator's real estate agent friend is the first paying customer and referral engine. This is the most direct path to initial traction.

---

## 7. PRODUCT CUSTOMIZATION NEEDED

- Points-based system (not hours) β€” 1 point β‰  1 hour in all cases
- Annual mandatory topic tracking β€” must update annually when Fair Trading announces the mandatory topic; agents need to see "have I completed THIS YEAR'S mandatory topic?"
- Structured vs. elective balance display β€” clear visual showing 3 structured points completed out of 9 total, for example
- Compliance year calendar β€” September 1 to August 31 (not calendar year)
- Multi-state tracking β€” for agents licensed in multiple states
- Provider integration β€” ideally, auto-import from approved CPD providers (REINSW, Real Plus, Kaplan, etc.)
- Team dashboard β€” for principals managing multiple agents
- Licence class differentiation β€” Class 1 (9 points) vs. Class 2 (3 points) requirements differ

---

## 8. COMPETITIVE THREAT

Existing tools:
- Real Plus (realestatecpdtraining.com.au) β€” CPD course provider, has basic tracking of courses purchased through them only; not a full CE tracker
- Kaplan Professional β€” similar, course provider with basic record-keeping
- REINSW member portal β€” has some CPD logging for members but not comprehensive
- Agency internal LMS β€” Ray White, LJ Hooker etc. have internal training platforms but these track agency training, not licence CPD specifically
- No dominant standalone CE tracking tool identified for Australian real estate agents

Gap assessment: The market has course providers with basic record-keeping and agency LMS tools, but no purpose-built compliance tracking tool for individual agent licence requirements. This is a real gap.

---

## 9. RECOMMENDATION: GO β€” HIGHEST PRIORITY

Rationale:
1. Operator has a warm lead (real estate agent friend) β€” direct access to first customer and referral network
2. Operator is NSW-based β€” geographic focus aligns perfectly with starting in NSW market
3. Genuine product gap β€” no dominant competitor
4. High pain score (8/10) with documented procrastination behavior
5. Clear regulatory complexity (mandatory topics, points vs. hours, structured vs. elective) that justifies a dedicated tool
6. Scalable: start NSW β†’ expand to all Australian states
7. B2B expansion path: individual β†’ agency team β†’ franchise networks

---
---

# NICHE 3: AU FINANCIAL ADVISERS (FASEA/ASIC)

## 1. EXACT CE REQUIREMENTS

Context: FASEA (Financial Adviser Standards and Ethics Authority) was abolished and its functions transferred to ASIC and the Financial Adviser Standards body in 2022. The CPD requirements persist under the Corporations Act.

Current Requirements (as of 2024):

Annual CPD Hours: 40 hours per year

Mandatory Category Breakdown:
- Technical competence: Minimum 5 hours
- Client care and practice: Minimum 5 hours
- Regulatory compliance and consumer protection: Minimum 5 hours
- Professionalism and ethics: Minimum 9 hours (this is the highest minimum)
- Managed investments (if applicable): Additional requirements for those providing advice on managed investment schemes

Total minimums: 24 hours of categorized content + 16 hours flexible

Ethics Requirement:
- Must include an approved ethics course β€” not just any ethics content
- The ethics requirement is particularly stringent and was a major compliance point post-FASEA reforms

Record Keeping:
- Advisers must maintain CPD records for 7 years
- Records submitted to and maintained through their Australian Financial Services Licence (AFSL) holder (the licensee, not directly to ASIC)
- ASIC maintains the Financial Advisers Register β€” publicly searchable
- Licensees (AFSL holders) are responsible for monitoring adviser compliance
- Advisers must submit CPD records to their licensee annually

Licence Renewal/Register:
- Advisers must be registered on the ASIC Financial Advisers Register
- Annual registration renewal requires confirmation of CPD compliance
- Additional requirement: Must hold an approved degree or have passed an FASEA exam (deadline has passed β€” this is now a baseline requirement, not ongoing)

---

## 2. MARKET SIZE

Licensed Financial Advisers in Australia:
- As of 2024: approximately 15,500–16,500 registered financial advisers (this number has dropped significantly from ~28,000 in 2018 due to post-Royal Commission/FASEA reforms)
- The market contracted dramatically β€” many advisers left the industry due to compliance costs
- Geographic concentration: Sydney (NSW) ~35%, Melbourne (VIC) ~30%, Brisbane ~12%, Perth ~8%, Adelaide ~5%, other ~10%
- NSW estimate: approximately 5,500–6,000 advisers

Important market context:
- The post-FASEA exodus means remaining advisers are serious professionals who survived heavy regulation β€” they understand compliance and are already paying for it
- Remaining advisers tend to be higher earners ($120K–$300K+)
- Most advisers work under an AFSL licensee β€” there's a B2B angle targeting licensees who must monitor compliance for all their advisers

---

## 3. PAIN SCORE: 9/10

Reasoning:
- Category minimums (5+5+5+9 hours) across 4 categories create genuine tracking complexity
- 7-year record-keeping requirement β€” not just current year, historical records needed
- Ethics hours require specifically approved activities β€” can't just log any ethics content
- Dual accountability: adviser must track for themselves AND submit to licensee
- Post-FASEA reforms created a highly anxious compliance culture β€” advisers have seen colleagues lose registration, face ASIC action
- Many advisers switched licensees during industry consolidation β€” tracking continuity across licensee changes is painful
- This is probably the highest-stakes CPD environment in Australia β€” non-compliance can mean deregistration and career ending
- Pain is well-documented: Financial Planning Association (FPA) and Association of Financial Advisers (AFA) have published surveys showing CPD burden as top concern

---

## 4. WILLINGNESS TO PAY: 9/10

Evidence:
- Financial advisers are among the highest-earning professionals in Australia
- Already paying for: PI insurance ($3K–$15K/year), licensee fees ($5K–$30K+/year), professional memberships ($1K–$3K/year), software (Xplan, Midwinter, Advice OS β€” $3K–$15K/year per adviser)
- Compliance cost is existential β€” advisers have watched colleagues lose their registration
- Precedent for premium tool purchasing: Very strong. Advisers are heavy software users.
- Licensee WTP: Even higher β€” a licensee with 50 advisers paying $500K+ annually in licensee fees has strong incentive to buy a $50–200/month compliance monitoring tool
- B2B angle is the strongest WTP case β€” licensee buys for their entire adviser network

---

## 5. COMMUNITY LOCATIONS

Associations:
- Financial Planning Association of Australia (FPA) β€” primary professional body, ~12,000 members
- Association of Financial Advisers (AFA) β€” ~2,000 members, more traditional insurance-linked advisers
- SMSF Association β€” for SMSF specialists
- Stockbrokers and Investment Advisers Association (SIAA)
- These associations merged: FPA +
πŸ”§

Tech Stack & Build Plan

# CE/CPD Tracking SaaS β€” Complete Technical Blueprint

---

## 1. TECH STACK RECOMMENDATION

### Backend Framework: Flask

Choose Flask over FastAPI or Django for these specific reasons:

- vs FastAPI: FastAPI's async model adds complexity without benefit for a solo dev doing server-side rendering. Its strengths (OpenAPI auto-docs, async performance) don't matter for a Jinja2-rendered app with moderate traffic. Flask's synchronous model maps directly to how you think about request/response cycles.
- vs Django: Django's batteries-included philosophy becomes a burden when you don't want its ORM conventions, its admin (you'll build your own), or its project structure opinions. Django has a steeper "do it Django's way" tax. Flask lets you own every decision.
- Your situation: You have existing Python scripts. Flask lets you import them directly. You know Python β€” Flask is just Python with decorators.

Libraries on top of Flask:
```
Flask==3.0.x
Flask-Login==0.6.x # session management
Flask-WTF==1.2.x # CSRF protection + forms
Flask-Mail==0.10.x # email
Flask-Migrate==4.0.x # database migrations
SQLAlchemy==2.0.x # ORM
Werkzeug==3.0.x # password hashing (bundled with Flask)
```

---

### Database: PostgreSQL

Not SQLite, even though you're solo. Here's why:

- Concurrent writes: SQLite locks the entire database on writes. When Stripe webhooks hit simultaneously with user uploads, you will get `database is locked` errors. This will happen in production within week 2.
- Full-text search: PostgreSQL has `tsvector`/`tsquery` built in. You'll want to search CE records by description, provider, topic. SQLite's FTS5 is bolted on and limited.
- JSON columns: Storing Claude API responses, certificate metadata as structured data is clean with PostgreSQL's `JSONB`.
- Already on your VPS: `apt install postgresql` costs nothing.
- Migration path: You're already on PostgreSQL at scale β€” there is no painful migration later.

Use SQLAlchemy 2.0 as ORM with Alembic (via Flask-Migrate) for migrations.

```
psycopg2-binary==2.9.x # PostgreSQL adapter
```

---

### Frontend: Jinja2 + HTMX + Alpine.js (minimal)

This is the correct choice for your skills and timeline. Here's the exact philosophy:

- Jinja2: All page rendering server-side. You know Python, templates feel natural.
- HTMX: Handles dynamic interactions (form submissions without full reload, live search, inline editing) with zero JavaScript knowledge required. You add `hx-post` attributes to HTML elements. That's it.
- Alpine.js (3kb): Only for UI state that doesn't need server involvement β€” toggling dropdowns, showing/hiding elements, tab switching. No routing, no components, no build step.
- No React, no Vue, no Webpack, no Node.js required.

CSS Framework: Tailwind CSS via CDN for MVP (switch to compiled build post-launch if needed). Use the CDN `<script>` tag β€” no build toolchain.

---

### Authentication: Flask-Login + itsdangerous

```python
Flask-Login==0.6.x # session management, @login_required decorator
itsdangerous==2.1.x # signed tokens for email verification, password reset
bcrypt==4.1.x # password hashing (use instead of Werkzeug's pbkdf2)
```

Approach: Email/password only for MVP. No OAuth. Add Google OAuth in v1.1.

- Registration β†’ email verification token (itsdangerous `URLSafeTimedSerializer`)
- Login β†’ Flask-Login session cookie
- Password reset β†’ timed token via email
- Sessions stored server-side (Flask default cookie-based with signing is fine for MVP)

---

### File Storage: Local VPS with Nginx serving + structured directories

Not S3 for MVP. Reasons:
- $0 cost constraint
- MVP user count won't stress a VPS disk
- Nginx can serve files directly with `X-Accel-Redirect` (files stay protected behind auth)

Structure: `/var/app/cpdtracker/uploads/{user_id}/{year}/{uuid4}.pdf`

Hard limits to enforce in code:
- 10MB max per file
- PDF, JPG, PNG only
- Virus scanning: skip for MVP, add ClamAV post-launch

Migration path: When you hit 100GB or need CDN, swap to S3/Cloudflare R2 β€” change one function in `storage.py`.

---

### Email: Resend (provider) + Flask-Mail

- Resend is the right choice in 2024: generous free tier (3,000 emails/month), excellent deliverability, simple API, Python SDK
- Alternative: Postmark (slightly better deliverability tracking)
- Not: SendGrid (overkill), Mailgun (worse free tier), SES (requires AWS setup)

```
resend==2.x.x # or use Flask-Mail with SMTP credentials from Resend
```

---

### Payments: Stripe Checkout + Webhooks

You know Stripe already β€” use what you know.

Approach for subscription SaaS:
```
stripe==8.x.x
```

- Stripe Checkout (hosted page): Not custom payment form. Reduces PCI scope to near zero, handles SCA/3DS automatically, Stripe maintains the UI.
- Customer Portal: Stripe's hosted portal for subscription management. You build nothing for "cancel/upgrade/update card".
- Webhooks: `checkout.session.completed`, `customer.subscription.updated`, `customer.subscription.deleted`, `invoice.payment_failed`

---

## 2. DATABASE SCHEMA

```sql
-- Complete PostgreSQL Schema
-- Run via Flask-Migrate (Alembic)

-- ============================================================
-- USERS & AUTH
-- ============================================================

CREATE TABLE users (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
email VARCHAR(255) UNIQUE NOT NULL,
email_verified BOOLEAN DEFAULT FALSE,
password_hash VARCHAR(255) NOT NULL,

-- Profile
first_name VARCHAR(100) NOT NULL,
last_name VARCHAR(100) NOT NULL,
profession VARCHAR(100), -- 'Nurse', 'Accountant', 'Engineer', etc.
license_number VARCHAR(100),
license_state_province VARCHAR(100),

-- Licensing body / renewal cycle
licensing_body VARCHAR(200), -- 'AICPA', 'NMC', 'APEGA'
renewal_period_months INTEGER DEFAULT 12, -- how long their cycle is
cycle_start_date DATE, -- when their current cycle started
cycle_end_date DATE, -- when it ends (deadline)
required_hours NUMERIC(6,2), -- total CE hours required per cycle

-- Account state
is_active BOOLEAN DEFAULT TRUE,
is_admin BOOLEAN DEFAULT FALSE,
timezone VARCHAR(50) DEFAULT 'UTC',

-- Referral
referral_code VARCHAR(20) UNIQUE NOT NULL,
referred_by_user_id UUID REFERENCES users(id) ON DELETE SET NULL,

-- Stripe
stripe_customer_id VARCHAR(100) UNIQUE,

-- Timestamps
created_at TIMESTAMPTZ DEFAULT NOW(),
updated_at TIMESTAMPTZ DEFAULT NOW(),
last_login_at TIMESTAMPTZ
);

CREATE INDEX idx_users_email ON users(email);
CREATE INDEX idx_users_referral_code ON users(referral_code);
CREATE INDEX idx_users_stripe_customer_id ON users(stripe_customer_id);


-- ============================================================
-- EMAIL VERIFICATION & PASSWORD RESET TOKENS
-- ============================================================

CREATE TABLE auth_tokens (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
token_hash VARCHAR(255) NOT NULL, -- store hash, not raw token
token_type VARCHAR(50) NOT NULL, -- 'email_verify', 'password_reset'
expires_at TIMESTAMPTZ NOT NULL,
used_at TIMESTAMPTZ,
created_at TIMESTAMPTZ DEFAULT NOW()
);

CREATE INDEX idx_auth_tokens_user_id ON auth_tokens(user_id);
CREATE INDEX idx_auth_tokens_token_hash ON auth_tokens(token_hash);


-- ============================================================
-- SUBSCRIPTIONS & BILLING
-- ============================================================

CREATE TABLE subscription_plans (
id SERIAL PRIMARY KEY,
name VARCHAR(100) NOT NULL, -- 'Free', 'Pro', 'Team'
stripe_price_id VARCHAR(100) UNIQUE, -- price_xxxxx
price_cents INTEGER NOT NULL, -- monthly price in cents
billing_interval VARCHAR(20) DEFAULT 'month', -- 'month', 'year'
max_ce_entries INTEGER DEFAULT 10, -- NULL = unlimited
max_file_storage_mb INTEGER DEFAULT 100, -- NULL = unlimited
ai_summaries BOOLEAN DEFAULT FALSE,
reminder_emails BOOLEAN DEFAULT FALSE,
export_pdf BOOLEAN DEFAULT FALSE,
is_active BOOLEAN DEFAULT TRUE,
created_at TIMESTAMPTZ DEFAULT NOW()
);

INSERT INTO subscription_plans
(name, price_cents, max_ce_entries, max_file_storage_mb, ai_summaries, reminder_emails, export_pdf)
VALUES
('Free', 0, 10, 100, FALSE, FALSE, FALSE),
('Pro', 999, NULL, 2048, TRUE, TRUE, TRUE);


CREATE TABLE user_subscriptions (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
plan_id INTEGER NOT NULL REFERENCES subscription_plans(id),

-- Stripe references
stripe_subscription_id VARCHAR(100) UNIQUE,
stripe_current_period_start TIMESTAMPTZ,
stripe_current_period_end TIMESTAMPTZ,

-- State
status VARCHAR(50) NOT NULL DEFAULT 'active',
-- 'active', 'trialing', 'past_due', 'canceled', 'unpaid'

-- Trial tracking
trial_ends_at TIMESTAMPTZ,

-- Referral discount applied
discount_applied BOOLEAN DEFAULT FALSE,
discount_percent INTEGER DEFAULT 0,

created_at TIMESTAMPTZ DEFAULT NOW(),
updated_at TIMESTAMPTZ DEFAULT NOW(),
canceled_at TIMESTAMPTZ
);

CREATE INDEX idx_user_subscriptions_user_id ON user_subscriptions(user_id);
CREATE INDEX idx_user_subscriptions_stripe_id ON user_subscriptions(stripe_subscription_id);


-- ============================================================
-- CE/CPD ENTRIES (Core feature)
-- ============================================================

CREATE TABLE ce_entries (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,

-- Core fields
title VARCHAR(500) NOT NULL,
provider_name VARCHAR(300), -- 'AMA', 'Coursera', 'Local Hospital'
activity_type VARCHAR(100), -- 'Course', 'Conference', 'Webinar', 'Self-study', etc.
category VARCHAR(100), -- profession-specific: 'Ethics', 'Clinical', 'Technical'

-- Time
completion_date DATE NOT NULL,
credit_hours NUMERIC(6,2) NOT NULL,
credit_type VARCHAR(100), -- 'AMA PRA Category 1', 'CPD points', 'PDU', etc.

-- Description & notes
description TEXT,
learning_objectives TEXT, -- what they were supposed to learn
personal_notes TEXT, -- their reflective notes

-- Status
status VARCHAR(50) DEFAULT 'completed', -- 'completed', 'in_progress', 'planned'

-- External references
course_url VARCHAR(2048),
certificate_number VARCHAR(200), -- if the cert has a tracking number

-- AI-generated content (stored after Claude processing)
ai_summary TEXT,
ai_tags JSONB DEFAULT '[]', -- ["pharmacology", "patient safety"]
ai_processed_at TIMESTAMPTZ,

-- Compliance cycle assignment
-- Which renewal cycle does this entry belong to?
cycle_start_date DATE,
cycle_end_date DATE,

-- Soft delete
is_deleted BOOLEAN DEFAULT FALSE,
deleted_at TIMESTAMPTZ,

created_at TIMESTAMPTZ DEFAULT NOW(),
updated_at TIMESTAMPTZ DEFAULT NOW()
);

CREATE INDEX idx_ce_entries_user_id ON ce_entries(user_id);
CREATE INDEX idx_ce_entries_completion_date ON ce_entries(completion_date);
CREATE INDEX idx_ce_entries_user_cycle ON ce_entries(user_id, cycle_start_date, cycle_end_date);

-- Full-text search index
CREATE INDEX idx_ce_entries_fts ON ce_entries
USING gin(to_tsvector('english',
coalesce(title, '') || ' ' ||
coalesce(provider_name, '') || ' ' ||
coalesce(description, '')
));


-- ============================================================
-- CERTIFICATE FILES
-- ============================================================

CREATE TABLE ce_certificates (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
ce_entry_id UUID NOT NULL REFERENCES ce_entries(id) ON DELETE CASCADE,
user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,

-- File metadata
original_filename VARCHAR(500) NOT NULL,
stored_filename VARCHAR(500) NOT NULL, -- UUID-based filename on disk
file_path VARCHAR(1000) NOT NULL, -- relative path from upload root
file_size_bytes INTEGER NOT NULL,
mime_type VARCHAR(100) NOT NULL, -- 'application/pdf', 'image/jpeg', etc.

-- AI extraction results
extracted_text TEXT, -- text pulled from PDF/image via AI
extraction_status VARCHAR(50) DEFAULT 'pending', -- 'pending', 'completed', 'failed'

uploaded_at TIMESTAMPTZ DEFAULT NOW()
);

CREATE INDEX idx_ce_certificates_ce_entry_id ON ce_certificates(ce_entry_id);
CREATE INDEX idx_ce_certificates_user_id ON ce_certificates(user_id);


-- ============================================================
-- COMPLIANCE CYCLES
-- ============================================================

CREATE TABLE compliance_cycles (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,

cycle_name VARCHAR(200), -- '2024 Annual Renewal'
start_date DATE NOT NULL,
end_date DATE NOT NULL,
required_hours NUMERIC(6,2) NOT NULL,

-- Category requirements (stored as JSON for flexibility)
-- {"Ethics": 2.0, "Clinical": 15.0}
category_requirements JSONB DEFAULT '{}',

-- Status
is_current BOOLEAN DEFAULT FALSE,
is_completed BOOLEAN DEFAULT FALSE,
submitted_at TIMESTAMPTZ, -- when they submitted to licensing body

notes TEXT,

created_at TIMESTAMPTZ DEFAULT NOW(),
updated_at TIMESTAMPTZ DEFAULT NOW()
);

CREATE INDEX idx_compliance_cycles_user_id ON compliance_cycles(user_id);


-- ============================================================
-- REMINDERS & NOTIFICATIONS
-- ============================================================

CREATE TABLE reminder_settings (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
user_id UUID NOT NULL UNIQUE REFERENCES users(id) ON DELETE CASCADE,

-- Email reminders
email_reminders BOOLEAN DEFAULT TRUE,
reminder_days_before INTEGER[] DEFAULT '{90, 60, 30, 14, 7}',

-- Digest
weekly_digest BOOLEAN DEFAULT FALSE,
digest_day_of_week INTEGER DEFAULT 1, -- 1=Monday

created_at TIMESTAMPTZ DEFAULT NOW(),
updated_at TIMESTAMPTZ DEFAULT NOW()
);


CREATE TABLE sent_reminders (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
reminder_type VARCHAR(100) NOT NULL, -- 'deadline_90', 'deadline_30', 'weekly_digest'
sent_at TIMESTAMPTZ DEFAULT NOW(),
email_subject VARCHAR(500),

-- Prevent duplicate sends
UNIQUE(user_id, reminder_type, DATE_TRUNC('day', sent_at))
);


-- ============================================================
-- REFERRAL SYSTEM
-- ============================================================

CREATE TABLE referrals (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
referrer_user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
referred_user_id UUID REFERENCES users(id) ON DELETE SET NULL,
referred_email VARCHAR(255) NOT NULL,

-- Status tracking
status VARCHAR(50) DEFAULT 'pending',
-- 'pending' (signed up, not paid), 'converted' (paid), 'rewarded' (credit applied)

-- Reward details
referrer_discount_pct INTEGER DEFAULT 30, -- 30% off for referrer
referred_discount_pct INTEGER DEFAULT 30, -- 30% off for new user

-- Stripe coupon IDs generated for each
referrer_coupon_id VARCHAR(100), -- Stripe coupon applied to referrer
referred_coupon_id VARCHAR(100), -- Stripe coupon applied to referred

-- Timestamps
invited_at TIMESTAMPTZ DEFAULT NOW(), -- when link was clicked/used
signed_up_at TIMESTAMPTZ,
converted_at TIMESTAMPTZ, -- when referred user first paid
rewarded_at TIMESTAMPTZ -- when referrer got their credit
);

CREATE INDEX idx_referrals_referrer ON referrals(referrer_user_id);
CREATE INDEX idx_referrals_referred ON referrals(referred_user_id);
CREATE INDEX idx_referrals_email ON referrals(referred_email);


-- ============================================================
-- AI USAGE TRACKING (cost control)
-- ============================================================

CREATE TABLE ai_usage_log (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
feature VARCHAR(100) NOT NULL, -- 'certificate_extraction', 'ce_summary', 'gap_analysis'

-- Token tracking
input_tokens INTEGER,
output_tokens INTEGER,
model VARCHAR(100), -- 'claude-3-5-haiku-20241022'

-- Cost in microdollars (integer math, no float errors)
cost_microdollars INTEGER,

-- Reference
ce_entry_id UUID REFERENCES ce_entries(id) ON DELETE SET NULL,

created_at TIMESTAMPTZ DEFAULT NOW()
);

CREATE INDEX idx_ai_usage_user_id ON ai_usage_log(user_id);
CREATE INDEX idx_ai_usage_created_at ON ai_usage_log(created_at);


-- ============================================================
-- AUDIT LOG
-- ============================================================

CREATE TABLE audit_log (
id BIGSERIAL PRIMARY KEY,
user_id UUID REFERENCES users(id) ON DELETE SET NULL,
action VARCHAR(200) NOT NULL, -- 'login', 'ce_entry.create', 'file.upload', etc.
target_type VARCHAR(100), -- 'ce_entry', 'user', 'subscription'
target_id VARCHAR(100), -- the UUID of the affected record
ip_address INET,
user_agent TEXT,
extra_data JSONB DEFAULT '{}',
created_at TIMESTAMPTZ DEFAULT NOW()
);

CREATE INDEX idx_audit_log_user_id ON audit_log(user_id);
CREATE INDEX idx_audit_log_created_at ON audit_log(created_at);


-- ============================================================
-- TRIGGERS: auto-update updated_at
-- ============================================================

CREATE OR REPLACE FUNCTION update_updated_at_column()
RETURNS TRIGGER AS $$
BEGIN
NEW.updated_at = NOW();
RETURN NEW;
END;
$$ language 'plpgsql';

CREATE TRIGGER update_users_updated_at
BEFORE UPDATE ON users
FOR EACH ROW EXECUTE PROCEDURE update_updated_at_column();

CREATE TRIGGER update_ce_entries_updated_at
BEFORE UPDATE ON ce_entries
FOR EACH ROW EXECUTE PROCEDURE update_updated_at_column();

CREATE TRIGGER update_user_subscriptions_updated_at
BEFORE UPDATE ON user_subscriptions
FOR EACH ROW EXECUTE PROCEDURE update_updated_at_column();
```

---

## 3. 6-WEEK BUILD PLAN

### Week 1: Foundation & Auth
Goal: Working Flask app with user accounts on production server.

Day 1-2: Project scaffold & deployment pipeline
- Set up project structure (see Section 5)
- Configure PostgreSQL, create database and user
- Set up Python virtual environment
- Configure nginx + gunicorn + systemd (see Section 6)
- `.env` file, `config.py` with dev/prod environments
- First `git push` β†’ auto-deploy via git hook

Day 3-4: Authentication
- User model + SQLAlchemy setup
- Flask-Migrate initialized, first migration
- Registration form (Flask-WTF): email, password, first/last name
- Login/logout (Flask-Login)
- Email verification flow (itsdangerous token β†’ Resend email)
- Password reset flow (forgot password β†’ email β†’ reset form)
- Basic user profile page

Day 5: Onboarding flow
- Post-registration onboarding wizard (3 steps):
1. Profession + licensing body
2. Cycle dates + required hours
3. Category requirements (optional)
- Store to `users` and create first `compliance_cycles` record
- Basic dashboard shell (empty state)

Deliverable: Can register, verify email, log in, complete onboarding, see empty dashboard. Lives on production URL.

---

### Week 2: Core CE Entry Management
Goal: Users can log and manage CE entries.

Day 1-2: CE entry CRUD
- Create CE entry form: title, provider, date, hours, type, description
- List view with sorting (date, hours) and basic filtering (by cycle, by status)
- Edit CE entry
- Soft delete CE entry
- Validation: future dates rejected, hours > 0, required fields

Day 3: File upload
- Certificate upload attached to CE entry
- File validation (type, size)
- Nginx X-Accel-Redirect for secure file serving (files not publicly accessible)
- View/download certificate from entry detail page

Day 4: Dashboard
- Progress ring/bar: hours completed vs required
- Hours by category (if categories configured)
- Recent entries list
- Days until deadline countdown
- "Entries needed to meet requirement" calculation

Day 5: HTMX polish
- Inline edit for CE entry fields (HTMX swap)
- Delete with confirmation dialog (Alpine.js modal, HTMX DELETE)
- Live search on entries list
- Pagination with HTMX (no full page reload)

**Deliv
🀝

Network & Word-of-Mouth

# Complete Network Activation & Word-of-Mouth Strategy
## CE/CPD Tracking App β€” Early-Stage B2B2C Growth Playbook

---

# SECTION 1: APPROACHING FRIEND #1 β€” REAL ESTATE AGENT (NSW)

## The Context You Need to Know First

NSW real estate agents must complete 12 CPD hours per year (Class 1 licence holders need more), with specific categories mandated by NSW Fair Trading. This is genuinely painful to track β€” agents often scramble at renewal time, risk licence suspension if non-compliant, and have zero good tools for it. You are solving a real, recurring, high-stakes problem.

---

## Exact Conversation Script β€” Real Estate Agent

Set the context first (text or voice message, casual):

> *"Hey [Name], got something I think might actually be useful for you β€” nothing salesy, just want your honest opinion. You still doing your CPD hours for your real estate licence? Got 2 minutes to chat this week?"*

When they respond yes, on the call/coffee:

> *"So I've been building this app β€” it's basically a CPD tracker for professionals who have to log continuing education for their licence. Real estate agents in NSW are one of the main groups I built it for because the NSW Fair Trading requirements are genuinely annoying to track manually.*
>
> *It lets you log your hours as you complete them, categorises them correctly, gives you a compliance report you can pull up instantly if someone asks β€” or just for your own peace of mind at renewal time. No more digging through emails and certificates at the end of the year.*
>
> *Honestly, I'd love for you to just try it and tell me if it actually solves the problem or if I've missed something obvious. I'll give you [offer β€” see below] because your feedback is more valuable to me right now than the subscription fee.*
>
> *The only thing I'd ask β€” if you find it useful, would you be comfortable mentioning it to a few of your colleagues? Not in a weird way, just like 'hey this thing actually works.' That's how I'm trying to grow this early on."*

If they ask "how much is it?":

> *"It's $7.99 a month after a free trial β€” less than a coffee a week. But for you, I'm giving you [extended offer] because I want you to actually use it and give me real feedback."*

---

## What to Offer Friend #1

Recommended offer: 3-month free extension + lifetime 50% discount

Here's the logic: A lifetime free account has no perceived value. A cash commission feels transactional and may make them uncomfortable recommending it. But a 3-month free trial (instead of 30 days) gives them time to genuinely fall in love with the product, and a permanent 50% discount ($3.99/month) gives them ongoing skin in the game β€” they're a paying customer, which makes their recommendation authentic.

The exact offer line:

> *"I'm going to give you 3 months completely free β€” no credit card needed yet. And when you do convert, I'll lock you in at half price permanently, $3.99 a month, as a founding user. That rate never goes up even when I raise prices later."*

If they become an active referrer (5+ signups from them): Upgrade to lifetime free, which you communicate as a surprise reward, not an upfront bribe.

---

## How to Turn Them Into an Active Advocate

Step 1 β€” The Seeding Moment (Week 1)
After they sign up, send them a message:
> *"Once you've logged a couple of things, try pulling up the compliance report β€” it shows your total hours, the category breakdown, everything. I'd love to see what you think of it."*

Getting them to use that one feature early is critical β€” it's the "wow moment."

Step 2 β€” The Natural Share Setup (Week 2)
> *"I know agents in your office also have to do CPD. Would you be comfortable just mentioning it in your next team meeting or WhatsApp group? Even just 'hey this app I'm using seems to do what we've all been complaining about' β€” that's all I need."*

Step 3 β€” Give Them a Tool to Share (Week 3)
Send them a unique referral link with their name in the URL parameter (e.g., app.com/try?ref=sarah-jones). This feels personalised, not spammy.

> *"I made you a personal invite link β€” if you share it and they sign up, I'll track it and make sure you get credit for it. Thinking of doing something nice for people who bring in early users."*

Step 4 β€” Make It About Their Status, Not Your Growth
Frame sharing as them being the person who "found the good tool first":
> *"You could genuinely be the person in your office who sorted this out for everyone. Agents are always complaining about CPD admin β€” you'd be the one who fixed it."*

---

## NSW Real Estate Agent Network Reach

One active real estate agent in NSW realistically has access to:

| Network | Estimated Size |
|---|---|
| Their immediate office/agency | 10–30 agents |
| Principal/office WhatsApp groups | 20–50 people |
| Industry events / CPD training days | 50–200 peers |
| NSW real estate Facebook groups | 2,000–15,000 members |
| LinkedIn professional connections | 200–500 industry contacts |
| REINSW member network (indirect) | ~4,000 active members |

One well-connected agent, properly motivated, could realistically drive 15–40 signups through organic sharing alone. Two or three such agents creates a genuine growth loop.

---

# SECTION 2: APPROACHING FRIEND #2 β€” ACCOUNTANT (CPA/CA ANZ)

## The Context You Need to Know First

CPA Australia requires 120 hours of CPD over a 3-year rolling period (minimum 20 hours per year), with requirements for structured vs. unstructured learning. CA ANZ requires 120 hours over 3 years as well. Both require members to self-report and maintain records β€” and both associations can audit members. An accountant who can't produce records faces suspension of their designation. This is high-stakes compliance, not optional admin.

---

## Exact Conversation Script β€” Accountant

Opening message:

> *"Hey [Name], quick question β€” how do you track your CPD hours for CPA/CA? Like do you have a system or is it the usual 'I'll figure it out at the end of the year' situation?"*

*(This question is designed to surface the pain before you pitch the solution.)*

When they admit to the problem (they will):

> *"Yeah, that's exactly why I built this. I've been working on a CPD tracker β€” it logs your hours, tells you where you're at against your annual and triennial requirements, and spits out a compliance report. For CPA and CA members specifically.*
>
> *I want you to be one of my first users β€” not because I want your money, but because I want feedback from someone who actually lives this problem. You'll tell me if something's wrong or missing.*
>
> *I'll give you [offer] and if you like it, the only ask is that you mention it to a few people. Not a formal thing β€” just 'hey this actually works' in the right moment."*

Key framing difference from the real estate script: Accountants are analytical. Lean into the compliance audit angle:

> *"The thing that resonates most with accountants is this: if CPA Australia audits your CPD records, you need to produce them on demand. Most people have a folder somewhere with PDFs they hope they can find. This app means you can pull up a formatted report in 30 seconds. That's the peace of mind it's really selling."*

---

## What to Offer Friend #2

Same structure as Friend #1: 3 months free + lifetime 50% discount

But add one element specifically for the accountant:

> *"I'm also going to make you a 'Professional Advisor' for the app β€” which just means I'll occasionally ask you whether the CPD tracking logic is right for CPA/CA requirements. It keeps you in the loop as I develop it, and means the product actually reflects how accountants work."*

This gives them identity investment β€” they helped build it. That makes them a natural advocate.

---

## How to Activate Their Professional Network

Accountants have uniquely high-value professional networks. Here's how to activate them:

Channel 1 β€” The Accounting Firm
Most accountants work in firms with 5–50 staff, most of whom have CPA or CA designations. The accountant can:
- Mention it in a team meeting ("I found something that actually works for our CPD tracking")
- Forward a sign-up link via internal email
- Suggest it to their practice manager as a firm-wide solution

Ask them specifically:
> *"Is there a team meeting coming up where you could mention it? Even just 'I've been testing this app for CPD tracking, anyone else interested' β€” I'd set everyone up on the free trial."*

Channel 2 β€” Study Groups / Exam Cohorts
CPA and CA candidates often have informal study groups from their qualification days. These people are highly active CPD trackers because they're still in compliance mode.

> *"Do you still have a WhatsApp or group chat from when you were doing your CPA modules? Those people would probably love this."*

Channel 3 β€” LinkedIn Professional Content
Accountants on LinkedIn are often looking for content to post. Offer to help them write a post:

> *"Would you be up for posting about it on LinkedIn once you've used it for a few weeks? I can help you draft something if that's useful β€” or you just write it in your own words, that's honestly better anyway."*

A single LinkedIn post from a credible accountant in their professional network can reach 500–2,000 relevant people.

Channel 4 β€” CPA/CA Local Chapter Events
CPA Australia and CA ANZ both have local chapter events, study groups, and webinars. Your accountant friend may attend these.

> *"Do you ever go to CPA local chapter events or anything like that? If you're heading to one, would you be willing to just mention it if the topic comes up?"*

---

# SECTION 3: WORD-OF-MOUTH MECHANICS

## What Makes Professionals Share a Tool With Colleagues

Professional sharing is fundamentally different from consumer sharing. People don't share tools to look generous β€” they share them to look competent, informed, and helpful. The psychological trigger is: *"I am the person who found the good solution to our shared problem."*

Your app needs to activate three specific sharing triggers:

Trigger 1 β€” Shared Pain Recognition
The moment two colleagues complain about the same CPD hassle, whoever has the solution wins social capital. Design for this moment: make the app's value so immediately obvious that a user instinctively thinks "I need to tell [colleague] about this."

Trigger 2 β€” Visible Credibility
When a user pulls up a clean compliance report in a professional context (team meeting, licence renewal, audit response), colleagues see it and ask "what is that?" This is the single most powerful organic sharing moment. Design the compliance report to be visually impressive, branded with the app name.

Trigger 3 β€” FOMO at Compliance Season
Licence renewal periods and CPD audit periods are your peak virality windows. When one person in an office gets reminded about their CPD deadline, everyone does. Your user who's already on top of it becomes an instant advocate.

---

## In-App Shareable Elements

1. The Compliance Status Card
A one-screen summary showing:
- "βœ… 34/40 hours completed β€” On Track"
- Visual progress bar
- Next deadline countdown

This should be shareable as a PNG or screenshot-friendly. Users will screenshot it to send to their employer/principal/manager to prove compliance. The app name and branding should be clearly visible in the corner.

2. The Annual CPD Report (PDF)
A formatted, professional PDF that looks like it could be handed to a regulator. Include:
- User's name and licence/membership number
- Total hours logged
- Category breakdown
- Individual activity log with dates and certificates

When a user emails this to their employer or attaches it to a licence renewal, anyone who receives it sees the app name. This is passive word of mouth at zero cost.

3. Shareable Milestone Notifications
In-app moment: *"You've completed your annual CPD requirement πŸŽ‰"*
Make this shareable to LinkedIn with one tap β€” pre-written copy:

> *"Just logged my final CPD hours for the year with [App Name] β€” first time I haven't been scrambling at renewal time. If you're in [profession], worth a look: [link]"*

This is authentic, not promotional-feeling, and reaches exactly the right professional audience.

---

## The "Show-Off" Moment

The specific scenario where users naturally pull out the app in front of a colleague:

Scenario A β€” The CPD Training Day
An agent or accountant attends a mandatory CPD session. At the end, while others are scribbling on paper or making a mental note, your user opens the app and logs it immediately. A colleague asks "what are you doing?" β€” this is your word-of-mouth moment.

Design for this: Make the log-activity flow take under 30 seconds. A fast, slick logging experience is what gets noticed in this moment. If it takes 90 seconds with multiple fields, they won't bother and the moment dies.

Scenario B β€” The "I'm Already Done" Moment
Team meeting, someone raises the CPD deadline coming up. The anxiety hits the room. Your user casually says "oh I've already done mine" and opens the app to show they're 100% compliant. That visual is magnetic.

Scenario C β€” The Renewal Conversation
Licence renewal time. Your user emails their compliance report to their principal/employer in 30 seconds flat. The employer is impressed and asks what tool they used.

---

## Making Referral Feel Natural, Not Transactional

The rule: Never ask someone to "refer" a friend. Ask them to "tell" a colleague if they're finding it useful.

Transactional framing (avoid):
> *"Share your referral link and earn $5 for each signup."*

Natural framing (use):
> *"If you know anyone else who's doing the same CPD juggle, feel free to send them the link β€” I'm giving everyone from your circle the same free trial."*

The difference: Transactional framing makes people feel like salespeople. Natural framing makes them feel like a generous colleague passing on a useful tip.

Other natural sharing moments to engineer:
- After they generate their first compliance report: "Want to send this to your employer? There's a share button β€” and if they ask how you made it, the app name's at the bottom."
- When they hit their annual requirement: offer a shareable LinkedIn badge
- In the onboarding email sequence (Day 7): "Most people tell 1–2 colleagues who are in the same boat β€” feel free to send them your invite link. There's no obligation and no weird referral stuff, just extending the free trial to people you think would benefit."

---

# SECTION 4: ASSOCIATION PARTNERSHIPS

## REINSW (Real Estate Institute of NSW)

Who they are: Peak body for NSW real estate professionals. ~4,000+ active members. They run CPD training courses themselves, publish resources on CPD requirements, and communicate with members via email newsletters, webinars, and events.

Why they might care:
REINSW is in the business of making their members' professional lives easier. A tool that helps members stay compliant (and stay members in good standing) serves REINSW's mission. However, they also run CPD training themselves, so you need to be clear you're a tracking tool, not a training provider β€” you're complementary, not competitive.

How to approach:

*Step 1 β€” Find the right contact*
Look for: Membership Manager, Head of Member Services, or Education Manager on the REINSW website or LinkedIn. This is not a cold sales call to a procurement team β€” it's an outreach to a membership services person.

*Step 2 β€” The opening email (exact draft):*

Subject: Tool that helps REINSW members stay CPD compliant β€” worth 10 minutes?

> *Hi [Name],*
>
> *I'm the founder of [App Name], a CPD tracking app built specifically for licenced professionals β€” including real estate agents under NSW Fair Trading requirements.*
>
> *I'm reaching out because I think there's a natural alignment between what we're building and what REINSW does for its members. We're not a CPD training provider β€” we're purely a tracking and compliance tool. Members use it to log their hours as they complete them, track progress against their annual requirements, and generate a compliance report they can