Create Darkroom Component

SkillDev tools

Create UI component / widget / reusable piece. Triggers "create component", "new component", "add component", or naming a component (Button, Header, Card).

Available today. Use it from your connected AI after setup.

Connect ahel once, and every AI you use reads what you have installed.

Then ask your AI: use the Create Darkroom Component skill

What this skill tells your AI

The instructions your AI receives, as published by darkroomengineering/cc-settings in skills/component/SKILL.md and read by ahel’s review.

Create a React component following Darkroom conventions. Detect the stack first — satus (Next.js) and novus (React Router) have different conventions for client/server boundaries, image/link wrappers, and path aliases.

Step 1 — Detect stack

Read package.json:

  • dependencies.next present → Next.js / satus conventions
  • dependencies["react-router"] or devDependencies["@react-router/dev"] → React Router / novus conventions
  • Neither → ask user, or assume satus if unclear

Step 2 — Resolve target paths

StackComponent pathCSS module pathImage wrapperLink wrapperPath alias
satus (Next.js)components/<name>/index.tsxcomponents/<name>/<name>.module.cssimport { Image } from '@/components/image'import { Link } from '@/components/link'@/
novus (React Router)components/<name>/index.tsxcomponents/<name>/<name>.module.cssNative <img> (or project's wrapper if it exists)import { Link } from 'react-router'~/

Step 3 — Emit template

satus / Next.js

// components/<name>/index.tsx
// 'use client' — only add if component needs:
// - useState, useEffect, or other hooks
// - Event handlers (onClick, onChange, etc.)
// - Browser APIs (window, document, etc.)

import s from './<name>.module.css'

interface <Name>Props {
  children?: React.ReactNode
  className?: string
}

export function <Name>({ children, className }: <Name>Props) {
  return (
    <div className={`${s.<name>} ${className ?? ''}`}>
      {children}
    </div>
  )
}

novus / React Router

// components/<name>/index.tsx
// React Router components are isomorphic — no directive needed.
// They run on server during SSR and on client after hydration.

import s from './<name>.module.css'

interface <Name>Props {
  children?: React.ReactNode
  className?: string
}

export function <Name>({ children, className }: <Name>Props) {
  return (
    <div className={`${s.<name>} ${className ?? ''}`}>
      {children}
    </div>
  )
}

CSS module (both stacks)

.<name> {
  /* Component styles */
}

Before you start

If this component wraps or uses an external library (Radix, Framer Motion, GSAP, etc.):

  1. Fetch docs first — use Context7 MCP (mcp__context7__resolve-library-idget-library-docs) for the current API in Claude or when the user configured it in standalone Codex. Otherwise use official docs through native browsing or inspect the pinned local package. cc-settings does not auto-run unpinned registry MCP packages in Codex.
  2. Check version — run bun info <package> before installing.

Never implement against external library APIs from memory.

Conventions (both stacks)

  1. CSS Module as s — always import as s for consistency.
  2. Props interface — define explicitly, include className for composition.
  3. Named export — use export function, not export default.
  4. No memoization — React Compiler handles it.

Conventions (satus only)

  1. Server Component by default — only add 'use client' if needed.
  2. Image wrapperimport { Image } from '@/components/image'.
  3. Link wrapperimport { Link } from '@/components/link'.

Conventions (novus only)

  1. Components are isomorphic — no 'use client' directive.
  2. Path alias is ~/, not @/.
  3. Linkimport { Link } from 'react-router' (declarative routing).
  4. Images — native <img> with explicit width/height/fetchPriority. No project-level wrapper unless the project added one.

Arguments

  • $ARGUMENTS — Component name (e.g., "Button", "Header")
  • --client flag (Next.js only) — Force client component

Example

User: "create a Button component"
→ detect stack → satus → creates components/button/index.tsx + button.module.css with @/-aliased imports

User: "create a Button component" (in novus repo)
→ detect stack → novus → creates same files but with ~/-aliased imports and no 'use client' directive

Signals

GitHub stars
44
Forks
3
Last commit
Sep 2026
Advanced
Catalog kind
skill
Gateway key
component
Source
github.com/darkroomengineering/cc-settings