- Add AGENTS.md with comprehensive project rules and guidelines - Add opencode.json with model configuration (Sonnet 4.5 + Haiku 4.5) - Add .ignore to exclude build artifacts and generated files - Enable AI-assisted development with proper monorepo context
5.9 KiB
5.9 KiB
TPMJS OpenCode Configuration
This file contains project-specific rules and guidance for OpenCode agents working in the TPMJS monorepo.
Repository Overview
TPMJS is a Turborepo monorepo for AI tool discovery and registry. Key characteristics:
- Package Manager: pnpm with workspace configuration
- Build System: Turborepo for task orchestration
- Main App: Next.js 16 App Router (
apps/web) - Component Library:
.ts-only React components (packages/ui) - Database: Prisma with PostgreSQL (
packages/db) - Tool Registry: npm package discovery and metadata sync
Core Commands (Always Use These)
# Development
pnpm dev # Start all dev servers
pnpm --filter=@tpmjs/web dev # Start web app only
# Building (Respects Dependencies)
pnpm build # Build all packages
pnpm --filter=@tpmjs/ui build # Build specific package
pnpm --filter=@tpmjs/web... build # Build web + all dependencies
# Testing & Quality
pnpm test # Run all tests
pnpm lint # Lint all packages
pnpm format # Format with Biome
pnpm type-check # TypeScript checking
Architecture Rules (Critical)
Module Boundaries
- Apps (
apps/*) can only import from published packages (@tpmjs/*) - Packages (
packages/*) cannot import from apps - UI Package (
packages/ui) cannot import from utils (stays dependency-free) - No barrel exports - always import directly:
@tpmjs/ui/Button/Button
Component Usage
ALWAYS use @tpmjs/ui components instead of raw HTML:
// Good
import { Button } from '@tpmjs/ui/Button/Button';
import { Input } from '@tpmjs/ui/Input/Input';
// Bad
<button onClick={handleClick}>Submit</button>
<input value={value} onChange={onChange} />
TypeScript Configuration
- All packages extend from
@tpmjs/tsconfig - Strict mode enabled
- Composite projects for proper dependency resolution
Package Structure
Published Packages (@tpmjs scope)
@tpmjs/ui- React component library (.ts-only, createElement)@tpmjs/utils- Utility functions (cn, format, etc.)@tpmjs/types- Shared TypeScript types and Zod schemas@tpmjs/env- Environment variable validation with Zod
Internal Tooling (Private)
@tpmjs/config- Shared configurations (Biome, ESLint, Tailwind, TypeScript)@tpmjs/test- Vitest shared configuration@tpmjs/mocks- MSW mock server for testing@tpmjs/storybook- Component documentation
Applications
@tpmjs/web- Next.js 16 App Router (main website)@tpmjs/playground- Tool testing playground
Development Workflow
Before Making Changes
- Run
pnpm type-checkto ensure clean state - Check existing patterns in similar files
- Use
@tpmjs/uicomponents for any UI changes
After Making Changes
pnpm lint- Check lintingpnpm type-check- Verify TypeScriptpnpm test- Run tests if applicablepnpm format- Auto-format with Biome
Database Changes
If modifying Prisma schema:
pnpm --filter=@tpmjs/db db:generate # Regenerate client
pnpm --filter=@tpmjs/db db:push # Apply changes (dev)
Tool Development
Tool Package Structure
Tools live in packages/tools/* with this pattern:
packages/tools/tool-name/
├── package.json
├── tsconfig.json
├── src/
│ ├── index.ts # Main export
│ ├── tool.ts # Tool definition
│ └── implementation.ts # Actual logic
├── README.md
└── examples/
└── basic.ts
Tool Metadata
Tools must have proper tpmjs field in package.json:
{
"tpmjs": {
"category": "text-analysis",
"tier": "rich",
"description": "Tool description"
}
}
Quality Standards
Code Quality
- No
anytypes or@ts-ignore - Strict TypeScript compliance
- Proper error handling with try/catch
- Meaningful variable names
Testing
- Unit tests for utilities
- Integration tests for API routes
- Component tests for UI changes
- Use Vitest + Testing Library
Documentation
- README for all packages
- JSDoc for public APIs
- Examples for tool usage
- Type definitions for all public interfaces
Common Patterns
API Routes
import { NextResponse } from 'next/server';
import { prisma } from '@tpmjs/db';
export const runtime = 'nodejs';
export const dynamic = 'force-dynamic';
export const maxDuration = 60;
export async function GET() {
try {
// Implementation
return NextResponse.json({ success: true, data });
} catch (error) {
return NextResponse.json(
{ success: false, error: error.message },
{ status: 500 }
);
}
}
Component Pattern
import { createElement } from 'react';
import { cn } from '@tpmjs/utils';
interface ButtonProps {
onClick?: () => void;
children: React.ReactNode;
className?: string;
}
export function Button({ onClick, children, className }: ButtonProps) {
return createElement('button', {
onClick,
className: cn('default-styles', className),
}, children);
}
What NOT to Do
- Never edit lockfiles unless explicitly requested
- Never use barrel exports (
index.tsfiles) - Never suppress TypeScript errors with
as anyor@ts-ignore - Never use raw HTML elements when
@tpmjs/uicomponents exist - Never import from apps in packages
- Never commit without running
pnpm lintandpnpm type-check
Deployment & CI
- Vercel deployment requires all CI checks to pass
- Pre-commit hooks run
format,lint, andtype-check - Use
vercel inspectto debug deployments - Check
/api/healthto verify production deployments
Getting Help
- Check existing implementations in similar packages
- Use
pnpm --filter=<package> devfor package-specific development - Refer to
CLAUDE.mdfor detailed architectural decisions - Look at
packages/tools/*for tool development examples