Introducing CAF: Clean Architecture Frontend
Source: Dev.to
Write your business logic once. Run it in React, Vue, or Angular—or the next framework. CAF (Clean Architecture Frontend) is a library that gives you a framework‑agnostic core so the same domain and use cases can run in any frontend by swapping adapters.
Frontend apps often mix UI, state, and business rules. When you switch frameworks or need to share logic across React, Vue, and Angular, you usually rewrite a lot of code. Clean Architecture helps, but doing it well with a single, framework‑agnostic core is hard. CAF provides that core: primitives and interfaces so your domain and use cases stay framework‑free.
CAF is a framework‑agnostic core for building frontends with Clean Architecture. You implement domain and application layers once; React, Vue, or Angular (and future frameworks) plug in via small adapter packages. No lock‑in to a single UI stack.
In short
- Framework‑agnostic – One core; many UIs.
- Clean Architecture – Clear domain, application, and infrastructure layers.
- Reactive primitives – A single reactive engine (
Pulse) andPlocfor presentation logic. - Pluggable adapters – Routing, HTTP, and UI are interfaces; you (or the ecosystem) implement them.
- TypeScript‑first – Typed
UseCase,RequestResult, andPlocs end‑to‑end.
Core Concepts
Pulse
A single reactive value (like a ref). Use it for one piece of state (e.g., loading flag, current user).
Ploc
Presentation Logic Component – a stateful bloc built on Pulse. Holds UI‑related state and methods.
UseCase
An application operation (command or query). Returns RequestResult (loading, data, error) so the UI can show loading/error/success.
RouteRepository
Abstraction over routing. Your app implements it (e.g., with React Router or Vue Router); RouteManager uses it for auth and navigation.
Domain and application code depend only on these abstractions. Infrastructure (HTTP, routing, storage) and the UI layer depend on your framework; the core does not.
Getting Started
1. Wire the app with CAFProvider
// main.tsx or App.tsx
import { CAFProvider } from '@c-a-f/infrastructure-react';
import { setupUserPloc } from './caf/setup';
const userPloc = setupUserPloc();
export default function App() {
return (
<CAFProvider>
{/* Your app UI goes here */}
</CAFProvider>
);
}
2. Use a Ploc in a component
import { usePlocFromContext, usePloc } from '@c-a-f/infrastructure-react';
import type { UserPloc } from '../caf/application';
export function UserList() {
const ploc = usePlocFromContext('user');
if (!ploc) return null;
const [state] = usePloc(ploc);
return (
<div>
{state.loading && <p>Loading...</p>}
{state.error && <p>Error: {state.error}</p>}
<button onClick={() => ploc.loadUsers()} disabled={state.loading}>
Refresh
</button>
<ul>
{state.users.map((u) => (
<li key={u.id}>
{u.name} – {u.email}
</li>
))}
</ul>
</div>
);
}
The same UserPloc and use cases can drive a Vue or Angular UI; only the hooks (or composables/injectors) change.
Repository Structure
The CAF repository is a monorepo with the following packages:
- Core:
@c-a-f/core–UseCase,Ploc,Pulse,ApiRequest,RouteManager, and shared interfaces. - Infrastructure (adapters):
@c-a-f/infrastructure-react– React hooks (usePloc,useUseCase,CAFProvider,useRouteManager,useRouteRepository).@c-a-f/infrastructure-vue– Vue composables and providers.@c-a-f/infrastructure-angular– Angular services and injectors.
- Optional modules: validation (
@c-a-f/validation), workflow, permission, i18n, testing, devtools, CLI scaffolding, etc.
Examples
example-reactexample-vueexample-angularexample-vue-graphqlexample-angular-websocket
Each example contains its own caf/ folder (domain, application, infrastructure) that you can copy into your project.
Target Audience
- Teams that want a single domain/application layer and the flexibility to ship with React, Vue, or Angular.
- Developers who care about testability and clear boundaries (domain vs. application vs. infrastructure).
- Anyone tired of framework‑specific “Clean Architecture” recipes and looking for a small, shared core with conventions.
Installation
npm install @c-a-f/core
npm install @c-a-f/infrastructure-react # or -vue, -angular
Optional: scaffold a project
npm install -g @c-a-f/cli
caf-init
Then create a caf/ folder with domain/, application/, infrastructure/, and a setup that wires repositories, use cases, and Plocs. The docs and README in the repo walk through the exact layout and a minimal flow (e.g., GetUsers UseCase → Ploc → React/Vue/Angular UI).
Links
- GitHub:
- npm organization:
- Documentation: (intro, packages, getting started, best practices, ADRs)