Understanding Shipd's Modular Architecture
Deep dive into how Shipd's modular architecture works and why it's perfect for building scalable SaaS applications.
Understanding Shipd's Modular Architecture
One of Shipd's core strengths is its modular architecture. But what does that mean, and why should you care?
What is Modular Architecture?
Modular architecture means your application is built from independent, self-contained modules that can be added or removed without affecting the rest of your codebase.
Traditional Approach
┌─────────────────────────────────┐
│ Monolithic SaaS Template │
│ │
│ ✓ Auth ✓ Payments │
│ ✓ Blog ✓ Analytics │
│ ✓ Docs ✓ Support │
│ ✓ Email ✓ Everything else │
│ │
│ (You get it all, whether │
│ you need it or not) │
└─────────────────────────────────┘
Shipd's Modular Approach
┌──────────┐
│ Base │ ← Minimal foundation
└────┬─────┘
│
├─── [Auth Module]
├─── [Payments Module]
├─── [Blog Module] ← Add only what you need
├─── [Analytics Module]
└─── [Docs Module]
Benefits of Modular Architecture
1. Start Small, Scale Smart
Begin with just the essentials:
npx shipd init my-app --modules auth,payments
Add features as you grow:
npx shipd append --features blog,analytics
2. Cleaner Codebase
Only include code you actually use. No bloat, no unnecessary dependencies, no confusing features you'll never touch.
3. Easier Maintenance
Each module is self-contained with:
- Its own documentation
- Isolated dependencies
- Clear interfaces
- Independent testing
4. Faster Development
Skip features you don't need:
- Building a B2B tool? Skip the blog
- Internal tool? Skip marketing pages
- MVP? Start minimal, add later
How Modules Work
Each Shipd module is a complete, production-ready feature package.
Module Structure
features/
└── blog/
├── app/
│ └── blog/
│ ├── page.tsx # Blog listing
│ └── [slug]/
│ └── page.tsx # Blog post
├── lib/
│ └── blog.ts # Blog utilities
├── components/
│ └── blog/ # Blog components
├── content/
│ └── blog/ # MDX content
├── package.json # Module dependencies
└── README.md # Module docs
Module Dependencies
Modules can depend on other modules:
// blog module config { "name": "blog", "dependencies": [], "optionalDependencies": ["analytics"], "conflicts": [] }
Module Injection
Modules integrate seamlessly using injection points:
// app/layout.tsx import type { Metadata } from "next"; import "./globals.css"; /*APPEND_IMPORTS*/ // ← Modules inject imports here export default function RootLayout({ children }) { return ( <html lang="en"> <body> {/*APPEND_PROVIDERS*/} // ← Modules inject providers {children} {/*APPEND_PROVIDERS_END*/} {/*APPEND_COMPONENTS*/} // ← Modules inject components </body> </html> ); }
When you add the analytics module:
// Automatically becomes: import { Analytics } from "@/lib/analytics"; /*APPEND_IMPORTS*/ // ... {/*APPEND_COMPONENTS*/} <Analytics />
Available Modules
Core Modules
| Module | Description | Dependencies |
|---|---|---|
| auth | User authentication with Better Auth | database |
| database | PostgreSQL with Drizzle ORM | - |
| payments | Polar.sh integration | auth, database |
| Transactional emails with Resend | - |
Feature Modules
| Module | Description | Dependencies |
|---|---|---|
| blog | MDX-powered blog | - |
| docs | Documentation site | - |
| analytics | PostHog analytics | - |
| dashboard | Admin dashboard | auth |
Creating Custom Modules
You can create your own modules:
# Create a custom module npx shipd create-module my-feature # This generates: features/ └── my-feature/ ├── app/ # Pages ├── lib/ # Utilities ├── components/ # Components ├── config.json # Module config └── README.md # Documentation
Module Configuration
{ "name": "my-feature", "version": "1.0.0", "description": "My custom feature", "dependencies": ["auth"], "files": { "app/my-feature": "app/my-feature", "lib/my-feature.ts": "lib/my-feature.ts" }, "injections": { "app/layout.tsx": { "/*APPEND_IMPORTS*/": "import { MyFeature } from '@/lib/my-feature';" } }, "envVars": [ "MY_FEATURE_API_KEY" ] }
Best Practices
1. Start Minimal
Begin with the absolute minimum:
npx shipd init --modules auth,database,payments
2. Add Features Incrementally
Don't add modules "just in case":
# Wait until you actually need it npx shipd append --features blog
3. Keep Modules Independent
Design your custom modules to be self-contained and reusable.
4. Document Integration Points
If your module needs manual setup, document it clearly:
## Manual Integration After installing, update your navigation: \`\`\`tsx <Nav> <NavLink href="/my-feature">My Feature</NavLink> </Nav> \`\`\`
Comparison with Other Approaches
vs. Monolithic Templates
| Shipd Modular | Monolithic Template |
|---|---|
| Add what you need | Get everything |
| Clean codebase | Lots of unused code |
| Easy to maintain | Complicated |
| Fast builds | Slow builds |
vs. Building from Scratch
| Shipd Modular | From Scratch |
|---|---|
| Minutes to set up | Weeks to set up |
| Production-ready | Need to harden |
| Best practices | Your implementation |
| Maintained | Unmaintained |
Future Modules
We're constantly adding new modules:
- Waitlist - Collect emails pre-launch
- Referrals - Built-in referral system
- A/B Testing - Experiment framework
- Customer Support - Help desk integration
- Stripe - Alternative payment provider
Conclusion
Modular architecture gives you the best of both worlds:
✅ Fast setup like a template ✅ Flexibility like building from scratch ✅ Clean code without bloat ✅ Easy maintenance with isolated modules
Start with what you need, add features as you grow, and keep your codebase clean.
Ready to experience modular architecture? Run npx shipd init and build your SaaS the smart way.