create-claudeportal 0.1.0 → 0.2.1

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/dist/index.html CHANGED
@@ -4,8 +4,8 @@
4
4
  <meta charset="UTF-8" />
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
6
  <title>Claude Portal</title>
7
- <script type="module" crossorigin src="/assets/index-BBU5K5iA.js"></script>
8
- <link rel="stylesheet" crossorigin href="/assets/index-fNmv07eE.css">
7
+ <script type="module" crossorigin src="/assets/index-DT9wvgYq.js"></script>
8
+ <link rel="stylesheet" crossorigin href="/assets/index-BG0yZd9Y.css">
9
9
  </head>
10
10
  <body>
11
11
  <div id="root"></div>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-claudeportal",
3
- "version": "0.1.0",
3
+ "version": "0.2.1",
4
4
  "description": "Get from npx to a working app in under 5 minutes — Claude Code setup wizard",
5
5
  "bin": {
6
6
  "create-claudeportal": "bin/cli.js"
package/server/index.js CHANGED
@@ -18,6 +18,7 @@ const { createEventsRouter } = require('./routes/events')
18
18
  const { validateProjectPath } = require('./lib/validate-path')
19
19
  const folderRoutes = require('./routes/folder')
20
20
  const { createDocEventsRouter } = require('./routes/doc-events')
21
+ const { createPreviewProxy } = require('./routes/preview-proxy')
21
22
 
22
23
  function startServer(port) {
23
24
  return new Promise((resolve) => {
@@ -112,6 +113,9 @@ function startServer(port) {
112
113
  app.use('/api', folderRoutes)
113
114
  app.use('/api', createDocEventsRouter(sseManager))
114
115
 
116
+ // Preview proxy — captures browser console errors and feeds them to terminal
117
+ app.use('/api', createPreviewProxy(() => activePty))
118
+
115
119
  // Serve project files for live preview
116
120
  app.use('/preview', (req, res) => {
117
121
  const projectPath = validateProjectPath(req.query.projectPath) || path.join(os.homedir(), 'Claude')
@@ -0,0 +1,61 @@
1
+ const { execSync } = require('child_process')
2
+
3
+ function checkCli(command, parseOutput) {
4
+ try {
5
+ const output = execSync(command, { timeout: 10000, encoding: 'utf8', stdio: ['pipe', 'pipe', 'pipe'] }).trim()
6
+ return parseOutput(output)
7
+ } catch {
8
+ return { connected: false, detail: 'Not installed' }
9
+ }
10
+ }
11
+
12
+ function checkCLIs() {
13
+ const results = []
14
+
15
+ // GitHub CLI
16
+ results.push({
17
+ id: 'github',
18
+ label: 'GitHub',
19
+ ...checkCli('gh auth status 2>&1', (output) => {
20
+ if (output.includes('Logged in to')) {
21
+ const match = output.match(/Logged in to ([^\s]+) as ([^\s]+)/)
22
+ return {
23
+ connected: true,
24
+ detail: match ? `${match[2]}` : 'Connected',
25
+ }
26
+ }
27
+ return { connected: false, detail: 'Not authenticated — run: gh auth login' }
28
+ }),
29
+ })
30
+
31
+ // Vercel CLI
32
+ results.push({
33
+ id: 'vercel',
34
+ label: 'Vercel',
35
+ ...checkCli('vercel whoami 2>&1', (output) => {
36
+ if (output && !output.includes('Error') && !output.includes('not logged in')) {
37
+ return { connected: true, detail: output.split('\n').pop().trim() }
38
+ }
39
+ return { connected: false, detail: 'Not authenticated — run: vercel login' }
40
+ }),
41
+ })
42
+
43
+ // Supabase CLI
44
+ results.push({
45
+ id: 'supabase',
46
+ label: 'Supabase',
47
+ ...checkCli('supabase projects list 2>&1', (output) => {
48
+ if (output.includes('ID') || output.includes('│')) {
49
+ return { connected: true, detail: 'Connected' }
50
+ }
51
+ if (output.includes('not logged in') || output.includes('access token')) {
52
+ return { connected: false, detail: 'Not authenticated — run: supabase login' }
53
+ }
54
+ return { connected: false, detail: 'Not installed — run: brew install supabase/tap/supabase' }
55
+ }),
56
+ })
57
+
58
+ return results
59
+ }
60
+
61
+ module.exports = { checkCLIs }
@@ -44,10 +44,58 @@ async function installTool(toolId, onProgress) {
44
44
  }
45
45
 
46
46
  async function installViaNpm(packageName, onProgress) {
47
+ const os = require('os')
48
+ const path = require('path')
49
+ const fs = require('fs')
50
+
51
+ // Check if npm prefix needs fixing (avoid /usr/local which requires sudo)
52
+ let npmArgs = ['install', '-g', packageName]
53
+ try {
54
+ const { execSync } = require('child_process')
55
+ const currentPrefix = execSync('npm config get prefix', {
56
+ encoding: 'utf8',
57
+ timeout: 5000,
58
+ env: { ...process.env, PATH: getExpandedPath() },
59
+ }).trim()
60
+
61
+ if (currentPrefix === '/usr/local') {
62
+ // Use a user-owned prefix instead
63
+ const userPrefix = path.join(os.homedir(), '.npm-global')
64
+ fs.mkdirSync(path.join(userPrefix, 'bin'), { recursive: true })
65
+ fs.mkdirSync(path.join(userPrefix, 'lib'), { recursive: true })
66
+ npmArgs = ['install', '-g', '--prefix', userPrefix, packageName]
67
+ onProgress(`Using ${userPrefix} to avoid permission issues...`)
68
+
69
+ // Also persist the config for future installs
70
+ try {
71
+ execSync(`npm config set prefix "${userPrefix}"`, {
72
+ timeout: 5000,
73
+ env: { ...process.env, PATH: getExpandedPath() },
74
+ })
75
+ } catch {}
76
+
77
+ // Add to PATH for this process
78
+ const binDir = path.join(userPrefix, 'bin')
79
+ if (!process.env.PATH.includes(binDir)) {
80
+ process.env.PATH = `${binDir}:${process.env.PATH}`
81
+ }
82
+
83
+ // Add to .zshrc if not already there
84
+ const zshrc = path.join(os.homedir(), '.zshrc')
85
+ const pathLine = `export PATH="$HOME/.npm-global/bin:$PATH"`
86
+ try {
87
+ const existing = fs.existsSync(zshrc) ? fs.readFileSync(zshrc, 'utf8') : ''
88
+ if (!existing.includes('.npm-global')) {
89
+ fs.appendFileSync(zshrc, `\n# Added by Claude Portal\n${pathLine}\n`)
90
+ }
91
+ } catch {}
92
+ }
93
+ } catch {}
94
+
47
95
  onProgress(`Installing ${packageName} via npm...`)
48
96
 
49
97
  return new Promise((resolve) => {
50
- const child = spawn('npm', ['install', '-g', packageName], {
98
+ const child = spawn('npm', npmArgs, {
51
99
  env: { ...process.env, PATH: getExpandedPath() },
52
100
  stdio: ['pipe', 'pipe', 'pipe'],
53
101
  timeout: 120000,
@@ -0,0 +1,217 @@
1
+ const fs = require('fs')
2
+ const path = require('path')
3
+ const os = require('os')
4
+
5
+ // MCP servers recommended for document mode / work automation
6
+ const RECOMMENDED_MCPS = [
7
+ // Research & Data
8
+ {
9
+ id: 'brave-search',
10
+ name: 'Brave Search',
11
+ description: 'Web search with 2,000 free queries/month',
12
+ installHint: 'claude mcp add brave-search -- npx -y @modelcontextprotocol/server-brave-search',
13
+ usefulFor: ['draft', 'analyse', 'review', 'summarize', 'compare'],
14
+ category: 'research',
15
+ },
16
+ {
17
+ id: 'serper',
18
+ name: 'Serper (Google Search)',
19
+ description: 'Google search results for research and fact-checking',
20
+ installHint: 'claude mcp add serper -- npx -y mcp-server-serper',
21
+ usefulFor: ['draft', 'analyse', 'review', 'summarize', 'extract', 'compare'],
22
+ category: 'research',
23
+ },
24
+ {
25
+ id: 'jina',
26
+ name: 'Jina (Web Reader)',
27
+ description: 'Read web pages, PDFs, and extract content',
28
+ installHint: 'Add via Claude settings → MCP',
29
+ usefulFor: ['draft', 'analyse', 'review', 'summarize', 'extract', 'compare', 'transform'],
30
+ category: 'research',
31
+ },
32
+ {
33
+ id: 'firecrawl',
34
+ name: 'Firecrawl',
35
+ description: 'Turn any website into clean markdown data',
36
+ installHint: 'claude mcp add firecrawl -- npx -y firecrawl-mcp',
37
+ usefulFor: ['extract', 'analyse', 'summarize', 'transform'],
38
+ category: 'research',
39
+ },
40
+ // Design & Build
41
+ {
42
+ id: 'stitch',
43
+ name: 'Google Stitch',
44
+ description: 'AI design-to-code — generate UI from text prompts',
45
+ installHint: 'claude mcp add stitch -- npx -y stitch-mcp',
46
+ usefulFor: ['draft', 'transform'],
47
+ category: 'design',
48
+ },
49
+ {
50
+ id: 'figma',
51
+ name: 'Figma',
52
+ description: 'Read designs, extract specs, generate layers',
53
+ installHint: 'Enable in Figma Dev Mode → MCP settings',
54
+ usefulFor: ['draft', 'extract', 'transform'],
55
+ category: 'design',
56
+ },
57
+ // Productivity & Workspace
58
+ {
59
+ id: 'google-workspace',
60
+ name: 'Google Workspace',
61
+ description: 'Gmail, Calendar, Docs, Sheets, Drive — 100+ tools',
62
+ installHint: 'claude mcp add google-workspace -- npx -y @alanxchen/google-workspace-mcp',
63
+ usefulFor: ['draft', 'summarize', 'extract', 'analyse', 'transform'],
64
+ category: 'workspace',
65
+ },
66
+ {
67
+ id: 'notion',
68
+ name: 'Notion',
69
+ description: 'Read/write pages and query databases',
70
+ installHint: 'Connect via claude.ai settings → MCP',
71
+ usefulFor: ['draft', 'summarize', 'extract', 'transform'],
72
+ category: 'workspace',
73
+ },
74
+ {
75
+ id: 'slack',
76
+ name: 'Slack',
77
+ description: 'Search messages, draft replies, channel summaries',
78
+ installHint: 'claude mcp add slack -- npx -y @anthropic/slack-mcp',
79
+ usefulFor: ['summarize', 'extract', 'draft'],
80
+ category: 'workspace',
81
+ },
82
+ // Automation
83
+ {
84
+ id: 'zapier',
85
+ name: 'Zapier',
86
+ description: 'Connect to 7,000+ apps — automate anything',
87
+ installHint: 'Visit zapier.com/mcp to connect',
88
+ usefulFor: ['draft', 'extract', 'transform'],
89
+ category: 'automation',
90
+ },
91
+ // Meetings & Notes
92
+ {
93
+ id: 'fireflies',
94
+ name: 'Fireflies',
95
+ description: 'Access meeting transcripts and AI summaries',
96
+ installHint: 'claude mcp add fireflies -- npx -y @fireflies-ai/mcp-server',
97
+ usefulFor: ['summarize', 'extract', 'draft', 'analyse'],
98
+ category: 'meetings',
99
+ },
100
+ // Project Management
101
+ {
102
+ id: 'todoist',
103
+ name: 'Todoist',
104
+ description: 'Manage tasks, projects, and deadlines',
105
+ installHint: 'claude mcp add todoist (see pulsemcp.com/servers/todoist)',
106
+ usefulFor: ['extract', 'draft'],
107
+ category: 'projects',
108
+ },
109
+ {
110
+ id: 'linear',
111
+ name: 'Linear',
112
+ description: 'Manage issues, sprints, and backlogs',
113
+ installHint: 'claude mcp add linear -- npx -y @mkusaka/linear-mcp',
114
+ usefulFor: ['extract', 'analyse', 'summarize'],
115
+ category: 'projects',
116
+ },
117
+ // Data & Database
118
+ {
119
+ id: 'supabase',
120
+ name: 'Supabase',
121
+ description: 'Query databases, manage tables, run migrations',
122
+ installHint: 'Add via Claude settings → MCP',
123
+ usefulFor: ['extract', 'analyse', 'transform'],
124
+ category: 'data',
125
+ },
126
+ {
127
+ id: 'postgres',
128
+ name: 'PostgreSQL',
129
+ description: 'Query any Postgres database with natural language',
130
+ installHint: 'claude mcp add postgres -- npx -y @crystaldba/postgres-mcp',
131
+ usefulFor: ['extract', 'analyse'],
132
+ category: 'data',
133
+ },
134
+ // Memory & Thinking
135
+ {
136
+ id: 'memory-keeper',
137
+ name: 'Memory Keeper',
138
+ description: 'Remember context across conversations',
139
+ installHint: 'claude mcp add memory-keeper -- npx -y mcp-memory-keeper',
140
+ usefulFor: ['draft', 'analyse', 'review'],
141
+ category: 'utility',
142
+ },
143
+ {
144
+ id: 'sequential-thinking',
145
+ name: 'Sequential Thinking',
146
+ description: 'Break down complex problems step by step',
147
+ installHint: 'claude mcp add sequential-thinking -- npx -y @modelcontextprotocol/server-sequential-thinking',
148
+ usefulFor: ['analyse', 'review', 'compare'],
149
+ category: 'utility',
150
+ },
151
+ ]
152
+
153
+ const CATEGORY_LABELS = {
154
+ research: 'Research',
155
+ design: 'Design & Build',
156
+ workspace: 'Workspace',
157
+ automation: 'Automation',
158
+ meetings: 'Meetings',
159
+ projects: 'Project Management',
160
+ data: 'Data',
161
+ utility: 'Utilities',
162
+ }
163
+
164
+ function getInstalledMCPs() {
165
+ const configPaths = [
166
+ path.join(os.homedir(), '.claude.json'),
167
+ path.join(os.homedir(), '.claude', 'settings.json'),
168
+ path.join(os.homedir(), '.claude', 'settings.local.json'),
169
+ ]
170
+
171
+ const installed = new Set()
172
+
173
+ for (const configPath of configPaths) {
174
+ try {
175
+ if (!fs.existsSync(configPath)) continue
176
+ const raw = fs.readFileSync(configPath, 'utf8')
177
+ const config = JSON.parse(raw)
178
+ const servers = config.mcpServers || {}
179
+ for (const key of Object.keys(servers)) {
180
+ installed.add(key.toLowerCase())
181
+ }
182
+ // Also check claudeAiMcpEverConnected for claude.ai-connected MCPs
183
+ const connected = config.claudeAiMcpEverConnected || []
184
+ for (const name of connected) {
185
+ installed.add(name.toLowerCase().replace(/^claude\.ai\s+/i, ''))
186
+ }
187
+ } catch {}
188
+ }
189
+
190
+ return installed
191
+ }
192
+
193
+ function checkMCPs(outcomeKey) {
194
+ const installed = getInstalledMCPs()
195
+
196
+ const mcps = RECOMMENDED_MCPS.map(mcp => {
197
+ const isInstalled = installed.has(mcp.id.toLowerCase()) ||
198
+ [...installed].some(k => k.includes(mcp.id.toLowerCase()) || mcp.id.toLowerCase().includes(k))
199
+
200
+ const isRelevant = !outcomeKey || mcp.usefulFor.includes(outcomeKey)
201
+
202
+ return {
203
+ id: mcp.id,
204
+ name: mcp.name,
205
+ description: mcp.description,
206
+ installed: isInstalled,
207
+ relevant: isRelevant,
208
+ category: mcp.category,
209
+ categoryLabel: CATEGORY_LABELS[mcp.category] || mcp.category,
210
+ installHint: isInstalled ? undefined : mcp.installHint,
211
+ }
212
+ })
213
+
214
+ return mcps
215
+ }
216
+
217
+ module.exports = { checkMCPs, CATEGORY_LABELS }
@@ -1,6 +1,8 @@
1
1
  const express = require('express')
2
2
  const { scanProject } = require('../lib/file-scanner')
3
3
  const { validateProjectPath } = require('../lib/validate-path')
4
+ const { checkCLIs } = require('../lib/cli-checker')
5
+ const { checkMCPs } = require('../lib/mcp-checker')
4
6
  const router = express.Router()
5
7
 
6
8
  router.get('/health-scan', (req, res) => {
@@ -13,4 +15,21 @@ router.get('/health-scan', (req, res) => {
13
15
  }
14
16
  })
15
17
 
18
+ router.get('/cli-status', (_req, res) => {
19
+ try {
20
+ res.json({ clis: checkCLIs() })
21
+ } catch (err) {
22
+ res.status(500).json({ error: err.message })
23
+ }
24
+ })
25
+
26
+ router.get('/mcp-status', (req, res) => {
27
+ try {
28
+ const outcome = req.query.outcome || null
29
+ res.json({ mcps: checkMCPs(outcome) })
30
+ } catch (err) {
31
+ res.status(500).json({ error: err.message })
32
+ }
33
+ })
34
+
16
35
  module.exports = router
@@ -18,16 +18,30 @@ router.post('/install/:toolId', async (req, res) => {
18
18
  res.write(`data: ${JSON.stringify(data)}\n\n`)
19
19
  }
20
20
 
21
- send({ tool: toolId, status: 'installing', message: `Installing ${toolId}...` })
21
+ try {
22
+ // Fix npm prefix on Mac to avoid sudo for global installs
23
+ try {
24
+ const prefixResult = fixNpmPrefix()
25
+ if (prefixResult.fixed) {
26
+ send({ tool: toolId, status: 'progress', message: 'npm configured for global installs (no sudo needed)' })
27
+ }
28
+ } catch (prefixErr) {
29
+ send({ tool: toolId, status: 'progress', message: `npm prefix check skipped: ${prefixErr.message}` })
30
+ }
22
31
 
23
- const result = await installTool(toolId, (message) => {
24
- send({ tool: toolId, status: 'progress', message })
25
- })
32
+ send({ tool: toolId, status: 'installing', message: `Installing ${toolId}...` })
33
+
34
+ const result = await installTool(toolId, (message) => {
35
+ send({ tool: toolId, status: 'progress', message })
36
+ })
26
37
 
27
- if (result.success) {
28
- send({ tool: toolId, status: 'done' })
29
- } else {
30
- send({ tool: toolId, status: 'error', error: result.error })
38
+ if (result.success) {
39
+ send({ tool: toolId, status: 'done' })
40
+ } else {
41
+ send({ tool: toolId, status: 'error', error: result.error })
42
+ }
43
+ } catch (err) {
44
+ send({ tool: toolId, status: 'error', error: err.message || 'Unknown error during install' })
31
45
  }
32
46
 
33
47
  send({ status: 'complete' })
@@ -99,4 +113,26 @@ router.post('/install-all', async (req, res) => {
99
113
  res.end()
100
114
  })
101
115
 
116
+ // Launch Claude Code authentication (opens browser)
117
+ router.post('/launch-auth', (req, res) => {
118
+ const { spawn } = require('child_process')
119
+ const { getExpandedPath } = require('../lib/detect-tools')
120
+
121
+ try {
122
+ const child = spawn('claude', ['login'], {
123
+ env: { ...process.env, PATH: getExpandedPath() },
124
+ stdio: ['pipe', 'pipe', 'pipe'],
125
+ timeout: 60000,
126
+ })
127
+
128
+ // Claude login opens a browser — just let it run
129
+ child.on('error', () => {})
130
+ child.unref()
131
+
132
+ res.json({ launched: true })
133
+ } catch {
134
+ res.status(500).json({ error: 'Failed to launch claude login' })
135
+ }
136
+ })
137
+
102
138
  module.exports = router
@@ -0,0 +1,136 @@
1
+ const express = require('express')
2
+ const http = require('http')
3
+
4
+ const router = express.Router()
5
+
6
+ // Script injected into the user's dev server HTML to capture console errors
7
+ const ERROR_CATCHER_SCRIPT = `
8
+ <script data-claude-portal-injected>
9
+ (function() {
10
+ var endpoint = window.location.protocol + '//' + window.location.hostname + ':3456/api/console-errors';
11
+
12
+ function send(payload) {
13
+ try {
14
+ navigator.sendBeacon(endpoint, JSON.stringify(payload));
15
+ } catch(e) {}
16
+ }
17
+
18
+ // Capture console.error
19
+ var origError = console.error;
20
+ console.error = function() {
21
+ var args = Array.from(arguments).map(function(a) {
22
+ try { return typeof a === 'object' ? JSON.stringify(a) : String(a); }
23
+ catch(e) { return String(a); }
24
+ });
25
+ send({ type: 'console.error', message: args.join(' ') });
26
+ origError.apply(console, arguments);
27
+ };
28
+
29
+ // Capture unhandled errors
30
+ window.addEventListener('error', function(e) {
31
+ send({
32
+ type: 'error',
33
+ message: e.message,
34
+ source: e.filename,
35
+ line: e.lineno,
36
+ col: e.colno,
37
+ });
38
+ });
39
+
40
+ // Capture unhandled promise rejections
41
+ window.addEventListener('unhandledrejection', function(e) {
42
+ send({
43
+ type: 'unhandledrejection',
44
+ message: e.reason ? (e.reason.message || String(e.reason)) : 'Unknown rejection',
45
+ });
46
+ });
47
+ })();
48
+ </script>
49
+ `
50
+
51
+ /**
52
+ * Creates the preview proxy routes.
53
+ * @param {Function} getActivePty - returns the active PTY process (or null)
54
+ */
55
+ function createPreviewProxy(getActivePty) {
56
+ // Receive console errors from the injected script and write to terminal
57
+ router.post('/console-errors', express.json(), (req, res) => {
58
+ const { type, message, source, line } = req.body || {}
59
+ if (!message) return res.status(400).end()
60
+
61
+ const pty = getActivePty()
62
+ const location = source ? ` (${source}${line ? ':' + line : ''})` : ''
63
+ const formatted = `\r\n⚠️ Browser ${type}: ${message}${location}\r\n`
64
+
65
+ // Write to terminal so Claude Code can see it
66
+ if (pty) {
67
+ try { pty.write(formatted) } catch {}
68
+ }
69
+
70
+ res.status(204).end()
71
+ })
72
+
73
+ // Proxy dev server and inject error catcher into HTML responses
74
+ router.get('/dev-preview/*', (req, res) => {
75
+ const devPort = req.query.port || '5173'
76
+ const urlPath = req.params[0] || ''
77
+
78
+ const proxyReq = http.request(
79
+ {
80
+ hostname: 'localhost',
81
+ port: parseInt(devPort),
82
+ path: '/' + urlPath,
83
+ method: 'GET',
84
+ headers: {
85
+ ...req.headers,
86
+ host: `localhost:${devPort}`,
87
+ },
88
+ },
89
+ (proxyRes) => {
90
+ const contentType = proxyRes.headers['content-type'] || ''
91
+ const isHtml = contentType.includes('text/html')
92
+
93
+ // Forward non-HTML responses as-is
94
+ if (!isHtml) {
95
+ res.writeHead(proxyRes.statusCode, proxyRes.headers)
96
+ proxyRes.pipe(res)
97
+ return
98
+ }
99
+
100
+ // Buffer HTML response to inject our script
101
+ const chunks = []
102
+ proxyRes.on('data', (chunk) => chunks.push(chunk))
103
+ proxyRes.on('end', () => {
104
+ let html = Buffer.concat(chunks).toString()
105
+
106
+ // Inject before </head> or at start of <body>
107
+ if (html.includes('</head>')) {
108
+ html = html.replace('</head>', ERROR_CATCHER_SCRIPT + '</head>')
109
+ } else if (html.includes('<body')) {
110
+ html = html.replace(/<body([^>]*)>/, `<body$1>${ERROR_CATCHER_SCRIPT}`)
111
+ } else {
112
+ html = ERROR_CATCHER_SCRIPT + html
113
+ }
114
+
115
+ // Update content-length
116
+ const headers = { ...proxyRes.headers }
117
+ delete headers['content-length']
118
+ headers['transfer-encoding'] = 'chunked'
119
+
120
+ res.writeHead(proxyRes.statusCode, headers)
121
+ res.end(html)
122
+ })
123
+ }
124
+ )
125
+
126
+ proxyReq.on('error', () => {
127
+ res.status(502).json({ error: 'Dev server not running' })
128
+ })
129
+
130
+ proxyReq.end()
131
+ })
132
+
133
+ return router
134
+ }
135
+
136
+ module.exports = { createPreviewProxy }
@@ -1 +1 @@
1
- {"root":["./src/app.tsx","./src/main.tsx","./src/components/chat/buildsidebar.tsx","./src/components/checklist/featurebuilder.tsx","./src/components/checklist/healthcheckitem.tsx","./src/components/checklist/healthsection.tsx","./src/components/checklist/prepushsection.tsx","./src/components/checklist/testingsection.tsx","./src/components/document/contextsection.tsx","./src/components/document/docsidebar.tsx","./src/components/document/foldersection.tsx","./src/components/document/outcomesection.tsx","./src/components/document/outputpanel.tsx","./src/components/document/stylereferencesection.tsx","./src/components/layout/checklistdrawer.tsx","./src/components/layout/errorbanner.tsx","./src/components/layout/iconrail.tsx","./src/components/layout/topbar.tsx","./src/components/preview/previewpanel.tsx","./src/components/setup/howitworks.tsx","./src/components/setup/projectselector.tsx","./src/components/setup/setupwizard.tsx","./src/components/setup/tooldetection.tsx","./src/components/setup/toolinstaller.tsx","./src/components/terminal/terminalpanel.tsx","./src/context/docmodecontext.tsx","./src/context/projectcontext.tsx","./src/context/terminalcontext.tsx","./src/hooks/usedocevents.ts","./src/hooks/usehealthscan.ts","./src/hooks/useprojectinfo.ts","./src/hooks/usesse.ts","./src/lib/api.ts","./src/lib/doc-prompts.ts","./src/lib/storage.ts","./src/lib/style-templates.ts","./src/types/doc.ts","./src/types/index.ts"],"version":"5.9.3"}
1
+ {"root":["./src/app.tsx","./src/main.tsx","./src/components/chat/buildsidebar.tsx","./src/components/checklist/clistatussection.tsx","./src/components/checklist/featurebuilder.tsx","./src/components/checklist/futurebuildsection.tsx","./src/components/checklist/healthcheckitem.tsx","./src/components/checklist/healthsection.tsx","./src/components/checklist/prepushsection.tsx","./src/components/checklist/testingsection.tsx","./src/components/document/contextsection.tsx","./src/components/document/docsidebar.tsx","./src/components/document/foldersection.tsx","./src/components/document/mcpsection.tsx","./src/components/document/outcomesection.tsx","./src/components/document/outputpanel.tsx","./src/components/document/stylereferencesection.tsx","./src/components/layout/checklistdrawer.tsx","./src/components/layout/errorbanner.tsx","./src/components/layout/iconrail.tsx","./src/components/layout/topbar.tsx","./src/components/preview/previewpanel.tsx","./src/components/setup/howitworks.tsx","./src/components/setup/projectselector.tsx","./src/components/setup/setupwizard.tsx","./src/components/setup/tooldetection.tsx","./src/components/setup/toolinstaller.tsx","./src/components/terminal/terminalpanel.tsx","./src/context/docmodecontext.tsx","./src/context/projectcontext.tsx","./src/context/terminalcontext.tsx","./src/hooks/usedocevents.ts","./src/hooks/usehealthscan.ts","./src/hooks/useprojectinfo.ts","./src/hooks/usesse.ts","./src/lib/api.ts","./src/lib/doc-prompts.ts","./src/lib/storage.ts","./src/lib/style-templates.ts","./src/types/doc.ts","./src/types/index.ts"],"version":"5.9.3"}