Skip to content
cccskills
FreePublished on GitHub

scaffold-feature

Generate page and component folder structures with a command, keeping related files together by feature. Create tabbed page shells, starter tests, and README files, and register page routes within the supplied frontend structure.

OriginalShow the original description

Scaffold the co-located feature structure in frontend/src. Use when creating a new page, feature, view (tab), or component folder, when a feature needs a shell with tabs, or when moving existing code out of src/container into src/pages. Generates the full folder tree (components/hooks/store/types/utils/constants/__tests__/README) and registers the page's routes with one command.

See how to install

Good for

  • Starting a page with a consistent folder structure
  • Creating a page shell with multiple tabs
  • Adding components within a feature
  • Moving existing code from src/container to src/pages

Files included (24)

  • SKILL.md7.3 KB
  • lib.mjs2.4 KB
  • references/layout.md4.1 KB
  • scaffold.mjs17.5 KB
  • scaffold.test.mjs3.2 KB
  • templates/component-extras/constants.ts.tmpl0 B
  • templates/component-extras/README.md.tmpl568 B
  • templates/component-extras/types.ts.tmpl0 B
  • templates/component-extras/utils.ts.tmpl0 B
  • templates/component/__Pascal__.module.scss.tmpl61 B
  • templates/component/__Pascal__.tsx.tmpl185 B
  • templates/component/__tests__/__Pascal__.test.tsx.tmpl246 B
  • templates/feature/__Pascal__.module.scss.tmpl218 B
  • templates/feature/__tests__/__Pascal__.test.tsx.tmpl255 B
  • templates/feature/constants.ts.tmpl0 B
  • templates/feature/index.tsx.tmpl259 B
  • templates/feature/README.md.tmpl997 B
  • templates/feature/types.ts.tmpl0 B
  • templates/feature/utils.ts.tmpl0 B
  • templates/shell/__Pascal__.module.scss.tmpl311 B
  • templates/shell/__tests__/__Pascal__.test.tsx.tmpl835 B
  • templates/shell/constants.tsx.tmpl194 B
  • templates/shell/index.tsx.tmpl805 B
  • templates/shell/README.md.tmpl899 B

SKILL.md (original)

Review the instructions the agent will receive before you install.

Scaffold a feature

The frontend is moving to a co-located layout (Bulletproof React / FSD): everything a feature owns lives in the feature's folder. Read references/layout.md for the full target structure and the rules about what may live where.

Never hand-create these folders. Run the generator so every feature comes out identical, then fill it in.

Command

pnpm scaffold page <Name> [options]        # a page/feature under src/pages
pnpm scaffold component <Name> [options]   # a component folder
OptionApplies toEffect
--views A,B,CpageMakes the page a shell with tab switching and generates one view folder per name.
--parent <path>componentParent, relative to src (default components). A feature path like pages/Traces/Explorer nests the component under that feature's components/.
--fullcomponentAlso adds components/, hooks/, store/, types.ts, utils.ts, constants.ts, README.md for a component that owns children.
--no-testsbothSkips __tests__/.
--dry-runbothPrints what would be written, writes nothing.
--forcebothOverwrites files that already exist (off by default; existing entries are reported as skipped).

Folder names keep the casing you type, with the first letter forced up, so LLMObservability stays LLMObservability rather than being re-cased. Separated names collapse to PascalCase: api-monitoring and api monitoring both give pages/ApiMonitoring. Test ids, headings, tab paths and constants are all derived from that folder name — TracesFunnels gives traces-funnels-page, Traces Funnels and TRACES_FUNNELS_TABS.

What you get

pages/ApiMonitoring/
  index.tsx                       # the page component
  ApiMonitoring.module.scss
  components/  hooks/  store/     # empty, ready for the first file
  types.ts  utils.ts  constants.ts
  __tests__/ApiMonitoring.test.tsx
  README.md

With --views, the root becomes a RouteTab shell and each view gets the tree above. The shell mirrors the Logs and Traces root pages: constants.tsx exports one TabRoutes per view (icon from @signozhq/icons, label, ROUTES key, view component), index.tsx composes them into the tab bar, the SCSS module carries the tab-bar overrides, and the test asserts one tab per view plus the active view. Tab icons come from a small name map in scaffold.mjs (Explorer, Funnels, Pipelines, Views, SavedViews); other names get a neutral icon to replace.

Examples

pnpm scaffold page ApiMonitoring                                    # leaf page, no shell
pnpm scaffold page Traces --views Explorer,Funnels,Views            # shell + 3 views
pnpm scaffold page Traces/Explorer                                  # one more view under an existing shell
pnpm scaffold component DataTable                                   # global, src/components/DataTable
pnpm scaffold component QueryBar --parent pages/Traces/Explorer     # feature-local component

Route registration

page also registers the routes, so the page is reachable as soon as it is generated:

FileWhat is added
src/constants/routes.tsOne key per path: API_MONITORING: '/api-monitoring' for a leaf page; TRACES_BASE plus TRACES_EXPLORER, TRACES_FUNNELS, … for a shell.
src/utils/permission/index.tsA routePermission entry per new key, open to ADMIN, EDITOR and VIEWER. Tighten it if the page is admin-only.
src/AppRoutes/pageComponents.tsA Loadable export named <Page>Page pointing at pages/<Page>.
src/AppRoutes/routes.tsThe import plus one private, exact route per path. For a shell the base path and every tab path render the shell; the shell redirects the base path to its first tab and RouteTab picks the tab otherwise.
src/container/TopNav/DateTimeSelectionV2/constants.tsEvery new path in routesToSkip, so the global time-range picker stays hidden until the page opts in.

Existing keys, exports and entries are left alone, so re-running is safe. An existing key or export that points somewhere else is a naming collision and the run stops before writing anything. --dry-run lists the edits without making them. page Traces/Explorer registers TRACES_EXPLORER pointing at the Traces shell; wiring the new tab into the shell's constants.tsx and index.tsx is still by hand. The generator never adds a SideNav item; do that in src/container/SideNav/menuItems.tsx when the page needs one.

After generating

  1. Review the route registration (pages only) and add the SideNav entry if the page needs one. For a view added under an existing shell, add its TabRoutes export to the shell's constants.tsx and include it in the routes array in the shell's index.tsx.
  2. Delete the placeholders you don't need — empty types.ts / utils.ts / constants.ts, and any of components/, hooks/, store/ the feature won't use. Those three folders are created empty; git only picks them up once they hold a file.
  3. Fill the README — the generated file has the prompts; a feature folder without a filled-in README is not done.
  4. Follow the repo rules while filling it in: @signozhq/ui + @signozhq/icons only, CSS Modules (docs/css-modules-guide.md), React Query for server state (prefer api/generated hooks), nuqs for URL state, Zustand for client state, data-testid on every interactive element.
  5. Verify before reporting done:
    pnpm tsgo --noEmit
    pnpm oxlint src/pages/<Feature>
    pnpm jest src/pages/<Feature>
    
    pnpm tsgo --noEmit is the authority. A running dev server can show errors such as Property 'X_BASE' does not exist or has no exported member 'XPage' right after generation. Its type-checker notices new files but, on some machines, not in-place edits to existing ones, and the generator edits the shared files in place. If tsgo is clean, restart pnpm dev.

Editing the templates

Templates live in templates/ — feature/, shell/, component/ and component-extras/ (the --full additions). Every template file ends in .tmpl, which keeps TypeScript, lint and your editor from reading them as source; the generator strips that suffix on the way out, so index.tsx.tmpl becomes index.tsx. Tokens are substituted in both file names and contents: __Pascal__, __kebab__, __camel__, __CONST__, __Title__. The shell templates additionally take tokens the generator builds from --views: __ICON_IMPORTS__, __VIEW_IMPORTS__, __TAB_EXPORTS__, __TAB_NAMES__, __BASE_ROUTE__, __FIRST_TAB__, __FIRST_VIEW_TESTID__ and __TAB_ASSERTIONS__. Tab icons come from TAB_ICONS and the empty folders from FEATURE_DIRS, both in scaffold.mjs. Name and route derivations live in lib.mjs; run node --test .claude/skills/scaffold-feature/scaffold.test.mjs after changing them. Change these, not the generated output, when the team's conventions move.

Reviews

No reviews yet. Tell others what you thought.

Comments

No login needed. Share how it worked for you, ask a question, or note where it did not run.

No comments yet. Be the first to write one.

Comments are published right away. Do not include personal information such as email addresses or phone numbers. Up to 2 URLs.

0 / 1,000 characters

This form is protected by reCAPTCHA, and the Google Privacy Policy and Terms of Service apply.

More skills from this repository

Refactor state held in Redux or React Context by separating API data, URL settings, shared interface state, and local component state. Move each part to React Query, nuqs, Zustand, or React’s local state hooks.

  • Migrating away from Redux or React Context
  • Removing duplicate storage of API responses
  • Sharing filters and pagination through URLs
SigNoz/signoz32.4KUpdated Oct 18, 2026

Build Storybook page stories for SigNoz by mapping API requests, display states, and URL parameters. Use msw mock responses, which simulate API replies, and controls to inspect loading, errors, permissions, and other page states.

  • Creating Storybook stories for SigNoz pages
  • Switching between loading, empty, and error states
  • Checking how permissions affect buttons and controls
SigNoz/signoz32.4KUpdated Oct 18, 2026

See all skills by SigNoz

Report a problem with this skill