Skills DirectorySkills Directory
SkillsLearnSecurityCategoriesDocsBlogPro
Sign InSubmit Skill
Skills Directory

Security-tested agent skills for Claude, coding agents, and AI workflows.

Directory

  • Browse Skills
  • All Skills A–Z
  • Claude Skills
  • Claude Code Skills
  • Agent Skills
  • Categories
  • Authors
  • Submit a Skill

Learn

  • Learn Hub
  • Install Claude Skills
  • Write SKILL.md
  • Skills vs MCP
  • Directories Compared

Security

  • Security
  • Methodology
  • Secure Claude Skills
  • Security Badges
  • Chrome Extension
  • Skill Manager

Company

  • About
  • Community
  • Blog
  • API Docs
  • Advertise

2026 Skills Directory. All rights reserved.

ProTermsPrivacyRefunds
Back to skills

vue-ddd-architecture

ASecurity

Build and maintain scalable Vue 3 + TypeScript applications using a layered, module-per-domain architecture (domain / application / infrastructure / ui) with enforced dependency boundaries and a public API per module. Use this skill whenever the user adds a feature or a business module to a Vue app, bootstraps a new Vue project, asks where a file or piece of logic belongs, wonders whether their layering is correct, or wants to refactor a messy pages/components Vue codebase into modules — even...

2 stars
0 votes
0 copies
1 views
Added 9/19/2026
developmenttypescriptrustgobashreactvuenodeapifrontendbackend

Works with

cliapi

Security Analysis

A100/100

Pro scans all 12 files and shows the line behind each finding

Scanned 9/19/2026

$npx -y skills add magersoft/vue-ddd-architecture --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of vue-ddd-architecture?

Add the live security badge to your README — it updates automatically with every re-scan.

Security grade badge for vue-ddd-architecture
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/magersoft-vue-ddd-architecture/badge)](https://www.skillsdirectory.com/skills/magersoft-vue-ddd-architecture)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
Files
SKILL.md
---
name: vue-ddd-architecture
description: >-
  Build and maintain scalable Vue 3 + TypeScript applications using a layered,
  module-per-domain architecture (domain / application / infrastructure / ui) with
  enforced dependency boundaries and a public API per module. Use this skill whenever
  the user adds a feature or a business module to a Vue app, bootstraps a new Vue
  project, asks where a file or piece of logic belongs, wonders whether their layering
  is correct, or wants to refactor a messy pages/components Vue codebase into modules —
  even if they never say the words "architecture" or "DDD". Triggers EN: "add a module",
  "new feature in Vue", "structure my Vue app", "DDD frontend", "where should this
  service live", "split this component", "refactor to modules", "scalable Vue
  architecture", "domain layer", "clean architecture Vue". Триггеры RU: «добавь модуль»,
  «новая фича», «разложи по слоям», «куда положить этот файл», «структура Vue-проекта»,
  «DDD на фронтенде», «отрефактори на модули», «масштабируемая архитектура», «доменный
  слой», «сделай по-нормальному, а не всё в компоненте».
license: MIT
---

# Vue DDD Architecture

A layered, module-per-domain architecture for Vue 3 + TypeScript applications, distilled
from a production codebase. It gives a growing app a shape that stays navigable: business
logic lives in modules, each module has four layers with one direction of dependency, and
each module exposes exactly one public API.

## Be honest about what this is

This is **DDD-inspired layering, not tactical DDD**. There are no aggregates, no value
objects, no domain events, no rich entities with behaviour. On the frontend, the domain
model is usually already owned by the backend, and reimplementing it in the browser buys
complexity without buying correctness.

What this architecture actually delivers is narrower and more useful: business logic is
separated from transport and from presentation, every file has one obvious home, modules
can be deleted or extracted without archaeology, and the boundaries are machine-checkable
by a linter rather than by memory.

Say this plainly if the user calls it "DDD" and expects aggregates. Do not invent a
domain model that the app does not need.

## Scope

Vue 3 with the Composition API and TypeScript. The layering ideas port to React and other
frameworks, but this skill deliberately does not cover them — the concrete guidance below
(composables as the unit of composition, Pinia stores, `unref`) is Vue-specific, and vague
framework-neutral advice would produce worse code than no advice.

## The shape

```
src/
├── app/          composition root: router, layouts, providers, config, global styles
├── modules/      business modules — the app's actual subject matter
└── shared/       reusable, business-free building blocks (portable to another project)
```

A module:

```
modules/<module>/
├── domain/           types + pure factories. No side effects, no imports of runtime code.
├── application/      use cases. services/ + the use<Module>() facade = the public API.
├── infrastructure/   models/ (talks to the network) + stores/ (holds state)
├── ui/               views/ and components/, each component owning its composables/ and styles/
├── utils/            mappers and helpers specific to this module's subject matter
├── routes.ts         this module's route declarations (entity/screen modules)
└── index.ts          the public API — the only thing other modules may import
```

Read `references/layers.md` for what belongs in each layer, with examples of the mistakes
that keep recurring.

## The one rule that makes this worth doing

**Dependencies point one way, and modules talk to each other only through their front door.**

```
app ──▶ modules ──▶ shared
```

- `shared` knows nothing about `app` or `modules`. It should survive being copy-pasted into
  an unrelated project.
- `modules` never import from `app`.
- A module imports another module only as `@/modules/<other>` — never
  `@/modules/other/infrastructure/stores`. Deep imports are what turn a modular app back
  into a ball of mud, one "just this once" at a time.

Inside a module:

```
ui ──▶ application ──▶ infrastructure ──▶ domain
```

`ui` never imports `infrastructure` directly. When a component needs data, it needs a use
case, and the use case is what should be edited when the requirement changes.

These rules are enforced by ESLint, not by good intentions — see
`references/eslint-boundaries.md`. Set that up early; a boundary that only exists in prose
degrades within weeks.

## Deciding where code goes

Ask, in order:

1. **Does it talk to the outside world or hold state?** → `infrastructure`
   (HTTP endpoints in `models/`, reactive state in `stores/`).
2. **Does it describe something the application *does*?** → `application/services/`.
   "Fetch the incomes and put them in the store, tracking loading and errors" is a use
   case, even though it feels plumbing-ish.
3. **Is it a type, or a factory for an initial value?** → `domain/`.
4. **Is it a pure transformation of this module's data?** → `utils/`
   (mappers, groupers, formatters tied to the subject matter).
5. **Is it rendering, or logic that exists only to serve one component?** → `ui/`.
6. **Is it none of the above and has no business meaning at all?** → `shared/`.

The test that resolves most arguments: *if the backend changed shape, which files would
you edit?* Those are infrastructure. *If the product requirement changed, which files
would you edit?* Those are application.

## What counts as a module

Not everything deserves a module, and not every module needs every layer. Creating empty
layers "for symmetry" is the most common way this architecture accumulates noise.

| Kind | Recognise it by | Required layers |
|---|---|---|
| **Entity module** | owns an API resource (`incomes`, `wallets`, `categories`) | all four |
| **Screen module** | a page composing other modules' data (`dashboard`, `welcome`) | `application` + `ui`; no models, usually no store |
| **Domain-service module** | pure calculation over other modules' data (`calculations`, `pricing`) | `domain` + `application` only |
| **Cross-cutting state** | needed by nearly everything, not a subject in itself (`settings`, `theme`, `session`) | see below |

The last row is the one that causes arguments, so decide it with a single question: **who
consumes this?**

- Only `app` — route guards, layouts, the HTTP transport (a session token, the active
  locale) → put it in `app/`. Modules never import `app`, so nothing else can reach it,
  which is correct: nothing else should.
- Business modules consume it too (user settings, selected currency, feature flags) → keep
  it a module with a deliberately wide facade, and consume it as `@/modules/settings`.

What is never right is a module that everything deep-imports. If you find
`@/modules/settings/infrastructure/stores` in twenty files, the fix is not to ban the
import — it is that the facade was never written.

## Workflows

Pick the one that matches the request and read that file before starting.

| Situation | Read |
|---|---|
| Add a new module, or a feature inside an existing one | `references/new-module.md` |
| Set up a new Vue project with this architecture | `references/new-project.md` |
| Restructure an existing pages/components codebase | `references/migration.md` |
| Check that code follows the rules (do this before reporting done) | `references/audit-checklist.md` |
| Wire up the boundary linter | `references/eslint-boundaries.md` |
| Understand a layer in depth | `references/layers.md` |

A complete, real reference module lives in `examples/incomes/` — every layer, CRUD with
pagination, a list component, a form. When writing new code, read it rather than
reconstructing the pattern from the prose above; the prose omits the small things
(barrel files, `unref` placement, error plumbing) that are exactly where generated code
tends to go wrong.

## Adapt to the project, don't overwrite it

Before generating anything, read `package.json` and look at two or three existing modules
or components.

- **State**: Pinia is the default this architecture was built against, but the layer
  contract is what matters — a store exposes state plus setters, and only
  `application/services` mutate it. If the project uses something else, keep the contract
  and change the implementation.
- **HTTP**: `shared/infrastructure/api` owns the transport, behind a four-method
  `ApiClient` interface. The base services depend on that interface, not on any HTTP
  library, so a project already using axios, ky, a generated SDK or `@vueuse/core` keeps
  its client and writes one small adapter — see `assets/adapters/`. Reaching for
  hand-written services instead is almost always the wrong trade: it re-implements loading,
  error and pagination behaviour per module, which is exactly the drift the primitives
  exist to prevent.
- **UI kit, styling, i18n**: not this skill's business. Match whatever the project already
  does — Vant or shadcn-vue, CSS modules or Tailwind, i18n or plain strings. The only UI
  rule that is architectural is that components reach data through `application`, and that
  non-trivial component logic lives in a composable next to the component instead of
  swelling the `<script setup>` block.
- **OpenAPI**: if the backend publishes a schema, generating DTO types is the cheapest
  possible domain layer. If it doesn't, hand-write the types — the structure is unchanged.

## When the project doesn't fit, say so out loud

Sometimes the project genuinely resists part of this architecture — an HTTP client that
does not map onto `ApiClient`, a state library without the store contract, a module
boundary the existing code contradicts. Deviating is often the right answer; deviating
*silently* never is, because the person reading the diff cannot tell a deliberate
adaptation from a misunderstanding.

Stop and put the choice to them: name what does not fit, the two or three ways forward, and
which you would pick. A brief question costs a minute. Discovering the divergence later, in
a summary or during review, costs the trust that makes the rest of the guidance worth
following.

## Scaffolding

`scripts/scaffold-module.mjs` creates the skeleton — every directory, every barrel file,
the `index.ts`, and minimal valid contents:

```bash
node scripts/scaffold-module.mjs --name incomes --kind entity --root src
```

`--kind` is one of `entity`, `screen`, `domain-service` and controls which layers appear.
Run it first, then fill in the real content. It exists because the file that gets forgotten
is always `index.ts`, and a module without its public API silently invites deep imports
from everywhere else.

## Before you say it's done

Run the project's own checks — typecheck, lint, build — and read
`references/audit-checklist.md`. The boundary rules are easy to break accidentally while
concentrating on behaviour, and the linter catches most of it, but not the parts about
side effects in `domain/` or a service that has quietly grown a second responsibility.

Attribution

magersoftmagersoft
View sourceSee grades on GitHubMore from magersoft →
SSkills Directory ProSkills Directory

Get any skill into Claude in one click.

Download any skill as a ZIP for Claude.ai, Claude Desktop, or .claude/skills. $9/mo.

See Pro

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments (0)

No comments yet. Be the first to comment!

SSkills Directory ProSkills Directory

Get any skill into Claude in one click.

Download any skill as a ZIP for Claude.ai, Claude Desktop, or .claude/skills. $9/mo.

See Pro

Related Skills

Clean Code

Pragmatic coding standards - concise, direct, no over-engineering, no unnecessary comments

304955 votes

Browser Extension Developer

Use this skill when developing or maintaining browser extension code in the `browser/` directory, including Chrome/Firefox/Edge compatibility, content scripts, background scripts, or i18n updates.

285172 votes

Seo Optimizer

SEO optimization with keyword analysis, readability assessment, technical validation, content quality. Use for search rankings, blog posts, content audits, or encountering keyword density, readability scores, meta tags, schema markup errors.

2222 votes

Google Official Seo Guide

Official Google SEO guide covering search optimization, best practices, Search Console, crawling, indexing, and improving website search visibility based on official Google documentation

1862 votes

Tanstack Start

Build a full-stack TanStack Start app on Cloudflare Workers from scratch — SSR, file-based routing, server functions, D1+Drizzle, better-auth, Tailwind v4+shadcn/ui. Use whenever the user mentions TanStack Start, asks to scaffold a full-stack Cloudflare app with SSR, wants an SSR dashboard, or asks for a React 19 + Cloudflare Workers app with file-based routing and server functions — even if they don't name TanStack Start specifically. No template repo — Claude generates every file fresh per ...

10341 votes
View all in development →