Skip to content
Back to skills

Ayunis Core Frontend Dev

ASecurity

Frontend development in ayunis-core. Use when creating, modifying, or debugging frontend code (React, Feature-Sliced Design, API client).

  • 33 stars
  • 0 votes
  • 0 copies
  • 1 view
  • Added September 20, 2026
developmentbashreactawsdebuggingapidatabasefrontendbackend

Works with

  • cli
  • api

Security analysis

A100/100

Scanned October 5, 2026

npx -y skills add ayunis-core/ayunis-core --skill ayunis-core-frontend-dev --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Ayunis Core Frontend Dev?

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

Security grade badge for Ayunis Core Frontend Dev
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/ayunis-core-ayunis-core-frontend-dev/badge)](https://www.skillsdirectory.com/skills/ayunis-core-ayunis-core-frontend-dev)

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: ayunis-core-frontend-dev
description: Frontend development in ayunis-core. Use when creating, modifying, or debugging frontend code (React, Feature-Sliced Design, API client).
---

# Frontend Development — ayunis-core-frontend

## Working Directory

**All commands run from `ayunis-core-frontend/`:**

```bash
cd ayunis-core-frontend
```

Before modifying any layer, read its `SUMMARY.md` in `src/[layer]/SUMMARY.md`. The top-level `src/SUMMARY.md` provides an overview.

## Concise UI Copy

Give users enough information to choose confidently, with minimal repetition.

- Use short, specific action verbs for buttons: **Archive**, **Restore**, **Delete**. Include the target when the control would otherwise be ambiguous on its own.
- Let nearby titles identify the subject and descriptions explain the consequence. When an action row already says **Archive organisation** and explains its effect, its button can simply say **Archive**.
- Apply the same approach inside confirmation modals: keep the subject and consequences in the title and body, and use the action verb for the confirmation button. Avoid generic **Yes**, **OK**, or **Confirm** when a specific verb is clearer.
- Preserve information that changes the decision: what is affected, whether the action is reversible, and any required confirmation. Concision must not weaken destructive-action warnings or remove the resource name needed to confirm deletion.
- Prefer one useful explanation over repeated helper text. Keep implementation details out of product copy unless they help the user decide or recover from an error.
- Review the rendered copy in each affected locale. Short labels must remain clear in context; do not impose word limits that make translations unnatural.

## Validation Sequence

Choose validation breadth using the repository's Proportional Workflow.

For Standard and High-Risk changes:

```bash
pnpm run build                 # Must succeed
pnpm run lint                  # Must pass
```

For Fast Path changes, run the narrowest relevant test when behavior or test
code changed, plus any lint/type check applicable to the touched files. Run the
build when imports, types, dependencies, bundling, or other compile-time
behavior could be affected.

**Browser journey or system boundary changed?** Load the `e2e` skill when
lower-level tests do not sufficiently prove the behavior. Add `data-testid`s
needed by the journey to touched components in the same PR
(`<feature>-<element>`, kebab-case) — text selectors are banned because the UI
is i18n'd.

**Would visual evidence materially help review?** After the product PR exists,
load the `pr-media` skill and publish the smallest useful scene set to
`pr-media/pr-<number>`. Do not commit media scenes to the product branch.

## Architecture (Feature-Sliced Design)

```text
packages/ui/  # Framework-level UI primitives, tokens, and utilities

ayunis-core-frontend/src/
├── pages/      # Route components (compose widgets/features)
├── widgets/    # Reusable composites (used in ≥2 pages)
├── features/   # Self-contained business logic
└── shared/     # App-wide infrastructure and app-aware UI
```

**Import rules**: `pages → widgets → features → shared`

Layers only depend on layers to their right. Never import upward.

### Check demonstrated conventions before deciding placement

The FSD rules above are the theory; **this repo's actual conventions are the tie-breaker.** Before deciding where a slice or component lives — feature vs widget vs page, which page a route maps to, whether something is "shared enough" to promote a layer — grep how comparable cases are already structured and follow that, rather than reasoning from FSD principles alone. Before adding any frontend file or introducing a new slice segment, inspect the target slice's existing directories and the two closest analogues.

- The abstract heuristics ("used in ≥2 pages → widget", "used from more than one slice → promote") are necessary but not sufficient. They routinely disagree with how the codebase actually draws its boundaries when viewed across the whole repo instead of a single branch.
- Concrete convention that has bitten before: **pages map one slice per route** — e.g. a list route and its detail route are separate page slices (`skills.index` vs `skill.$id`), not one page reused across two routes. Check the route files and `src/pages/` before assuming a shared placement.
- When a colocated placement (feature/page) and a "promote to shared/widget" placement both look defensible, the existing convention wins. Look at the `Reference Pages` in the `new-page` skill and grep sibling slices before moving code.
- Do not double down on a theory-driven placement after pushback — re-check the convention first. See "Confirm placement before mutating a stacked PR chain" below.

### Confirm placement before mutating a stacked PR chain

Do not execute structural moves and amend commits across a stacked-PR chain (e.g. `gt modify` a parent, then check out and amend the child) off a _preliminary_ placement conclusion. Settle the placement against repo conventions first, then move — reverting a wrong move across stacked branches means restoring exact pre-session SHAs from the reflog.

## Shared UI Package — Registry-Managed Primitives

Framework-level primitives live in the repository-root `packages/ui/` workspace and are imported through `@ayunis/ui` subpaths. App-aware shared components remain in `ayunis-core-frontend/src/shared/ui/`.

- Run shadcn registry commands from `packages/ui/`, whose `components.json` owns the aliases and registry configuration: `cd ../packages/ui && pnpm dlx shadcn@latest add <component>`.
- Do not patch `packages/ui/src/components/` for a feature-specific use case. Wrap or compose the primitive in the relevant frontend `ui/` directory or `src/shared/ui/` instead.
- Changes inside `packages/ui/` must remain application-independent and be intentional design-system work. If a primitive genuinely needs a new generic capability, confirm that scope with the user before changing it.
- Every newly introduced `packages/ui/src/components/<name>.tsx` component must include a colocated `<name>.stories.tsx`. Cover its representative default state and meaningful generic variants, states, or interactions; compound components should be demonstrated as a usable composition.
- Import primitives from their public subpaths, such as `@ayunis/ui/components/button`, and `cn` from `@ayunis/ui/lib/cn`. Do not reach into `packages/ui/src/` from the frontend.

### Reach for existing primitives and tokens

Compose the existing design system before hand-rolling layout, and use design tokens instead of raw Tailwind color scales:

- **Look for a composite primitive first.** For an icon-plus-label row (banners, result cards, list rows) use the `Item` family — `Item` / `ItemMedia variant="icon"` / `ItemContent` — rather than assembling a bare `flex` container yourself. Check `@ayunis/ui` for a framework primitive and `src/shared/ui/` for an app-aware component before adding your own.
- **Use semantic color tokens, never hardcoded palette classes.** `text-brand`, `text-muted-foreground`, etc. — not `text-amber-500`, `text-blue-600`, or other raw Tailwind color scales, which break theming and dark mode.

### Page module internals

Each page module can have these subdirectories:

```text
src/pages/<page-name>/
├── ui/       # Components — component-local state/hooks and JSX
├── hooks/    # Standalone React behavior hooks, when the slice uses this segment
├── api/      # Mutation hooks (one per operation)
├── model/    # Types, constants, schemas
└── lib/      # Pure helpers and established reusable behavior hooks
```

Keep `ui/` components focused on component logic. Calling hooks inside a component does not make `ui/` the home for standalone `use*.ts` files. Put standalone interaction or presentation behavior hooks in the slice's established `hooks/` or `lib/` segment, choosing between them from the target slice and its two closest analogues; keep server operations in `api/` and state/domain concerns in `model/` when that is the slice convention. A component-specific hook may stay colocated only when comparable components in that slice already follow that pattern.

## API Client

After backend API changes, regenerate the client:

```bash
pnpm run openapi:update  # Regenerates src/shared/api/generated/
```

**Never edit generated code manually** — it will be overwritten.

## Hook Pattern

One hook per operation, encapsulating mutation logic. Use `showSuccess`/`showError` from `@/shared/lib/toast` for user feedback, and `extractErrorData` from `@/shared/api/extract-error-data` for structured error handling.

For hooks that back a form (create/update dialogs), load the **frontend-form-pattern** skill — it covers form types, structure, and the full end-to-end validation pattern including backend DTO validation, field-level error display, and i18n.

## Verifying in the Browser

When the change affects rendered UI or browser behavior, use your harness's browser tooling to check the affected page renders and the console is clean. A render failure shows the React dev-server error overlay — the element `#webpack-dev-server-client-overlay` must not exist. The frontend URL depends on the dev slot (see `dev-environment`); seeded login credentials are in `seed-database`.

## Completion Checklist

- [ ] Validation matches the repository's Proportional Workflow
- [ ] Relevant focused tests pass when behavior or test code changed
- [ ] Build and package lint pass for Standard and High-Risk changes
- [ ] Affected page renders without console errors when UI or browser behavior changed
- [ ] No `any` types introduced
- [ ] Import rules respected (no upward imports)
- [ ] UI primitives use public `@ayunis/ui` subpaths
- [ ] New `packages/ui` components include representative Storybook stories
- [ ] No feature-specific behavior added to `packages/ui/`

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…