Changelog

New updates, improvements, and fixes for Optio.

Core Gets a VA Seat

v0.14.0

Optio exists so you can hand student support to an assistant without handing over your admin password. Until today the entry plan couldn't actually do that — Core included a single seat, and the school admin already occupied it. Core now includes a seat for one VA.

Updates

  • Core includes 1 admin + 1 VA. Your assistant gets student lookup by email and course progress. They cannot see revenue, lifetime value, or your full student list — that's enforced by their role, not by a setting they can switch off.
  • Clearer seat counts. Plan seat limits have always counted the admin. That's now stated explicitly rather than implied.
  • Core plan messaging now leads with delegation rather than "essential student tracking", which is what the plan is actually for.

Fixed

  • Expired schools now lock staff too. When a subscription lapsed, the school admin lost access but their VAs and tutors kept working — so a school could stop paying and carry on through delegated staff. All roles are now locked consistently. Active trials and the 48-hour payment grace period are unaffected.
  • VA search access on older accounts. Schools created before role permissions shipped could end up with a VA who could sign in but not search for anyone. The fallback defaults now match the ones new schools get.
  • Access Policies permission accuracy. The permission check for editing role policies reported access that admins on Core and Insight don't have. The page itself always showed the correct upgrade prompt, so nothing changes in practice — the underlying check is simply no longer misleading.
  • Course data on transactions was never being stored. Teachable doesn't include a course on a transaction — it's only on the pricing plan — so every synced transaction recorded no course at all. Optio now resolves it properly. This is why the Ascension & Leakage report could show no products to choose from. Existing transactions pick up the course on their next sync.
  • "Access Until" now correct for fixed-date products. If a product is set so that every student loses access on one specific date, Optio previously showed no end date at all — indistinguishable from access that never expires. Both of Teachable's limited-access modes are now handled, and dates read from the product's real settings are no longer marked as estimates.
  • Analytics pages now respect your plan. Retention Risk, Course Insights and the Ascension report checked only whether you were an admin, not whether your plan included them — so they were reachable by direct link from a plan that doesn't include analytics, and stayed reachable after a subscription lapsed. All three now apply the same plan and role checks as everywhere else. They also now show the correct school when a Optio support session is viewing your account.

Course Extensions

v0.13.0

A student pays for six months of access, gets to 86%, and runs out of time. Teachable can't help — its access limits are one-time by design, and its own documentation says the only remedy is to manually re-enrol the student. Do that by hand and you've granted access with no end date and nothing to remind you to take it back.

Optio now does it properly: grant the extra days, and access is removed automatically when they're up.

Added

  • Course Extensions tab: A new tab on Student Search. Pick a course, set a duration in days, add an optional note, and the student is re-enrolled immediately. Live extensions show days remaining and can be revoked in one click.
  • Grant history: Every extension keeps a permanent record — who granted it, when, the note attached, and how it ended. This replaces tracking extensions by hand in a spreadsheet or an email label.
  • Extend before or after access ends. Students usually ask for more time shortly before they lose access. Either works — if their access is still live, Optio tells you the new expiry date will be the one that applies.
  • Renewal protection: If a student re-purchases the course during an extension, the expiry leaves their access alone and closes the extension with a note explaining why. You can't accidentally strip something they just paid for.
  • Visible at a glance: A student with a live extension carries a badge next to their name on Overview & Data, and a panel listing each course and how long is left. You don't have to open the Extensions tab to find out.
  • Recorded in Internal Notes: Granting and ending an extension both write a line into the student's notes — the course, the duration, the expiry date, and the reason if one was given. These entries are locked: they can't be edited or deleted, because they're the record of who gave away access to a paid course.
  • Access ends automatically. A background job removes access when an extension runs out, so nothing depends on someone remembering. If a student re-purchased in the meantime, it leaves their access alone.
  • Dashboard summary: Your home page now shows how many extensions are live and how many are due today, within three days, and within seven — with the most urgent listed by student and course, one click from their record.
  • Extensions page under Students. Every extension in one table, opening on the live ones, with filters for those that have ended and a search across students, courses and notes. Revoke from the list without opening each student.
  • "View All Extensions" permission. Granting an extension and seeing the whole school's are now separate toggles under Access Policies, the same way viewing the student directory is separate from searching for one student. VAs get both by default; turn the second off to keep a VA to the student they're working on.
  • Expiry warnings: Extensions with three days or fewer remaining are highlighted.

Updates

  • Extensions are now their own plan feature. Previously extensions were gated on the same permission as Student Notes, which meant school admins on Core could grant them while their own VAs could not. Extensions are now an explicit Insight and Mastery feature, applied consistently to admins and staff alike.
  • Per-role control: As with other staff capabilities, admins choose which roles can grant extensions from Role Permissions. A VA needs both the plan and the toggle.
  • Courses the student can still reach are labelled in the picker so you know before you grant.
  • API usage card removed from the dashboard. Teachable doesn't meter API calls, so the figure was our own count shown against a limit that doesn't exist. The space now carries the extensions summary.

Data Ingestion, CSV Imports & Engine Stability

v0.12.0

Today's release focuses on massive improvements to our data ingestion engine, giving users more ways to import their historical data while bulletproofing our background workers.

Added

  • Manual CSV Import: Added a robust client-side CSV importer. Users can now manually upload their Teachable transaction exports to populate their dashboards.
  • Tiered Import Limits: Implemented smart file-size limits for CSV uploads (10MB for Core users to get a "cold start", 50MB for premium tiers).
  • Onboarding Dashboard: Added a new "Cold Start" view to the Financials dashboard, clearly presenting users with their data connection options (Automated API Sync vs. Manual CSV Upload).
  • Dynamic Upsells: Added custom marketing copy capabilities to locked features, explaining exactly what users unlock when they upgrade.

Updates

  • Permission Simplification: Streamlined our access control logic. The Core plan now officially supports manual data imports to help new users experience the platform faster.
  • Background Worker Efficiency: Upgraded the QStash background sync engine to detect terminal authentication errors (like an invalid API key) and gracefully abort, saving server resources.
  • Database Schema: Upgraded the Transaction schema to natively capture Product Names, ensuring imported CSV data (which lacks Teachable Course IDs) still beautifully populates dashboard charts.

Fixed

  • Bug: Fixed a critical "Ghost Tenant" database crash where overlapping Teachable transaction IDs across different accounts would cause imports to fail.
  • Bug: Fixed an issue where the CSV importer would crash on batch duplicate transactions. (Deduplication is now handled efficiently in-memory before saving).
  • Bug: Fixed a UI bug where invalid Teachable API keys would fail silently in the background. The dashboard now instantly flags the user with a helpful error message and a link to update their settings.
  • Bug: Fixed a naming mismatch in the feature lock UI between the "Scale" and "Mastery" subscription tiers.

Feedback from our Beta Users

v0.11.0

Today we focused on reviewing the excellent feedback we've received via email and videos from our beta users.

Added

  • Sorting Columns: Added sorting options to the transaction and VIP tables for easy sorting by LTV and number of enrollments.
  • Custom Date Range Filter: Added a custom date range filter to the transaction table and VIP views.

Updates

  • UI Improvement: Added info badge to show exactly what date period the data table is showing.

Fixed

  • Bug: Connected Google Sign in so that users can now sign in with their Google account.
  • Bug: Fixed a problem where new users would not be able to create a new subscription.
  • Bug: Fixed a bug where the pricing table would not display the monthly price.

Student LTV, Risk Badges, and Transaction Fixes

v0.10.0

Today's update brings powerful new CRM metrics to the student profile, laying the groundwork for better insights, alongside several key bug fixes for historical transaction data.

Added

  • Student Lifetime Value (LTV): Updated the LTV metric to the student profile that dynamically calculates total revenue generated by a student, automatically deducting any partial or full refunds.
  • Risk Indicator Badges: The student profile now automatically flags high-risk accounts with visual warning badges if a student has a history of standard refunds or bank chargebacks.
  • CSV Importer UI (Beta): Shipped the foundation for the new Insight tier's drag-and-drop CSV importer dropzone (parsing logic coming soon).

Changed

  • Discount Detection: Upgraded the discount detection logic to strictly check for the presence of a coupon_id, eliminating bugs caused by cross-currency exchange rate math.
  • Discount Badges: Updated the "COUPON APPLIED" badge to the transaction table for easily identifying discounted sales.
  • Payout Normalization: Hardcoded the "Paid" column in the transaction table to exclusively format as USD, accurately reflecting Teachable's backend payout normalization regardless of the local list price currency.

Fixed

  • List Price Display Bug: Fixed an issue where the transaction list price would display as $0 for archived or custom-bundled plans. The system now correctly pulls the exact historical final_price from the original receipt.
  • Refund Math Accuracy: Patched the LTV calculation engine to use the exact amount_refunded field from the API, ensuring perfect math across both partial and full refunds without relying on fragile status strings.
  • UI Table Styling: Resolved an HTML/Tailwind layering bug that was preventing custom row background colors and hover states from displaying properly in the transaction table.

Background Sync Engine & QStash Migration

v0.9.0

Today we completed a major architectural overhaul of our data synchronization engine. By migrating from synchronous server actions to a resilient, background-driven queue system, we've positioned the platform to handle schools with hundreds of thousands of transactions without timing out or exceeding API limits.

🚀 Major Improvements

  • QStash Background Worker Implementation: Replaced the vulnerable while(true) loop in Next.js server actions with a recursive background worker powered by Upstash QStash. This ensures that long-running imports are decoupled from the frontend and can run reliably in the background.
  • Adaptive Time Windowing: Implemented a "smart" sync cursor that automatically adjusts its time window. The engine now attempts to sync in 1-month chunks for speed but automatically downshifts to 1-day or 1-hour increments if it detects a period with more than 10,000 transactions, staying safely within Teachable's pagination limits.
  • Incremental Sync Logic: Introduced smart incremental syncing. The engine now detects previous successful syncs and only pulls the last 5 days of data for existing schools, drastically reducing API overhead and Upstash message usage.
  • Schema Simplification: Streamlined the Transaction model by removing redundant schoolId fields in favor of our internal encrypted tenantId partitioning.

🛠 Technical Changes

  • Teachable SDK Enhancements: Modified lib/teachable.ts to support an override context, allowing background workers to bypass Clerk authentication and inject decrypted API keys directly into requests.
  • Real-time Progress Polling: Refactored SyncManager.tsx to poll the database state. The UI now accurately reflects background progress even if the user navigates away and returns to the dashboard.
  • Automated Retries: Leveraged QStash's built-in retry logic to automatically handle Teachable API 429 (Rate Limit) errors with exponential backoff.

🔒 Security & Access

  • RBAC Refinement: Centralized feature gating in lib/access-rules.ts by integrating the checkPermission helper from lib/plan-details.ts. This ensures that Admin vs. Staff permissions are consistently applied across all subscription tiers.
  • Worker Authentication: Secured the new /api/qstash/sync endpoint using QStash signature verification to ensure only authorized queue messages can trigger data processing.

New Pricing Tiers, Infrastructure Upgrades, and API Mitigations

v0.8.0

This release includes a major overhaul of our subscription tiers to better align with the value we provide, alongside critical infrastructure upgrades and mitigations for third-party API instability.

Added

  • Pricing Page Safeguards: Added a highly visible warning banner to the pricing page clarifying that an active Teachable Pro plan (or higher) is strictly required to unlock the API and webhook access Optio needs.
  • Import Feature Gating: Restructured the historical data import strategy to align compute costs with customer Lifetime Value (LTV). Core is now real-time webhook only, Insight will support CSV uploads, and Mastery retains the premium background API sync.
  • Smart Quota Resets: Added defensive logic to the Stripe webhook listener so that email limits (quota.emailsSent) only reset on genuine recurring subscription payments, ignoring manual one-off invoices.
  • Update Notice: Added a link to the changelog and repo hash on GitHub (for internal tracking) into the update notice banner.

Changed

  • Tier Renaming: Completely overhauled the subscription tier names from Starter, Growth, and Scale to Core, Insight, and Mastery. This eliminates UI and marketing confusion with Teachable's native plan names.
  • Database Migration: Successfully executed a database-wide update across the MongoDB tenants collection, safely mapping all existing user records to the new plan identifiers.
  • Stripe Webhook Resiliency: Refactored the POST webhook listener for Stripe renewals. The mapping function now safely supports the new uppercase STRIPE_PRICE_* environment variables while retaining legacy ID fallbacks, ensuring existing users are never accidentally downgraded during their billing cycle.

Fixed

  • Teachable Pagination Crashing: Investigated and mitigated a critical failure where the Teachable API threw unhandled exceptions ("error": "unknown") during paginated batch requests. Isolated the issue to specific malformed records on their backend and adjusted our internal import strategy to handle their API's fragility.

Tutor Access Controls & Settings Architecture Split

v0.7.0

We've deployed a major update to how Optio handles permissions, specifically focusing on the new Tutor role, alongside a critical database upgrade that isolates financial configurations from course management.

🛡️ Tutor Role-Based Access Control (RBAC)

Tutors now have a strictly walled-off experience to ensure they only see the students and courses relevant to their assigned subjects.

  • Smart Course Filtering: Tutors navigating to the Courses view will now only see courses that are mapped to their assigned categories (e.g., a "Math" tutor only sees Math courses).
  • Filtered Student Directory: The Student Directory now pre-filters API requests so Tutors only see students who are actively enrolled in their specific courses, eliminating data leakage.
  • Robust Category Matching: The category matching engine was overhauled to be case-insensitive and support comma-separated lists. An admin can now map a course to "Math, Science", and tutors assigned to either category will securely gain access.

🗄️ Architecture: Settings Data Split

Previously, financial product aliases and course categories shared a single database field (productMappings). This created a risk where a VA cleaning up financial dashboards could accidentally overwrite a Tutor's course access.

  • Two Distinct Maps: The database has been cleanly split into productOverrides (used exclusively for Financial reporting) and courseCategories (used exclusively for Tutor RBAC).
  • Dedicated Manager UIs: We launched two separate UI views in the Settings dashboard:
    • Product Name Overrides: A manual mapping tool for VAs and Admins to clean up raw Teachable Bundle IDs on the Financials dashboard.
    • Course Categories: A new, smart UI that automatically fetches and searches through all Teachable courses, allowing Admins to assign categories with a seamless auto-save feature.

🐛 Bug Fixes & Stability

  • Zod Schema Modernization: Upgraded the Teachable API response validation to use Zod's modern looseObject() pattern, ensuring unexpected future payload changes from Teachable don't break the application.
  • Sentry / Clerk Middleware Crash Resolved: Fixed a persistent issue where automated bot traffic requesting missing static assets (like favicon.png) bypassed the Next.js proxy matcher but triggered the root layout's auth() check, causing false-positive crashes in Sentry.
  • Prop Cleanup: Standardized prop drilling across the Student Lookup and Financial components to properly reflect the new productOverrides nomenclature.

Changelog Launched and other fixes

v0.6.0

Today, we are rolling out our changelog so everyone can see what's available in our latest release.

Added

  • A simple markdown changelog.

Changed

  • Improved the footer navigation links.

Transaction Sync Engine & Advanced Financials

v0.5.0

A major leap forward in financial reporting. The new Sync Manager allows schools to pull in historical transaction data to generate beautiful, server-side rendered financial pulses.

Added

  • Transaction Sync Manager: A robust sync feature to safely import your Teachable transaction history.
  • Financial Pulse Dashboard: Daily revenue trend graphs, tooltips, and server-side rendering for lightning-fast financial insights.
  • Whales Tracking: Advanced models to identify and track your highest-spending "Whale" students.
  • Founder Tier & Feature Locking: Rolled out the exclusive Founder tier and implemented dynamic feature locking based on active subscription tiers.
  • Legal: Published official Privacy Policy and Terms of Service.

Fixed

  • Strict enforcement of LTV views: Virtual Assistants without explicit financial permissions can no longer view Lifetime Value data.
  • Fixed the team quote calculation bug.
  • Corrected redirect URLs to properly utilize environment variables in production.

Stripe Billing Integration & Feature Locking

v0.4.0

This release introduces our self-serve billing infrastructure and gives school owners more control over how their courses are mapped within Optio.

Added

  • Stripe Integration: Full checkout, webhooks, and a self-serve customer billing portal.
  • Product Mapping & Course Hiding: You can now map specific products and hide certain courses from your dashboard views.
  • Announcements: New admin capability to push platform announcements.
  • VIP Views: Initial mockups and data structures for tracking high-value students.

Fixed

  • Fixed edge cases resulting in duplicated tenants and improved user linking during onboarding.
  • Addressed upgrade/downgrade logic issues, including removing "none" plan errors from the billing view.
  • Fixed multiple bugs related to the admin-initiated invite system, token generation, and invite messaging.
  • Platform owners no longer count towards the admin seat limits.

Optio Rebrand, RBAC & Teachable API Bridge

v0.3.0

A massive update that defines our core value proposition: secure, granular control for scaling schools. We've officially rebranded from Cato to Optio and completed our core Teachable integration.

Added

  • Granular Role-Based Access Control (RBAC): Complete overhaul of our permissions system allowing for highly specific access rules across the platform.
  • Teachable API Bridge: The main data conduit connecting Optio to your Teachable school is now fully operational.
  • Official Rebrand: All branding, UI, and references updated to Optio.

Fixed

  • Restored and stabilized the tenant creation flow, including edge cases for empty domains.
  • Fixed multiple Next.js build errors and integration bugs related to Clerk middleware and school connection states.
  • Ensure user synchronization occurs flawlessly when loading the dashboard layout.

Student Insights, LTV & Directory Alpha

v0.2.0

Moving beyond infrastructure, this update introduces the first analytical capabilities to help schools understand their student base better.

Added

  • Insights & Home Dashboard: A brand new high-level overview of school performance.
  • Student Directory: Initial concept rollout for searching and managing the student roster.
  • LTV & Retention Tracking: New features to track Student Lifetime Value (LTV) and course retention metrics.
  • Student Notes: The ability for team members to edit, delete, and manage notes on individual student profiles.
  • Team Settings: Expanded control over team member configurations.

Fixed

  • Resolved an issue with the missing dashboard client on initial load.

Core Infrastructure, Authentication & Theming

v0.1.0

Welcome to the first official development log! The core foundation of the application has been laid down, focusing on top-tier security and a seamless user experience.

Added

  • Clerk Authentication: Enterprise-grade security for user sign-ins and team management.
  • Database & Security: Implemented MongoDB with secure encryption protocols and dynamic tenant context to keep school data strictly isolated.
  • School Settings Page: Secure area for API key management with masking and role-based navigation.
  • User Management Dashboard: A dedicated space to manage active users and view actual course enrollment statuses.
  • Theming: Full light and dark mode support across the entire application interface.