@tpitre/story-ui 2.7.0 → 2.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -10,7 +10,7 @@ Story UI revolutionizes component documentation by automatically generating Stor
10
10
  ## Why Story UI?
11
11
 
12
12
  - **Framework Agnostic**: Works with React, Vue, Angular, Svelte, and Web Components
13
- - **Multi-Provider AI**: Choose between Claude (Anthropic), GPT-4 (OpenAI), or Gemini (Google)
13
+ - **Multi-Provider AI**: Choose between Claude (Anthropic), GPT-5 (OpenAI), or Gemini (Google)
14
14
  - **Design System Aware**: Learns your component library and generates appropriate code
15
15
  - **Production Ready**: Deploy as a standalone web app with full MCP integration
16
16
  - **Zero Lock-in**: Use any component library - Mantine, Vuetify, Angular Material, Shoelace, or your own
@@ -51,19 +51,19 @@ Story UI will guide you through:
51
51
 
52
52
  | Framework | Design Systems | Status |
53
53
  |-----------|---------------|--------|
54
- | React | Mantine, Chakra UI, MUI, Ant Design, ShadCN, Custom | Fully Supported |
55
- | Vue | Vuetify, Element Plus, PrimeVue, Quasar, Custom | Fully Supported |
56
- | Angular | Angular Material, PrimeNG, NG-ZORRO, Custom | Fully Supported |
57
- | Svelte | Skeleton, Custom | Fully Supported |
58
- | Web Components | Shoelace, Lit, Custom | Fully Supported |
54
+ | React | Mantine, Chakra UI, Material UI, Custom | Fully Supported |
55
+ | Vue | Vuetify, Custom | Fully Supported |
56
+ | Angular | Angular Material, Custom | Fully Supported |
57
+ | Svelte | Skeleton UI, Custom | Fully Supported |
58
+ | Web Components | Shoelace, Custom | Fully Supported |
59
59
 
60
60
  ### Multi-Provider LLM Support
61
61
 
62
62
  | Provider | Models | Best For |
63
63
  |----------|--------|----------|
64
64
  | **Claude** (Anthropic) | Opus 4.5, Sonnet 4.5, Haiku 4.5 | Complex reasoning, code quality |
65
- | **GPT-5** (OpenAI) | GPT-5.1, GPT-5 Mini, GPT-5 Nano | Versatility, speed |
66
- | **Gemini** (Google) | Gemini 3 Pro, Gemini 2.5 Pro, Gemini 2.5 Flash | Fast generation, cost efficiency |
65
+ | **GPT** (OpenAI) | GPT-5.1, GPT-5.1 Thinking, GPT-4o, GPT-4o Mini | Versatility, speed |
66
+ | **Gemini** (Google) | Gemini 3 Pro, Gemini 2.0 Flash, Gemini 1.5 Pro | Fast generation, cost efficiency |
67
67
 
68
68
  ### Production Deployment
69
69
  - **Cloudflare Workers**: Edge-deployed API proxy
@@ -97,25 +97,19 @@ The interactive installer will ask:
97
97
  ```
98
98
  # For React:
99
99
  ? Choose a design system:
100
- > ShadCN/UI
101
- Mantine
100
+ > Mantine - Most Popular
102
101
  Chakra UI
103
- Ant Design
102
+ Material UI
104
103
  Custom
105
104
 
106
105
  # For Vue:
107
106
  ? Choose a design system:
108
- > Vuetify
109
- Element Plus
110
- PrimeVue
111
- Quasar
107
+ > Vuetify - Most Popular
112
108
  Custom
113
109
 
114
110
  # For Angular:
115
111
  ? Choose a design system:
116
- > Angular Material
117
- PrimeNG
118
- NG-ZORRO
112
+ > Angular Material - Most Popular
119
113
  Custom
120
114
  ```
121
115
 
@@ -254,11 +248,31 @@ export class DataTableComponent { }
254
248
 
255
249
  ## MCP Server Integration
256
250
 
257
- Story UI includes a Model Context Protocol (MCP) server, allowing direct integration with AI clients like Claude Desktop.
251
+ Story UI includes a Model Context Protocol (MCP) server, allowing direct integration with AI clients like Claude Desktop and Claude Code.
258
252
 
259
- ### Local MCP Setup
253
+ ### Claude Code Integration (Recommended)
260
254
 
261
- Add to your Claude Desktop config (`~/Library/Application Support/Claude/claude_desktop_config.json` on macOS):
255
+ The easiest way to connect is via Claude Code's built-in MCP support:
256
+
257
+ ```bash
258
+ # Add remote HTTP MCP server
259
+ claude mcp add --transport http story-ui https://your-worker.workers.dev/mcp
260
+
261
+ # Or for local development
262
+ claude mcp add --transport http story-ui-local http://localhost:4005/mcp
263
+ ```
264
+
265
+ ### Claude Desktop Integration
266
+
267
+ Claude Desktop now supports a connector UI for adding MCP servers. Simply:
268
+
269
+ 1. Open Claude Desktop Settings
270
+ 2. Navigate to the MCP Servers section
271
+ 3. Add a new server with:
272
+ - **Name**: Story UI
273
+ - **URL**: `https://your-worker.workers.dev/mcp` (production) or `http://localhost:4005/mcp` (local)
274
+
275
+ For advanced users who prefer manual configuration, add to your Claude Desktop config (`~/Library/Application Support/Claude/claude_desktop_config.json` on macOS):
262
276
 
263
277
  ```json
264
278
  {
@@ -274,28 +288,13 @@ Add to your Claude Desktop config (`~/Library/Application Support/Claude/claude_
274
288
  }
275
289
  ```
276
290
 
277
- Then start the Story UI HTTP server:
291
+ ### Starting the Local MCP Server
292
+
278
293
  ```bash
279
294
  npx story-ui start
280
295
  ```
281
296
 
282
- ### Production MCP Setup
283
-
284
- Connect Claude Desktop to your deployed Story UI instance:
285
-
286
- ```json
287
- {
288
- "mcpServers": {
289
- "story-ui-production": {
290
- "command": "npx",
291
- "args": ["mcp-remote", "https://your-worker.workers.dev/mcp"],
292
- "env": {}
293
- }
294
- }
295
- }
296
- ```
297
-
298
- This allows you to generate stories in your production environment directly from Claude Desktop, with all your design system configurations loaded.
297
+ This starts the Story UI HTTP server with MCP endpoint at `http://localhost:4005/mcp`.
299
298
 
300
299
  ### Available MCP Commands
301
300
 
@@ -365,19 +364,50 @@ wrangler pages deploy dist --project-name=your-app-name
365
364
 
366
365
  Update the frontend to point to your worker URL in the configuration.
367
366
 
368
- ### Alternative: Railway Backend
367
+ ### Railway Deployment (Recommended)
369
368
 
370
- For a full Node.js environment:
369
+ Railway provides the most complete deployment experience with:
370
+ - Full Storybook dev server with HMR
371
+ - Integrated Story UI MCP server
372
+ - Live story generation directly in the sidebar
373
+ - Easy environment variable management
374
+
375
+ **1. Deploy to Railway**
371
376
 
372
377
  ```bash
373
- cd mcp-server
378
+ # From your Storybook project with Story UI configured
379
+ npx story-ui deploy --live --platform=railway --dry-run
380
+
381
+ # Review the generated configuration, then deploy:
374
382
  railway up
383
+ ```
384
+
385
+ **2. Set Environment Variables in Railway Dashboard:**
386
+ - `ANTHROPIC_API_KEY` - Required for Claude models
387
+ - `OPENAI_API_KEY` - Optional for OpenAI models
388
+ - `GEMINI_API_KEY` - Optional for Gemini models
389
+ - `STORY_UI_DEV_MODE=true` - Enable file-based story storage
390
+
391
+ **3. Connect External MCP Clients**
392
+
393
+ Once deployed, your Railway instance provides an MCP endpoint that AI clients can connect to:
375
394
 
376
- # Set environment variables in Railway dashboard:
377
- # - ANTHROPIC_API_KEY
378
- # - OPENAI_API_KEY (optional)
379
- # - GEMINI_API_KEY (optional)
380
395
  ```
396
+ https://your-app.up.railway.app/story-ui
397
+ ```
398
+
399
+ **For Claude Desktop/Claude Code:**
400
+ ```bash
401
+ # Add your Railway deployment as an MCP server
402
+ claude mcp add --transport http story-ui https://your-app.up.railway.app/story-ui
403
+ ```
404
+
405
+ **For other MCP clients**, use the full URL:
406
+ ```
407
+ https://your-app.up.railway.app/mcp
408
+ ```
409
+
410
+ This allows you to generate stories from Claude Desktop, ChatGPT (with MCP support), or any other MCP-compatible AI client, and see them appear in your deployed Storybook instance.
381
411
 
382
412
  ---
383
413
 
@@ -1,12 +1,13 @@
1
1
  interface DeployOptions {
2
+ live?: boolean;
3
+ platform?: 'railway' | 'fly';
4
+ projectName?: string;
5
+ dryRun?: boolean;
2
6
  backend?: boolean;
3
7
  frontend?: boolean;
4
8
  app?: boolean;
5
- platform?: 'railway' | 'render' | 'fly';
6
9
  backendUrl?: string;
7
10
  storybookDir?: string;
8
- projectName?: string;
9
- dryRun?: boolean;
10
11
  init?: boolean;
11
12
  edge?: boolean;
12
13
  pages?: boolean;
@@ -1 +1 @@
1
- {"version":3,"file":"deploy.d.ts","sourceRoot":"","sources":["../../cli/deploy.ts"],"names":[],"mappings":"AASA,UAAU,aAAa;IAErB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,QAAQ,CAAC,EAAE,SAAS,GAAG,QAAQ,GAAG,KAAK,CAAC;IACxC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,CAAC,EAAE,OAAO,CAAC;IAEjB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,GAAG,CAAC,EAAE,OAAO,CAAC;CACf;AAotBD,wBAAsB,aAAa,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAwHzE"}
1
+ {"version":3,"file":"deploy.d.ts","sourceRoot":"","sources":["../../cli/deploy.ts"],"names":[],"mappings":"AASA,UAAU,aAAa;IAErB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,QAAQ,CAAC,EAAE,SAAS,GAAG,KAAK,CAAC;IAC7B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,CAAC,EAAE,OAAO,CAAC;IAEjB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;IAEtB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,GAAG,CAAC,EAAE,OAAO,CAAC;CACf;AA6hCD,wBAAsB,aAAa,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CA0JzE"}
@@ -34,6 +34,360 @@ function isToolInstalled(tool) {
34
34
  return false;
35
35
  }
36
36
  }
37
+ /**
38
+ * Generate deployment files for live Storybook deployment
39
+ * This creates Dockerfile, start script, and platform configs
40
+ */
41
+ function generateLiveDeploymentFiles(projectDir, platform) {
42
+ console.log('📝 Generating deployment files...\n');
43
+ // 1. Create Dockerfile for running both servers
44
+ const dockerfilePath = path.join(projectDir, 'Dockerfile');
45
+ const dockerfile = `# Story UI Live Deployment
46
+ # Runs Storybook in dev mode with Story UI MCP server
47
+
48
+ FROM node:20-slim
49
+
50
+ WORKDIR /app
51
+
52
+ # Install dependencies
53
+ COPY package*.json ./
54
+ RUN npm install
55
+
56
+ # Copy project files
57
+ COPY . .
58
+
59
+ # Make start script executable
60
+ RUN chmod +x ./start-production.sh
61
+
62
+ # Expose ports: Storybook (6006) and MCP server (4005)
63
+ EXPOSE 6006 4005
64
+
65
+ # Start both servers
66
+ CMD ["./start-production.sh"]
67
+ `;
68
+ fs.writeFileSync(dockerfilePath, dockerfile);
69
+ console.log('✅ Created Dockerfile');
70
+ // 2. Create start script that runs both servers
71
+ const startScriptPath = path.join(projectDir, 'start-production.sh');
72
+ const startScript = `#!/bin/bash
73
+
74
+ # Story UI Live Production Start Script
75
+ # Runs Storybook in dev mode with Story UI MCP server
76
+
77
+ echo "🚀 Starting Story UI Live Environment..."
78
+
79
+ # Start Storybook dev server in background
80
+ echo "📖 Starting Storybook dev server on port 6006..."
81
+ npm run storybook -- --port 6006 --host 0.0.0.0 --ci --no-open &
82
+ STORYBOOK_PID=$!
83
+
84
+ # Wait a moment for Storybook to initialize
85
+ sleep 5
86
+
87
+ # Start Story UI MCP server in background
88
+ echo "🤖 Starting Story UI MCP server on port 4005..."
89
+ npx story-ui start --port 4005 &
90
+ MCP_PID=$!
91
+
92
+ echo ""
93
+ echo "✅ Story UI Live Environment is running!"
94
+ echo " 📖 Storybook: http://localhost:6006"
95
+ echo " 🤖 MCP Server: http://localhost:4005"
96
+ echo " 📡 MCP Endpoint: http://localhost:4005/mcp"
97
+ echo ""
98
+
99
+ # Wait for either process to exit
100
+ wait $STORYBOOK_PID $MCP_PID
101
+ `;
102
+ fs.writeFileSync(startScriptPath, startScript);
103
+ fs.chmodSync(startScriptPath, '755');
104
+ console.log('✅ Created start-production.sh');
105
+ // 3. Create platform-specific config
106
+ switch (platform) {
107
+ case 'railway':
108
+ createRailwayConfig(projectDir);
109
+ break;
110
+ case 'fly':
111
+ createFlyConfig(projectDir);
112
+ break;
113
+ }
114
+ // 4. Create .dockerignore if it doesn't exist
115
+ const dockerignorePath = path.join(projectDir, '.dockerignore');
116
+ if (!fs.existsSync(dockerignorePath)) {
117
+ const dockerignore = `node_modules
118
+ .git
119
+ .gitignore
120
+ *.md
121
+ .DS_Store
122
+ storybook-static
123
+ dist
124
+ .env.local
125
+ `;
126
+ fs.writeFileSync(dockerignorePath, dockerignore);
127
+ console.log('✅ Created .dockerignore');
128
+ }
129
+ // 5. Update package.json to ensure story-ui is a dependency
130
+ const packageJsonPath = path.join(projectDir, 'package.json');
131
+ if (fs.existsSync(packageJsonPath)) {
132
+ const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf-8'));
133
+ // Add story-ui as a dependency if not present
134
+ if (!packageJson.dependencies?.['@tpitre/story-ui'] && !packageJson.devDependencies?.['@tpitre/story-ui']) {
135
+ packageJson.devDependencies = packageJson.devDependencies || {};
136
+ packageJson.devDependencies['@tpitre/story-ui'] = 'latest';
137
+ fs.writeFileSync(packageJsonPath, JSON.stringify(packageJson, null, 2));
138
+ console.log('✅ Added @tpitre/story-ui to package.json');
139
+ }
140
+ }
141
+ }
142
+ function createRailwayConfig(projectDir) {
143
+ const railwayJsonPath = path.join(projectDir, 'railway.json');
144
+ const railwayJson = {
145
+ "$schema": "https://railway.app/railway.schema.json",
146
+ "build": {
147
+ "builder": "DOCKERFILE"
148
+ },
149
+ "deploy": {
150
+ "numReplicas": 1,
151
+ "restartPolicyType": "ON_FAILURE"
152
+ }
153
+ };
154
+ fs.writeFileSync(railwayJsonPath, JSON.stringify(railwayJson, null, 2));
155
+ console.log('✅ Created railway.json');
156
+ // Also create nixpacks.toml as alternative
157
+ const nixpacksPath = path.join(projectDir, 'nixpacks.toml');
158
+ const nixpacks = `[start]
159
+ cmd = "./start-production.sh"
160
+
161
+ [phases.install]
162
+ cmds = ["npm install"]
163
+
164
+ [phases.build]
165
+ cmds = []
166
+ `;
167
+ fs.writeFileSync(nixpacksPath, nixpacks);
168
+ console.log('✅ Created nixpacks.toml (Railway alternative)');
169
+ }
170
+ function createFlyConfig(projectDir) {
171
+ const flyTomlPath = path.join(projectDir, 'fly.toml');
172
+ const projectName = path.basename(projectDir).toLowerCase().replace(/[^a-z0-9-]/g, '-');
173
+ const flyToml = `app = "${projectName}-story-ui"
174
+ primary_region = "sjc"
175
+
176
+ [build]
177
+ dockerfile = "Dockerfile"
178
+
179
+ [[services]]
180
+ internal_port = 6006
181
+ protocol = "tcp"
182
+
183
+ [[services.ports]]
184
+ handlers = ["http"]
185
+ port = 80
186
+
187
+ [[services.ports]]
188
+ handlers = ["tls", "http"]
189
+ port = 443
190
+
191
+ [[services]]
192
+ internal_port = 4005
193
+ protocol = "tcp"
194
+
195
+ [[services.ports]]
196
+ handlers = ["http"]
197
+ port = 4005
198
+
199
+ [env]
200
+ NODE_ENV = "production"
201
+ `;
202
+ fs.writeFileSync(flyTomlPath, flyToml);
203
+ console.log('✅ Created fly.toml');
204
+ }
205
+ /**
206
+ * Deploy live Storybook (dev mode) with MCP server to a cloud platform
207
+ * This is the RECOMMENDED approach for production Story UI deployment
208
+ */
209
+ async function deployLiveStorybook(options) {
210
+ console.log('\n🚀 Story UI Live Deployment');
211
+ console.log('═'.repeat(50));
212
+ console.log('This deploys your Storybook in DEV MODE with the MCP server.');
213
+ console.log('Works with ANY components - exactly like your local environment!\n');
214
+ const projectDir = process.cwd();
215
+ const platform = options.platform || 'railway';
216
+ // Validate project has Storybook
217
+ const packageJsonPath = path.join(projectDir, 'package.json');
218
+ if (!fs.existsSync(packageJsonPath)) {
219
+ console.error('❌ No package.json found. Run this from your Storybook project root.');
220
+ return { storybookUrl: null, mcpUrl: null };
221
+ }
222
+ const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf-8'));
223
+ const hasStorybook = packageJson.devDependencies?.storybook ||
224
+ packageJson.dependencies?.storybook ||
225
+ packageJson.devDependencies?.['@storybook/react'] ||
226
+ packageJson.dependencies?.['@storybook/react'];
227
+ if (!hasStorybook) {
228
+ console.error('❌ No Storybook found in package.json.');
229
+ console.log(' Make sure you have Storybook installed: npx storybook@latest init');
230
+ return { storybookUrl: null, mcpUrl: null };
231
+ }
232
+ // Generate deployment files
233
+ generateLiveDeploymentFiles(projectDir, platform);
234
+ if (options.dryRun) {
235
+ console.log('\n[DRY RUN] Deployment files generated. Would deploy to', platform);
236
+ console.log('[DRY RUN] To deploy manually:');
237
+ switch (platform) {
238
+ case 'railway':
239
+ console.log(' 1. railway login');
240
+ console.log(' 2. railway init');
241
+ console.log(' 3. railway up');
242
+ console.log(' 4. railway domain (to get URL)');
243
+ break;
244
+ case 'fly':
245
+ console.log(' 1. fly auth login');
246
+ console.log(' 2. fly launch');
247
+ console.log(' 3. fly secrets set ANTHROPIC_API_KEY=...');
248
+ console.log(' 4. fly deploy');
249
+ break;
250
+ }
251
+ return { storybookUrl: 'https://dry-run.example.com', mcpUrl: 'https://dry-run.example.com:4005/mcp' };
252
+ }
253
+ // Actually deploy based on platform
254
+ console.log(`\n☁️ Deploying to ${platform}...`);
255
+ switch (platform) {
256
+ case 'railway':
257
+ return await deployLiveToRailway(projectDir);
258
+ case 'fly':
259
+ return await deployLiveToFly(projectDir);
260
+ default:
261
+ console.error(`❌ Unknown platform: ${platform}`);
262
+ return { storybookUrl: null, mcpUrl: null };
263
+ }
264
+ }
265
+ async function deployLiveToRailway(projectDir) {
266
+ console.log('\n🚂 Deploying to Railway...\n');
267
+ if (!isToolInstalled('railway')) {
268
+ console.log('📦 Railway CLI not found. Installing...');
269
+ try {
270
+ execSync('npm install -g @railway/cli', { stdio: 'inherit' });
271
+ }
272
+ catch {
273
+ console.error('❌ Failed to install Railway CLI');
274
+ console.log(' Install manually: npm install -g @railway/cli');
275
+ return { storybookUrl: null, mcpUrl: null };
276
+ }
277
+ }
278
+ // Check if logged in
279
+ try {
280
+ execSync('railway whoami', { stdio: 'pipe' });
281
+ }
282
+ catch {
283
+ console.log('🔐 Not logged into Railway. Please login:');
284
+ execSync('railway login', { stdio: 'inherit' });
285
+ }
286
+ try {
287
+ // Check if project is linked
288
+ try {
289
+ execSync('railway status', { cwd: projectDir, stdio: 'pipe' });
290
+ console.log('✅ Railway project already linked');
291
+ }
292
+ catch {
293
+ console.log('📁 Creating new Railway project...');
294
+ execSync('railway init', { cwd: projectDir, stdio: 'inherit' });
295
+ }
296
+ // Set environment variables reminder
297
+ console.log('\n⚠️ Remember to set your API keys in Railway dashboard:');
298
+ console.log(' railway variables set ANTHROPIC_API_KEY=your-key');
299
+ console.log(' (or OPENAI_API_KEY, GEMINI_API_KEY)\n');
300
+ // Deploy
301
+ console.log('🚀 Deploying to Railway...');
302
+ const result = execSync('railway up --detach 2>&1', {
303
+ cwd: projectDir,
304
+ encoding: 'utf-8'
305
+ });
306
+ console.log(result);
307
+ // Get the deployment URL
308
+ console.log('\n📋 Getting deployment URL...');
309
+ try {
310
+ const urlResult = execSync('railway domain 2>&1', {
311
+ cwd: projectDir,
312
+ encoding: 'utf-8'
313
+ }).trim();
314
+ if (urlResult && !urlResult.includes('No domain')) {
315
+ const storybookUrl = `https://${urlResult}`;
316
+ const mcpUrl = `https://${urlResult}:4005/mcp`;
317
+ console.log(`\n✅ Deployment successful!`);
318
+ console.log(` 📖 Storybook: ${storybookUrl}`);
319
+ console.log(` 🤖 MCP Server: ${mcpUrl}`);
320
+ return { storybookUrl, mcpUrl };
321
+ }
322
+ }
323
+ catch {
324
+ console.log('⚠️ Could not get domain automatically.');
325
+ }
326
+ // Try to generate a domain
327
+ console.log('🌐 Generating Railway domain...');
328
+ execSync('railway domain', { cwd: projectDir, stdio: 'inherit' });
329
+ console.log('\n✅ Deployment submitted!');
330
+ console.log(' Run "railway domain" to get your deployment URL.');
331
+ return { storybookUrl: null, mcpUrl: null };
332
+ }
333
+ catch (error) {
334
+ console.error('❌ Railway deployment failed:', error.message);
335
+ return { storybookUrl: null, mcpUrl: null };
336
+ }
337
+ }
338
+ async function deployLiveToFly(projectDir) {
339
+ console.log('\n🪁 Deploying to Fly.io...\n');
340
+ const flyCmd = isToolInstalled('flyctl') ? 'flyctl' : (isToolInstalled('fly') ? 'fly' : null);
341
+ if (!flyCmd) {
342
+ console.log('📦 Fly CLI not found. Installing...');
343
+ try {
344
+ execSync('curl -L https://fly.io/install.sh | sh', { stdio: 'inherit' });
345
+ }
346
+ catch {
347
+ console.error('❌ Failed to install Fly CLI');
348
+ console.log(' Install manually: https://fly.io/docs/hands-on/install-flyctl/');
349
+ return { storybookUrl: null, mcpUrl: null };
350
+ }
351
+ }
352
+ const cmd = flyCmd || 'fly';
353
+ try {
354
+ // Check if logged in
355
+ try {
356
+ execSync(`${cmd} auth whoami`, { stdio: 'pipe' });
357
+ }
358
+ catch {
359
+ console.log('🔐 Not logged into Fly.io. Please login:');
360
+ execSync(`${cmd} auth login`, { stdio: 'inherit' });
361
+ }
362
+ // Launch or deploy
363
+ try {
364
+ execSync(`${cmd} status`, { cwd: projectDir, stdio: 'pipe' });
365
+ console.log('🚀 Deploying to existing Fly app...');
366
+ execSync(`${cmd} deploy`, { cwd: projectDir, stdio: 'inherit' });
367
+ }
368
+ catch {
369
+ console.log('📁 Creating new Fly app...');
370
+ execSync(`${cmd} launch --no-deploy`, { cwd: projectDir, stdio: 'inherit' });
371
+ console.log('\n⚠️ Before deploying, set your secrets:');
372
+ console.log(` ${cmd} secrets set ANTHROPIC_API_KEY=your-key`);
373
+ console.log('\n Then run:');
374
+ console.log(` ${cmd} deploy`);
375
+ return { storybookUrl: null, mcpUrl: null };
376
+ }
377
+ // Get URL
378
+ const appName = path.basename(projectDir).toLowerCase().replace(/[^a-z0-9-]/g, '-') + '-story-ui';
379
+ const storybookUrl = `https://${appName}.fly.dev`;
380
+ const mcpUrl = `https://${appName}.fly.dev:4005/mcp`;
381
+ console.log(`\n✅ Deployment successful!`);
382
+ console.log(` 📖 Storybook: ${storybookUrl}`);
383
+ console.log(` 🤖 MCP Server: ${mcpUrl}`);
384
+ return { storybookUrl, mcpUrl };
385
+ }
386
+ catch (error) {
387
+ console.error('❌ Fly.io deployment failed:', error.message);
388
+ return { storybookUrl: null, mcpUrl: null };
389
+ }
390
+ }
37
391
  /**
38
392
  * Deploy backend to Railway
39
393
  */
@@ -116,61 +470,6 @@ async function deployToRailway(dryRun) {
116
470
  return null;
117
471
  }
118
472
  }
119
- /**
120
- * Deploy backend to Render
121
- */
122
- async function deployToRender(dryRun) {
123
- console.log('\n🎨 Deploying backend to Render...\n');
124
- const pkgRoot = getPackageRoot();
125
- // Create render.yaml if it doesn't exist
126
- const renderYamlPath = path.join(pkgRoot, 'render.yaml');
127
- if (!fs.existsSync(renderYamlPath)) {
128
- console.log('📝 Creating render.yaml...');
129
- const renderYaml = `services:
130
- - type: web
131
- name: story-ui-backend
132
- env: node
133
- buildCommand: npm install && npm run build
134
- startCommand: node dist/mcp-server/index.js
135
- healthCheckPath: /story-ui/providers
136
- envVars:
137
- - key: NODE_ENV
138
- value: production
139
- - key: PORT
140
- value: 4001
141
- - key: CLAUDE_API_KEY
142
- sync: false
143
- - key: OPENAI_API_KEY
144
- sync: false
145
- - key: GEMINI_API_KEY
146
- sync: false
147
- `;
148
- fs.writeFileSync(renderYamlPath, renderYaml);
149
- console.log('✅ Created render.yaml');
150
- }
151
- if (dryRun) {
152
- console.log('[DRY RUN] render.yaml created at:', renderYamlPath);
153
- console.log('[DRY RUN] To deploy:');
154
- console.log(' 1. Push this repo to GitHub');
155
- console.log(' 2. Go to https://render.com');
156
- console.log(' 3. Create new Web Service from your repo');
157
- console.log(' 4. Set environment variables');
158
- return 'https://dry-run.onrender.com';
159
- }
160
- console.log('\n📋 Render deployment is Git-based.');
161
- console.log(' To deploy to Render:\n');
162
- console.log(' 1. Push your code to GitHub/GitLab');
163
- console.log(' 2. Go to https://dashboard.render.com');
164
- console.log(' 3. Click "New" → "Web Service"');
165
- console.log(' 4. Connect your repository');
166
- console.log(' 5. Render will auto-detect the render.yaml config');
167
- console.log(' 6. Add your API keys as environment variables:');
168
- console.log(' - CLAUDE_API_KEY');
169
- console.log(' - OPENAI_API_KEY');
170
- console.log(' - GEMINI_API_KEY');
171
- console.log('\n render.yaml has been created in your project root.');
172
- return null;
173
- }
174
473
  /**
175
474
  * Deploy backend to Fly.io
176
475
  */
@@ -334,12 +633,12 @@ async function deployStorybook(backendUrl, storybookDir, projectName, dryRun) {
334
633
  }
335
634
  }
336
635
  /**
337
- * Build and deploy standalone production app (Lovable/Bolt-style)
636
+ * Build and deploy standalone production app
338
637
  * This builds a React app with the user's component library bundled in
339
638
  */
340
639
  async function deployProductionApp(backendUrl, projectName, dryRun) {
341
640
  console.log('\n🚀 Building Standalone Production App...\n');
342
- console.log(' This creates a Lovable/Bolt-style UI with your component library\n');
641
+ console.log(' This creates a standalone web app with your component library\n');
343
642
  const pkgRoot = getPackageRoot();
344
643
  const userCwd = process.cwd();
345
644
  const templateDir = path.join(pkgRoot, 'templates/production-app');
@@ -616,7 +915,7 @@ function printSummary(backendUrl, frontendUrl, appUrl) {
616
915
  }
617
916
  if (appUrl) {
618
917
  console.log(`\n🚀 Production App: ${appUrl}`);
619
- console.log(' This is your Lovable/Bolt-style UI with your component library');
918
+ console.log(' This is your standalone web app with your component library');
620
919
  console.log(' Users can prompt and see live-rendered components!');
621
920
  }
622
921
  if (frontendUrl) {
@@ -660,7 +959,32 @@ export async function deployCommand(options) {
660
959
  await legacyEdgeDeployment(options);
661
960
  return;
662
961
  }
663
- // New recommended deployment flow
962
+ // NEW RECOMMENDED: Live Storybook deployment
963
+ // Runs Storybook in dev mode with MCP server - works with ANY components
964
+ if (options.live) {
965
+ const result = await deployLiveStorybook(options);
966
+ if (result.storybookUrl || result.mcpUrl) {
967
+ console.log('\n' + '═'.repeat(60));
968
+ console.log('📋 LIVE DEPLOYMENT SUMMARY');
969
+ console.log('═'.repeat(60));
970
+ if (result.storybookUrl) {
971
+ console.log(`\n📖 Storybook (Live Dev Mode): ${result.storybookUrl}`);
972
+ console.log(' This runs in dev mode - Story UI can generate & hot-reload stories!');
973
+ }
974
+ if (result.mcpUrl) {
975
+ console.log(`\n🤖 MCP Server: ${result.mcpUrl}`);
976
+ console.log(' Connect Claude Desktop with:');
977
+ console.log(` claude mcp add --transport http story-ui ${result.mcpUrl}`);
978
+ }
979
+ console.log('\n✅ This is the EXACT same experience as local development!');
980
+ console.log(' - Works with ANY components (custom, Tailwind, multiple libraries)');
981
+ console.log(' - Generated stories are hot-reloaded instantly');
982
+ console.log(' - MCP server accessible from anywhere');
983
+ console.log('\n' + '═'.repeat(60));
984
+ }
985
+ return;
986
+ }
987
+ // Legacy deployment flows
664
988
  let backendUrl = options.backendUrl || null;
665
989
  let frontendUrl = null;
666
990
  let appUrl = null;
@@ -671,15 +995,12 @@ export async function deployCommand(options) {
671
995
  case 'railway':
672
996
  backendUrl = await deployToRailway(options.dryRun || false);
673
997
  break;
674
- case 'render':
675
- backendUrl = await deployToRender(options.dryRun || false);
676
- break;
677
998
  case 'fly':
678
999
  backendUrl = await deployToFly(options.dryRun || false);
679
1000
  break;
680
1001
  default:
681
1002
  console.error(`❌ Unknown platform: ${platform}`);
682
- console.log(' Supported platforms: railway, render, fly');
1003
+ console.log(' Supported platforms: railway, fly');
683
1004
  return;
684
1005
  }
685
1006
  if (!backendUrl && !options.dryRun) {
@@ -717,40 +1038,45 @@ export async function deployCommand(options) {
717
1038
  printSummary(backendUrl, frontendUrl, appUrl);
718
1039
  }
719
1040
  // Show help if no flags provided
720
- if (!options.backend && !options.frontend && !options.app && !options.edge && !options.pages && !options.all && !options.init) {
721
- console.log('Story UI Deployment - Deploy your component library as a production app\n');
722
- console.log('RECOMMENDED APPROACH (Lovable/Bolt-style App):');
723
- console.log(''.repeat(50));
724
- console.log(' --backend Deploy MCP server backend');
725
- console.log(' --app Deploy standalone production app (RECOMMENDED)');
726
- console.log(' Builds a Lovable/Bolt-style UI with your components');
727
- console.log(' --platform <name> Backend platform: railway (default), render, fly');
728
- console.log(' --backend-url <url> Use existing backend URL');
729
- console.log(' --project-name <name> Project name prefix (default: story-ui)');
730
- console.log(' --dry-run Show what would be deployed\n');
1041
+ if (!options.backend && !options.frontend && !options.app && !options.live && !options.edge && !options.pages && !options.all && !options.init) {
1042
+ console.log('Story UI Deployment - Deploy your Storybook with AI story generation\n');
1043
+ console.log('═'.repeat(60));
1044
+ console.log(' RECOMMENDED: Live Storybook Deployment');
1045
+ console.log(''.repeat(60));
1046
+ console.log(' --live Deploy Storybook in DEV MODE with MCP server');
1047
+ console.log(' Works with ANY components - exactly like local dev!');
1048
+ console.log(' --platform <name> Platform: railway (default), fly');
1049
+ console.log(' --dry-run Generate deployment files only\n');
731
1050
  console.log('EXAMPLES:');
732
- console.log('─'.repeat(50));
733
- console.log(' # Deploy everything (recommended)');
734
- console.log(' npx story-ui deploy --backend --app\n');
735
- console.log(' # Deploy backend only to Railway');
736
- console.log(' npx story-ui deploy --backend --platform=railway\n');
737
- console.log(' # Deploy app with existing backend');
738
- console.log(' npx story-ui deploy --app --backend-url=https://your-api.railway.app\n');
739
- console.log(' # Custom project name');
740
- console.log(' npx story-ui deploy --backend --app --project-name=my-design-system\n');
741
- console.log('ENVIRONMENT VARIABLES (set on backend platform):');
742
- console.log(''.repeat(50));
743
- console.log(' CLAUDE_API_KEY - Anthropic API key');
744
- console.log(' OPENAI_API_KEY - OpenAI API key');
745
- console.log(' GEMINI_API_KEY - Google Gemini API key');
1051
+ console.log('─'.repeat(60));
1052
+ console.log(' # Deploy your Storybook to Railway (recommended)');
1053
+ console.log(' npx story-ui deploy --live\n');
1054
+ console.log(' # Deploy to Fly.io');
1055
+ console.log(' npx story-ui deploy --live --platform=fly\n');
1056
+ console.log(' # Just generate deployment files (no actual deploy)');
1057
+ console.log(' npx story-ui deploy --live --dry-run\n');
1058
+ console.log('WHY --live IS RECOMMENDED:');
1059
+ console.log(''.repeat(60));
1060
+ console.log(' - Works with ANY components (custom, Tailwind, multiple libraries)');
1061
+ console.log(' - Exactly the same experience as local development');
1062
+ console.log(' - Story UI writes stories to disk, Storybook hot-reloads them');
1063
+ console.log(' - MCP server accessible from Claude Desktop anywhere');
1064
+ console.log(' - No design system lock-in - completely agnostic\n');
1065
+ console.log('ENVIRONMENT VARIABLES (set on your platform):');
1066
+ console.log('─'.repeat(60));
1067
+ console.log(' ANTHROPIC_API_KEY - Claude API key (recommended)');
1068
+ console.log(' OPENAI_API_KEY - OpenAI API key (optional)');
1069
+ console.log(' GEMINI_API_KEY - Google Gemini API key (optional)');
746
1070
  console.log(' (Set at least one of these)\n');
747
- console.log('LEGACY OPTIONS (Storybook-based frontend):');
748
- console.log('─'.repeat(50));
749
- console.log(' --frontend Deploy Storybook frontend (use --app instead)');
750
- console.log(' --storybook-dir <dir> Path to Storybook project\n');
751
- console.log('DEPRECATED OPTIONS (Cloudflare Edge approach):');
752
- console.log(''.repeat(50));
1071
+ console.log('ALTERNATIVE APPROACHES (for specific use cases):');
1072
+ console.log('─'.repeat(60));
1073
+ console.log(' --backend Deploy only the MCP server backend');
1074
+ console.log(' --app Deploy standalone production app (static)');
1075
+ console.log(' --frontend Deploy Storybook static build');
1076
+ console.log(' --backend-url <url> Use existing backend URL\n');
1077
+ console.log('DEPRECATED:');
1078
+ console.log('─'.repeat(60));
753
1079
  console.log(' --init, --edge, --pages, --all');
754
- console.log(' These are deprecated. Use --backend and --app instead.\n');
1080
+ console.log(' These Cloudflare Edge options are deprecated. Use --live instead.\n');
755
1081
  }
756
1082
  }
package/dist/cli/index.js CHANGED
@@ -264,21 +264,23 @@ program
264
264
  });
265
265
  program
266
266
  .command('deploy')
267
- .description('Deploy Story UI to production (backend + standalone app)')
268
- // New recommended approach
269
- .option('--backend', 'Deploy MCP server backend to Railway/Render/Fly.io')
270
- .option('--app', 'Deploy standalone production app (Lovable/Bolt-style with live preview)')
271
- .option('--frontend', 'Deploy Storybook frontend (legacy, use --app instead)')
272
- .option('--platform <platform>', 'Backend platform: railway (default), render, fly', 'railway')
273
- .option('--backend-url <url>', 'Use existing backend URL for app/frontend deployment')
274
- .option('--storybook-dir <dir>', 'Path to Storybook project (for --frontend only)')
267
+ .description('Deploy Story UI to production')
268
+ // RECOMMENDED: Live Storybook deployment
269
+ .option('--live', 'Deploy Storybook in DEV MODE with MCP server (RECOMMENDED)')
270
+ .option('--platform <platform>', 'Platform: railway (default), render, fly', 'railway')
271
+ .option('--dry-run', 'Generate deployment files only, don\'t deploy')
272
+ // Alternative approaches
273
+ .option('--backend', 'Deploy only the MCP server backend')
274
+ .option('--app', 'Deploy standalone production app (static build)')
275
+ .option('--frontend', 'Deploy Storybook static build (legacy)')
276
+ .option('--backend-url <url>', 'Use existing backend URL for app/frontend')
277
+ .option('--storybook-dir <dir>', 'Path to Storybook project')
275
278
  .option('--project-name <name>', 'Project name prefix', 'story-ui')
276
- .option('--dry-run', 'Show what would be deployed without deploying')
277
279
  // Legacy flags (deprecated)
278
- .option('--init', '[DEPRECATED] Initialize deployment templates')
279
- .option('--edge', '[DEPRECATED] Deploy Edge Worker only')
280
- .option('--pages', '[DEPRECATED] Deploy Pages UI only')
281
- .option('--all', '[DEPRECATED] Deploy both Edge Worker and Pages UI')
280
+ .option('--init', '[DEPRECATED] Use --live instead')
281
+ .option('--edge', '[DEPRECATED] Use --live instead')
282
+ .option('--pages', '[DEPRECATED] Use --live instead')
283
+ .option('--all', '[DEPRECATED] Use --live instead')
282
284
  .action(async (options) => {
283
285
  await deployCommand(options);
284
286
  });
@@ -1 +1 @@
1
- {"version":3,"file":"setup.d.ts","sourceRoot":"","sources":["../../cli/setup.ts"],"names":[],"mappings":"AAkCA;;GAEG;AACH,wBAAgB,iCAAiC,SA8ChD;AAiYD,MAAM,WAAW,YAAY;IAC3B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,WAAW,CAAC,EAAE,QAAQ,GAAG,QAAQ,GAAG,QAAQ,CAAC;IAC7C,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAED,wBAAsB,YAAY,CAAC,OAAO,GAAE,YAAiB,iBA2wB5D"}
1
+ {"version":3,"file":"setup.d.ts","sourceRoot":"","sources":["../../cli/setup.ts"],"names":[],"mappings":"AAkCA;;GAEG;AACH,wBAAgB,iCAAiC,SA8ChD;AA2VD,MAAM,WAAW,YAAY;IAC3B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,WAAW,CAAC,EAAE,QAAQ,GAAG,QAAQ,GAAG,QAAQ,CAAC;IAC7C,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAED,wBAAsB,YAAY,CAAC,OAAO,GAAE,YAAiB,iBAwsB5D"}
package/dist/cli/setup.js CHANGED
@@ -87,7 +87,7 @@ function setupStorybookPreview(designSystem) {
87
87
  return;
88
88
  }
89
89
  // Verify required packages are installed before creating preview
90
- if (['antd', 'mantine', 'chakra'].includes(designSystem)) {
90
+ if (['mantine', 'chakra'].includes(designSystem)) {
91
91
  const packageJsonPath = path.join(process.cwd(), 'package.json');
92
92
  if (fs.existsSync(packageJsonPath)) {
93
93
  const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf-8'));
@@ -119,18 +119,6 @@ function setupStorybookPreview(designSystem) {
119
119
  <ChakraProvider value={defaultSystem}>
120
120
  <Story />
121
121
  </ChakraProvider>
122
- )`
123
- },
124
- antd: {
125
- imports: [
126
- "import type { Preview } from '@storybook/react-vite'",
127
- "import { ConfigProvider } from 'antd'",
128
- "import React from 'react'"
129
- ],
130
- decorator: `(Story) => (
131
- <ConfigProvider>
132
- <Story />
133
- </ConfigProvider>
134
122
  )`
135
123
  },
136
124
  mantine: {
@@ -144,18 +132,6 @@ function setupStorybookPreview(designSystem) {
144
132
  <MantineProvider>
145
133
  <Story />
146
134
  </MantineProvider>
147
- )`
148
- },
149
- shadcn: {
150
- imports: [
151
- "import type { Preview } from '@storybook/react-vite'",
152
- "import '../src/index.css'", // or globals.css for Tailwind styles
153
- "import React from 'react'"
154
- ],
155
- decorator: `(Story) => (
156
- <div className="min-h-screen bg-background text-foreground">
157
- <Story />
158
- </div>
159
135
  )`
160
136
  }
161
137
  };
@@ -199,16 +175,16 @@ const LLM_PROVIDERS = {
199
175
  description: 'Recommended - Best for complex reasoning and code quality'
200
176
  },
201
177
  openai: {
202
- name: 'OpenAI (GPT-5)',
178
+ name: 'OpenAI (GPT)',
203
179
  envKey: 'OPENAI_API_KEY',
204
- models: ['gpt-5.1', 'gpt-5-mini', 'gpt-5-nano'],
180
+ models: ['gpt-5.1', 'gpt-5.1-thinking', 'gpt-4o', 'gpt-4o-mini'],
205
181
  docsUrl: 'https://platform.openai.com/api-keys',
206
182
  description: 'Versatile and fast'
207
183
  },
208
184
  gemini: {
209
185
  name: 'Google Gemini',
210
186
  envKey: 'GEMINI_API_KEY',
211
- models: ['gemini-3-pro-preview', 'gemini-2.5-pro', 'gemini-2.5-flash'],
187
+ models: ['gemini-3-pro', 'gemini-2.0-flash-exp', 'gemini-2.0-flash', 'gemini-1.5-pro'],
212
188
  docsUrl: 'https://aistudio.google.com/app/apikey',
213
189
  description: 'Cost-effective with good performance'
214
190
  }
@@ -216,13 +192,6 @@ const LLM_PROVIDERS = {
216
192
  // Design system installation configurations (organized by framework)
217
193
  const DESIGN_SYSTEM_CONFIGS = {
218
194
  // React design systems
219
- antd: {
220
- packages: ['antd'],
221
- name: 'Ant Design',
222
- importPath: 'antd',
223
- additionalSetup: 'import "antd/dist/reset.css";',
224
- framework: 'react'
225
- },
226
195
  mantine: {
227
196
  packages: ['@mantine/core', '@mantine/hooks', '@mantine/notifications'],
228
197
  name: 'Mantine',
@@ -244,13 +213,6 @@ const DESIGN_SYSTEM_CONFIGS = {
244
213
  additionalSetup: 'import { ThemeProvider } from "@mui/material/styles";',
245
214
  framework: 'react'
246
215
  },
247
- shadcn: {
248
- packages: ['class-variance-authority', 'clsx', 'tailwind-merge', '@radix-ui/react-slot', 'lucide-react'],
249
- name: 'shadcn/ui',
250
- importPath: '@/components/ui',
251
- additionalSetup: '// shadcn/ui components are locally installed. Run: npx shadcn@latest init',
252
- framework: 'react'
253
- },
254
216
  // Angular design systems
255
217
  'angular-material': {
256
218
  packages: ['@angular/material', '@angular/cdk'],
@@ -541,10 +503,13 @@ export async function setupCommand(options = {}) {
541
503
  return [
542
504
  baseChoice,
543
505
  { name: '🎯 Mantine (@mantine/core) - Most Popular', value: 'mantine' },
506
+ { name: '⚡ Chakra UI (@chakra-ui/react)', value: 'chakra' },
507
+ { name: '🎨 Material UI (@mui/material)', value: 'mui' },
544
508
  customChoice
545
509
  ];
546
510
  }
547
511
  };
512
+ ;
548
513
  // Non-interactive mode: build answers from CLI options
549
514
  let answers;
550
515
  if (options.yes || options.designSystem) {
@@ -767,31 +732,6 @@ export async function setupCommand(options = {}) {
767
732
  }
768
733
  };
769
734
  }
770
- else if (answers.designSystem === 'antd') {
771
- config = {
772
- importPath: 'antd',
773
- componentPrefix: '',
774
- layoutRules: {
775
- multiColumnWrapper: 'Row',
776
- columnComponent: 'Col',
777
- containerComponent: 'div',
778
- layoutExamples: {
779
- twoColumn: `<Row gutter={16}>
780
- <Col span={12}>
781
- <Card title="Left Card" bordered={false}>
782
- <p>Left content goes here</p>
783
- </Card>
784
- </Col>
785
- <Col span={12}>
786
- <Card title="Right Card" bordered={false}>
787
- <p>Right content goes here</p>
788
- </Card>
789
- </Col>
790
- </Row>`
791
- }
792
- }
793
- };
794
- }
795
735
  else if (answers.designSystem === 'mantine') {
796
736
  config = {
797
737
  importPath: '@mantine/core',
@@ -823,52 +763,6 @@ export async function setupCommand(options = {}) {
823
763
  }
824
764
  };
825
765
  }
826
- else if (answers.designSystem === 'shadcn') {
827
- config = {
828
- importPath: '@/components/ui',
829
- componentPrefix: '',
830
- layoutRules: {
831
- multiColumnWrapper: 'div',
832
- columnComponent: 'div',
833
- containerComponent: 'div',
834
- layoutExamples: {
835
- twoColumn: `<div className="grid grid-cols-2 gap-4">
836
- <Card>
837
- <CardHeader>
838
- <CardTitle>Left Card</CardTitle>
839
- </CardHeader>
840
- <CardContent>
841
- <p className="text-sm text-muted-foreground">
842
- Left content goes here
843
- </p>
844
- </CardContent>
845
- </Card>
846
- <Card>
847
- <CardHeader>
848
- <CardTitle>Right Card</CardTitle>
849
- </CardHeader>
850
- <CardContent>
851
- <p className="text-sm text-muted-foreground">
852
- Right content goes here
853
- </p>
854
- </CardContent>
855
- </Card>
856
- </div>`
857
- }
858
- },
859
- designSystemGuidelines: {
860
- name: 'shadcn/ui',
861
- additionalNotes: `
862
- shadcn/ui components are locally installed in the project.
863
- - Import components from "@/components/ui" (e.g., import { Button } from "@/components/ui/button")
864
- - Use the cn() utility from "@/lib/utils" for conditional classes
865
- - Components use Tailwind CSS for styling
866
- - Use CSS variables for theming (--primary, --secondary, --muted, etc.)
867
- - Prefer composition over configuration
868
- `.trim()
869
- }
870
- };
871
- }
872
766
  else if (answers.designSystem === 'mui') {
873
767
  config = {
874
768
  importPath: '@mui/material',
@@ -18,7 +18,7 @@ import { logger } from '../logger.js';
18
18
  */
19
19
  export function loadSettingsConfig() {
20
20
  const defaultProvider = process.env.DEFAULT_PROVIDER || 'claude';
21
- const defaultModel = process.env.DEFAULT_MODEL || 'claude-sonnet-4-5-20250929';
21
+ const defaultModel = process.env.DEFAULT_MODEL || 'claude-opus-4-5-20251101';
22
22
  // Parse allowed providers
23
23
  const allowedProvidersEnv = process.env.ALLOWED_PROVIDERS;
24
24
  const allowedProviders = allowedProvidersEnv
@@ -79,14 +79,14 @@ export function getAvailableModels(provider, config) {
79
79
  // Mark recommended models based on capabilities
80
80
  const recommendedModels = [
81
81
  // Claude
82
+ 'claude-opus-4-5-20251101', // Claude Opus 4.5 - flagship
82
83
  'claude-sonnet-4-5-20250929',
83
- 'claude-opus-4-5-20251101',
84
84
  // OpenAI
85
- 'gpt-5.1',
85
+ 'gpt-5.1', // GPT-5.1 - flagship
86
86
  'gpt-4o',
87
87
  // Gemini
88
+ 'gemini-3-pro-preview', // Gemini 3 Pro Preview - flagship
88
89
  'gemini-3-pro',
89
- 'gemini-2.0-flash',
90
90
  ];
91
91
  return filteredModels.map((model) => ({
92
92
  id: model.id,
@@ -1 +1 @@
1
- {"version":3,"file":"productionGitignoreManager.d.ts","sourceRoot":"","sources":["../../story-generator/productionGitignoreManager.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAEtD;;GAEG;AACH,qBAAa,0BAA0B;IACrC,OAAO,CAAC,MAAM,CAAgB;IAC9B,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,YAAY,CAAU;gBAElB,MAAM,EAAE,aAAa,EAAE,WAAW,GAAE,MAAsB;IAMtE;;OAEG;IACH,OAAO,CAAC,2BAA2B;IAgBnC;;OAEG;IACH,OAAO,CAAC,qBAAqB;IAW7B;;OAEG;IACH,yBAAyB,IAAI,IAAI;IAQjC;;OAEG;IACH,OAAO,CAAC,2BAA2B;IAUnC;;OAEG;IACH,OAAO,CAAC,4BAA4B;IAQpC;;OAEG;IACH,OAAO,CAAC,uBAAuB;IAmB/B;;OAEG;IACH,OAAO,CAAC,uBAAuB;IAY/B;;OAEG;IACH,0BAA0B,IAAI,MAAM;IAuBpC;;OAEG;IACH,OAAO,CAAC,8BAA8B;IAStC;;OAEG;IACH,OAAO,CAAC,+BAA+B;IA0BvC;;OAEG;IACH,OAAO,CAAC,wBAAwB;IAmBhC;;OAEG;IACH,OAAO,CAAC,eAAe;IAMvB;;OAEG;IACH,OAAO,CAAC,aAAa;IAkBrB;;OAEG;IACH,OAAO,CAAC,aAAa;IAWrB;;OAEG;IACH,OAAO,CAAC,wBAAwB;IAOhC;;OAEG;IACH,OAAO,CAAC,8BAA8B;IAyCtC;;OAEG;IACH,iBAAiB,CAAC,MAAM,GAAE,MAAgC,GAAG,IAAI;IAoCjE;;OAEG;IACH,sBAAsB,IAAI,MAAM;IAYhC;;OAEG;IACH,gBAAgB,IAAI,OAAO;CAG5B;AAED;;GAEG;AACH,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,aAAa,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,0BAA0B,CAIhH"}
1
+ {"version":3,"file":"productionGitignoreManager.d.ts","sourceRoot":"","sources":["../../story-generator/productionGitignoreManager.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAEtD;;GAEG;AACH,qBAAa,0BAA0B;IACrC,OAAO,CAAC,MAAM,CAAgB;IAC9B,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,YAAY,CAAU;gBAElB,MAAM,EAAE,aAAa,EAAE,WAAW,GAAE,MAAsB;IAMtE;;OAEG;IACH,OAAO,CAAC,2BAA2B;IAuBnC;;OAEG;IACH,OAAO,CAAC,qBAAqB;IAW7B;;OAEG;IACH,yBAAyB,IAAI,IAAI;IAQjC;;OAEG;IACH,OAAO,CAAC,2BAA2B;IAUnC;;OAEG;IACH,OAAO,CAAC,4BAA4B;IAQpC;;OAEG;IACH,OAAO,CAAC,uBAAuB;IAmB/B;;OAEG;IACH,OAAO,CAAC,uBAAuB;IAY/B;;OAEG;IACH,0BAA0B,IAAI,MAAM;IAuBpC;;OAEG;IACH,OAAO,CAAC,8BAA8B;IAStC;;OAEG;IACH,OAAO,CAAC,+BAA+B;IA0BvC;;OAEG;IACH,OAAO,CAAC,wBAAwB;IAmBhC;;OAEG;IACH,OAAO,CAAC,eAAe;IAMvB;;OAEG;IACH,OAAO,CAAC,aAAa;IAkBrB;;OAEG;IACH,OAAO,CAAC,aAAa;IAWrB;;OAEG;IACH,OAAO,CAAC,wBAAwB;IAOhC;;OAEG;IACH,OAAO,CAAC,8BAA8B;IAyCtC;;OAEG;IACH,iBAAiB,CAAC,MAAM,GAAE,MAAgC,GAAG,IAAI;IAoCjE;;OAEG;IACH,sBAAsB,IAAI,MAAM;IAYhC;;OAEG;IACH,gBAAgB,IAAI,OAAO;CAG5B;AAED;;GAEG;AACH,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,aAAa,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,0BAA0B,CAIhH"}
@@ -14,6 +14,12 @@ export class ProductionGitignoreManager {
14
14
  * Detects if we're running in a production/read-only environment
15
15
  */
16
16
  detectProductionEnvironment() {
17
+ // Explicit override: Force development mode for file-based story generation
18
+ // Use this on Railway/Render when running Storybook dev mode
19
+ if (process.env.STORY_UI_DEV_MODE === 'true') {
20
+ logger.log('📁 STORY_UI_DEV_MODE=true - forcing file-based story generation');
21
+ return false;
22
+ }
17
23
  // Check common production environment indicators
18
24
  const prodIndicators = [
19
25
  process.env.NODE_ENV === 'production',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tpitre/story-ui",
3
- "version": "2.7.0",
3
+ "version": "2.8.0",
4
4
  "description": "AI-powered Storybook story generator with dynamic component discovery",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",