agentsclimarketplace

Add feature

Skill makigjuro/cloudstack-ai-plugins/plugins/react-developer/skills/add-feature

Claude Code plugin marketplace — AI-powered full-stack cloud engineer for .NET 10 + React 19 + Azure/Terraform/Helm projects. 29 skills, 6 agents, 14 rules.

Install
npx -y skills add makigjuro/cloudstack-ai-plugins --skill add-feature

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

One thing to look at

  • 1 stars1 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

What its author says it does

Copied from the file, not written here

Scaffold a new frontend feature module with page, components, API service, and hooks. Use whenever the user wants to add a new page, dashboard section, UI module, or frontend feature to the React app.

SKILL.md

7.6 KB, as published. Nobody here has run it

Add Frontend Feature

Scaffold a new feature module following the project's React + TypeScript conventions.

Arguments

  • {feature} — Feature name in kebab-case (e.g., alerts, settings, users)

Configuration

Read cloudstack.json from the project root at the start of execution. Extract:

  • FRONTEND_PATH = frontend.path (default: web)
  • DEV_PORT = frontend.devPort (default: 5173)
  • UI_LIBRARY = frontend.uiLibrary (default: shadcn)
  • STATE_SERVER = frontend.stateManagement.server (default: tanstack-query)
  • STATE_CLIENT = frontend.stateManagement.client (default: zustand)
  • MULTI_TENANT = backend.multiTenancy (default: false)

If cloudstack.json does not exist, auto-detect by checking package.json dependencies.

Structure

Creates the following structure under {FRONTEND_PATH}/src/features/{feature}/:

{feature}/
├── pages/
│   └── {feature}-page.tsx
└── components/
    └── {feature}-overview.tsx

And adds an API service at {FRONTEND_PATH}/src/api/services/{feature}.api.ts.

0. Detect Existing Patterns

Before scaffolding, scan the project for existing conventions:

# Find existing API client
find {FRONTEND_PATH}/src/api -name "client.*" -o -name "http.*" -o -name "axios.*" 2>/dev/null | head -5

# Find existing feature modules for reference
ls -d {FRONTEND_PATH}/src/features/*/pages/ 2>/dev/null | head -3

# Check for multi-tenancy utility
grep -rl "tenantId\|appendTenant\|multiTenant" {FRONTEND_PATH}/src/api/ 2>/dev/null | head -3

Read any existing API service file and feature page to match the project's established patterns.

1. API Service ({FRONTEND_PATH}/src/api/services/{feature}.api.ts)

Adapt the template based on the existing API client pattern detected in step 0.

If using a custom apiRequest wrapper:

/**
 * {Feature} API client
 */

import { apiRequest } from '../client'
import type { PaginatedResponse } from '../types'

// Define types inline or in ../types/index.ts
export interface {Entity} {
  id: string
  // fields
}

const BASE_PATH = '/api/{feature}'

export const {feature}Api = {
  /**
   * Get paginated list
   */
  async getAll(page = 1, pageSize = 20): Promise<PaginatedResponse<{Entity}>> {
    const params = new URLSearchParams()
    params.set('pageNumber', page.toString())
    params.set('pageSize', pageSize.toString())

    return apiRequest({ url: BASE_PATH, params })
  },

  /**
   * Get by ID
   */
  async getById(id: string): Promise<{Entity}> {
    return apiRequest({ url: `${BASE_PATH}/${id}` })
  },
}

If MULTI_TENANT is true:

Look for the existing tenant utility (e.g., appendTenantId, withTenantParams, or similar). If found, import it and apply to each API call's query parameters. If no utility exists, add tenant ID from the auth store:

// Add to each method that needs tenant scoping:
const params = new URLSearchParams()
appendTenantId(params) // or use whatever pattern the project uses

If using plain axios/fetch:

Match the existing pattern exactly. Do not introduce a new abstraction.

2. Page ({FRONTEND_PATH}/src/features/{feature}/pages/{feature}-page.tsx)

import { {Feature}Overview } from '../components/{feature}-overview'

export function {Feature}Page() {
  return (
    <div className="container mx-auto py-6">
      <{Feature}Overview />
    </div>
  )
}

3. Overview Component ({FRONTEND_PATH}/src/features/{feature}/components/{feature}-overview.tsx)

Adapt based on STATE_SERVER:

If tanstack-query (default):

import { useQuery } from '@tanstack/react-query'
import { {feature}Api } from '@/api/services/{feature}.api'

export function {Feature}Overview() {
  const { data, isLoading, error } = useQuery({
    queryKey: ['{feature}'],
    queryFn: () => {feature}Api.getAll(),
    staleTime: 30_000,
  })

  if (isLoading) return <div>Loading...</div>
  if (error) return <div>Error loading {feature}</div>

  return (
    <div>
      <h1 className="text-2xl font-bold mb-4">{Feature}</h1>
      {/* Render data */}
    </div>
  )
}

If swr:

import useSWR from 'swr'
import { {feature}Api } from '@/api/services/{feature}.api'

export function {Feature}Overview() {
  const { data, error, isLoading } = useSWR('{feature}', () => {feature}Api.getAll())

  if (isLoading) return <div>Loading...</div>
  if (error) return <div>Error loading {feature}</div>

  return (
    <div>
      <h1 className="text-2xl font-bold mb-4">{Feature}</h1>
      {/* Render data */}
    </div>
  )
}

If redux-toolkit (RTK Query):

Follow the project's existing RTK Query slice pattern. Look for createApi usage and extend it rather than creating a standalone file.

UI Library Adaptation

  • shadcn (default): Use shadcn/ui components with Tailwind CSS classes
  • mui: Use Material UI <Box>, <Typography>, <Stack> etc.
  • chakra: Use Chakra UI <Box>, <Heading>, <VStack> etc.
  • ant: Use Ant Design <Card>, <Table>, <Typography.Title> etc.

Match whichever UI library is detected in the project's package.json.

4. Add Route

Find the router configuration file and add the route automatically:

# Find the router file
grep -rl "createBrowserRouter\|RouteObject\|path:" {FRONTEND_PATH}/src/routes/ {FRONTEND_PATH}/src/App.tsx 2>/dev/null | head -1

Read the router file, then add the import and route entry:

import { {Feature}Page } from '@/features/{feature}/pages/{feature}-page'

// Add to the routes array alongside existing routes:
{ path: '/{feature}', element: <{Feature}Page /> }

If the router structure is unclear or uses a pattern you don't recognize, show the user what to add and where instead of guessing.

Checklist

  • API service follows existing client pattern
  • Multi-tenancy support included if MULTI_TENANT is true
  • Types defined as interfaces, no any
  • Server state management matches STATE_SERVER config
  • UI components match UI_LIBRARY config
  • Functional components only
  • Route added to router config

Guidelines

  • Follow existing features in the project as reference
  • Keep components small and focused
  • Use barrel exports where the project already does
  • If using unfamiliar library patterns (infinite queries, optimistic updates, prefetching), use context7 to look up the current API

Output

After scaffolding, report:

## Scaffolded: {Feature} frontend feature

Files created:
- `{FRONTEND_PATH}/src/api/services/{feature}.api.ts`
- `{FRONTEND_PATH}/src/features/{feature}/pages/{feature}-page.tsx`
- `{FRONTEND_PATH}/src/features/{feature}/components/{feature}-overview.tsx`
- Route added to `{router-file}`

Next: Run `cd {FRONTEND_PATH} && npm run dev` to preview, or `/verify-feature /{feature}` to verify.

Error Handling

  • Router file not found: Show the route snippet and ask the user where to add it.
  • API client pattern not detected: Check {FRONTEND_PATH}/src/api/ — if no client exists, create a minimal fetch-based client and note it for the user.
  • Feature directory already exists: Warn the user and ask whether to overwrite or extend.

Related Skills

  • /verify-feature to visually verify the scaffolded feature
  • /screenshot to capture what the new page looks like

Keep looking

Skills are one crate of 328,083. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.