Getting Started with Subscrio Core
This tutorial walks through the minimum set of steps to bootstrap the Subscrio core library, define features/products/plans, onboard a customer, issue a subscription, and verify feature access. It is a distilled version of the full sample app—aimed at engineers who want a fast path to a working setup.
Prerequisites
- Node.js 18+, PNPM or NPM.
- PostgreSQL connection string (same one used by the core library and admin app).
- Run
pnpm install(ornpm install) at the repo root:
- Optional: copy
core.typescript/.env.exampleto.envand setDATABASE_URL.
Step 1 – Initialize Subscrio
Create a file such as scripts/bootstrap.ts:
import { Subscrio } from '@subscrio/core';
import { loadConfig } from '@subscrio/core/config';
async function main() {
const config = loadConfig();
const subscrio = new Subscrio(config);
// Check if schema exists
const schemaVersion = await subscrio.verifySchema();
if (schemaVersion === null) {
await subscrio.installSchema();
console.log('Schema installed.');
} else {
console.log(`Schema version: ${schemaVersion}`);
// NOTE: Only include this migration code if you want your application
// to automatically run migrations at startup. Alternatively, run migrations
// manually via CLI (npm run migrate) or as a separate deployment step.
const migrationsApplied = await subscrio.migrate();
if (migrationsApplied > 0) {
console.log(`Applied ${migrationsApplied} migration(s).`);
}
}
console.log('Ready to use Subscrio services.');
}
main().catch((error) => {
console.error(error);
process.exit(1);
});
Run with ts-node or compile to JavaScript. This sets up the database tables and exposes the service collection on subscrio.
Running Migrations
When you update the @subscrio/core package, you may need to run migrations to update your database schema. You can do this in two ways:
Option 1: Programmatically
Option 2: CLI Command
The migration system tracks schema versions in the system_config table and only applies pending migrations, so it's safe to run multiple times.
Step 2 – Define Features
Features are global definitions with typed defaults. Plans and subscriptions draw from them later.
Tip: Define all keys—products, plans, billing cycles, features—as constants or in a shared module so both backend and admin UI reference the same strings. This prevents typos and makes refactors safer.
const FEATURE_KEYS = {
Analytics: 'analytics-dashboard',
MaxProjects: 'max-projects'
} as const;
const analyticsFeature = await subscrio.features.createFeature({
key: FEATURE_KEYS.Analytics,
displayName: 'Analytics Dashboard',
valueType: 'toggle',
defaultValue: 'false'
});
const maxProjectsFeature = await subscrio.features.createFeature({
key: FEATURE_KEYS.MaxProjects,
displayName: 'Max Projects',
valueType: 'numeric',
defaultValue: '3'
});
Step 3 – Create Product, Plan, and Billing Cycle
- Create a product (using a constant for the key):
- Associate features with the product:
- Define a plan and billing cycle:
const PLAN = 'starter'; await subscrio.plans.createPlan({ productKey: PRODUCT, key: PLAN, displayName: 'Starter Plan', description: 'Best for small teams' }); const BILLING_CYCLE = 'starter-monthly'; await subscrio.billingCycles.createBillingCycle({ planKey: PLAN, key: BILLING_CYCLE, displayName: 'Monthly', durationValue: 1, durationUnit: 'months' }); - Set plan feature values:
Step 4 – Onboard a Customer
const customer = await subscrio.customers.createCustomer({
key: 'acme-corp',
displayName: 'Acme Corporation',
email: 'admin@acme.test',
externalBillingId: 'cus_123' // optional (Stripe ID, etc.)
});
Step 5 – Issue a Subscription
Subscriptions tie the customer to a plan/billing cycle (and optionally contain overrides).
const subscription = await subscrio.subscriptions.createSubscription({
key: 'acme-subscription',
customerKey: customer.key,
billingCycleKey: BILLING_CYCLE,
trialEndDate: new Date(Date.now() + 14 * 24 * 60 * 60 * 1000).toISOString()
});
Need a temporary override? For example, bump max-projects to 20 for a month:
await subscrio.subscriptions.addFeatureOverride(
subscription.key,
FEATURE_KEYS.MaxProjects,
'20',
'temporary'
);
Step 6 – Verify Feature Access
Use the Feature Checker service to evaluate the final resolved values.
const maxProjects = await subscrio.featureChecker.getValueForCustomer<number>(
customer.key,
PRODUCT,
FEATURE_KEYS.MaxProjects,
0
);
const hasAnalytics = await subscrio.featureChecker.isEnabledForCustomer(
customer.key,
PRODUCT,
FEATURE_KEYS.Analytics
);
console.log({ maxProjects, hasAnalytics });
Results obey the hierarchy: subscription override → plan value → feature default.
Where to Go Next
core-overview.md– service-by-service reference.products.md,plans.md,billing-cycles.md– deeper dives on catalog modeling.subscriptions.md&subscription-lifecycle.md– lifecycle rules.feature-checker.md– advanced feature resolution scenarios.sample/project – full demo covering trials, upgrades, overrides, and downgrades.
Once these steps succeed end-to-end, you can expand into Stripe integration, API key management, admin UI, and automated migrations. Happy building!