Introducing Caf: Clean Architecture Frontend
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.
The problem
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.
What is CAF?
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) and Ploc for presentation logic.
- Pluggable adapters — Routing, HTTP, and UI are interfaces; you (or the ecosystem) implement them.
- TypeScript-first — Typed UseCases, RequestResult, and Plocs end-to-end.
Core ideas
| Concept | What it does |
|---|---|
| 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<T> (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.
Example: React + TypeScript
You put your domain, use cases, and Plocs in a caf/ folder (framework-agnostic), then wire them at the app root and use React hooks in components.
1. Wire the app with CAFProvider (e.g. in 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 plocs={{ user: userPloc }}>
<YourApp />
</CAFProvider>
);
}
2. In a component, read state from the Ploc and call methods:
import { usePlocFromContext, usePloc } from '@c-a-f/infrastructure-react';
import type { UserPloc } from '../caf/application';
export function UserList() {
const ploc = usePlocFromContext<UserPloc>('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.
The repo at a glance
The CAF repository is a monorepo with:
-
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:
@c-a-f/validation(Zod, Yup, etc.),@c-a-f/workflow,@c-a-f/permission,@c-a-f/i18n,@c-a-f/testing,@c-a-f/devtools,@c-a-f/clifor scaffolding.
Examples live in the same repo: example-react, example-vue, example-angular, plus example-vue-graphql and example-angular-websocket. Each app has its own caf/ folder (domain, application, infrastructure) so you can copy the structure into your project.
Who is it for?
- Teams that want one domain/application layer and the option 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 wants a small, shared core and conventions.
Quick start
# Core + your framework
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).
Where to go next
- GitHub: github.com/ialiaslani/caf
- npm: npmjs.com/org/c-a-f
- Docs: docs-caf.vercel.app (intro, packages, getting started, best practices, ADRs)
If you're looking for a small, type-safe core to share Clean Architecture across React, Vue, and Angular, CAF is worth a look.
Popular Products
-
Devil Horn Headband$25.99$11.78 -
WiFi Smart Video Doorbell Camera with...$61.56$30.78 -
Smart GPS Waterproof Mini Pet Tracker$59.56$29.78 -
Unisex Adjustable Back Posture Corrector$71.56$35.78 -
Smart Bluetooth Aroma Diffuser$585.56$292.87