Skip to content
Back to skills

Set Up Frontend Structure

ASecurity

Use when laying down the folder layout of a frontend project - atomic-design components, hooks or composables, libs, utils, stores, styles, and feature modules from the second domain on, with one example component.

  • 5 stars
  • 0 votes
  • 0 copies
  • 1 view
  • Added October 10, 2026
developmentbashreactvuenodegitfrontend

Works with

  • cli

Security analysis

A100/100

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

Scanned October 10, 2026

npx -y skills add VelimirMueller/lab-claude-skills --skill set-up-frontend-structure --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Set Up Frontend Structure?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Set Up Frontend Structure
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/velimirmueller-set-up-frontend-structure-lab-claude-skills/badge)](https://www.skillsdirectory.com/skills/velimirmueller-set-up-frontend-structure-lab-claude-skills)

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

Download with Pro
SKILL.md
---
name: set-up-frontend-structure
description: Use when laying down the folder layout of a frontend project - atomic-design components, hooks or composables, libs, utils, stores, styles, and feature modules from the second domain on, with one example component.
---

# Set Up Frontend Structure

## 1. Audit current state

For each folder below, check if it already exists and is non-empty:
- `src/components/atoms`
- `src/components/molecules`
- `src/components/organisms`
- `src/components/templates`
- `src/components/pages`
- `src/hooks` (React) **or** `src/composables` (Vue)
- `src/libs`
- `src/utils`
- `src/stores`
- `src/styles`
- `src/features` (only if the app already has two or more domains)

(The test tree lives at a top-level `tests/`, created by `configure-test-stack` — not here.)

Read `.claude/stack-profile.md` if present: `frontend.framework` (`react` | `vue`) replaces the `package.json` detection; `frontend.meta` of `nuxt` or `next` switches to the mapping table in `folder-conventions.md` ("Nuxt and Next use the same names inside their own roots"): the source root is `app/` for Nuxt, routing folders belong to the framework, and `pages/` is not created twice. Otherwise detect from `package.json`. The hook-vs-composable folder is framework-specific — see `../_shared/conventions.md`.

If every folder exists and is non-empty, exit: "Structure already in place."

## 2. Decide what to do

- Nothing in place → full setup (steps 3–5).
- Partial → create only missing folders; do not overwrite existing files.
- Already structured → exit.

## 3. Create folder tree

Create:

```
src/
├── components/
│   ├── atoms/
│   ├── molecules/
│   ├── organisms/
│   ├── templates/
│   └── pages/
├── hooks/        (React) OR composables/ (Vue)
├── libs/
├── utils/
├── stores/
└── styles/
```

`src/features/<domain>/` is created by `create-module` when the second domain arrives; `src/locales/` by `set-up-i18n`. The full map, the findability table and the Nuxt/Next mapping: `folder-conventions.md`.

(By default tests are **not** under `src/`: `configure-test-stack` creates a top-level `tests/{unit,ui,integration,e2e}` tree. With `tests.layout: colocated` in the profile, tests sit beside the code and no `tests/` tree is needed except for `e2e/`.)

Drop a `.gitkeep` in each empty folder so git tracks them; delete it in the commit that adds the first real file.

## 4. Barrels: component folders and features only

Do **not** create layer-level barrels (`components/atoms/index.ts`, `utils/index.ts`, …): importing one atom would make Vite load every file in the layer (`../_shared/conventions.md`, "barrels re-export, never define"). Each component folder gets a one-line `index.ts` (step 5); each feature gets `features/<domain>/index.ts` when `create-module` adds it. Import utilities by path: `@/utils/formatDate`.

## 5. Generate one example component

One example is enough to show the convention; the other layers are described in `atomic-design.md`, and a component written to "fill the layer" is a component someone deletes. Generate the `Button` atom. Add the `*.stories.ts` sibling **only if Storybook is installed** (`grep storybook package.json`); the scaffold does not install it. Tests are **not** co-located by default — they live in a top-level `tests/` tree created by `configure-test-stack` (ref `test-layout.md`; `tests.layout: colocated` in the profile reverses that); stories sit beside their component, where the Storybook Vitest addon runs them as tests in place.

```
src/components/atoms/Button/
├── Button.tsx
├── Button.stories.ts     # only with Storybook
└── index.ts
```

### Example file content (React `Button` atom)

```tsx
// src/components/atoms/Button/Button.tsx
import type { ButtonHTMLAttributes, ReactNode } from 'react';

type ButtonProps = ButtonHTMLAttributes<HTMLButtonElement> & {
  children: ReactNode;
};

export function Button({ children, ...rest }: ButtonProps) {
  return (
    <button
      type="button"
      className="px-3 py-1.5 rounded-md bg-blue-600 text-white hover:bg-blue-700 disabled:opacity-50"
      {...rest}
    >
      {children}
    </button>
  );
}
```

```ts
// src/components/atoms/Button/index.ts
export * from './Button';
```

```ts
// src/components/atoms/Button/Button.stories.ts
import type { Meta, StoryObj } from '@storybook/react-vite';
import { Button } from './Button';

const meta = {
  title: 'Atoms/Button',
  component: Button,
} satisfies Meta<typeof Button>;
export default meta;

type Story = StoryObj<typeof meta>;

export const Default: Story = {
  args: { children: 'Click me' },
};
```

Import `Meta`/`StoryObj` from the **framework** package (`@storybook/react-vite`, Vue: `@storybook/vue3-vite`), not `@storybook/react`: the framework package re-exports them, and under pnpm's strict layout the renderer package is not a direct dependency, so importing it fails to resolve.

For Vue projects, write `Button.vue` (+ `Button.stories.ts`) in the Vue 3.5 shape — `<script setup>`, destructured props with defaults, `useTemplateRef`, `defineModel` — see `../_shared/framework-idioms.md`.

## 6. Verify

```bash
pnpm typecheck
```

Expected: exit 0. The example component (and its story, if Storybook is installed) compile.

A story that cannot resolve `@storybook/*` means Storybook is not installed: delete the story or install Storybook (`pnpm dlx storybook@latest init`). The test stack (Vitest browser mode, Playwright, MSW, and the top-level `tests/` tree) is set up separately by `configure-test-stack`.

## References
- ./atomic-design.md — methodology, criteria for each layer, anti-patterns.
- ./folder-conventions.md — the shared layout, the findability table, the Nuxt/Next mapping, naming, barrels, hooks vs composables.
- ../_shared/framework-idioms.md — Vue 3.5 / React 19 idioms for the generated examples.
- ../_shared/glossary.md — atomic terms (atom / molecule / organism / template / page) with the "test" question for each.

Files in this skill

  • SKILL.md5.9 KB
  • atomic-design.md4.6 KB
  • folder-conventions.md7.9 KB

Attribution

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

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.