Skip to main content

← Blog

Frontend Platform vs. Boilerplate: What You Actually Standardize

A boilerplate gives teams the same starting point. A frontend platform keeps HTTP, environment access, cache policy, and ownership aligned as products evolve.

Published
June 13, 2026
Updated
Updated July 13, 2026
Author
Daniel Mark
Reading time
13 min read

Imagine three product teams cloning the same Next.js starter on the same Monday.

Six months later, one team wraps every API call in a shared client with correlation IDs. Another calls fetch() inside mutation hooks and returns ad hoc error strings. A third accesses process.env directly because it was faster than reading the environment documentation.

The repositories still share a Git ancestor. They no longer share an architecture.

That divergence is the problem a frontend platform tries to solve. A boilerplate solves a different problem: getting the first commit out the door with sensible defaults.

I built Atlas after working with both approaches. The AxLabs enterprise frontend boilerplate was a capable starting point for new applications. Atlas is my attempt to keep important decisions aligned after those applications begin evolving independently.

The gap between those goals is smaller than most platform marketing suggests and larger than most boilerplate READMEs admit.

A shared ancestor does not create shared architecture

Copying a repository does not preserve the reasoning behind it.

As products evolve, they tend to drift in predictable places:

  • How HTTP requests are made
  • How errors are normalized and displayed
  • How environment variables are accessed
  • What React Query considers fresh
  • Where providers are mounted
  • Which folders own domain logic
  • What gets reported to observability tools
  • Which security protections are enabled by default

None of that drift requires bad engineering. It is the normal outcome when teams optimize locally under delivery pressure.

A boilerplate can solve the first-week setup problem. It cannot, by itself, solve third-year divergence.

A frontend platform is not necessarily one monorepo that other repositories must copy wholesale. Distribution can include shared packages, a reference application, templates, codemods, CI policies, documentation, and ownership processes.

Repository mechanics such as pnpm workspaces and Turbo help distribute those capabilities. They are not the platform. A Turbo monorepo can still allow every consumer to invent a different HTTP abstraction or environment-access pattern.

The platform is the maintained contract behind the files.

Boilerplates standardize beginnings; platforms standardize change

The AxLabs enterprise frontend boilerplate is a useful contrast because it had a clear and appropriate scope.

It is a single Next.js application rather than a workspace. It standardizes what a good starter should:

  • t3-env validation split across server and client schemas
  • MainProvider that nests environment, React Query, theme, and toaster providers
  • Co-located component tests
  • Airbnb ESLint rules with import sorting
  • Husky hooks
  • Gitleaks secret scanning in pre-commit and CI
  • Documented React Query defaults
  • A small fetcher abstraction for read paths

The boilerplate configures a one-minute staleTime, disables refetchOnWindowFocus, and allows one retry. Those are meaningful defaults. A new application begins with a defensible data-fetching policy instead of whatever the first feature developer happens to choose.

What the boilerplate does not attempt to standardize is equally informative.

It has no ADR collection, no features/ ownership model, no OpenAPI contract layer, no centralized API client with normalized errors, no observability ADR, no capability showroom, and no ESLint rule preventing mutation hooks from calling fetch() directly. Its useCreateUser hook does exactly that.

That is not a failure of the boilerplate. It is a scope choice.

Starters optimize for comprehension and initialization speed. Platforms try to maintain alignment after teams begin changing the starter.

Atlas inherits some of that lineage deliberately. ADR-0002 retains t3-env. Gitleaks follows the same pre-commit pattern. The provider model evolved rather than disappeared.

Atlas uses a configuration facade through useConfig and getServerConfig instead of exposing an environment provider directly. It scopes React Query to routes that fetch data through DataProviderLayout. Feature flags, consent bridging, and web vitals are integrated as platform capabilities rather than left for each product to rediscover.

The shift is from “here is a working stack” to “here is a documented decision with an enforcement path.”

What is actually worth standardizing

Not every engineering preference deserves platform treatment.

Standardizing the wrong decision can scale damage faster than individual teams can recover. If a platform encodes a poor cache policy in shared packages, lint rules, and documentation, it has industrialized the mistake.

Platform work is justified when repeated divergence creates enough cost that maintaining a shared decision becomes cheaper than allowing every product to choose independently.

Those decisions usually fall into six layers.

Decisions and policies

Why is refetchOnWindowFocus disabled? Why must environment variables pass through a facade? Why does authentication use Google OAuth with PKCE? Which errors should be retried?

These decisions belong in ADRs and convention documents rather than tribal knowledge.

Architectural ownership boundaries

Where does routing end and domain logic begin? Can features import from one another? Which code belongs in shared infrastructure?

Atlas documents thin app/ routes, domain logic inside features/, and shared infrastructure inside lib/. Those boundaries appear in AGENTS.md and docs/how-we-build/folder-structure.md.

They are documented conventions, not fully enforced constraints.

Reusable capabilities and paved roads

A central HTTP client, shared UI components, query key factories, form helpers, and consent infrastructure make the supported path easier than reinventing it.

A good paved road reduces the number of decisions a product team must make without preventing legitimate product-specific behavior.

Enforcement through linting, tests, and CI

Documentation explains the standard. Enforcement catches accidental divergence.

The goal is not to make deviations painful for their own sake. The goal is to make the supported path easy, enforceable, observable, and upgradeable while keeping deliberate exceptions visible.

Executable evidence

Documentation can claim that a capability works. A demo or test can prove it.

Capability showrooms are particularly useful for infrastructure that would otherwise remain abstract until a product needs it.

Documentation, ownership, and governance

Someone must own upgrades, exceptions, migrations, and the retirement of obsolete decisions.

Without that ownership, shared rules gradually become folklore.

How Atlas encodes those decisions

At the inspected snapshot, Atlas is a private monorepo with one reference application and three shared workspace packages.

Those packages establish reusable boundaries inside the repository. The codebase does not, by itself, prove that they form a mature cross-repository distribution channel. Atlas is therefore better described as a reference implementation with reusable workspace packages than as a framework that another team can install and forget.

Six accepted ADRs capture its major cross-cutting decisions:

  1. Tailwind v4 CSS-first theming without next-themes
  2. Environment validation through t3-env
  3. React Query with OpenAPI types and a central HTTP client
  4. Google OAuth with PKCE
  5. Sentry observability
  6. Optional consent management

Each ADR records a decision that can later be challenged or superseded. That is the point. A platform decision should be durable, not permanent.

The HTTP layer shows where boilerplate divergence becomes visible to users.

Atlas routes application traffic through @/lib/apinormalizeApiError creates a consistent failure shape, while getUserFacingMessage separates technical errors from messages suitable for the interface.

The React Query configuration also goes beyond the starter defaults. createQueryClient() sets a ten-minute gcTime, disables refetching on mount and reconnect, and gates retries through isRetryableError().

Those defaults affect perceived freshness, network usage, retry behavior, and error recovery. They are architectural decisions. They should not vary silently from feature to feature.

Provider placement is another standardization target.

Mounting React Query at the marketing root would add a client-side provider to pages that never fetch interactive data. Atlas instead wraps only its application and demo surfaces with DataProviderLayout.

That boundary is unnecessary in a starter that assumes one authenticated application surface. It becomes valuable in a platform intended to demonstrate several kinds of frontend delivery.

Why enforcement changes the category

Documentation without enforcement decays.

Atlas encodes transport and configuration access through ESLint rules that fail CI. Direct fetch() calls are prohibited in app/components/features/, and providers/ outside explicitly exempt infrastructure modules.

Direct process.env access and imports from @/env are also prohibited in application layers. Config modules, route handlers, analytics adapters, and tests receive targeted exemptions.

The lint errors point developers toward the sanctioned replacement. That matters. A rule that only says “do not do this” creates friction. A rule that explains the paved road teaches the architecture at the moment someone attempts to bypass it.

This is qualitatively different from a README recommendation.

The boundaries that remain convention-only are equally important to state. Cross-feature imports and business logic inside route files are prohibited by repository instructions and folder-structure documentation, but no ESLint rule currently enforces them.

Atlas therefore enforces HTTP and environment access more strongly than feature ownership. Claiming otherwise would exaggerate its maturity.

CI adds another layer through environment validation, linting, console checks, typechecking, unit tests, package coverage thresholds, production builds, Playwright smoke tests, Gitleaks, and scheduled dependency audits.

Those checks protect the paved road. They do not replace engineering judgment when a product has a legitimate reason to diverge.

Demos as executable platform evidence

Atlas ships seven capability demos under /demo, plus a hub page that links to all seven:

  • Authentication
  • Data fetching
  • Forms
  • Feature flags
  • Observability
  • Accessibility and theming
  • Consent management

Each route exercises one concern with mocked or in-memory data.

/demo/data demonstrates loading, empty, error, and success states. /demo/form shows Zod validation and server-error mapping. /demo/flags demonstrates FeatureGuard and the kill-switch naming convention.

That is useful evidence. It is not integration evidence.

No current demo combines authenticated session handling, typed data fetching, and form submission into one product flow. The capabilities coexist inside the same reference application, but the demo routes do not prove that all of them compose correctly in a realistic feature.

The distinction matters because platform documentation often jumps from “each example works” to “the system works together.” Those are different claims.

The documentation also reveals a smaller governance problem. The root README demo table and docs/public/demo.md list six demos and omit /demo/consent, while the routed demo hub contains seven.

When documentation disagrees with executable code, newcomers receive two different platform contracts. The routed implementation may be the better source of truth, but the documentation still needs to catch up.

What should remain optional

A platform becomes bloated when it mandates every capability for every consumer.

Atlas treats consent management as optional infrastructure. ADR-0006 accepts @atlas/consent, built on CookieConsent v3, and connects it through ConsentBridgeNEXT_PUBLIC_CONSENT_ENABLED defaults to false.

The package exists. The demo exists. Production adoption remains a consumer decision.

That is the right posture for a capability that not every product requires. A platform can document and demonstrate a solution without forcing every application to ship it.

Security hardening has similar layers.

proxy.ts can apply Content Security Policy headers in report-only or enforce modes, but getCspMode() defaults to off when CSP_MODE is unset. Static headers in next.config.js still provide baseline protections such as X-Frame-Options and Referrer-Policy.

The presence of CSP code does not mean CSP is enabled in production. Supported, configured, and enabled are three different states.

Optionality also requires deliberate escape hatches. A product should be able to diverge when its requirements genuinely differ, but that decision should be documented rather than hidden through ignored lint rules or copied infrastructure.

Atlas does not yet formalize that exception process.

Standardization requires ownership

Patterns without owners become folklore.

Atlas documents ownership boundaries in AGENTS.md, indexes ADRs with a lifecycle, and organizes convention documentation under docs/how-we-build/. Renovate groups dependency updates, while Changesets provides tooling for package versioning.

Those mechanisms support governance. Their presence does not prove that upgrades and migrations operate smoothly across external consumer repositories.

The thinner areas are the operational ones: a named exception path, current migration playbooks, and a clear process for reconciling public documentation with internal implementation.

Distribution terms need the same precision.

At the inspected snapshot, the root README describes Atlas as closed-source but ends with an MIT reference, while no root LICENSE file exists. The FAQ says the source is unavailable, while the marketing homepage links to GitHub.

That does not require a legal conclusion. It requires consistent positioning.

A private internal platform does not need to be open source. However, before Atlas can be presented as externally adoptable, its public messaging and distribution terms need to agree.

Where Atlas still falls short

A candid case study should name the gaps that affect platform trust without turning the article into an audit report.

The application shell still links to /dashboard/dashboard/project, and /settings, but those product routes do not exist in the current routed application. The folder-structure documentation also diagrams a dashboard page that has not been implemented.

That is incomplete scaffold work. If the platform deliberately omits a finished dashboard, its navigation and documentation should not imply otherwise.

Feature ownership also remains more documented than enforced. HTTP and environment access have lint-backed boundaries. Folder discipline still depends on repository instructions and code review.

The demos prove isolated capabilities rather than a complete product flow. The documentation does not fully match the routed showroom.

These gaps do not invalidate the platform direction. They limit how much maturity Atlas should claim today.

When a boilerplate is enough

The existence of four repositories does not automatically justify a platform team.

A platform becomes worthwhile when repeated divergence creates measurable cost: duplicated HTTP clients, incompatible error shapes, environment-access sprawl, upgrade work repeated across forks, and architectural debates that every team must resolve independently.

A good boilerplate is enough when:

  • You maintain one product, or forks are rare and short-lived.
  • The team is small enough for code review to catch architectural drift.
  • Cross-cutting concerns are stable.
  • You do not need packages shared across repositories.
  • A provider tree and concise documentation cover the real operating model.
  • The cost of governing a platform would exceed the cost of occasional divergence.

The AxLabs boilerplate is the right tool for that tier. It is not an inferior repository. It solves a narrower problem.

Platform investment becomes defensible when the expensive failures are organizational: the third team re-decides React Query defaults, the fourth fork bypasses environment validation, or a security review discovers several incompatible HTTP error models.

That is the justification bar.

A practical platform-readiness checklist

Before calling a repository a frontend platform, I would ask:

  1. Can a new engineer learn why refetchOnWindowFocus is disabled without asking the original author?
  2. Does CI fail when someone calls fetch() directly inside a feature hook?
  3. Is there a demo or test proving the highest-risk composition actually works?
  4. Do the documentation and routed application describe the same capabilities?
  5. Can consumers adopt a capability without copying unrelated infrastructure?
  6. Are the distribution terms unambiguous?
  7. Is there an owner for upgrades, exceptions, and ADR supersession?
  8. Are deliberate omissions documented so that newcomers do not confuse scaffold gaps with defects?

The checklist is not a passing score. Its purpose is to reveal whether you have a maintained platform contract or a starter surrounded by good intentions.

There is nothing wrong with having a good starter. Problems begin when an organization gives it a larger name and assumes that repository structure will solve governance.

Conclusion

The AxLabs boilerplate gave applications a shared first commit: validated environment variables, nested providers, tested primitives, and secret scanning.

Atlas tries to keep the decisions behind those files aligned after products begin evolving independently. That requires ADRs, paved-road libraries, lint enforcement for the areas most likely to drift, executable demonstrations, and enough governance to keep documentation aligned with implementation.

The distinction is not monorepo versus single application or Turbo versus plain pnpm.

The real question is whether the third product, third team, or third year still agrees on what a failed request looks like, where environment variables may be read, and which layer owns domain logic.

A boilerplate standardizes beginnings. A platform standardizes change.

Most organizations only need the first. The ones that need the second should understand the difference before renaming a starter and calling it a platform.


Portrait of Daniel Mark

Written by

Daniel Mark

Senior Frontend Engineer

Daniel Mark is a senior frontend engineer and product consultant with 7+ years of experience building resilient product interfaces for Web3, SaaS, and enterprise teams. He writes about frontend architecture, design systems, performance, SEO, and the engineering decisions that turn complex systems into dependable user experiences.