commit bc2f4a01cf680796e1461254a3862e0dafa4df7c Author: Ajax Davis Date: Tue Nov 25 21:59:15 2025 +1000 feat: initial monorepo setup with Turborepo, Next.js 16, and .ts-only components - Set up Turborepo monorepo with pnpm workspaces - Configure shared configs (Biome, ESLint, Tailwind, TypeScript) - Create @tpmjs/ui package with .ts-only React components (Button, Card) - Create @tpmjs/utils package with utility functions - Create @tpmjs/types package with Zod schemas - Create @tpmjs/env package for environment validation - Set up Next.js 16 App Router application - Configure Storybook in separate package - Add GitHub Actions CI/CD workflows - Configure Changesets for versioning and publishing - Set up Lefthook pre-commit hooks - Add comprehensive documentation Key architecture decisions: - All React components use .ts extension with createElement (no JSX) - No barrel exports (index.ts) - direct imports required - Module boundaries enforced via ESLint - tsup for package builds with ESM + types - Tailwind CSS with shared design tokens 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude diff --git a/packages/storybook/.storybook/main.ts b/packages/storybook/.storybook/main.ts new file mode 100644 index 0000000..056cfd0 --- /dev/null +++ b/packages/storybook/.storybook/main.ts @@ -0,0 +1,19 @@ +import type { StorybookConfig } from "@storybook/react-vite"; + +const config: StorybookConfig = { + stories: ["../stories/**/*.stories.@(ts|tsx)"], + addons: [ + "@storybook/addon-links", + "@storybook/addon-essentials", + "@storybook/addon-interactions", + ], + framework: { + name: "@storybook/react-vite", + options: {}, + }, + docs: { + autodocs: "tag", + }, +}; + +export default config; diff --git a/packages/storybook/.storybook/preview.ts b/packages/storybook/.storybook/preview.ts new file mode 100644 index 0000000..e2f735d --- /dev/null +++ b/packages/storybook/.storybook/preview.ts @@ -0,0 +1,15 @@ +import type { Preview } from "@storybook/react"; +import "../styles/globals.css"; + +const preview: Preview = { + parameters: { + controls: { + matchers: { + color: /(background|color)$/i, + date: /Date$/i, + }, + }, + }, +}; + +export default preview; diff --git a/packages/storybook/package.json b/packages/storybook/package.json new file mode 100644 index 0000000..4b1520b --- /dev/null +++ b/packages/storybook/package.json @@ -0,0 +1,33 @@ +{ + "name": "@tpmjs/storybook", + "version": "0.0.0", + "private": true, + "type": "module", + "scripts": { + "dev": "storybook dev -p 6006", + "build": "storybook build", + "clean": "rm -rf storybook-static .turbo" + }, + "dependencies": { + "@tpmjs/ui": "workspace:*", + "react": "^19.0.0", + "react-dom": "^19.0.0" + }, + "devDependencies": { + "@storybook/addon-essentials": "^8.5.0", + "@storybook/addon-interactions": "^8.5.0", + "@storybook/addon-links": "^8.5.0", + "@storybook/blocks": "^8.5.0", + "@storybook/react": "^8.5.0", + "@storybook/react-vite": "^8.5.0", + "@storybook/test": "^8.5.0", + "@tpmjs/tailwind-config": "workspace:*", + "@types/react": "^19.0.2", + "@types/react-dom": "^19.0.2", + "autoprefixer": "^10.4.20", + "postcss": "^8.5.1", + "storybook": "^8.5.0", + "tailwindcss": "^3.4.17", + "vite": "^6.0.7" + } +} diff --git a/packages/storybook/postcss.config.cjs b/packages/storybook/postcss.config.cjs new file mode 100644 index 0000000..12a703d --- /dev/null +++ b/packages/storybook/postcss.config.cjs @@ -0,0 +1,6 @@ +module.exports = { + plugins: { + tailwindcss: {}, + autoprefixer: {}, + }, +}; diff --git a/packages/storybook/stories/Button.stories.ts b/packages/storybook/stories/Button.stories.ts new file mode 100644 index 0000000..e1f756f --- /dev/null +++ b/packages/storybook/stories/Button.stories.ts @@ -0,0 +1,69 @@ +import type { Meta, StoryObj } from "@storybook/react"; +import { Button } from "@tpmjs/ui/Button/Button"; + +const meta = { + title: "Components/Button", + component: Button, + parameters: { + layout: "centered", + }, + tags: ["autodocs"], +} satisfies Meta; + +export default meta; +type Story = StoryObj; + +export const Default: Story = { + args: { + children: "Button", + }, +}; + +export const Destructive: Story = { + args: { + variant: "destructive", + children: "Delete", + }, +}; + +export const Outline: Story = { + args: { + variant: "outline", + children: "Outline", + }, +}; + +export const Secondary: Story = { + args: { + variant: "secondary", + children: "Secondary", + }, +}; + +export const Ghost: Story = { + args: { + variant: "ghost", + children: "Ghost", + }, +}; + +export const Link: Story = { + args: { + variant: "link", + children: "Link", + }, +}; + +export const Large: Story = { + args: { + size: "lg", + children: "Large Button", + }, +}; + +export const Small: Story = { + args: { + size: "sm", + children: "Small Button", + }, +}; diff --git a/packages/storybook/stories/Card.stories.ts b/packages/storybook/stories/Card.stories.ts new file mode 100644 index 0000000..37caf23 --- /dev/null +++ b/packages/storybook/stories/Card.stories.ts @@ -0,0 +1,39 @@ +import type { Meta, StoryObj } from "@storybook/react"; +import { Card, CardContent, CardHeader, CardTitle } from "@tpmjs/ui/Card/Card"; +import { createElement } from "react"; + +const meta = { + title: "Components/Card", + component: Card, + parameters: { + layout: "centered", + }, + tags: ["autodocs"], +} satisfies Meta; + +export default meta; +type Story = StoryObj; + +export const Default: Story = { + render: () => + createElement( + Card, + { className: "w-[350px]" }, + createElement(CardHeader, {}, createElement(CardTitle, {}, "Card Title")), + createElement(CardContent, {}, "This is the card content."), + ), +}; + +export const WithLongContent: Story = { + render: () => + createElement( + Card, + { className: "w-[400px]" }, + createElement(CardHeader, {}, createElement(CardTitle, {}, "TPMJS")), + createElement( + CardContent, + {}, + "Tool Package Manager for AI Agents. The registry for AI tools. Discover, share, and integrate tools that give your agents superpowers.", + ), + ), +}; diff --git a/packages/storybook/styles/globals.css b/packages/storybook/styles/globals.css new file mode 100644 index 0000000..ed3b6aa --- /dev/null +++ b/packages/storybook/styles/globals.css @@ -0,0 +1,26 @@ +@tailwind base; +@tailwind components; +@tailwind utilities; + +@layer base { + :root { + --background: 0 0% 100%; + --foreground: 222.2 84% 4.9%; + --card: 0 0% 100%; + --card-foreground: 222.2 84% 4.9%; + --primary: 222.2 47.4% 11.2%; + --primary-foreground: 210 40% 98%; + --secondary: 210 40% 96.1%; + --secondary-foreground: 222.2 47.4% 11.2%; + --muted: 210 40% 96.1%; + --muted-foreground: 215.4 16.3% 46.9%; + --accent: 210 40% 96.1%; + --accent-foreground: 222.2 47.4% 11.2%; + --destructive: 0 84.2% 60.2%; + --destructive-foreground: 210 40% 98%; + --border: 214.3 31.8% 91.4%; + --input: 214.3 31.8% 91.4%; + --ring: 222.2 84% 4.9%; + --radius: 0.5rem; + } +} diff --git a/packages/storybook/tailwind.config.ts b/packages/storybook/tailwind.config.ts new file mode 100644 index 0000000..25e1ee0 --- /dev/null +++ b/packages/storybook/tailwind.config.ts @@ -0,0 +1,7 @@ +import baseConfig from "@tpmjs/tailwind-config/base"; +import type { Config } from "tailwindcss"; + +export default { + ...baseConfig, + content: ["./stories/**/*.{ts,tsx}", "../ui/src/**/*.{ts,tsx}"], +} satisfies Config; diff --git a/packages/storybook/tsconfig.json b/packages/storybook/tsconfig.json new file mode 100644 index 0000000..b5955c1 --- /dev/null +++ b/packages/storybook/tsconfig.json @@ -0,0 +1,4 @@ +{ + "extends": "@tpmjs/tsconfig/react-library.json", + "include": [".storybook", "stories"] +}