14 KiB
Library with Playground Implementation Plan
For agentic workers: REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (
- [ ]) syntax for tracking.
Goal: Transform nychthemeron into a monorepo with a Vue component library (with PrimeVue + Tailwind) and interactive Storybook playground.
Architecture: Bun workspaces manage two independent packages — library (builds to ESM) and playground (Storybook dev server and static build). Shared configs at root level.
Tech Stack: Vue 3, PrimeVue, Tailwind CSS, Vite, Storybook, Vitest, TypeScript, Bun workspaces
Task 1: Create monorepo directory structure
Files:
-
Create:
packages/library/directory -
Create:
packages/playground/directory -
Step 1: Create packages directories
mkdir -p packages/library/src/{components,composables}
mkdir -p packages/library/__tests__
mkdir -p packages/playground/.storybook
mkdir -p packages/playground/stories
- Step 2: Verify structure
ls -la packages/
# Expected output shows: library/ and playground/ directories
Task 2: Move existing source to library package
Files:
-
Move:
src/→packages/library/src/ -
Delete:
vite.config.ts,vitest.config.ts,index.html(will recreate in packages) -
Step 1: Move src directory
mv src packages/library/src
- Step 2: Verify move
ls packages/library/src/
# Expected: App.vue, main.ts, __tests__/
- Step 3: Delete old root-level config files
rm vite.config.ts vitest.config.ts index.html
Task 3: Update root package.json for monorepo
Files:
-
Modify:
package.json -
Step 1: Add workspaces and update root config
Replace the entire package.json with:
{
"name": "nychthemeron",
"version": "0.0.0",
"private": true,
"type": "module",
"workspaces": [
"packages/*"
],
"scripts": {
"dev": "bun -r --cwd packages/playground dev",
"build": "bun -r --cwd packages/library build && bun -r --cwd packages/playground build",
"preview": "bun -r --cwd packages/playground preview",
"type-check": "vue-tsc --build",
"lint": "eslint packages/*/src --fix",
"format": "prettier --write --experimental-cli packages/*/src",
"test": "bun -r --cwd packages/library test:unit"
},
"devDependencies": {
"@tsconfig/node24": "^24.0.4",
"@types/jsdom": "^28.0.1",
"@types/node": "^24.12.2",
"@vitejs/plugin-vue": "^6.0.6",
"@vitest/eslint-plugin": "^1.6.16",
"@vue/eslint-config-typescript": "^14.7.0",
"@vue/test-utils": "^2.4.6",
"@vue/tsconfig": "^0.9.1",
"eslint": "^10.2.1",
"eslint-config-prettier": "^10.1.8",
"eslint-plugin-oxlint": "~1.60.0",
"eslint-plugin-vue": "~10.8.0",
"jiti": "^2.6.1",
"jsdom": "^29.0.2",
"npm-run-all2": "^8.0.4",
"oxlint": "~1.60.0",
"prettier": "3.8.3",
"typescript": "~6.0.0",
"vite": "^8.0.8",
"vite-plugin-vue-devtools": "^8.1.1",
"vitest": "^4.1.4",
"vue": "^3.5.32",
"vue-tsc": "^3.2.6"
},
"engines": {
"node": "^20.19.0 || >=22.12.0"
}
}
- Step 2: Install dependencies for new workspace structure
bun install
Expected output: Bun detects workspaces and creates symlinks in each packages/*/node_modules
Task 4: Create library package.json
Files:
-
Create:
packages/library/package.json -
Step 1: Create library package config
{
"name": "@nychthemeron/library",
"version": "0.1.0",
"type": "module",
"exports": {
".": {
"import": "./dist/index.js"
}
},
"files": [
"dist"
],
"scripts": {
"build": "vite build",
"test:unit": "vitest"
},
"peerDependencies": {
"vue": "^3.5.0",
"primevue": "^18.0.0"
},
"devDependencies": {
"@vitest/coverage-v8": "^2.0.0",
"@vue/test-utils": "^2.4.6"
}
}
Write this to packages/library/package.json
- Step 2: Verify file exists
cat packages/library/package.json | grep '"name"'
# Expected: "@nychthemeron/library"
Task 5: Create library tsconfig.json
Files:
-
Create:
packages/library/tsconfig.json -
Step 1: Create library TypeScript config
{
"extends": "../../tsconfig.json",
"compilerOptions": {
"outDir": "./dist",
"declaration": true,
"declarationMap": true,
"emitDeclarationOnly": false
},
"include": [
"src/**/*.ts",
"src/**/*.vue"
],
"exclude": [
"dist",
"**/*.spec.ts"
]
}
Write this to packages/library/tsconfig.json
Task 6: Create library vite.config.ts
Files:
-
Create:
packages/library/vite.config.ts -
Step 1: Create Vite library config
import { fileURLToPath } from 'node:url'
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
export default defineConfig({
plugins: [vue()],
build: {
lib: {
entry: fileURLToPath(new URL('./src/index.ts', import.meta.url)),
name: 'NychthemeronLibrary',
formats: ['es'],
fileName: () => 'index.js',
},
rollupOptions: {
external: ['vue', 'primevue'],
output: {
globals: {
vue: 'Vue',
primevue: 'PrimeVue',
},
},
},
},
})
Write this to packages/library/vite.config.ts
Task 7: Create library vitest.config.ts
Files:
-
Create:
packages/library/vitest.config.ts -
Step 1: Create Vitest config
import { defineConfig } from 'vitest/config'
import vue from '@vitejs/plugin-vue'
export default defineConfig({
plugins: [vue()],
test: {
globals: true,
environment: 'jsdom',
include: ['**/*.spec.ts'],
},
})
Write this to packages/library/vitest.config.ts
Task 8: Create library export structure
Files:
-
Create:
packages/library/src/components/index.ts -
Create:
packages/library/src/composables/index.ts -
Modify:
packages/library/src/index.ts -
Step 1: Create components index (empty for now)
// Re-export all components here as they're added
// export { default as Button } from './Button/Button.vue'
// export { default as DatePicker } from './DatePicker/DatePicker.vue'
Write this to packages/library/src/components/index.ts
- Step 2: Create composables index (empty for now)
// Re-export all composables here as they're added
// export { useDate } from './useDate'
Write this to packages/library/src/composables/index.ts
- Step 3: Create root library entry point
export * from './components'
export * from './composables'
Write this to packages/library/src/index.ts
- Step 4: Remove old App.vue and main.ts from library (they were for the app)
rm packages/library/src/App.vue packages/library/src/main.ts
Task 9: Create playground package.json
Files:
-
Create:
packages/playground/package.json -
Step 1: Create playground package config
{
"name": "@nychthemeron/playground",
"version": "0.1.0",
"type": "module",
"scripts": {
"dev": "storybook dev -p 6006",
"build": "storybook build",
"preview": "npx vite preview"
},
"dependencies": {
"@nychthemeron/library": "workspace:*",
"primevue": "^18.0.0",
"vue": "^3.5.32"
},
"devDependencies": {
"@storybook/addon-essentials": "^8.0.0",
"@storybook/addon-interactions": "^8.0.0",
"@storybook/addon-links": "^8.0.0",
"@storybook/blocks": "^8.0.0",
"@storybook/vue3": "^8.0.0",
"@storybook/vue3-vite": "^8.0.0",
"storybook": "^8.0.0",
"tailwindcss": "^3.4.0",
"autoprefixer": "^10.4.0",
"postcss": "^8.4.0",
"typescript": "~6.0.0",
"vue": "^3.5.32"
}
}
Write this to packages/playground/package.json
Task 10: Create playground tsconfig.json
Files:
-
Create:
packages/playground/tsconfig.json -
Step 1: Create playground TypeScript config
{
"extends": "../../tsconfig.json",
"compilerOptions": {
"composite": false,
"jsx": "preserve",
"lib": [
"dom",
"dom.iterable",
"esnext"
]
},
"include": [
".storybook/**/*.ts",
".storybook/**/*.tsx",
".storybook/**/*.vue",
"stories/**/*.ts",
"stories/**/*.tsx",
"stories/**/*.vue"
]
}
Write this to packages/playground/tsconfig.json
Task 11: Create playground Tailwind config
Files:
-
Create:
packages/playground/tailwind.config.ts -
Step 1: Create Tailwind config
import type { Config } from 'tailwindcss'
export default {
content: [
'./.storybook/**/*.{ts,tsx,vue}',
'./stories/**/*.{ts,tsx,vue}',
'../library/src/**/*.vue',
],
theme: {
extend: {
colors: {
primary: {
50: '#f0f9ff',
500: '#0ea5e9',
900: '#0c2d6b',
},
},
},
},
plugins: [],
} satisfies Config
Write this to packages/playground/tailwind.config.ts
Task 12: Create Storybook main config
Files:
-
Create:
packages/playground/.storybook/main.ts -
Step 1: Create Storybook main configuration
import type { StorybookConfig } from '@storybook/vue3-vite'
const config: StorybookConfig = {
stories: [
'../stories/**/*.stories.ts',
],
addons: [
'@storybook/addon-essentials',
'@storybook/addon-interactions',
'@storybook/addon-links',
],
framework: {
name: '@storybook/vue3-vite',
options: {},
},
core: {
disableTelemetry: true,
},
}
export default config
Write this to packages/playground/.storybook/main.ts
Task 13: Create Storybook preview config
Files:
-
Create:
packages/playground/.storybook/preview.ts -
Step 1: Create Storybook preview configuration
import type { Preview } from '@storybook/vue3'
import 'primevue/resources/themes/lara-light-blue/theme.css'
import 'primevue/resources/primevue.min.css'
import '../tailwind.css'
const preview: Preview = {
parameters: {
layout: 'centered',
docs: {
description: {
component: 'Component documentation',
},
},
},
}
export default preview
Write this to packages/playground/.storybook/preview.ts
Task 14: Create Tailwind CSS entry point
Files:
-
Create:
packages/playground/tailwind.css -
Step 1: Create Tailwind directives file
@tailwind base;
@tailwind components;
@tailwind utilities;
Write this to packages/playground/tailwind.css
Task 15: Create example story
Files:
-
Create:
packages/playground/stories/Example.stories.ts -
Step 1: Create example story for testing
import type { Meta, StoryObj } from '@storybook/vue3'
const meta = {
title: 'Example/Welcome',
parameters: {
layout: 'centered',
},
tags: ['autodocs'],
} satisfies Meta
export default meta
type Story = StoryObj<typeof meta>
export const Welcome: Story = {
render: () => ({
template: `
<div class="p-8 text-center">
<h1 class="text-3xl font-bold text-primary-500 mb-4">
Nychthemeron Component Library
</h1>
<p class="text-gray-600">
Interactive playground for Vue components with PrimeVue + Tailwind
</p>
</div>
`,
}),
}
Write this to packages/playground/stories/Example.stories.ts
Task 16: Install dependencies and verify structure
Files:
-
None (verification only)
-
Step 1: Install dependencies for all packages
bun install
Expected: All packages get dependencies installed, workspace links created
- Step 2: Verify workspace structure
ls -la packages/library/node_modules/@nychthemeron/library
# Expected: symlink to ../..
ls -la packages/playground/node_modules/@nychthemeron/library
# Expected: symlink to ../../../library
- Step 3: Type-check across monorepo
bun type-check
Expected: No TypeScript errors
Task 17: Test dev server startup
Files:
-
None (verification only)
-
Step 1: Start Storybook playground
bun dev
Expected output:
Storybook 8.x started
Local: http://localhost:6006
- Step 2: Verify Storybook loads in browser
Open http://localhost:6006 in a browser.
Expected: Storybook UI loads with "Example/Welcome" story visible showing the welcome message.
- Step 3: Verify story renders correctly
In Storybook, click "Example/Welcome" → verify the welcome message displays with correct styling.
Expected:
-
Title: "Nychthemeron Component Library" (blue, large)
-
Subtitle: "Interactive playground..." (gray, smaller)
-
Step 4: Stop dev server
# Press Ctrl+C in terminal
Task 18: Test library build
Files:
-
None (verification only)
-
Step 1: Build library
bun -r --cwd packages/library build
Expected output:
✓ 123 modules transformed
dist/index.js 1.23 kb
dist/index.d.ts 0.5 kb
- Step 2: Verify dist files exist
ls packages/library/dist/
Expected:
index.d.ts
index.js
- Step 3: Verify exports are correct
head -20 packages/library/dist/index.js
Expected: JavaScript code with ES module exports (starts with import or defines exports)
Task 19: Initialize git for monorepo
Files:
-
None (git initialization only)
-
Step 1: Initialize git repo (if not already)
git init
- Step 2: Add gitignore entries for workspace
Append to .gitignore:
packages/*/dist
packages/*/node_modules
packages/*/.storybook-static
- Step 3: Create initial commit (SKIP - user requested no commits)
Note: Commit skipped per user request
Self-Review
Spec coverage:
- ✅ Monorepo structure (Task 1)
- ✅ Bun workspaces setup (Tasks 2-3)
- ✅ Library package creation (Tasks 4-8)
- ✅ Composables structure (Task 8)
- ✅ Playground/Storybook setup (Tasks 9-15)
- ✅ Tailwind integration (Tasks 11, 14)
- ✅ PrimeVue initialization (Task 13)
- ✅ Dev workflow verification (Task 17)
- ✅ Build verification (Task 18)
- ✅ Git initialization (Task 19)
Placeholder scan: No TBDs, "fill in later", incomplete steps. All code blocks are complete and exact.
Type consistency: Package names consistent (@nychthemeron/library, @nychthemeron/playground). All import paths and config keys match across tasks.
Scope: Plan produces working, testable monorepo. Library builds to dist/, Storybook starts and loads stories. Next phase (adding components) is separate.