The problem with boilerplate that includes everything
Most SaaS boilerplates ship their marketing site alongside the product code. The pitch sounds reasonable: "You get everything — landing pages, pricing tables, blog, dashboard. Delete what you do not need."
The problem is that nobody knows what is safe to delete.
Marketing components import shared utilities. Shared utilities are used by dashboard components. CSS classes defined for landing page animations might be referenced in the Tailwind configuration that your product depends on. After an hour of tracing imports and testing deletions, you start wondering whether ripping out the marketing code will break something in production that you will not discover until a customer reports it.
This is not a theoretical concern. Every hour a customer spends auditing code they did not ask for is an hour they are not building their actual product. And that cleanup tax compounds — every future dependency update, every refactor, every new hire onboarding session has to navigate around code that was supposed to be "just delete it."
We decided this was the wrong default.
Our separation strategy
nextsaas.ai uses a monorepo architecture with Turborepo and pnpm workspaces. The product and the marketing site live in completely separate applications:
| Aspect | Typical Boilerplate | nextsaas.ai Approach |
|---|---|---|
| Structure | Single app with everything | apps/boilerplate/ + apps/marketing/ |
| Dependencies | Shared, often tangled | Scoped per application |
| Build | One build, one bundle | Independent builds, parallel execution |
| Component leakage | Marketing components importable anywhere | Enforced scope boundaries |
| Customer cleanup | Hours of manual deletion | Zero — they get only the product |
| Dev server | Single port, everything loads | Separate ports, start only what you need |
The key insight is that separation is not just about file organization. It is about dependency isolation. When marketing and product are separate applications with separate package.json files, separate build configurations, and separate deployment targets, there is no way for marketing code to accidentally become a dependency of the product.
Scoped packages in practice
Shared code between the two applications goes through explicitly scoped packages. The UI component library uses a scope system that controls which components are available to which application:
@nextsaasai/ui/boilerplateexports components designed for the product dashboard — data tables, form layouts, settings panels.@nextsaasai/ui/marketingexports components designed for the marketing site — hero sections, feature grids, testimonial cards.@nextsaasai/ui/sharedexports components that are genuinely cross-cutting — buttons, badges, tooltips, theme primitives.
The bar for "shared" is deliberately high. A component only lands in the shared scope when both applications genuinely need the exact same implementation. When in doubt, we duplicate rather than share, because a false dependency between marketing and product is worse than a few lines of repeated code.
This is enforced at the import level. apps/boilerplate/ cannot import from @nextsaasai/ui/marketing, and apps/marketing/ cannot import from @nextsaasai/ui/boilerplate. The boundary is structural, not just a convention that someone might accidentally violate during a late-night coding session.
The delivery pipeline
When a customer receives nextsaas.ai Kit, they get a clean monorepo workspace. The delivery pipeline automatically strips marketing-specific applications and configurations while preserving the full workspace structure that the product depends on.
This means customers start with a workspace that contains their product, the shared packages it needs, and nothing else. No leftover marketing routes to confuse their routing. No unused marketing dependencies inflating their node_modules. No marketing CSS competing with their product styles.
The delivery pipeline runs automated checks to verify that the customer package builds independently, all tests pass, and no references to removed marketing code remain. A customer should be able to run pnpm install and pnpm dev immediately after receiving their package, without any cleanup step.
What clean architecture enables
The architectural boundary between marketing and product is not just about code cleanliness. It is a form of respect for the customer's time and attention.
When a developer starts building on a boilerplate, their first experience shapes their confidence in the entire codebase. If that first experience involves figuring out which files to delete and which to keep, the implicit message is: "We built this for ourselves first and adapted it for you second." If the first experience is a clean workspace where every file is relevant to their goals, the implicit message is different: "We built this for you."
This separation also enables something practical that matters as the project grows. Marketing can ship new landing pages, blog posts, and documentation updates without affecting the product. The product can receive new features, security patches, and dependency upgrades without touching marketing. Independent release cycles mean faster iteration and less risk for both sides.
Architectural decisions are product decisions. The way you organize code communicates what you value. We chose to value the customer's experience from the first pnpm install forward.