From dbee5771e18781076c66458f94db0f1f0033b0d9 Mon Sep 17 00:00:00 2001 From: Paul Mulligan Date: Thu, 2 Apr 2026 13:34:03 -0400 Subject: [PATCH] feat(templates): complete all framework starter templates Add missing configs so every template can scaffold a working project with `pnpm install && pnpm dev`: Vite: package.json, tsconfig.json, vitest.config.ts.tpl Next.js: package.json, tsconfig.json, vitest.config.ts.tpl Expo: babel.config.js, jest.config.js (fix broken inline jest config) SvelteKit: .storybook/ config Vue: tailwind.config.ts, .storybook/ config Also rewrites setup-project.sh to support all 6 targets (--next, --vite, --react, --vue, --svelte, --expo) with framework-appropriate deps, Storybook selection, and config filtering. Closes #42 Co-Authored-By: Claude Opus 4.6 (1M context) --- scripts/setup-project.sh | 164 +++++++++++++++++----- templates/expo/babel.config.js | 7 + templates/expo/jest.config.js | 24 ++++ templates/expo/package.json | 4 - templates/nextjs/package.json | 39 +++++ templates/nextjs/tsconfig.json | 30 ++++ templates/nextjs/vitest.config.ts.tpl | 37 +++++ templates/sveltekit/.storybook/main.ts | 16 +++ templates/sveltekit/.storybook/preview.ts | 15 ++ templates/sveltekit/package.json | 4 +- templates/vite/package.json | 40 ++++++ templates/vite/tsconfig.json | 26 ++++ templates/vite/vitest.config.ts.tpl | 35 +++++ templates/vue/.storybook/main.ts | 16 +++ templates/vue/.storybook/preview.ts | 15 ++ templates/vue/package.json | 4 +- templates/vue/tailwind.config.ts | 33 +++++ 17 files changed, 470 insertions(+), 39 deletions(-) create mode 100644 templates/expo/babel.config.js create mode 100644 templates/expo/jest.config.js create mode 100644 templates/nextjs/package.json create mode 100644 templates/nextjs/tsconfig.json create mode 100644 templates/nextjs/vitest.config.ts.tpl create mode 100644 templates/sveltekit/.storybook/main.ts create mode 100644 templates/sveltekit/.storybook/preview.ts create mode 100644 templates/vite/package.json create mode 100644 templates/vite/tsconfig.json create mode 100644 templates/vite/vitest.config.ts.tpl create mode 100644 templates/vue/.storybook/main.ts create mode 100644 templates/vue/.storybook/preview.ts create mode 100644 templates/vue/tailwind.config.ts diff --git a/scripts/setup-project.sh b/scripts/setup-project.sh index 51d7210..70b0d09 100644 --- a/scripts/setup-project.sh +++ b/scripts/setup-project.sh @@ -2,24 +2,30 @@ set -euo pipefail # Project Setup -# Initialize a new React project with standard tooling +# Initialize a new project with standard tooling # # Usage: # ./scripts/setup-project.sh my-app # Interactive framework prompt # ./scripts/setup-project.sh my-app --next # Create Next.js app # ./scripts/setup-project.sh my-app --vite # Create Vite + React app # ./scripts/setup-project.sh my-app --react # Create plain React app (via Vite) +# ./scripts/setup-project.sh my-app --vue # Create Vue 3 app +# ./scripts/setup-project.sh my-app --svelte # Create SvelteKit app +# ./scripts/setup-project.sh my-app --expo # Create Expo (React Native) app PROJECT_NAME="${1:-}" FRAMEWORK="" if [[ -z "$PROJECT_NAME" ]]; then - echo "Usage: $0 [--next|--vite|--react]" + echo "Usage: $0 [--next|--vite|--react|--vue|--svelte|--expo]" echo "" echo "Options:" echo " --next Create a Next.js app" echo " --vite Create a Vite + React app" echo " --react Create a plain React app (via Vite)" + echo " --vue Create a Vue 3 app" + echo " --svelte Create a SvelteKit app" + echo " --expo Create an Expo (React Native) app" exit 1 fi @@ -29,6 +35,9 @@ for arg in "${@:2}"; do --next) FRAMEWORK="next" ;; --vite) FRAMEWORK="vite" ;; --react) FRAMEWORK="react" ;; + --vue) FRAMEWORK="vue" ;; + --svelte) FRAMEWORK="svelte" ;; + --expo) FRAMEWORK="expo" ;; *) echo "Unknown option: $arg"; exit 1 ;; esac done @@ -39,13 +48,19 @@ if [[ -z "$FRAMEWORK" ]]; then echo " 1) Next.js" echo " 2) Vite + React" echo " 3) Plain React (via Vite)" + echo " 4) Vue 3" + echo " 5) SvelteKit" + echo " 6) Expo (React Native)" echo "" - read -rp "Enter choice [1-3]: " CHOICE + read -rp "Enter choice [1-6]: " CHOICE case "$CHOICE" in 1) FRAMEWORK="next" ;; 2) FRAMEWORK="vite" ;; 3) FRAMEWORK="react" ;; + 4) FRAMEWORK="vue" ;; + 5) FRAMEWORK="svelte" ;; + 6) FRAMEWORK="expo" ;; *) echo "Invalid choice. Exiting." exit 1 @@ -73,6 +88,18 @@ case "$FRAMEWORK" in echo "Creating React app (via Vite)..." pnpm create vite "$PROJECT_NAME" --template react-ts ;; + vue) + echo "Creating Vue 3 app..." + pnpm create vite "$PROJECT_NAME" --template vue-ts + ;; + svelte) + echo "Creating SvelteKit app..." + pnpm create svelte@latest "$PROJECT_NAME" + ;; + expo) + echo "Creating Expo app..." + pnpm create expo-app "$PROJECT_NAME" --template tabs + ;; esac echo "" @@ -90,16 +117,24 @@ echo "Installing additional tooling..." ADDITIONAL_DEPS=() -# Tailwind CSS (skip for Next.js as it's included via create-next-app) -if [[ "$FRAMEWORK" != "next" ]]; then - ADDITIONAL_DEPS+=(tailwindcss @tailwindcss/vite) -fi - -# Linting and formatting -ADDITIONAL_DEPS+=(prettier) - -# Testing -ADDITIONAL_DEPS+=(vitest @testing-library/react @testing-library/jest-dom @testing-library/user-event jsdom @vitest/coverage-v8) +case "$FRAMEWORK" in + next) + # Tailwind included via create-next-app; add testing + formatting + ADDITIONAL_DEPS+=(prettier vitest @testing-library/react @testing-library/jest-dom @testing-library/user-event jsdom @vitest/coverage-v8 @vitejs/plugin-react) + ;; + vite|react) + ADDITIONAL_DEPS+=(tailwindcss @tailwindcss/vite prettier vitest @testing-library/react @testing-library/jest-dom @testing-library/user-event jsdom @vitest/coverage-v8) + ;; + vue) + ADDITIONAL_DEPS+=(prettier vitest @vue/test-utils @testing-library/vue jsdom @vitest/coverage-v8) + ;; + svelte) + ADDITIONAL_DEPS+=(prettier vitest @testing-library/svelte jsdom @vitest/coverage-v8) + ;; + expo) + ADDITIONAL_DEPS+=(prettier jest jest-expo @testing-library/react-native) + ;; +esac if [[ ${#ADDITIONAL_DEPS[@]} -gt 0 ]]; then pnpm add -D "${ADDITIONAL_DEPS[@]}" @@ -109,17 +144,42 @@ fi SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" TEMPLATES_DIR="$SCRIPT_DIR/../templates" +# Determine the template directory for the framework +FRAMEWORK_TEMPLATE="$FRAMEWORK" +case "$FRAMEWORK" in + react) FRAMEWORK_TEMPLATE="vite" ;; + svelte) FRAMEWORK_TEMPLATE="sveltekit" ;; +esac + if [[ -d "$TEMPLATES_DIR" ]]; then echo "" echo "Copying template configurations..." # Copy shared configs (ESLint, Prettier, Vitest, Tailwind, tsconfig) + # Expo uses its own tsconfig and doesn't use vitest/storybook if [[ -d "$TEMPLATES_DIR/shared" ]]; then for template_file in "$TEMPLATES_DIR/shared"/*; do if [[ -f "$template_file" ]]; then FILENAME=$(basename "$template_file") # Strip .tpl suffix (template configs renamed to avoid IDE auto-discovery) FILENAME="${FILENAME%.tpl}" + + # Skip shared configs that don't apply to the framework + case "$FRAMEWORK" in + expo) + # Expo doesn't use vitest, tailwind config (uses NativeWind), or storybook + case "$FILENAME" in + vitest.config.template.ts|tailwind.config.ts) continue ;; + esac + ;; + vue) + # Vue has its own tailwind.config.ts with Vue file extensions + case "$FILENAME" in + tailwind.config.ts) continue ;; + esac + ;; + esac + if [[ ! -f "$FILENAME" ]]; then cp "$template_file" "./$FILENAME" echo " Copied: $FILENAME" @@ -129,18 +189,23 @@ if [[ -d "$TEMPLATES_DIR" ]]; then fi done - # Copy Storybook config directory - if [[ -d "$TEMPLATES_DIR/shared/.storybook" ]] && [[ ! -d ".storybook" ]]; then - cp -r "$TEMPLATES_DIR/shared/.storybook" ./.storybook - echo " Copied: .storybook/" + # Copy Storybook config directory (not for Expo) + if [[ "$FRAMEWORK" != "expo" ]]; then + # Prefer framework-specific storybook config if it exists + STORYBOOK_SRC="$TEMPLATES_DIR/$FRAMEWORK_TEMPLATE/.storybook" + if [[ ! -d "$STORYBOOK_SRC" ]]; then + STORYBOOK_SRC="$TEMPLATES_DIR/shared/.storybook" + fi + + if [[ -d "$STORYBOOK_SRC" ]] && [[ ! -d ".storybook" ]]; then + cp -r "$STORYBOOK_SRC" ./.storybook + echo " Copied: .storybook/ (from $(basename "$(dirname "$STORYBOOK_SRC")"))" + fi fi fi # Copy framework-specific configs - FRAMEWORK_DIR="$TEMPLATES_DIR/$FRAMEWORK" - if [[ "$FRAMEWORK" == "react" ]]; then - FRAMEWORK_DIR="$TEMPLATES_DIR/vite" - fi + FRAMEWORK_DIR="$TEMPLATES_DIR/$FRAMEWORK_TEMPLATE" if [[ -d "$FRAMEWORK_DIR" ]]; then for template_file in "$FRAMEWORK_DIR"/*; do @@ -166,21 +231,54 @@ echo "Project created at: $(pwd)" echo "" echo "Next steps:" echo " cd $PROJECT_NAME" -echo " pnpm dev # Start development server" -echo " pnpm build # Build for production" -echo " pnpm vitest # Run tests" -echo " pnpm vitest --coverage # Run tests with coverage" -echo "" -if [[ "$FRAMEWORK" == "vite" ]] || [[ "$FRAMEWORK" == "react" ]]; then - echo "Tailwind CSS:" - echo " Add '@import \"tailwindcss\";' to your main CSS file." - echo " Add the @tailwindcss/vite plugin to vite.config.ts." - echo "" -fi +case "$FRAMEWORK" in + next) + echo " pnpm dev # Start development server (port 3000)" + echo " pnpm build # Build for production" + echo " pnpm vitest # Run tests" + echo " pnpm vitest --coverage # Run tests with coverage" + ;; + vite|react) + echo " pnpm dev # Start development server (port 5173)" + echo " pnpm build # Build for production" + echo " pnpm vitest # Run tests" + echo " pnpm vitest --coverage # Run tests with coverage" + echo "" + echo "Tailwind CSS:" + echo " Add '@import \"tailwindcss\";' to your main CSS file." + echo " Add the @tailwindcss/vite plugin to vite.config.ts." + ;; + vue) + echo " pnpm dev # Start development server (port 5173)" + echo " pnpm build # Build for production" + echo " pnpm vitest # Run tests" + echo " pnpm vitest --coverage # Run tests with coverage" + ;; + svelte) + echo " pnpm dev # Start development server (port 5173)" + echo " pnpm build # Build for production" + echo " pnpm vitest # Run tests" + echo " pnpm vitest --coverage # Run tests with coverage" + ;; + expo) + echo " pnpm start # Start Expo dev server" + echo " pnpm ios # Run on iOS simulator" + echo " pnpm android # Run on Android emulator" + echo " pnpm test # Run Jest tests" + echo " pnpm test:coverage # Run tests with coverage" + ;; +esac +echo "" echo "Recommended VS Code extensions:" echo " - ESLint" echo " - Prettier" echo " - Tailwind CSS IntelliSense" -echo " - Vitest" + +case "$FRAMEWORK" in + next|vite|react) echo " - Vitest" ;; + vue) echo " - Volar (Vue)" ; echo " - Vitest" ;; + svelte) echo " - Svelte for VS Code" ; echo " - Vitest" ;; + expo) echo " - React Native Tools" ;; +esac diff --git a/templates/expo/babel.config.js b/templates/expo/babel.config.js new file mode 100644 index 0000000..6d8b1fb --- /dev/null +++ b/templates/expo/babel.config.js @@ -0,0 +1,7 @@ +module.exports = function (api) { + api.cache(true); + return { + presets: [["babel-preset-expo", { jsxImportSource: "nativewind" }]], + plugins: ["nativewind/babel"], + }; +}; diff --git a/templates/expo/jest.config.js b/templates/expo/jest.config.js new file mode 100644 index 0000000..79ae333 --- /dev/null +++ b/templates/expo/jest.config.js @@ -0,0 +1,24 @@ +/** @type {import('jest').Config} */ +module.exports = { + preset: "jest-expo", + setupFilesAfterFramework: [ + "@testing-library/react-native/extend-expect", + ], + transformIgnorePatterns: [ + "node_modules/(?!((jest-)?react-native|@react-native(-community)?)|expo(nent)?|@expo(nent)?/.*|@expo-google-fonts/.*|react-navigation|@react-navigation/.*|@sentry/react-native|native-base|react-native-svg|nativewind)", + ], + collectCoverageFrom: [ + "src/**/*.{ts,tsx}", + "!src/**/*.d.ts", + "!src/test/**", + "!src/**/*.stories.{ts,tsx}", + ], + coverageThreshold: { + global: { + statements: 80, + branches: 80, + functions: 80, + lines: 80, + }, + }, +}; diff --git a/templates/expo/package.json b/templates/expo/package.json index cfeff14..cc06bda 100644 --- a/templates/expo/package.json +++ b/templates/expo/package.json @@ -30,9 +30,5 @@ "typescript": "^5.7.0", "eslint": "^9.0.0", "prettier": "^3.4.0" - }, - "jest": { - "preset": "jest-expo", - "setupFilesAfterSetup": ["@testing-library/react-native/extend-expect"] } } diff --git a/templates/nextjs/package.json b/templates/nextjs/package.json new file mode 100644 index 0000000..d007616 --- /dev/null +++ b/templates/nextjs/package.json @@ -0,0 +1,39 @@ +{ + "name": "my-next-app", + "private": true, + "version": "0.0.0", + "scripts": { + "dev": "next dev", + "build": "next build", + "start": "next start", + "test": "vitest run", + "test:watch": "vitest", + "test:coverage": "vitest run --coverage", + "lint": "next lint && eslint .", + "format": "prettier --write .", + "storybook": "storybook dev -p 6006", + "build-storybook": "storybook build" + }, + "dependencies": { + "next": "^15.0.0", + "react": "^19.0.0", + "react-dom": "^19.0.0" + }, + "devDependencies": { + "@testing-library/jest-dom": "^6.6.0", + "@testing-library/react": "^16.1.0", + "@testing-library/user-event": "^14.5.0", + "@types/node": "^22.0.0", + "@types/react": "^19.0.0", + "@types/react-dom": "^19.0.0", + "@vitejs/plugin-react": "^4.3.0", + "@vitest/coverage-v8": "^3.0.0", + "eslint": "^9.0.0", + "eslint-config-next": "^15.0.0", + "jsdom": "^25.0.0", + "prettier": "^3.4.0", + "tailwindcss": "^4.0.0", + "typescript": "^5.7.0", + "vitest": "^3.0.0" + } +} diff --git a/templates/nextjs/tsconfig.json b/templates/nextjs/tsconfig.json new file mode 100644 index 0000000..2251987 --- /dev/null +++ b/templates/nextjs/tsconfig.json @@ -0,0 +1,30 @@ +{ + "compilerOptions": { + "target": "ES2022", + "lib": ["DOM", "DOM.Iterable", "ES2022"], + "module": "ESNext", + "moduleResolution": "bundler", + "jsx": "preserve", + "strict": true, + "noEmit": true, + "esModuleInterop": true, + "skipLibCheck": true, + "forceConsistentCasingInFileNames": true, + "resolveJsonModule": true, + "isolatedModules": true, + "incremental": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "noFallthroughCasesInSwitch": true, + "allowImportingTsExtensions": true, + "baseUrl": ".", + "paths": { + "@/*": ["./src/*"] + }, + "plugins": [ + { "name": "next" } + ] + }, + "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"], + "exclude": ["node_modules", ".next"] +} diff --git a/templates/nextjs/vitest.config.ts.tpl b/templates/nextjs/vitest.config.ts.tpl new file mode 100644 index 0000000..f360034 --- /dev/null +++ b/templates/nextjs/vitest.config.ts.tpl @@ -0,0 +1,37 @@ +import { defineConfig } from "vitest/config"; +import react from "@vitejs/plugin-react"; +import { resolve } from "path"; + +export default defineConfig({ + plugins: [react()], + resolve: { + alias: { + "@": resolve(__dirname, "./src"), + }, + }, + test: { + globals: true, + environment: "jsdom", + setupFiles: ["./src/test/setup.ts"], + include: ["src/**/*.{test,spec}.{ts,tsx}"], + exclude: ["node_modules", ".next", "e2e"], + coverage: { + provider: "v8", + reporter: ["text", "html", "lcov"], + exclude: [ + "node_modules/", + ".next/", + "src/test/", + "**/*.d.ts", + "**/*.config.*", + "**/types/**", + ], + thresholds: { + statements: 80, + branches: 80, + functions: 80, + lines: 80, + }, + }, + }, +}); diff --git a/templates/sveltekit/.storybook/main.ts b/templates/sveltekit/.storybook/main.ts new file mode 100644 index 0000000..7039cb9 --- /dev/null +++ b/templates/sveltekit/.storybook/main.ts @@ -0,0 +1,16 @@ +import type { StorybookConfig } from "@storybook/sveltekit"; + +const config: StorybookConfig = { + stories: ["../src/**/*.mdx", "../src/**/*.stories.@(ts|svelte)"], + addons: [ + "@storybook/addon-essentials", + "@storybook/addon-a11y", + "@storybook/addon-interactions", + ], + framework: { + name: "@storybook/sveltekit", + options: {}, + }, +}; + +export default config; diff --git a/templates/sveltekit/.storybook/preview.ts b/templates/sveltekit/.storybook/preview.ts new file mode 100644 index 0000000..55610cc --- /dev/null +++ b/templates/sveltekit/.storybook/preview.ts @@ -0,0 +1,15 @@ +import type { Preview } from "@storybook/svelte"; +import "../src/app.css"; + +const preview: Preview = { + parameters: { + controls: { + matchers: { + color: /(background|color)$/i, + date: /Date$/i, + }, + }, + }, +}; + +export default preview; diff --git a/templates/sveltekit/package.json b/templates/sveltekit/package.json index 5945463..b1f6822 100644 --- a/templates/sveltekit/package.json +++ b/templates/sveltekit/package.json @@ -12,7 +12,9 @@ "test:coverage": "vitest run --coverage", "check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json", "lint": "eslint .", - "format": "prettier --write ." + "format": "prettier --write .", + "storybook": "storybook dev -p 6006", + "build-storybook": "storybook build" }, "dependencies": { "@sveltejs/kit": "^2.15.0", diff --git a/templates/vite/package.json b/templates/vite/package.json new file mode 100644 index 0000000..c8698ca --- /dev/null +++ b/templates/vite/package.json @@ -0,0 +1,40 @@ +{ + "name": "my-vite-app", + "private": true, + "version": "0.0.0", + "type": "module", + "scripts": { + "dev": "vite", + "build": "tsc && vite build", + "preview": "vite preview", + "test": "vitest run", + "test:watch": "vitest", + "test:coverage": "vitest run --coverage", + "lint": "eslint .", + "format": "prettier --write .", + "storybook": "storybook dev -p 6006", + "build-storybook": "storybook build" + }, + "dependencies": { + "react": "^19.0.0", + "react-dom": "^19.0.0", + "react-router-dom": "^7.0.0" + }, + "devDependencies": { + "@tailwindcss/vite": "^4.0.0", + "@testing-library/jest-dom": "^6.6.0", + "@testing-library/react": "^16.1.0", + "@testing-library/user-event": "^14.5.0", + "@types/react": "^19.0.0", + "@types/react-dom": "^19.0.0", + "@vitejs/plugin-react": "^4.3.0", + "@vitest/coverage-v8": "^3.0.0", + "eslint": "^9.0.0", + "jsdom": "^25.0.0", + "prettier": "^3.4.0", + "tailwindcss": "^4.0.0", + "typescript": "^5.7.0", + "vite": "^6.0.0", + "vitest": "^3.0.0" + } +} diff --git a/templates/vite/tsconfig.json b/templates/vite/tsconfig.json new file mode 100644 index 0000000..7704c90 --- /dev/null +++ b/templates/vite/tsconfig.json @@ -0,0 +1,26 @@ +{ + "compilerOptions": { + "target": "ES2022", + "lib": ["DOM", "DOM.Iterable", "ES2022"], + "module": "ESNext", + "moduleResolution": "bundler", + "jsx": "react-jsx", + "strict": true, + "noEmit": true, + "esModuleInterop": true, + "skipLibCheck": true, + "forceConsistentCasingInFileNames": true, + "resolveJsonModule": true, + "isolatedModules": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "noFallthroughCasesInSwitch": true, + "allowImportingTsExtensions": true, + "baseUrl": ".", + "paths": { + "@/*": ["./src/*"] + } + }, + "include": ["src"], + "exclude": ["node_modules", "dist"] +} diff --git a/templates/vite/vitest.config.ts.tpl b/templates/vite/vitest.config.ts.tpl new file mode 100644 index 0000000..b2b8655 --- /dev/null +++ b/templates/vite/vitest.config.ts.tpl @@ -0,0 +1,35 @@ +import { defineConfig } from "vitest/config"; +import react from "@vitejs/plugin-react"; +import { resolve } from "path"; + +export default defineConfig({ + plugins: [react()], + resolve: { + alias: { + "@": resolve(__dirname, "./src"), + }, + }, + test: { + globals: true, + environment: "jsdom", + setupFiles: ["./src/test/setup.ts"], + include: ["src/**/*.{test,spec}.{ts,tsx}"], + coverage: { + provider: "v8", + reporter: ["text", "html", "lcov"], + exclude: [ + "node_modules/", + "src/test/", + "**/*.d.ts", + "**/*.config.*", + "**/types/**", + ], + thresholds: { + statements: 80, + branches: 80, + functions: 80, + lines: 80, + }, + }, + }, +}); diff --git a/templates/vue/.storybook/main.ts b/templates/vue/.storybook/main.ts new file mode 100644 index 0000000..10babaf --- /dev/null +++ b/templates/vue/.storybook/main.ts @@ -0,0 +1,16 @@ +import type { StorybookConfig } from "@storybook/vue3-vite"; + +const config: StorybookConfig = { + stories: ["../src/**/*.mdx", "../src/**/*.stories.@(ts|vue)"], + addons: [ + "@storybook/addon-essentials", + "@storybook/addon-a11y", + "@storybook/addon-interactions", + ], + framework: { + name: "@storybook/vue3-vite", + options: {}, + }, +}; + +export default config; diff --git a/templates/vue/.storybook/preview.ts b/templates/vue/.storybook/preview.ts new file mode 100644 index 0000000..938c9d1 --- /dev/null +++ b/templates/vue/.storybook/preview.ts @@ -0,0 +1,15 @@ +import type { Preview } from "@storybook/vue3"; +import "../src/assets/main.css"; + +const preview: Preview = { + parameters: { + controls: { + matchers: { + color: /(background|color)$/i, + date: /Date$/i, + }, + }, + }, +}; + +export default preview; diff --git a/templates/vue/package.json b/templates/vue/package.json index 0663ae1..0d2db0c 100644 --- a/templates/vue/package.json +++ b/templates/vue/package.json @@ -11,7 +11,9 @@ "test:watch": "vitest", "test:coverage": "vitest run --coverage", "lint": "eslint .", - "format": "prettier --write ." + "format": "prettier --write .", + "storybook": "storybook dev -p 6006", + "build-storybook": "storybook build" }, "dependencies": { "vue": "^3.5.0", diff --git a/templates/vue/tailwind.config.ts b/templates/vue/tailwind.config.ts new file mode 100644 index 0000000..3fbaee3 --- /dev/null +++ b/templates/vue/tailwind.config.ts @@ -0,0 +1,33 @@ +import type { Config } from "tailwindcss"; + +const config: Config = { + content: [ + "./index.html", + "./src/**/*.{vue,ts,tsx,js,jsx}", + "./components/**/*.{vue,ts,tsx,js,jsx}", + ], + theme: { + extend: { + // Design tokens from Figma go here + colors: { + // primary: "#...", + // secondary: "#...", + }, + fontFamily: { + // sans: ["Inter", "system-ui", "sans-serif"], + }, + spacing: { + // Custom spacing scale + }, + borderRadius: { + // Custom radii + }, + boxShadow: { + // Custom shadows + }, + }, + }, + plugins: [], +}; + +export default config;