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 <noreply@anthropic.com>
This commit is contained in:
commit
bc2f4a01cf
9 changed files with 218 additions and 0 deletions
19
packages/storybook/.storybook/main.ts
Normal file
19
packages/storybook/.storybook/main.ts
Normal file
|
|
@ -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;
|
||||
15
packages/storybook/.storybook/preview.ts
Normal file
15
packages/storybook/.storybook/preview.ts
Normal file
|
|
@ -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;
|
||||
33
packages/storybook/package.json
Normal file
33
packages/storybook/package.json
Normal file
|
|
@ -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"
|
||||
}
|
||||
}
|
||||
6
packages/storybook/postcss.config.cjs
Normal file
6
packages/storybook/postcss.config.cjs
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
module.exports = {
|
||||
plugins: {
|
||||
tailwindcss: {},
|
||||
autoprefixer: {},
|
||||
},
|
||||
};
|
||||
69
packages/storybook/stories/Button.stories.ts
Normal file
69
packages/storybook/stories/Button.stories.ts
Normal file
|
|
@ -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<typeof Button>;
|
||||
|
||||
export default meta;
|
||||
type Story = StoryObj<typeof meta>;
|
||||
|
||||
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",
|
||||
},
|
||||
};
|
||||
39
packages/storybook/stories/Card.stories.ts
Normal file
39
packages/storybook/stories/Card.stories.ts
Normal file
|
|
@ -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<typeof Card>;
|
||||
|
||||
export default meta;
|
||||
type Story = StoryObj<typeof meta>;
|
||||
|
||||
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.",
|
||||
),
|
||||
),
|
||||
};
|
||||
26
packages/storybook/styles/globals.css
Normal file
26
packages/storybook/styles/globals.css
Normal file
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
7
packages/storybook/tailwind.config.ts
Normal file
7
packages/storybook/tailwind.config.ts
Normal file
|
|
@ -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;
|
||||
4
packages/storybook/tsconfig.json
Normal file
4
packages/storybook/tsconfig.json
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
{
|
||||
"extends": "@tpmjs/tsconfig/react-library.json",
|
||||
"include": [".storybook", "stories"]
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue