Skene
BLOG

BoxyHQ SaaS Starter Kit Review: PLG Audit 2026

Is the BoxyHQ SaaS Starter Kit good for product-led growth? We audited signup, feature gating, analytics, and billing. Score: 4.2/10 for PLG. Strong enterprise features (SAML, SCIM), but no plan-based gating or trials.

·bySkene·LinkedIn
Summarize this article with LLMs

The BoxyHQ SaaS Starter Kit is an enterprise-focused open-source boilerplate with 4,700+ GitHub stars. It stands out for its SAML SSO, SCIM directory sync, and audit log features — capabilities typically found in expensive enterprise software.

We ran it through a comprehensive PLG skills audit — analyzing signup flow CRO, feature gating, trial optimization, product analytics, self-serve motion, and paywall design.

Overall PLG score: 4.2/10 — Best-in-class enterprise features, working Stripe checkout, and Mixpanel analytics. But no plan-based feature gating or trial optimization.


The full audit

CategoryScoreKey finding
Signup flow7/104 fields, GitHub/Google OAuth, magic link, reCAPTCHA
Feature gating3/10Strong RBAC, but no plan-based tier gating
Trial optimization1/10Stripe supports trialing status, but not implemented
Product analytics4/10Mixpanel integrated with 10+ events tracked
Self-serve motion7/10Full Stripe checkout and billing portal
Paywall/upgrade CRO3/10Billing page exists, but no in-app upgrade prompts

1. Signup flow analysis

What's implemented

The signup form collects 4 fields with Yup validation:

// components/auth/Join.tsx
const JoinUserSchema = Yup.object().shape({
  name: Yup.string().required().max(maxLengthPolicies.name),
  email: Yup.string().required().email().max(maxLengthPolicies.email),
  password: Yup.string()
    .required()
    .min(passwordPolicies.minLength)
    .max(maxLengthPolicies.password),
  team: Yup.string().required().min(3).max(maxLengthPolicies.team),
});

Form fields: 4 required (name, email, password, team name)

Authentication options:

  • Email + password
  • Magic link
  • GitHub OAuth
  • Google OAuth
  • SAML SSO (enterprise)

Unique features:

Work email enforcement for B2B focus:

// pages/api/auth/join.ts
if (!isEmailAllowed(email)) {
  throw new ApiError(400,
    `We currently only accept work email addresses for sign-up...`
  );
}

Google reCAPTCHA v3 integration to prevent spam signups.

Signup event tracking:

// pages/api/auth/join.ts line 134
recordMetric('user.signup');

What's missing

  • No progressive profiling (all 4 fields required upfront)
  • No social login value extraction (pre-filling name from OAuth)
  • No signup page view tracking
  • No form abandonment analytics

2. Feature gating audit

What's implemented

Strong role-based access control with three roles:

// lib/permissions.ts
export const permissions: RolePermissions = {
  OWNER: [
    { resource: 'team', actions: '*' },
    { resource: 'team_member', actions: '*' },
    { resource: 'team_payments', actions: '*' },
    { resource: 'team_sso', actions: '*' },
    { resource: 'team_dsync', actions: '*' },
    { resource: 'team_audit_log', actions: '*' },
  ],
  ADMIN: [
    { resource: 'team', actions: '*' },
    { resource: 'team_member', actions: '*' },
    // ... most permissions except some payment actions
  ],
  MEMBER: [
    { resource: 'team', actions: ['read', 'leave'] },
  ],
};

Permission hook for UI-level checks:

// hooks/useCanAccess.ts usage example
{canAccess('team_payments', ['read']) && (
  <BillingSection />
)}

Environment-based feature flags:

// lib/env.ts
teamFeatures: {
  sso: process.env.FEATURE_TEAM_SSO !== 'false',
  dsync: process.env.FEATURE_TEAM_DSYNC !== 'false',
  webhook: process.env.FEATURE_TEAM_WEBHOOK !== 'false',
  auditLog: process.env.FEATURE_TEAM_AUDIT_LOG !== 'false',
  payments: Boolean(process.env.STRIPE_SECRET_KEY),
},

What's missing

No plan-based feature gating. Premium features are hidden by role, not by subscription tier.

Missing components:

  • No subscription tier checks in code
  • No usage limits (API calls, storage, seats)
  • No upgrade prompts when limits are reached
  • No "3 of 5 seats used" messaging
  • No freemium model

3. Trial optimization

What's implemented

Stripe subscription status includes trialing:

// pages/api/webhooks/stripe.ts comment
// type Stripe.Subscription.Status = "active" | "canceled" |
// "incomplete" | "past_due" | "paused" | "trialing" | "unpaid"

But that's just a comment — no actual trial logic.

What's missing

Trials are not implemented:

  • No trial_period, trial_ends_at fields in database
  • No trial-based feature access
  • No trial reminder emails
  • No trial countdown UI
  • No trial-to-paid conversion prompts
  • No trial extension functionality

4. Product analytics

What's implemented

Mixpanel integration with automatic pageviews:

// pages/_app.tsx
useEffect(() => {
  if (env.mixpanel.token) {
    mixpanel.init(env.mixpanel.token, {
      debug: true,
      ignore_dnt: true,
      track_pageview: true,
    });
  }
}, []);

Server-side event recording with OpenTelemetry:

// lib/metrics.ts
export const recordMetric = (metric: AppEvent) => {
  incrementCounter({
    meter: packageInfo.name,
    name: `${prefix}.${metric}`,
  });
};

Events tracked:

  • user.signup
  • user.password.updated
  • user.password.request
  • user.password.reset
  • team.fetched
  • team.created
  • invitation.created
  • invitation.fetched
  • invitation.removed
  • member.created

What's missing

  • No feature adoption tracking (SSO setup, webhook creation)
  • No user identification with custom properties
  • No checkout events (checkout_started, payment_success)
  • No funnel tracking
  • No error tracking for signup/payment failures

5. Self-serve motion

What's implemented

Full Stripe checkout with session creation:

// pages/api/teams/[slug]/payments/create-checkout-session.ts
const checkoutSession = await stripe.checkout.sessions.create({
  customer,
  mode: 'subscription',
  line_items: [{ price, quantity }],
  success_url: `${env.appUrl}/teams/${team.slug}/billing`,
  cancel_url: `${env.appUrl}/teams/${team.slug}/billing`,
});

Stripe billing portal for self-serve management:

// components/billing/LinkToPortal.tsx
const openStripePortal = async () => {
  const response = await fetch(
    `/api/teams/${team.slug}/payments/create-portal-link`,
    { method: 'POST' }
  );
  const result = await response.json();
  window.open(result.data.url, '_blank');
};

Webhook handling for subscription lifecycle:

// Handles these events:
'customer.subscription.created'
'customer.subscription.updated'
'customer.subscription.deleted'

What's missing

  • No instant signup flow (requires team creation first)
  • No one-click upgrade buttons in-app
  • No usage-based pricing support
  • No payment method management (only via Stripe portal)
  • No invoice history page
  • No dunning/failed payment recovery

6. Paywall and upgrade CRO

What's implemented

Billing page with plan display:

// components/billing/ProductPricing.tsx
{plans.map((plan) => (
  <div key={plan.id}>
    <h3>{plan.name}</h3>
    <p>{plan.description}</p>
    {hasActiveSubscription(price) ? (
      <Button disabled>{t('current')}</Button>
    ) : (
      <PaymentButton price={price} />
    )}
    <ul>
      {plan.features.map((feature) => (
        <li><CheckIcon /> {feature}</li>
      ))}
    </ul>
  </div>
))}

Current plan indicator shows which plan is active.

What's missing

No in-app paywalls:

  • No "upgrade to use X feature" prompts
  • No usage limit warnings ("You've used 100/1000 API calls")
  • No feature comparison table
  • No discount/promo code UI
  • No trial CTA
  • No urgency messaging (limited-time offers)
  • Landing page pricing uses "Lorem Ipsum" placeholder text

Enterprise features

Where BoxyHQ excels is enterprise readiness:

FeatureStatus
SAML SSOFull implementation via Jackson
SCIM directory syncUser provisioning from IdP
Audit logsActivity tracking with Retraced
WebhooksSvix integration
API keysTeam-level API key management

These features make it ideal for selling to enterprises, but they're not gated by subscription tier — they're either on or off via environment variables.


What you need to add

Priority 1: Plan-based gating

Connect subscription tiers to feature access:

// Example implementation needed
function canAccessFeature(team, feature) {
  const plan = team.subscription?.plan;
  const planFeatures = {
    free: ['basic_features'],
    pro: ['basic_features', 'sso', 'audit_logs'],
    enterprise: ['basic_features', 'sso', 'audit_logs', 'scim'],
  };
  return planFeatures[plan]?.includes(feature);
}

Priority 2: In-app upgrade prompts

Add contextual upgrade messaging:

{!canAccessFeature(team, 'sso') && (
  <UpgradePrompt
    feature="SAML SSO"
    plan="Pro"
    message="Enable single sign-on for your team"
  />
)}

Priority 3: Trial system

Add trial period tracking:

ALTER TABLE subscriptions ADD COLUMN trial_ends_at TIMESTAMP;

Then build trial emails and countdown UI.


First steps to PLG

BoxyHQ has the billing — now add the activation layer:

Week 1: Connect plans to features

The RBAC system is strong, but it's role-based not plan-based. Add plan checks:

// lib/subscription.ts
export function getTeamPlan(team) {
  const sub = team.subscriptions.find(s => s.status === 'active');
  return sub?.plan || 'free';
}

export function canAccessFeature(team, feature) {
  const plan = getTeamPlan(team);
  const planFeatures = {
    free: ['basic'],
    pro: ['basic', 'sso', 'audit_logs'],
    enterprise: ['basic', 'sso', 'audit_logs', 'scim'],
  };
  return planFeatures[plan]?.includes(feature);
}

Week 2: Expand Mixpanel tracking

Mixpanel is integrated but underutilized. Add events:

// In your checkout flow
mixpanel.track('checkout_started', { plan: 'pro', team_size: team.members.length });
mixpanel.track('checkout_completed', { plan: 'pro', mrr: 49 });

// Feature usage
mixpanel.track('feature_used', { feature: 'sso', plan: 'pro' });
mixpanel.track('upgrade_prompt_shown', { feature: 'audit_logs' });

Week 3: Add trial with enterprise features

For B2B SaaS, let trials include premium features:

// When creating checkout
const session = await stripe.checkout.sessions.create({
  mode: 'subscription',
  subscription_data: {
    trial_period_days: 14,
    metadata: { trial_features: 'sso,audit_logs,scim' }
  },
  // ...
});

Week 4: Build upgrade prompts

Show contextual upgrade CTAs when users try restricted features:

// When SSO is accessed but not available
{!canAccessFeature(team, 'sso') && (
  <Card>
    <h3>Enable SAML SSO</h3>
    <p>Upgrade to Pro for enterprise single sign-on</p>
    <Button onClick={() => router.push('/billing')}>
      Upgrade to Pro
    </Button>
  </Card>
)}

Enterprise PLG metrics

  • Team signup → first SSO connection (activation for enterprise)
  • Trial → paid conversion by feature usage
  • Seat expansion rate (teams adding members)
  • Feature adoption: which enterprise features drive retention?

When to use this template

Good fit:

  • You're selling to enterprises that need SSO and SCIM
  • You want working Stripe checkout out of the box
  • You need audit logs for compliance

Not ideal:

  • You want a freemium model with plan-based gating
  • You need trial optimization features
  • You're targeting SMB with simpler requirements

Conclusion

The BoxyHQ SaaS Starter Kit scores 4.2/10 for PLG readiness. It's the most enterprise-ready open-source boilerplate we've reviewed, with SAML SSO, SCIM, and audit logs that typically cost thousands in enterprise software.

The self-serve motion is solid (working Stripe checkout and billing portal), and Mixpanel analytics provide basic tracking. But the absence of plan-based feature gating means you can't create a true freemium or tiered pricing model without significant custom development.

Best for: Teams building B2B SaaS for enterprise customers who need compliance features but will handle pricing tiers themselves.


Frequently asked questions

Is BoxyHQ SaaS Starter Kit really free?

Yes, it's fully open source under Apache 2.0 license. All features including SAML SSO, SCIM, and Stripe integration are included. There's no paid tier.

How does it compare to other enterprise SaaS starters?

It has the strongest enterprise feature set (SSO, SCIM, audit logs) of any open-source option. However, it lacks PLG features like trial optimization and plan-based gating that templates like Launch MVP include.

Can I use it for a freemium product?

You'll need to add plan-based feature gating yourself. The template has role-based access (Owner/Admin/Member) but doesn't restrict features by subscription tier.

Does it support multi-tenancy?

Yes, it has full team/workspace support with member invitations, role management, and team-scoped resources.


This analysis was performed using PLG Skills, an open-source framework for product-led growth audits. Skills used: signup-flow-cro, feature-gating, trial-optimization, product-analytics, self-serve-motion, paywall-upgrade-cro.

Done with this article? Explore more ways to ship real PLG.