Makerkit Review 2026: Is the Plugin Architecture Worth It?
TL;DR
Makerkit is the highest-quality SaaS boilerplate in terms of code structure and testing. The plugin architecture is genuinely useful, and the multi-tenancy support is excellent. At $299+ (pricing varies by tier), it's worth it for teams that value code quality and long-term maintainability over time-to-launch. Not ideal for solo founders who need to ship in a week.
What You Get
Price: $149 (basic) to $599 (teams tier) — see makerkit.dev for current pricing
Core features:
- Next.js 14+ (App Router) + TypeScript (strict)
- Multi-tenancy: Organizations with roles and permissions
- Auth: Supabase Auth OR Firebase
- Payments: Stripe + Lemon Squeezy + Paddle
- Email: Nodemailer + Resend adapters
- UI: shadcn/ui + Tailwind
- Blog: MDX with full SEO
- i18n: Full internationalization
- Admin panel: Complete admin dashboard
- Testing: Vitest + Playwright configured
- Plugin system: Extend without forking
The Plugin Architecture
Makerkit's defining feature: a plugin system that lets you add functionality without modifying the core codebase.
# Add features via plugins (official plugins)
npx makerkit plugin:install @makerkit/plugin-ai-chatbot
npx makerkit plugin:install @makerkit/plugin-roadmap
npx makerkit plugin:install @makerkit/plugin-analytics
// plugins/ai-chatbot/index.ts — clean plugin interface
import type { MakerkitPlugin } from '@makerkit/core';
const aiChatbotPlugin: MakerkitPlugin = {
name: 'ai-chatbot',
routes: [
{
path: '/chat',
component: () => import('./pages/ChatPage'),
},
],
navigationItems: [
{
label: 'AI Assistant',
icon: BotIcon,
href: '/chat',
plans: ['pro', 'enterprise'], // Feature gating built-in
},
],
hooks: {
onUserCreated: async (user) => {
// Initialize chat history for new user
await createChatSession(user.id);
},
},
};
export default aiChatbotPlugin;
Why this matters: When Makerkit updates its core (new Next.js version, auth improvements), you pull updates without merge conflicts on feature code.
Code Quality
Makerkit has the highest code quality of any major boilerplate. Strict TypeScript, meaningful tests, proper separation of concerns:
// Domain-driven structure
// server/organizations/
// services/
// create-organization.service.ts
// update-organization.service.ts
// repositories/
// organization.repository.ts
// types.ts
// CreateOrganizationService — clean, testable, single responsibility
export class CreateOrganizationService {
constructor(
private readonly organizationRepository: OrganizationRepository,
private readonly billingService: BillingService,
private readonly emailService: EmailService
) {}
async execute(input: CreateOrganizationInput, userId: string): Promise<Organization> {
// Validate
const validated = createOrganizationSchema.parse(input);
// Create organization
const org = await this.organizationRepository.create({
name: validated.name,
slug: await this.generateSlug(validated.name),
});
// Add creator as owner
await this.organizationRepository.addMember(org.id, userId, 'owner');
// Send welcome email
await this.emailService.sendOrganizationCreated(userId, org);
return org;
}
}
This is maintainable code. Contrast with boilerplates that throw everything in /app/api/ route handlers.
Testing Setup
Makerkit ships with tests configured and working:
// suites/organizations/create-organization.spec.ts
import { describe, it, expect, vi } from 'vitest';
import { CreateOrganizationService } from './create-organization.service';
describe('CreateOrganizationService', () => {
const mockRepo = {
create: vi.fn().mockResolvedValue({ id: 'org_123', name: 'Acme', slug: 'acme' }),
addMember: vi.fn().mockResolvedValue(undefined),
};
it('creates organization and adds creator as owner', async () => {
const service = new CreateOrganizationService(mockRepo, mockBilling, mockEmail);
const org = await service.execute({ name: 'Acme' }, 'user_123');
expect(org.name).toBe('Acme');
expect(mockRepo.addMember).toHaveBeenCalledWith('org_123', 'user_123', 'owner');
});
});
You get tests you can actually run and extend — not just vitest config with no tests.
The Admin Panel
Makerkit includes a complete admin dashboard:
- User management (view, impersonate, ban)
- Organization management
- Subscription management
- System metrics
// /admin/users/[id]/page.tsx — impersonate for support
async function AdminUserPage({ params }) {
const user = await adminGetUser(params.id);
return (
<AdminLayout>
<UserDetails user={user} />
<ImpersonateButton userId={user.id} /> // Login as this user to debug issues
<UserActivity userId={user.id} />
<UserSubscription userId={user.id} />
</AdminLayout>
);
}
Customer support teams need this. Most boilerplates don't ship it.
The Not-So-Good
1. Price vs Value Assessment Depends on Tier
The basic tier ($149) gives you less than ShipFast. The teams tier ($599) gives you more but costs twice as much. The plugin system's value compounds over time, not immediately.
2. Learning Curve is Higher
The domain-driven architecture, plugin system, and service layer patterns are more sophisticated than other boilerplates. A junior developer might find it overwhelming. An experienced developer will appreciate it.
3. Supabase or Firebase — Both Have Lock-In
You choose your auth/database provider at setup. Both options create significant lock-in.
Who Should Buy Makerkit
Good fit:
- Teams of 2-5 developers building B2B SaaS
- Founders with software engineering backgrounds who value code quality
- Products expected to grow significantly (the architecture scales better)
- Long-term projects where maintainability matters
Bad fit:
- Solo founders who need to validate quickly (overhead isn't worth it at idea stage)
- B2C products (single-user billing, the complexity is unnecessary)
- Founders new to React/Next.js (the patterns require experience to navigate)
Final Verdict
Rating: 4.5/5
Makerkit is the best boilerplate for teams. The code quality, plugin architecture, and admin panel are genuinely superior. If you're building a product you plan to grow for years, the investment in code quality pays off. For a solo founder validating an idea, it's overkill.
Compare Makerkit with alternatives on StarterPick.
Check out this boilerplate
View Makerkit on StarterPick →