softinter-chiangrai/up-ai-skill-training

d2-03-main-menu

Creates a main menu/navigation hub component with dynamically generated menu items based on selected capabilities (search, create, save, delete).

First seen Aug 17, 2026

Installation

$ npx skills add softinter-chiangrai/up-ai-skill-training --skill d2-03-main-menu

Summary

  • Creates a main menu/navigation hub component with dynamically generated menu items based on selected capabilities (search, create, save, delete).
  • Prompts for entity name and available actions, generates menu card and routes.
  • Use when the user asks for Day 2 step 3 of the CRUD drill, or asks to build a main menu for up-app.

Similar popular skills

Related neighbors and high-traction skills in the same topics — useful to compare before installing.

Also in this package

Other skills from softinter-chiangrai/up-ai-skill-training · top by installs.

npx skills add softinter-chiangrai/up-ai-skill-training

Browse all from softinter-chiangrai/up-ai-skill-training

More details

Agent compatibility

Declared targets from SKILL.md / docs. Unmarked agents are not listed — the skill may still install via the CLI.

Claude Code Not declared
Cursor Not declared
Codex Not declared
GitHub Copilot Not declared
Windsurf Not declared
Gemini CLI Not declared
Cline Not declared
OpenCode Not declared

Repository health

Default branch main
Open issues 0
Status Active

Skill metadata

Parsed from SKILL.md frontmatter.

CompatibilityRequires an existing up-app project with routing already in place (from d2-00/d2-01/d2-02). Component is standalone.

Package contents

Files included with this skill beyond the listing page.

  • skill md SKILL.md 7,292 B
  • docs SUMMARY.md 347 B

History

  1. First seen on skills.sh
  2. First recorded snapshot · 40 installs

SKILL.md

Day 2 · Step 3 — Main menu with capability-driven menu items

Before starting: Ask for:

  1. Entity name (PascalCase, e.g., Product, Order, Employee) — REQUIRED
  2. Available capabilities (select one or more: search, create, save, delete) — REQUIRED

- search: Browse/list all records - create: Create new records - save: Save to database (used with create/edit) - delete: Delete records

Use exactly as specified. Menu buttons will be generated based on selected capabilities.

Routing Setup (app.routes.ts) — COMPLETE ROUTING TABLE FOR ALL PAGES:

  • Import MenuComponent, all <Entity>SearchComponents, and all <Entity>FormComponents
  • Add menu as the default/landing page route (path: '')
  • Define entity routes for each program: search, create, edit
  • This route table is shared by d2-03 (menu), d2-04 (search), and d2-05 (form)
import { Routes } from '@angular/router';
import { MenuComponent } from './pages/menu/menu.component';
import { <Entity>SearchComponent } from './pages/<entity>-search/<entity>-search.component';
import { <Entity>FormComponent } from './pages/<entity>-form/<entity>-form.component';
// Add more imports for additional entities as needed

export const routes: Routes = [
  // Landing page (menu comes first!)
  { path: '', component: MenuComponent },

  // <Entity> CRUD routes
  { path: '<entity>', component: <Entity>SearchComponent },        // Search/list page
  { path: '<entity>/new', component: <Entity>FormComponent },      // Create new record
  { path: '<entity>/:id/edit', component: <Entity>FormComponent }, // Edit existing record

  // Add more entity routes here for additional programs:
  // { path: 'customer', component: CustomerSearchComponent },
  // { path: 'customer/new', component: CustomerFormComponent },
  // { path: 'customer/:id/edit', component: CustomerFormComponent },
];

Route Usage:

  • d2-03-main-menu uses { path: '', component: MenuComponent } — landing page
  • d2-04-search-delete-page uses /<entity> route and navigates via router.navigate(['/<entity>/new']), router.navigate(['/<entity>', id, 'edit'])
  • d2-05-form-page uses /<entity>/new and /<entity>/:id/edit routes

Component TypeScript (capability-driven):

import { Component } from '@angular/core';
import { Router } from '@angular/router';
import { CommonModule } from '@angular/common';

interface MenuItem {
  name: string;
  icon: string;
  path: string;
}

interface Program {
  name: string;
  entity: string;
  icon: string;
  description: string;
  capabilities: string[];
  menuItems: MenuItem[];
}

@Component({
  selector: 'app-menu',
  standalone: true,
  imports: [CommonModule],
  templateUrl: './menu.component.html',
  styleUrls: ['./menu.component.css']
})
export class MenuComponent {
  appTitle = 'CRUD Dashboard';
  appSubtitle = 'Manage your data with ease';

  programs: Program[] = [];

  constructor(private router: Router) {
    this.programs = [
      {
        name: '<Entity>',
        entity: '<entity>',
        icon: '📦',
        description: 'Manage <entity> records',
        capabilities: ['search', 'create', 'save', 'delete'],
        menuItems: this.generateMenuItems('<entity>', ['search', 'create', 'save', 'delete'])
      },
      // Add more programs here:
      // { name: 'Customer', entity: 'customer', icon: '👥', description: 'Manage customer data', capabilities: [...], menuItems: ... }
    ];
  }

  generateMenuItems(entity: string, capabilities: string[]): MenuItem[] {
    const items: MenuItem[] = [];
    
    if (capabilities.includes('search')) {
      items.push({ name: 'Browse', icon: '📋', path: `/${entity}` });
    }
    if (capabilities.includes('create')) {
      items.push({ name: 'Create', icon: '✚', path: `/${entity}/new` });
    }
    
    return items;
  }

  navigate(path: string) {
    this.router.navigate([path]);
  }
}

Template (capability-driven menu with responsive card grid, standard Tailwind classes):

<div class="min-h-screen bg-gradient-to-br from-gray-50 to-gray-100 p-6">
  <!-- Header -->
  <div class="max-w-6xl mx-auto mb-12">
    <div class="text-center mb-8">
      <h1 class="text-5xl font-bold text-gray-900">{{ appTitle }}</h1>
      <p class="text-gray-600 text-xl mt-4">{{ appSubtitle }}</p>
    </div>
  </div>

  <!-- Program Cards Grid -->
  <div class="max-w-6xl mx-auto">
    <div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8">
      @for (program of programs; track program.entity) {
        <div class="bg-white rounded-xl shadow-md hover:shadow-xl transition-shadow p-6">
          <!-- Card Header -->
          <div class="flex items-center mb-4">
            <span class="text-5xl mr-4">{{ program.icon }}</span>
            <div>
              <h3 class="text-2xl font-bold text-gray-900">{{ program.name }}</h3>
              <p class="text-gray-600 text-sm">{{ program.description }}</p>
            </div>
          </div>

          <!-- Capabilities Badge -->
          <div class="flex flex-wrap gap-2 mb-4">
            @for (cap of program.capabilities; track cap) {
              <span class="bg-gray-100 text-gray-700 text-xs font-semibold px-3 py-1 rounded-full">
                {{ cap }}
              </span>
            }
          </div>

          <!-- Divider -->
          <div class="border-b border-gray-200 my-4"></div>

          <!-- Dynamic Menu Buttons -->
          <div class="flex flex-col gap-4">
            @for (item of program.menuItems; track item.name) {
              <button
                (click)="navigate(item.path)"
                [class]="item.name === 'Browse' ? 'w-full text-white font-semibold px-6 py-3 rounded-lg transition bg-blue-500 hover:bg-blue-600' : 'w-full text-white font-semibold px-6 py-3 rounded-lg transition bg-green-500 hover:bg-green-600'"
              >
                {{ item.icon }} {{ item.name }}
              </button>
            }
          </div>

          @if (program.menuItems.length === 0) {
            <p class="text-gray-600 text-sm text-center">No actions available for this program.</p>
          }
        </div>
      }
    </div>
  </div>

  <!-- Footer -->
  <div class="max-w-6xl mx-auto mt-12 text-center">
    <p class="text-gray-600 text-sm">Built with Angular + Tailwind CSS</p>
  </div>
</div>

Design System (Standard Tailwind):

  • Spacing: p-6 (padding), mb-4/8/12, gap-2/4/8
  • Colors: bg-blue-500/600, bg-green-500/600, text-gray-600, bg-gray-100
  • Shadows: shadow-md, hover:shadow-xl (card elevation)
  • Typography: text-5xl/2xl, font-bold/semibold
  • Layout: grid responsive (1-2-3 columns), flex flex-col
  • Interactions: rounded-lg, transition, hover states