agentleFS
moasqmoasq/ios-dev-agent/.agents/skills/feature-directory-structure/SKILL.md

feature-directory-structure

Skill4 starsChanged 6 months agoMITView on GitHub

Use when a Features/<Name>/ folder grows past ~5 files, or when adding subviews, sheets, overlays, or backdrops. Covers the nested-subdirectory convention (Sections/, Sheets/, Overlays/, Backdrop/) so features stay browsable instead of accumulating 15 flat files with similar names.

The file

We split this skill into the rules it gives an agent

4 rules. About 0 are common, 2 are distinctive, and 2 are very specific to this project.

  • ≈0

    Common · estimate

    Many files like this have a rule of this kind.

  • ≈2

    Distinctive · estimate

    This author's own choices. Worth a look.

  • 2

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Distinctive:

    When a feature has 5 or fewer files, keep it flat:

    line 13
  2. Distinctive:

    Use these names consistently across features.

    line 49
  3. Very specific:

    Don't create a subfolder for a single file.

    line 62
  4. Very specific:

    Don't mirror the folder structure into the shell view's body.

    line 64

≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

Feature Directory Structure

Features with many files must use nested subdirectories. Flat is fine up to a point; past that, subfolders are required.

The Rule

Flat — up to 5 files total per feature

When a feature has 5 or fewer files, keep it flat:

Features/Profile/
  ProfileView.swift
  ProfileViewModel.swift
  ProfileView+Header.swift

Three files, still scannable. No need for subfolders.

Nested — 6+ files per feature

Past ~5 files, group into subfolders by role:

Features/Home/
  HomeView.swift          ← main shell (body is table of contents)
  HomeViewModel.swift     ← one @Observable class
  Sections/               ← extracted body sections (View+X.swift)
    HomeView+Idle.swift
    HomeView+Recording.swift
    HomeView+Result.swift
  Sheets/                 ← .sheet / .fullScreenCover contents
    PillarDetailSheet.swift
    HistoryBrowseSheet.swift
  Overlays/               ← ZStack overlays, toasts, celebration
    CelebrationOverlay.swift
    StreakToastView.swift
  Backdrop/               ← ambient backgrounds, visual effects
    AmbientBackdrop.swift

The shell (HomeView.swift + HomeViewModel.swift) stays at the feature root. Everything else goes into a subfolder.

Canonical Subfolder Names

Use these names consistently across features. Don't invent new ones.

FolderWhat goes in it
Sections/View+X.swift extensions — extracted body sections of the main view
Sheets/Views presented via .sheet or .fullScreenCover — each is its own standalone View
Overlays/ZStack overlays, toasts, celebration cards, modal affordances
Backdrop/Ambient backgrounds, particle scenes, blur effects, visual-only layers
Components/Feature-local reusable subviews that don't fit the above and aren't shared (shared components belong in Features/Common/)
Rows/List row views when a feature has 3+ row variants

When NOT to split

Don't create a subfolder for a single file. Sheets/PillarDetailSheet.swift alone is fine only if you expect another sheet to land in v1.1 — otherwise keep it at the feature root until a second sheet forces the split.

Don't mirror the folder structure into the shell view's body. The body is a table of contents of section properties; subfolders are for the filesystem, not for SwiftUI hierarchy.

Rules

  1. Only use subfolders when the feature has more than ~5 files. Below that, flat is more scannable.
  2. The shell (View + ViewModel) stays at the feature root even in nested structures.
  3. Use the canonical subfolder names above. Consistency across features matters more than any one naming preference.
  4. One type per file still applies. Nesting doesn't dissolve that rule.
  5. Features/Common/ is for cross-feature shared views. Feature-local reusable views go in Features/<Name>/Components/.
  6. Hard line limit stays 200 lines per file, target 150. Subfolders don't change file-size rules — they solve folder browsability, not file size. If a single file is too big, split with View+Section.swift extensions inside Sections/.

Examples

Home feature (rich, nested)

Features/Home/
  HomeView.swift
  HomeViewModel.swift
  Sections/
    HomeView+Idle.swift
    HomeView+Recording.swift
    HomeView+Result.swift
  Sheets/
    PillarDetailSheet.swift

Onboarding feature (many steps → nested)

Features/Onboarding/
  OnboardingView.swift
  OnboardingViewModel.swift
  OnboardingTopBar.swift
  Steps/
    OnboardingWelcomeStep.swift
    OnboardingGoalStep.swift
    OnboardingPaywallStep.swift
    ... (more steps)

Steps/ is a valid subfolder name here — it's the canonical term for an onboarding flow's per-screen views. Prefer Steps/ over Sections/ for step-by-step flows.

Small feature (stays flat)

Features/AuthGate/
  AuthGateView.swift
  AuthGateViewModel.swift

Two files, no subfolders needed.

Why this matters

A Features/Home/ with 15 flat files named HomeView.swift, HomeView+Hero.swift, HomeView+TopBar.swift, HomeView+Challenge.swift, HomeView+Activity.swift, HomeCelebrationOverlay.swift, HomeAmbientBackdrop.swift, StreakToastView.swift, HomeViewModel.swift, HomeViewModel+Contracts.swift, HomeViewModel+Progression.swift forces the reader to parse filename prefixes to understand the structure. With nested folders, the structure is visible from the file tree alone — the reader opens Sections/ to see body sections and Overlays/ to see overlays without reading any code.

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.