shipshitdev

fullstack-workspace-init

Scaffold a production-ready full-stack monorepo with working MVP features, tests, and CI/CD. Generates complete CRUD functionality, Clerk authentication, and quality gates that run immediately with `bun dev`.

shipshitdev 38 3 Updated 1w ago
GitHub

Install

npx skillscat add shipshitdev/library/fullstack-workspace-init

Install via the SkillsCat registry.

SKILL.md

Full Stack Workspace Init

Create a production-ready monorepo with working MVP features:

  • Frontend: NextJS 16 + React 19 + TypeScript + Tailwind + @agenticindiedev/ui
  • Backend: NestJS 11 + MongoDB + Clerk Auth + Swagger
  • Mobile: React Native + Expo (optional)
  • Quality: Vitest (80% coverage) + Biome + Husky + GitHub Actions CI/CD
  • Package Manager: bun

What Makes This Different

This skill generates working applications, not empty scaffolds:

  • Complete CRUD operations for your main entities
  • Clerk authentication configured and working
  • Tests with 80% coverage threshold
  • GitHub Actions CI/CD pipeline
  • Runs immediately with bun dev

Workflow

Phase 1: PRD Brief Intake

Ask the user for a 1-2 paragraph product description, then extract and confirm:

I'll help you build [Project Name]. Based on your description, I understand:

**Entities:**
- [Entity1]: [fields]
- [Entity2]: [fields]

**Features:**
- [Feature 1]
- [Feature 2]

**Routes:**
- / - Home/Dashboard
- /[entity] - List view
- /[entity]/[id] - Detail view

**API Endpoints:**
- GET/POST /api/[entity]
- GET/PATCH/DELETE /api/[entity]/:id

Is this correct? Any adjustments?

Phase 2: Auth Setup (Always Included)

Generate Clerk authentication:

Backend:

  • auth/guards/clerk-auth.guard.ts - Token verification guard
  • auth/decorators/current-user.decorator.ts - User extraction decorator

Frontend:

  • providers/clerk-provider.tsx - ClerkProvider wrapper
  • app/sign-in/[[...sign-in]]/page.tsx - Sign in page
  • app/sign-up/[[...sign-up]]/page.tsx - Sign up page
  • middleware.ts - Protected route middleware

Environment:

  • .env.example with all required variables

Phase 3: Entity Generation

For each extracted entity, generate complete CRUD with tests:

Backend (NestJS):

api/apps/api/src/collections/{entity}/
โ”œโ”€โ”€ {entity}.module.ts
โ”œโ”€โ”€ {entity}.controller.ts         # Full CRUD + Swagger + ClerkAuthGuard
โ”œโ”€โ”€ {entity}.controller.spec.ts    # Controller unit tests
โ”œโ”€โ”€ {entity}.service.ts            # Business logic
โ”œโ”€โ”€ {entity}.service.spec.ts       # Service unit tests
โ”œโ”€โ”€ schemas/
โ”‚   โ””โ”€โ”€ {entity}.schema.ts         # Mongoose schema with userId
โ””โ”€โ”€ dto/
    โ”œโ”€โ”€ create-{entity}.dto.ts     # class-validator decorators
    โ””โ”€โ”€ update-{entity}.dto.ts     # PartialType of create

api/apps/api/test/
โ”œโ”€โ”€ {entity}.e2e-spec.ts           # E2E tests with supertest
โ””โ”€โ”€ setup.ts                       # Test setup with MongoDB Memory Server

Frontend (NextJS):

frontend/apps/dashboard/
โ”œโ”€โ”€ app/{entity}/
โ”‚   โ”œโ”€โ”€ page.tsx                   # List view (protected)
โ”‚   โ””โ”€โ”€ [id]/page.tsx              # Detail view (protected)
โ”œโ”€โ”€ src/test/
โ”‚   โ””โ”€โ”€ setup.ts                   # Test setup with Clerk mocks
โ””โ”€โ”€ vitest.config.ts               # Frontend test config (jsdom)

frontend/packages/components/
โ”œโ”€โ”€ {entity}-list.tsx
โ”œโ”€โ”€ {entity}-list.spec.tsx         # Component tests
โ”œโ”€โ”€ {entity}-form.tsx
โ”œโ”€โ”€ {entity}-form.spec.tsx         # Component tests
โ””โ”€โ”€ {entity}-item.tsx

frontend/packages/hooks/
โ”œโ”€โ”€ use-{entities}.ts              # React hook for state management
โ””โ”€โ”€ use-{entities}.spec.ts         # Hook tests

frontend/packages/services/
โ””โ”€โ”€ {entity}.service.ts            # API client with auth headers

Phase 4: Quality Setup

Vitest Configuration:

  • vitest.config.ts in each project
  • 80% coverage threshold for lines, functions, branches
  • @vitest/coverage-v8 provider

GitHub Actions:

  • .github/workflows/ci.yml
  • Runs on push to main and PRs
  • Steps: install โ†’ lint โ†’ test โ†’ build

Husky Hooks:

  • Pre-commit: lint-staged (Biome check)
  • Pre-push: bun run typecheck

Biome:

  • biome.json in each project
  • 100 character line width
  • Double quotes, semicolons

Phase 5: Verification

Run quality gate and report results:

โœ… Generation complete!

Quality Report:
- bun install: โœ“ succeeded
- bun run lint: โœ“ 0 errors
- bun run test: โœ“ 24 tests passed
- Coverage: 82% (threshold: 80%)

Ready to run:
  cd [project]
  bun dev

Usage

# Create workspace with PRD-style prompt
python3 ~/.claude/skills/fullstack-workspace-init/scripts/init-workspace.py \
  --root ~/www/myproject \
  --name "My Project" \
  --brief "A task management app where users can create tasks with titles and due dates, organize them into projects, and mark them complete."

# Or interactive mode (prompts for brief)
python3 ~/.claude/skills/fullstack-workspace-init/scripts/init-workspace.py \
  --root ~/www/myproject \
  --name "My Project" \
  --interactive

Generated Structure

myproject/
โ”œโ”€โ”€ .github/
โ”‚   โ””โ”€โ”€ workflows/
โ”‚       โ””โ”€โ”€ ci.yml              # GitHub Actions CI/CD
โ”œโ”€โ”€ .husky/
โ”‚   โ”œโ”€โ”€ pre-commit              # Lint staged files
โ”‚   โ””โ”€โ”€ pre-push                # Type check
โ”œโ”€โ”€ .agents/                     # AI documentation
โ”œโ”€โ”€ package.json                # Workspace root
โ”œโ”€โ”€ biome.json                  # Root linting config
โ”‚
โ”œโ”€โ”€ api/                        # NestJS backend
โ”‚   โ”œโ”€โ”€ apps/api/src/
โ”‚   โ”‚   โ”œโ”€โ”€ main.ts
โ”‚   โ”‚   โ”œโ”€โ”€ app.module.ts
โ”‚   โ”‚   โ”œโ”€โ”€ auth/
โ”‚   โ”‚   โ”‚   โ”œโ”€โ”€ guards/clerk-auth.guard.ts
โ”‚   โ”‚   โ”‚   โ”œโ”€โ”€ guards/clerk-auth.guard.spec.ts  # Auth guard tests
โ”‚   โ”‚   โ”‚   โ””โ”€โ”€ decorators/current-user.decorator.ts
โ”‚   โ”‚   โ””โ”€โ”€ collections/
โ”‚   โ”‚       โ””โ”€โ”€ {entity}/
โ”‚   โ”‚           โ”œโ”€โ”€ {entity}.controller.ts
โ”‚   โ”‚           โ”œโ”€โ”€ {entity}.controller.spec.ts  # Controller tests
โ”‚   โ”‚           โ”œโ”€โ”€ {entity}.service.ts
โ”‚   โ”‚           โ””โ”€โ”€ {entity}.service.spec.ts     # Service tests
โ”‚   โ”œโ”€โ”€ apps/api/test/
โ”‚   โ”‚   โ”œโ”€โ”€ {entity}.e2e-spec.ts                 # E2E tests
โ”‚   โ”‚   โ””โ”€โ”€ setup.ts                             # E2E test setup
โ”‚   โ”œโ”€โ”€ vitest.config.ts
โ”‚   โ”œโ”€โ”€ package.json
โ”‚   โ””โ”€โ”€ .env.example
โ”‚
โ”œโ”€โ”€ frontend/                   # NextJS apps
โ”‚   โ”œโ”€โ”€ apps/dashboard/
โ”‚   โ”‚   โ”œโ”€โ”€ app/
โ”‚   โ”‚   โ”‚   โ”œโ”€โ”€ layout.tsx
โ”‚   โ”‚   โ”‚   โ”œโ”€โ”€ page.tsx
โ”‚   โ”‚   โ”‚   โ”œโ”€โ”€ sign-in/[[...sign-in]]/page.tsx
โ”‚   โ”‚   โ”‚   โ”œโ”€โ”€ sign-up/[[...sign-up]]/page.tsx
โ”‚   โ”‚   โ”‚   โ””โ”€โ”€ {entity}/       # Generated per entity
โ”‚   โ”‚   โ”œโ”€โ”€ src/test/
โ”‚   โ”‚   โ”‚   โ””โ”€โ”€ setup.ts        # Test setup with Clerk mocks
โ”‚   โ”‚   โ”œโ”€โ”€ middleware.ts       # Clerk route protection
โ”‚   โ”‚   โ””โ”€โ”€ providers/
โ”‚   โ”‚       โ””โ”€โ”€ clerk-provider.tsx
โ”‚   โ”œโ”€โ”€ packages/
โ”‚   โ”‚   โ”œโ”€โ”€ components/
โ”‚   โ”‚   โ”‚   โ”œโ”€โ”€ {entity}-list.tsx
โ”‚   โ”‚   โ”‚   โ”œโ”€โ”€ {entity}-list.spec.tsx   # Component tests
โ”‚   โ”‚   โ”‚   โ”œโ”€โ”€ {entity}-form.tsx
โ”‚   โ”‚   โ”‚   โ””โ”€โ”€ {entity}-form.spec.tsx   # Component tests
โ”‚   โ”‚   โ”œโ”€โ”€ hooks/
โ”‚   โ”‚   โ”‚   โ”œโ”€โ”€ use-{entities}.ts
โ”‚   โ”‚   โ”‚   โ””โ”€โ”€ use-{entities}.spec.ts   # Hook tests
โ”‚   โ”‚   โ”œโ”€โ”€ services/           # API clients
โ”‚   โ”‚   โ””โ”€โ”€ interfaces/
โ”‚   โ”œโ”€โ”€ vitest.config.ts        # Frontend test config (jsdom)
โ”‚   โ””โ”€โ”€ package.json
โ”‚
โ”œโ”€โ”€ mobile/                     # React Native + Expo (optional)
โ”‚   โ””โ”€โ”€ ...
โ”‚
โ””โ”€โ”€ packages/                   # Shared packages
    โ””โ”€โ”€ packages/
        โ”œโ”€โ”€ common/
        โ”‚   โ”œโ”€โ”€ interfaces/
        โ”‚   โ””โ”€โ”€ enums/
        โ””โ”€โ”€ helpers/

Key Patterns

Backend Controller Pattern

@ApiTags('tasks')
@ApiBearerAuth()
@UseGuards(ClerkAuthGuard)
@Controller('tasks')
export class TasksController {
  constructor(private readonly tasksService: TasksService) {}

  @Post()
  @ApiOperation({ summary: 'Create a new task' })
  create(
    @Body() createTaskDto: CreateTaskDto,
    @CurrentUser() user: { userId: string },
  ) {
    return this.tasksService.create(createTaskDto, user.userId);
  }
  // ... full CRUD
}

Backend Service Pattern

@Injectable()
export class TasksService {
  constructor(
    @InjectModel(Task.name) private taskModel: Model<TaskDocument>,
  ) {}

  async create(createTaskDto: CreateTaskDto, userId: string): Promise<Task> {
    const task = new this.taskModel({ ...createTaskDto, userId });
    return task.save();
  }
  // ... full CRUD with userId filtering
}

Frontend Component Pattern

'use client';

import { useEffect, useState } from 'react';
import { TaskService } from '@services/task.service';
import { Task } from '@interfaces/task.interface';

export function TaskList() {
  const [tasks, setTasks] = useState<Task[]>([]);
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    const controller = new AbortController();
    TaskService.getAll({ signal: controller.signal })
      .then(setTasks)
      .finally(() => setLoading(false));
    return () => controller.abort();
  }, []);

  // ... render
}

Additional Scripts

# Add a new entity to existing project
python3 ~/.claude/skills/fullstack-workspace-init/scripts/add-entity.py \
  --root ~/www/myproject \
  --name "comment" \
  --fields "content:string,taskId:string"

# Add a new frontend app
python3 ~/.claude/skills/fullstack-workspace-init/scripts/add-frontend-app.py \
  --root ~/www/myproject/frontend \
  --name admin

Development Commands

After scaffolding:

cd myproject

# Install all dependencies
bun install

# Start all services (backend + frontend)
bun dev

# Or start individually
bun run dev:api      # Backend on :3001
bun run dev:frontend # Frontend on :3000
bun run dev:mobile   # Mobile via Expo

# Quality commands
bun run lint         # Check code style
bun run test         # Run tests
bun run test:coverage # Run with coverage
bun run typecheck    # Type checking

Environment Variables

Create .env files based on .env.example:

API (.env):

PORT=3001
MONGODB_URI=mongodb://localhost:27017/myproject
CLERK_SECRET_KEY=sk_test_...

Frontend (.env.local):

NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY=pk_test_...
NEXT_PUBLIC_API_URL=http://localhost:3001

References

  • references/templates/ - Code generation templates
    • service.spec.template.ts - NestJS service unit test template
    • controller.spec.template.ts - NestJS controller unit test template
    • e2e.spec.template.ts - E2E test template with supertest + MongoDB Memory Server
    • component.spec.template.tsx - React component test template
    • hook.spec.template.ts - React hook test template
    • test-setup.template.ts - Frontend test setup with Clerk mocks
  • references/vitest.config.ts - Backend Vitest configuration (80% coverage)
  • references/vitest.config.frontend.ts - Frontend Vitest configuration (jsdom)
  • references/github-actions/ci.yml - CI/CD workflow
  • references/architecture-guide.md - Architectural decisions
  • references/coding-standards.md - Coding rules