Use when creating, moving, splitting, or organizing TypeScript files and folders. Applies fractal tree file-structuring rules which reduce the cognitive overhead of choosing where to put files and ultimately navigating a codebase (once the structure is established and understood).
71
88%
Does it follow best practices?
Run evals on this skill
Adds up to 20 points to the overall score
View guide
Passed
No findings from the security scan
TypeScript and JavaScript files should be organised in a fractal tree structure. Use this skill when deciding where to create, move, split, or organize files and folders in a TypeScript or JavaScript workspace.
This guidance is based on HASH's file-structuring approach: https://hash.dev/blog/file-structuring
Apply this skill to TypeScript and JavaScript source files, including modules, components, hooks, helpers, types, tests, scripts, and entry points.
Use kebab-case for all TypeScript and JavaScript file and folder names.
create-worker-factory.ts
playback-settings-menu.tsx
button.tsxAvoid PascalCase, camelCase, and mixed-case file names, even for React components.
Do not add index.ts, index.tsx, index.js, or index.jsx files for folder imports. Prefer explicit file entry points with meaningful names.
If a subtree needs a public entry point, name that file after the concept it exposes (e.g. schema.ts)
A file should expose one or more named exports with a shared semantic purpose. The file name should summarize that purpose (e.g. users.ts)
If a file contains only one main export, prefer naming the file after that export in kebab-case (e.g. create-user.ts)
Avoid default exports unless a framework or external API requires them.
When a file becomes too large or contains implementation details worth extracting, create a same-named folder next to it and move private pieces there.
editor-view.tsx # public mini-library: the component other files import
editor-view/
panels.tsx # private entry point imported by editor-view.tsx
panels/
simulate-view.tsx # private to panels.tsx
calculate-timeline-range.ts # private helper used only by editor-view.tsx
create-panel-state.ts # private helper used only by editor-view.tsxOnly editor-view.tsx should import from direct child mini-libraries such as editor-view/panels.tsx and editor-view/calculate-timeline-range.ts. Only editor-view/panels.tsx should import from editor-view/panels/*.tsx. Other files should import from editor-view.tsx, not from its private subtree. This keeps editor-view.tsx as the API boundary and makes editor-view/ read as its implementation.
If editor-view/calculate-timeline-range.ts grows and needs its own private implementation files, create editor-view/calculate-timeline-range/. Only editor-view/calculate-timeline-range.ts should import from that deeper subtree.
editor-view/
calculate-timeline-range.ts
calculate-timeline-range/
clamp-time.ts # private to calculate-timeline-range.ts
get-visible-duration.ts # private to calculate-timeline-range.tsDo not import directly from another file's implementation folder.
// Avoid: reaches into another file's private subtree
import { SimulateView } from "../editor-view/panels/simulate-view";
// Prefer (1): import from a public mini-library (if it is conceptually part of editor-view)
import { EditorView } from "../editor-view";
// Prefer (2): move shared code to a shared folder (if it is NOT conceptually part of editor-view)
import { Button } from "../shared/button";If a resource must be available outside the subtree, re-export it from the subtree root only when it is part of that root's public concept. If it is independently useful to sibling branches, move it to an appropriate shared/ folder instead.
When multiple sibling branches need the same helper, type, component, constant, or hook, place it in the nearest applicable shared/ folder.
editor-view.tsx
editor-view/
shared/
duration-label.tsx # used by both panels.tsx and bottom-section.tsx
playback-time.ts # shared formatting/parsing logic for this subtree
panels.tsx # imports from panels/
panels/
simulate-view.tsx # private to panels.tsx
bottom-section.tsx # imports from bottom-section/
bottom-section/
bottom-bar.tsx # private to bottom-section.tsxPlace shared files as deep as possible while still covering all current consumers. Do not move something to a high-level shared folder just because it might be reused later.
Here editor-view.tsx imports ./editor-view/panels and ./editor-view/bottom-section. panels.tsx may import ./panels/simulate-view and ./shared/duration-label; bottom-section.tsx may import ./bottom-section/bottom-bar and ./shared/duration-label. Nothing else should import from panels/ or bottom-section/ directly.
Shared files are mini-libraries too. A shared file can have its own private same-named subtree, and those internals should remain private to that shared file.
editor-view/
shared/
playback-time.ts # public to editor-view/* branches
playback-time/
parse-playback-time.ts # private to playback-time.ts
format-playback-time.ts # private to playback-time.tsIf later only bottom-bar.tsx uses duration-label.tsx, move it beside bottom-bar.tsx or under bottom-bar/. The folder structure should describe current consumers, not preserve old sharing.
For imports inside the same workspace, use relative paths. Do not introduce workspace-local aliases just to shorten paths.
Imports from other workspaces should use the package name.
Place unit tests next to the file they cover.
foo.ts
foo.test.tsIf a private extracted file needs direct tests, place those tests next to that extracted file.
editor-view.tsx
editor-view.test.tsx
editor-view/
calculate-timeline-range.ts
calculate-timeline-range.test.tsPrefer testing through the public mini-library when that gives enough coverage. Add direct tests for private extracted files when the logic is complex enough that tests through the owner would be indirect or brittle.
Organize files for the code's current relationships, not speculative future reuse. Moving files later is expected and cheaper than adding premature structure now.
Before creating a TypeScript or JavaScript file or folder:
shared/ folder.index files and implicit folder imports.Choose the location that communicates the file's current consumers and API boundary most clearly:
shared/ folder when multiple branches need that API.Do not add broad components, hooks, utils, types, or services folders unless absolutely necessary. If they exist, these folders MUST only be imported from by files called components.ts, hooks.ts, etc.
4f2d2ce
If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.