How this skill is triggered — by the user, by Claude, or both
Slash command
/co2-skills:mockgen-shadcnThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
---
Generate a Vite + React 19 + TypeScript + shadcn/ui mockup application from PRD.md for UI/UX
designer review. Layout uses React components (header, sidebar, footer) composed in a shared
layout route. Pages are React Router routes rendered inside the layout. All navigation is
client-side via React Router <Link> and useNavigate.
| Layer | Technology |
|---|---|
| Build tool | Vite 6 |
| UI framework | React 19 + TypeScript 5 |
| Component library | shadcn/ui (Radix UI + Tailwind CSS) |
| Routing / navigation | React Router v7 |
| Styling | Tailwind CSS v3 (PostCSS) |
| Icons | Lucide React |
| Dark mode | next-themes |
This skill uses standardized input resolution. Provide:
| Argument | Required | Example | Description |
|---|---|---|---|
<application> | Yes | hub_middleware | Application name to locate the context folder |
<version> | Yes | v1.0.3 | Version to scope processing (filter user stories <= this version) |
module:<name> | No | module:Location Information | Limit generation to a single module |
The application name is matched against root-level application folders:
<number>_ prefix from folder names (e.g., 1_hub_middleware → hub_middleware)| File | Resolved Path |
|---|---|
| PRD.md | <app_folder>/context/PRD.md |
| Module Models | <app_folder>/context/model/ |
| Output (mockup) | <app_folder>/context/mockup/ |
/mockgen-shadcn hub_middleware v1.0.3 (all modules, up to v1.0.3)/mockgen-shadcn hub_middleware v1.0.3 module:Location Information (one module, specific version)/mockgen-shadcn "Hub Middleware" v1.0.3 module:Employer (title-case app name)module:Location Information), only generate/update pages
for that specific module. All other modules are skipped. Common pages (home, profile,
account, notifications), layout components (header, footer, sidebars), and config files are
NOT regenerated when a module filter is active — only the module's own page components
are written (and MOCKUP.html is updated for only that module's cards).Argument parsing: The module: prefix is the canonical form. Also accept:
module:"Location Information" (quoted, with space)module:location_information (snake_case — convert to title-case for matching)for Location Information module, only Location InformationBefore starting any work, resolve the application folder first (see Input Resolution below), then check CHANGELOG.md in the application folder (<app_folder>/CHANGELOG.md):
<app_folder>/CHANGELOG.md does not exist, skip this check (first-ever execution for this application).<app_folder>/CHANGELOG.md exists, scan all ## vX.Y.Z headings and determine the highest version using semantic versioning comparison."Version {requested} is lower than the current application version {highest} recorded in <app_folder>/CHANGELOG.md. Execution rejected." Do NOT proceed with any work.Read the auto-resolved PRD.md file and extract:
Application name: Derive from the parent folder name containing PRD.md.
Strip leading number and underscore prefix, then title-case.
Example: 1_hub_middleware -> "Hub Middleware"
Application initials: First letter of each word, uppercase.
Example: 1_hub_middleware -> "HM"
Modules: Each ## Module Name section under a # Module Category heading.
Record the module name and its description (the line after the heading).
User stories per module: Lines matching - [USxx#####] As a {Role} user, I want to...
Extract: tag, role, action summary.
Unique roles: Collect all distinct roles from user stories. Example: "Hub Administrator", "Hub Operation Support"
Target version (from input argument): If a version was provided, record it for filtering in the next sub-step.
PRD.md is a version-controlled document. Each section (User Story, Non Functional
Requirement, Constraint, Reference) has a version tag in square brackets, e.g., [v1.0.1].
Items may also be marked with strikethrough (~~) to indicate they are deprecated/removed.
Strikethrough exclusion (always applied, regardless of version parameter):
~~strikethrough~~ markup MUST be excluded from processing~~[USHM00006] As a Hub Administrator user, I want to...~~ → SKIPVersion filtering (applied only when a target version is provided):
[v1.0.0] or [v1.0.1]v1.0.1):
Version tracking per section: Record which version tag each item belongs to, as this will be used for traceability in the generated pages.
Example parsing of a section with multiple versions:
### User Story
[v1.0.0]
- ~~[USHM00006] As a Hub Administrator user, I want to manage...~~
- [USHM00009] As a Hub Administrator user, I want to map...
[v1.0.1]
- [USHM00012] As a Hub Administrator user, I want to manage the list...
With target version v1.0.0:
With target version v1.0.1 (or no version specified):
When a module argument is present, apply module filtering after version filtering:
location_information → match "Location Information").Module-filtered generation mode differs from full generation in these ways:
| Aspect | Full Generation | Module-Filtered |
|---|---|---|
| Common pages (home, profile, account, notifications) | Generate for every role | SKIP — already exist |
| Layout components (header, footer, sidebar) | Generate | SKIP — already exist |
| Config files (package.json, vite.config.ts, etc.) | Generate | SKIP — already exist |
| shadcn/ui component files | Generate | SKIP — already exist |
| Route config (App.tsx) | Generate | Update — add routes for new module pages |
| Module page components (target module) | Generate | Generate / overwrite |
| Module page components (other modules) | Generate | SKIP — leave untouched |
| MOCKUP.html | Generate full file | Update only the target module's cards |
| Footer version string | Update | Update (version may have changed) |
MOCKUP.html partial update (module-filtered mode):
After parsing PRD.md, look for module models at the auto-resolved model path:
<app_folder>/context/model/
For each module extracted in Step 1:
Convert the module name to kebab-case to derive the model folder name:
location-information, "Industrial Classification" → industrial-classification, "Employer" → employerCheck for {model_dir}/{kebab-module}/model.md
If the file exists, parse it and extract the following sections:
Store this as the module model for the module, keyed by module name
Field classification (used during page generation in Step 6e):
| Category | Definition | Usage |
|---|---|---|
| System fields | _id, _audit, _version, deleted, deletedAt, deletedBy | Exclude from user-facing forms |
| Audit-only fields | Fields whose Source is CONVENTION and type is Audit | Show in detail views only |
| Required form fields | Required: Yes AND not a system field | Mandatory inputs in create/edit forms |
| Optional form fields | Required: No AND not a system field | Optional inputs in create/edit forms |
| Read-only after creation | Fields marked as unique identity keys (e.g., companyRegistrationNumber) | Show in edit forms as readonly |
| Search/filter fields | Fields referenced in Index Recommendations | Render as filter controls in list pages |
| Enum fields | Type matches an entry in Section 7 Enum Definitions | Render as <Select> dropdowns |
| Embedded object fields | Type is a custom embedded document type (not a primitive) | Render as grouped <Card> sections |
| Embedded array fields | Type ends in [] (e.g., PersonInCharge[]) | Render as repeatable row with Add/Remove |
Fallback: If no model.md exists for a module, infer fields from user story text (original behavior).
Load the design system using a two-tier resolution strategy:
Check if PRD.md contains a # Design System section. If it does:
[DESIGN_SYSTEM.md](reference/DESIGN_SYSTEM.md))tailwind.config.js) custom colors/fonts,
shadcn/ui CSS variables in src/index.css, and all generated componentsIf PRD.md does not have a # Design System section, or the referenced file does not exist, fall back to the application's <app_folder>/context/design/ folder. This folder contains pre-defined design tokens and Tailwind component guidelines maintained externally by the UI/UX team.
Read all files in {app_name}/context/design/ (where {app_name} is the resolved application folder name from Step 1). Apply the design tokens and guidelines found there to all generated mockup pages.
Expected files (any or all may be present):
design-system.md — Colors, typography, spacing, and visual style definitionscomponents.md — Reusable component patterns and Tailwind class conventionsguidelines.md — Layout rules, accessibility standards, and stack-specific guidelinesIf neither the PRD reference nor the {app_name}/context/design/ folder provides design tokens, use the default shadcn/ui "New York" style: zinc/neutral color palette, Inter/Geist font stack, and default shadcn/ui component styling with CSS variables.
If PRD.md contains a # High Level Process Flow section, scan it for entity status lifecycle descriptions (e.g., "Received → Validated → Enriched → Active"). For each status lifecycle found:
<Badge> variants for each statedefault for active/completed, secondary for pending, destructive for failed/rejected)For each role, determine ALL pages to generate. Every clickable link, tab, or action in any generated page MUST have a corresponding page component. No link may be a dead end.
Module filter applied here: If a module argument was provided (Step 1c), plan only the pages for that module across all roles. Skip common pages (home, profile, account, notifications) and skip all other modules entirely. The screen plan table should list only the filtered module's pages.
For each module page, analyze the user stories and identify sub-pages needed:
| User Story Pattern | Sub-Page Required |
|---|---|
| "view details of X" | {module}-detail.tsx - Detail view for a single record |
| "add/create/register X" | {module}-create.tsx - Create/add form |
| "edit/update/modify X" | {module}-edit.tsx - Edit form (pre-filled) |
| "view history/audit of X" | {module}-history.tsx - History/audit log view |
| "view associated X of Y" | {module}-{sub}-list.tsx - Associated records list |
Scan PRD.md for report-related content:
If report requirements are found, generate HTML report layout mockups for each identified report. These layouts serve as draft previews for human designers/stakeholders to verify the report structure before the AI coding agent implements the actual report generation code.
For each identified report, create a standalone HTML file in a public/reports/ subfolder:
| Report Source | File Generated |
|---|---|
| NFR describes "Staff Allocation Summary report" | public/reports/staff_allocation_summary.html |
| User story: "generate Job Demand report by country" | public/reports/job_demand_by_country.html |
| Report module NFR: "Monthly Activity Report" | public/reports/monthly_activity_report.html |
Report layout file conventions:
<html>, <head>, <body> tags and Tailwind CDN <script> in the head<body class="bg-gray-100">
<div class="mx-auto bg-white shadow" style="width: 210mm; min-height: 297mm; padding: 15mm;">
<!-- Report content -->
</div>
</body>
model/{module}/model.md exists, use its field definitions for column headers)style="width: 297mm; min-height: 210mm;"Report parameter section: Above the report data, include a gray-shaded "Parameters" box showing the filter criteria used to generate the report (e.g., Date Range: 2025-01-01 to 2025-12-31, Department: All, Status: Active).
Add to MOCKUP.html: Include a "Reports" section at the bottom of each role's screen cards (after all module cards) listing the report layout links. Report links open in new tabs pointing directly to the standalone HTML files.
Add to sidebar: If reports are present, add a "Reports" navigation group in each role's sidebar with links opening report layouts in new tabs.
If a module page contains tabs (e.g., a detail page with Overview, Documents, History tabs),
use shadcn/ui <Tabs> component within the same page component. Only create separate
page component files for tabs if the tab content is substantial (more than ~100 lines).
Use the naming convention for separate files: {module}-tab-{tab_name}.tsx
Example: employer-tab-overview.tsx, employer-tab-documents.tsx, employer-tab-history.tsx
Convert names to kebab-case for file names, PascalCase for component names.
Example: "Location Information" → file: location-information.tsx, component: LocationInformation
Build a complete screen plan. Every entry must map to a generated file:
| Role | Folder Name | Page File | Source | Description |
|---|---|---|---|---|
| Hub Administrator | hub-administrator | home.tsx | Common | Dashboard home |
| Hub Administrator | hub-administrator | profile.tsx | Common | User profile |
| Hub Administrator | hub-administrator | account.tsx | Common | Account settings |
| Hub Administrator | hub-administrator | notifications.tsx | Common | Notifications list |
| Hub Administrator | hub-administrator | location-information.tsx | Module | USHM00006, USHM00009 |
| Hub Administrator | hub-administrator | location-information-detail.tsx | Sub-page | View location details |
| Hub Administrator | hub-administrator | location-information-create.tsx | Sub-page | Add new location |
| Hub Operation Support | hub-operation-support | home.tsx | Common | Dashboard home |
| Hub Operation Support | hub-operation-support | profile.tsx | Common | User profile |
| Hub Operation Support | hub-operation-support | account.tsx | Common | Account settings |
| Hub Operation Support | hub-operation-support | notifications.tsx | Common | Notifications list |
| Hub Operation Support | hub-operation-support | employer.tsx | Module | USHM00021-USHM00033 |
| Hub Operation Support | hub-operation-support | employer-detail.tsx | Sub-page | View employer details |
| Hub Operation Support | hub-operation-support | employer-create.tsx | Sub-page | Register new employer |
Module filter: When a module argument is active, skip this step entirely — the folder structure already exists from a previous full generation. Only page components for the target module will be written in Step 6e.
Create the mockup folder at the auto-resolved mockup output path (full generation only):
<app_folder>/context/
mockup/
.gitignore
package.json
vite.config.ts
tsconfig.json
tsconfig.app.json
tsconfig.node.json
tailwind.config.js
postcss.config.js
components.json # shadcn/ui configuration
index.html # Vite entry HTML
MOCKUP.html # Standalone index/sitemap
public/
reports/ # Report layout files (if applicable)
src/
main.tsx # React entry point
App.tsx # Router configuration
index.css # Tailwind directives + shadcn/ui CSS variables
lib/
utils.ts # cn() utility
components/
ui/ # shadcn/ui components
button.tsx
card.tsx
table.tsx
badge.tsx
input.tsx
label.tsx
select.tsx
dialog.tsx
dropdown-menu.tsx
avatar.tsx
separator.tsx
tabs.tsx
switch.tsx
tooltip.tsx
breadcrumb.tsx
pagination.tsx
sheet.tsx
layout/
app-layout.tsx # Shared layout with sidebar + header + footer
app-header.tsx # Top header component
app-sidebar.tsx # Sidebar nav component (role-aware)
app-footer.tsx # Footer component
sidebar-config.ts # Sidebar menu items per role
pages/
{role-kebab-case}/
home.tsx
profile.tsx
account.tsx
notifications.tsx
{module-kebab-case}.tsx
{module-kebab-case}-detail.tsx
{module-kebab-case}-create.tsx
{module-kebab-case}-edit.tsx
...
Module filter: When a module argument is active, skip this step entirely.
Generate all config and entry files using the templates from references/admin-layout-template.md.
node_modules/
dist/
.DS_Store
*.log
*.local
Key project setup:
package.json — Vite + React 19 + TypeScript + Tailwind CSS + shadcn/ui dependenciesvite.config.ts — Vite config with React plugin and path aliasestsconfig.json / tsconfig.app.json / tsconfig.node.json — TypeScript configs with path aliasestailwind.config.js — Tailwind config with shadcn/ui integration and design system tokenspostcss.config.js — PostCSS with Tailwind and autoprefixercomponents.json — shadcn/ui configuration (New York style, zinc base)index.html — Vite entry HTML with Google Fontssrc/main.tsx — React root rendersrc/App.tsx — React Router configuration with all role/page routessrc/index.css — Tailwind directives + shadcn/ui CSS variables (light and dark)src/lib/utils.ts — cn() utility (clsx + tailwind-merge)Module filter: When a module argument is active, skip this step entirely.
Generate the shadcn/ui component files directly into src/components/ui/. These follow the
standard shadcn/ui "New York" style patterns. The components are owned by the project — they
are NOT imported from npm.
Required components (generate all of these):
| Component | File | Primary Usage |
|---|---|---|
| Button | button.tsx | Actions, navigation, form submission |
| Card | card.tsx | Content containers, stat cards, detail panels |
| Table | table.tsx | Data lists, records, audit logs |
| Badge | badge.tsx | Status indicators, tags, enum values |
| Input | input.tsx | Text fields, search, filters |
| Label | label.tsx | Form field labels |
| Select | select.tsx | Dropdowns, enum selectors, page size |
| Dialog | dialog.tsx | Delete confirmations, modals |
| DropdownMenu | dropdown-menu.tsx | Header user menu, notification dropdown |
| Avatar | avatar.tsx | User avatars in header and profile |
| Separator | separator.tsx | Visual dividers |
| Tabs | tabs.tsx | Detail page sections, notification filters |
| Switch | switch.tsx | Boolean toggles, notification preferences |
| Tooltip | tooltip.tsx | Field hints, readonly explanations |
| Breadcrumb | breadcrumb.tsx | Page navigation trail |
| Pagination | pagination.tsx | Table/list pagination |
| Sheet | sheet.tsx | Mobile sidebar overlay |
Each component follows the standard shadcn/ui implementation pattern:
@radix-ui/* primitives for accessibilityclassName prop via cn() utilitycva (class-variance-authority) for variants where applicableModule filter: When a module argument is active, do NOT regenerate the full MOCKUP.html. Instead, apply a partial update as described in Step 1c: update only the target module's screen cards, the version badge, and the per-role screen count. Leave all other content unchanged.
Create the index page using the template in references/mockup-index-template.md.
MOCKUP.html is a standalone static HTML file (no dev server required to open it) that shows:
npm install && npm run dev)target="_blank" rel="noopener noreferrer" pointing to
http://localhost:5173/{role}/{page} so they open in new tabs via the running Vite dev serverUse templates from references/admin-layout-template.md.
Apply the design system from Step 2 (colors, typography, spacing) to all components via
the CSS variables in src/index.css and the Tailwind config.
Module filter: When a module argument is active, skip steps 6a–6d (layout components).
Proceed directly to 6e for the target module's page components only. Also update the
footer version string in app-footer.tsx if the version changed.
Shared layout component using React Router <Outlet>. Contains:
<AppHeader> at the top (fixed)<AppSidebar> on the left (fixed, collapsible)<Outlet> for page content (scrollable)<AppFooter> at the bottomHeader component containing:
<Link> to home<DropdownMenu> and <Badge> count<DropdownMenu>useTheme()<Avatar> with <DropdownMenu> (Profile, Account, Logout)<Link> / useNavigate()Simple footer with copyright year and version string using <Separator> divider.
sidebar-config.ts: Export a configuration object mapping each role to its sidebar menu items:
export type SidebarItem = {
title: string;
path: string;
icon: string; // Lucide icon name
};
export type SidebarConfig = {
[role: string]: {
label: string;
items: SidebarItem[];
reports?: { title: string; href: string }[];
};
};
app-sidebar.tsx: Sidebar component that:
useParams()useLocation().pathname<Link> for navigation (not HTMX)Each page component is a standard React functional component that returns JSX. Pages use shadcn/ui components for all UI elements.
All navigation within page components uses React Router <Link> or useNavigate().
Breadcrumbs: Use shadcn/ui <Breadcrumb> component. Home link is a <Link>,
module link is a <Link>, current page is <BreadcrumbPage> (non-interactive).
For each module page, analyze the user stories and generate appropriate UI mockup elements:
| User Story Pattern | UI Element |
|---|---|
| "search for X based on parameters" | Filter <Card> with <Input>/<Select> + <Table> results |
| "view details of X" | Detail <Card> with labeled fields in grid layout |
| "manage X" / "configure X" | <Table> with Add/Edit/Delete action <Button> components |
| "view history/changes" | <Table> with timestamps and <Badge> change types |
| "map X to Y" | Two-panel mapping interface or matrix <Table> |
| "activate/deactivate X" | <Switch> toggles in table rows or config panel |
| "view associated X" | Related records <Table> or linked <Card> sections |
When a module model was loaded in Step 1b, use its actual field definitions — not generic placeholders — to populate every page. Generic field names like "Field 1" or "Description" are not acceptable when a model is available.
Field type → shadcn/ui component mapping:
| Model Type | Form Component | Notes |
|---|---|---|
String | <Input type="text"> with <Label> | Use maxLength if constraints specify length |
Number | <Input type="number"> with <Label> | |
Boolean | <Switch> with <Label> | |
ISODate | <Input type="date"> or <Input type="datetime-local"> | |
ObjectId (reference) | <Input readOnly> or lookup widget with <Tooltip> | Display as read-only ID reference |
| Enum (Section 7 match) | <Select> with all enum values as <SelectItem> | Show enum value descriptions as item text |
| Embedded Object | <Card> section grouping sub-fields | Title the card with embedded type name |
Embedded Array ([]) | Repeatable <Card> section with <Button> "+ Add" / "Remove" | Show one pre-filled example row |
List / Search pages ({module}.tsx):
<Card> with filter inputs only for fields in Index Recommendations (Section 9). Use the correct component per the mapping above. Enum-indexed fields use <Select>. Date-indexed fields use date range pickers.<Table> with 5–7 most identifying non-system fields as columns. For embedded objects, show as a single column (e.g., "Company Name"). Null/optional fields shown with a dash (—).<Link> to {module}-detail, Edit → <Link> to {module}-edit, Delete → shadcn/ui <Dialog> confirm<Pagination> directly below the table. Requirements:
<Select> with options 10, 25, 50 on the right (default 10)<Pagination> componentuseState (currentPage, pageSize, totalItems)Detail pages ({module}-detail.tsx):
<Card>address, contact): each in its own labeled sub-<Card>personsInCharge): rendered as a sub-<Table> with a row per item<Badge> with appropriate variantDD MMM YYYY HH:mm in sample data<Badge> ("Active" variant=default / "Inactive" variant=secondary)<Button>, Delete <Dialog> confirm, and Back to List <Button> actionsCreate pages ({module}-create.tsx):
Required: Yes non-system fields as mandatory inputs (mark with * via <Label>)Required: No fields as optional inputs where they make sense for initial creation<Card> sections with a title<Button> "+ Add"<Button> and Cancel <Button> (Cancel navigates back to {module} list via useNavigate())Edit pages ({module}-edit.tsx):
companyRegistrationNumber) must be rendered as <Input readOnly> with a <Tooltip> explaining they cannot be changed<Button> and Cancel <Button>History / Audit pages ({module}-history.tsx):
changeType → <Badge> using enum values from Section 7 with variant mappingfieldChanged → <code> styled textpreviousValue / newValue → inline diff or truncated displaychangedAt → formatted timestampchangedBy → plain text (e.g., "SYSTEM" or username)<Table>, newest first<Pagination> below the history table. Default 10 items per page.Sample data alignment: Placeholder values in pages must be consistent with field constraints:
countryCode → use actual allowed values (e.g., "MYS", "BHR", "MDV") per constraints if presentcompanyRegistrationNumber → e.g., "201901012345 (1234567-X)"ISODate fields → use realistic ISO dates (e.g., "2025-08-15T10:30:00Z")Every clickable element MUST navigate to a real route. No dead-end links allowed.
Table row actions (View, Edit, Delete):
<Link to="/{role}/{module}-detail"><Link to="/{role}/{module}-edit"><Dialog> confirm (no navigation, inline confirm)<Link to="/{role}/{module}-create">Tabs within a page:
<Tabs> component with <TabsContent> for inline tabs<Link> to the tab routeHeader links:
<Link> to notifications<Link> to notificationsuseTheme().setTheme() (no navigation)<Link> to profile<Link> to account<Link> to / (returns to landing)Sidebar links: React Router <Link> to correct module routes
Breadcrumb links: shadcn/ui <Breadcrumb>
<Link to="/{role}/home"><Link to="/{role}/{module}"><BreadcrumbPage> (non-interactive)Pagination links: shadcn/ui <Pagination> with React useState for page state — navigation is in-component state, not route-based
Back / Cancel buttons: React Router useNavigate() or <Link> to the parent page
Images (inline previews, thumbnails, etc.):
<a href="..." target="_blank" rel="noopener noreferrer">https://placehold.co/800x600PDFs and documents (download/view links):
<a href="..." target="_blank" rel="noopener noreferrer">Content guidelines:
{/* USHM00012 [v1.0.1] */})import { IconName } from "lucide-react")home.tsx: Dashboard home page showing:
<Card> grid (one per module: total count, recent activity)<Table> with recent actions across modulesprofile.tsx: User profile page showing:
<Avatar>, full name, email, role <Badge><Card> (read-only display): Name, Email, Phone, Department<Button> (navigates to self since it's a mockup)account.tsx: Account settings page showing:
<Card> (current password, new password, confirm password <Input> fields)<Card> (<Switch> toggles for email/SMS)<Select><Card> (active sessions <Table>)notifications.tsx: Notifications list page showing:
<Tabs>: All, Unread, Read<Card> items with: Lucide icon, title, message preview, timestamp, read/unread dot<Button><Pagination> below the notification list, default 10 items per page.{module}-detail.tsx: Record detail page showing:
<Button> (React Router <Link> to {module})<Card> panels with all relevant fields from user stories<Button> (<Link> to {module}-edit), Delete <Dialog>, Back to List<Tabs> or sectioned <Card> groups{module}-create.tsx: Create/add form page showing:
<Breadcrumb>: Home > {Module} > Add New<Card> with all required fields derived from user stories<Button> (Cancel: <Link> to {module}){module}-edit.tsx: Edit form page showing:
<Breadcrumb>: Home > {Module} > Edit<Card> with sample data<Button> (Cancel: <Link> to {module}-detail or {module})After generation, print a summary:
Mockup Generation Complete
===========================
Application: {App Name} ({Initials})
Target Version: {version or "latest (all versions)"}
Module Filter: {module name or "all modules"}
Output: {path}/mockup/
Filtering Summary:
- User stories included: {count}
- User stories excluded (strikethrough): {count}
- User stories excluded (version filter): {count}
- User stories excluded (module filter): {count}
- NFRs/Constraints included: {count}
- NFRs/Constraints excluded: {count}
| Role | Pages | Page Folder |
|-----------------------|-------|--------------------------------------|
| Hub Administrator | 8 | src/pages/hub-administrator/ |
| Hub Operation Support | 6 | src/pages/hub-operation-support/ |
Files generated:
- Config: .gitignore, package.json, vite.config.ts, tsconfig.json, tailwind.config.js, etc.
- shadcn/ui: {N} component files in src/components/ui/
- Layout: app-layout.tsx, app-header.tsx, app-sidebar.tsx, app-footer.tsx, sidebar-config.ts
- Pages: {N} page component files
- MOCKUP.html (standalone index)
Total: {N} files
Quick Start
===========
1. cd {mockup folder path}
2. npm install
3. npm run dev
4. Open http://localhost:5173 in your browser
(or open MOCKUP.html directly for the index)
Before finalizing output, perform a route integrity check across ALL generated files:
<Link to="...">, useNavigate("..."),
and <a href="..."> references<Link to="/{role}/{page}"> → verify src/pages/{role}/{page}.tsx exists<Link to="/"> → acceptable for logout / landingtarget="_blank" links → acceptable for images, PDFs, external resourceshref="#" or dead-end <Link> → NOT ALLOWED — must be fixedIf any dead-end link is found in the final output, the generation is incomplete.
After all mockup files are successfully generated, append an entry to CHANGELOG.md in the application folder (<app_folder>/CHANGELOG.md):
<app_folder>/CHANGELOG.md. If it does not exist, create it with:
# Changelog
- This file tracks all skill executions by version for this application.
- The highest version recorded here is the current application version.
- Skills MUST NOT execute for a version lower than the highest version in this file.
---
## {version} heading matching the current version.--- below the context header and before any existing ## vX.Y.Z section (newest-first ordering), with a new table header and the first row.| {YYYY-MM-DD} | {application_name} | mockgen-shadcn | {module or "All"} | Generated React + shadcn/ui mockup screens |module: is specified, only the named
module's page components are written/overwritten. All other files (layout components, other module
pages, config files) remain untouched. If the target module does not exist in PRD.md,
stop and report available module names before doing any file writes.module:Employer v1.0.2 means "generate Employer module pages as they exist at v1.0.2". Version filtering
and module filtering each apply independently; a story must satisfy BOTH to be included.<Link>, useNavigate(), and <a href> in every file must resolve. No href="#"<Table> of records MUST include
shadcn/ui <Pagination> below it. Default page size is 10 items per page. Applies to: module list
pages, history/audit pages, notifications page, and any embedded sub-tables within detail pages
that may grow unbounded. Use React useState for page state. Omitting pagination from any list
is a generation error.AppLayout via React Router <Outlet><Link> or useNavigate() — no
window.location assignments, no <a href> for internal routesimport { IconName } from "lucide-react" — no inline SVG,
no icon CDN dependenciestarget="_blank"target="_blank" rel="noopener noreferrer"target="_blank"https://placehold.co/ for placeholder images<Link><Tabs> componentuseNavigate() or <Link> to the parent page{/* USHM00012 [v1.0.1] */})~~ are deprecated/removedmodel/{kebab-module}/model.md,
use the actual field definitions (field names, types, required/nullable, enums) for all
form inputs, table columns, and detail panels. Generic placeholder field names are NOT
acceptable when a model is available. See Step 1b and the "Model-Driven Field Usage" section.<Select> options must use the exact values from the model's Enum
Definitions (Section 7), not inferred stringsMYS, BHR, MDV for countryCode fields constrained by CONSHM018)public/reports/ subfolder. These are self-contained A4
mockups (not React components) for stakeholder review of report structure before coding.
Use actual module model fields for column headers and realistic sample data rows. See
Step 3f for full report layout generation rules.dark: variant classes. shadcn/ui components handle this automatically through CSS variables..tsx files must be valid TypeScript. Use proper type annotations
for component props, state, and event handlers. Avoid any types.npx claudepluginhub rashidee/co2-skills --plugin co2-skillsProvides behavioral guidelines to reduce common LLM coding mistakes, focusing on simplicity, surgical changes, assumption surfacing, and verifiable success criteria.
Searches, retrieves, and installs Agent Skills from prompts.chat registry using MCP tools like search_skills and get_skill. Activates for finding skills, browsing catalogs, or extending Claude.