Terms and Concepts

System concepts and data standards define the foundational, global configurations and resources that apply across all customers. These entries shape the overall behavior, capabilities, and presentation of an application built on the Baseplate framework. They support consistency, security, and maintainability.  All of the following would be included as “example” system wide setting.

As noted above, this data will be provided to application via a pre-configured set of data provided centrally via a application configuration library. Examples of what we would provide include:

  • Static Configurations
    • Application-wide feature flags, default preferences, licensing terms, and versioning information.
    • Configurations controlling system behavior such as logging levels, API rate limiting, or maintenance schedules.
  • Security & Access Controls:
    • Definitions of global roles and permissions that apply to all customers (e.g., system admin roles).
    • API authentication and authorization configurations (e.g., OAuth client IDs, certificate stores).
  • Master Data/Lookups:
    • Lists of supported countries, languages, currencies, or time zones.
    • Enumerations for status codes, priority levels, or other universally applicable parameters.

Terms

This isn’t intended to be an exhaustive list but is representative of what we want to store as system level setting

  • Customer - A group of users that has access to the application.   This term is used as a synonym for what is variably thought of as a customer or tenant for a SaaS application.   We’ve chosen customer as it’s generally the most commonly used term we see in SaaS. 
    • A customer can either be “paying” or “non-paying” and, in essence, is a bucket that contains users and is mapped to a paying, legal entity that holds a license. 
    • Typically, a customer is a for profit business but a customer could also be a non-profit organization or government entity. 
  • User - An individual that is using the application.  
  • Role - A specific "type" of user of the application. Roles define the set of features a user can access in the application and how they interact with them.   This is principally used to define WHAT the user can access in the application.   We discuss this in detail in the Role Based Authentication document.

Out of Box User States

StateDescription
ActiveThe user is fully authorized to log in and access the system. They are in good standing and tied to a customer account that is also in good standing.
InactiveThe user is not currently able to access the system, but their account is preserved. This state is typically used for users who have left an organization or are temporarily deactivated but may return. They remain associated with the customer account.
SuspendedThe user’s access has been locked due to a policy violation, security issue, or manual administrative action. They cannot regain access until cleared by a customer administrator, customer success manager, or system administrator.
Pending InviteThe user has been invited to the system but has not yet accepted the invitation or completed account setup. No access is granted until activation.
Password Reset RequiredThe user must reset their password before gaining access—typically triggered by a security policy or manual reset request.
Locked OutThe user has been temporarily locked due to multiple failed login attempts or similar automated security protection mechanisms. May auto-resolve or require admin intervention.

Out of Box Customer Status Options

Every Customer (tenant) within the Baseplate Framework has a Status property that reflects its lifecycle stage. Status in the system is a single, specific state indicating their lifecycle. We support the following statuses out of the box:

StateDescription
SetupThe customer is a "shell" tenant that has yet to complete any onboarding process. This is used to model customers that the system has created but have not yet completed an onboarding flow. This is a transient state, often used for internal setup or incomplete registrations.
FreeThe customer (or internal team on their behalf) has completed onboarding. The account is active with access to free-tier features. Premium capabilities may be visible but disabled (e.g., grayed out) to encourage upgrades.
TrialThe customer is currently within a time-bound free trial period that grants access to premium or full platform capabilities. The customer has access to a fully functioning environment with all features enabled, but has not paid. This is typically used for high-touch sales or onboarding processes and is time-limited. Functionally similar to a trial, but with extended or ongoing access based on active billing.
SubscribedThe customer has an active paid subscription with access to all licensed features and services based on their plan.
SuspendedThe customer’s access is temporarily restricted—typically due to billing failures, policy violations, or manual admin action.
CancelledThe customer was previously subscribed or trialing, but their subscription has been cancelled and access has lapsed.
Expired TrialThe customer completed a trial but did not convert to a paid subscription. They may have reverted to a Free plan.
Pending SetupThe customer account has been created, but onboarding or initial configuration steps have not yet been completed.
ChurnedThe customer previously had an active subscription but has been inactive or unsubscribed for a defined period. Typically used for re-engagement tracking. Note that Customer that have stopped paying are not automatically handled. Instead, they are flagged for manual review and downgrade via Stripe. This ensures that potential churn is treated as a meaningful event—prompting internal analysis and, if necessary, customer outreach.
Internal/TestAn internal or sandbox account used for testing, demo, or staging purposes—excluded from billing and production metrics.

Handling Status Changes

In the early stages of building on the Baseplate Framework, we are intentionally adopting a manual-first approach to managing customer status changes. This not only minimizes upfront engineering cost but also forces deliberate human review of any account state transition, encouraging teams to think critically about why a customer is changing states and what implications that has for the product and business.This ensures that developers and product teams are actively thinking about:

  • What triggered the change?
  • Is this state transition appropriate for this customer?
  • What should the customer experience as a result?

This mindset is essential to building customer-centric products and prevents premature optimization through automation. As usage grows, we expect apps to layer in automation around common and predictable state changes (e.g., trial expiration, payment failures). But this will be guided by real-world usage data and grounded in a deep understanding of customer lifecycle dynamics, learned through the manual process.

Demo v. Production Customers

Demo tenants—used for internal testing and sales demos—are functionally identical to production tenants. To ensure realism, they use the same infrastructure and data models, differentiated only by their status value.

  • Demo tenants do not expire automatically. They are removed through manual processes, avoiding unnecessary code complexity until volume demands it.
  • Conversion to real customers is straightforward: when a demo user completes paid onboarding, the system simply transitions the tenant’s status to “Subscribed.”

Concepts

Industries

The system wide industry list is normalized to the diffbot industry list which provides a fine grained list of industries for all 246M companies in the database. This configuration data would be made available via Firebase Remote Config.

  
For certain apps that leverage LinkedIn integrations we will also need to provide a mapping between the Diffbot industry list and the officially LinkedIn industry list provided from Microsoft.   As and if needed this will be generated at the time of app buildout via a simple LLM query to map the diffbot list of the Microsoft list with a basic human review to follow.  

States and Provinces

Initially the Baseplate will limit country scope to US and Canada.  

Here is a list of the 50 US states and 10 Canadian provinces in a comma-delimited format:

States: Alabama, Alaska, Arizona, Arkansas, California, Colorado, Connecticut, Delaware, Florida, Georgia, Hawaii, Idaho, Illinois, Indiana, Iowa, Kansas, Kentucky, Louisiana, Maine, Maryland, Massachusetts, Michigan, Minnesota, Mississippi, Missouri, Montana, Nebraska, Nevada, New Hampshire, New Jersey, New Mexico, New York, North Carolina, North Dakota, Ohio, Oklahoma, Oregon, Pennsylvania, Rhode Island, South Carolina, South Dakota, Tennessee, Texas, Utah, Vermont, Virginia, Washington, West Virginia, Wisconsin, Wyoming, 

Provinces: Ontario, Quebec, British Columbia, Alberta, Saskatchewan, Manitoba, Nova Scotia, New Brunswick, Prince Edward Island, Newfoundland and Labrador.

Company Size Options

The system wide company size options are mapped to the LinkedIn company size options list available from Microsoft.

Restrictive and Prescriptive

Baseplate provides direct source code access to the framework inherently enabling developers full control over the development environment.   Ironically, as we implement the framework, then, we wanted to err on the side of "restrictive" and “prescriptive” in what we allow developers to modify and extend.   The idea is that we want to be very clear with developers in the environment about what they should be focused on and changing and what should simply “work for them.”  Examples:

What Developers Can Change:

  • Business Logic: Developers have the freedom to implement the specific business logic and features of their applications.
  • UI/UX: Customization of the user interface and experience is allowed within the boundaries of the React + Material UI framework and the overall style guide of the stock application
  • Data Models: Extending data models and defining application-specific data structures is expected to be the primary area of work.
  • Integrations: Integrating with third-party services and APIs that are specific to each application.

What Developers Can't Change:

  • Core Framework: The fundamental architecture, including Supabase + PostgreSQL for the backend and React + Material UI for the frontend, is fixed.
  • Authentication and Authorization: The base authentication and role-based access control mechanisms are standardized and would be implemented in a standardized fashion across all applications.
  • Customer Management: The multi-customer architecture and customer isolation principles are defined in the stock app and implemented in a standard fashion across all implementing apps.
  • Billing Integration: The Stripe integration for billing and subscription management is a core component and is standardized across all implementations.
  • DevOps Pipeline: The CI/CD pipeline and deployment processes are standardized to ensure consistency.

Why are we restricting these things?  The goal of being restrictive is to enable the following:

  • Faster Development: Senior, fullstack developers can be narrowly focused on making impactful, app specific features versus reimplementing the same screens over and over again.
  • Consistency: We can readily create a suite of applications that provide a uniform user experience and reliability level.
  • Maintainability: Developers can move between applications and have a familiar environment to work in.   Developers know what they need to build and maintain and what is the responsibility of the stock app.
  • Security: Enforces consistent security practices and compliance standards.
  • Reduced Costs: Minimizes redundant development efforts and infrastructure costs.

Extensibility v. Branching

Extensibility and branching offer distinct approaches to leveraging Baseplate for building new applications. Extensibility focuses on keeping the Baseplate codebase largely intact and extending its functionality through additional features, modules or customizations. This is similar to subclassing in object-oriented programming, where new features inherit and build upon the existing foundation.  This approach promotes code reuse and minimizes divergence from the core platform.    

Branching, on the other hand, involves creating a separate copy of the Baseplate codebase and modifying it directly to build the specific application.  This allows for greater flexibility and customization but can lead to code divergence and increased maintenance challenges.  The choice between extensibility and branching depends on the specific needs of the application being built.    
In general our default approach is to extend the functionality in the child apps.  Practically, though, we expect that the apps will need to branch certain aspects of the core code base of Baseplate to allow for maximum flexibility in the implementation of each app.