@invisibleloop/pulse 0.2.8 → 0.2.10
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/CLAUDE.md +2 -0
- package/docs/src/pages/performance.js +1 -0
- package/package.json +1 -1
- package/public/.pulse-ui-version +1 -1
- package/src/agent/commands/pulse-build.md +7 -0
- package/src/agent/commands/pulse-dev.md +7 -0
- package/src/agent/commands/pulse-start.md +9 -0
- package/src/agent/commands/pulse-stop.md +5 -0
- package/src/cli/dev.js +10 -0
- package/src/cli/index.js +14 -3
- package/src/cli/scaffold.js +9 -0
package/CLAUDE.md
CHANGED
|
@@ -454,3 +454,5 @@ First-visit JS = runtime chunk (~3.8 kB) + per-page boot file (~0.4–0.9 kB). O
|
|
|
454
454
|
Lighthouse: 100/100/100 (Accessibility / Best Practices / SEO) on both pages.
|
|
455
455
|
|
|
456
456
|
LCP is fast by design (streaming SSR sends HTML before data resolves) but actual millisecond values depend on machine speed, browser, network conditions, and server location — do not quote specific numbers.
|
|
457
|
+
|
|
458
|
+
**Caveat — third-party ads:** Pages that load ad network scripts will not achieve 100 across all categories. Ad scripts introduce render-blocking JS, third-party cookies (Best Practices), and late-loading content that causes CLS. Reserving fixed space for ad slots reduces CLS but cannot fully compensate for what ad networks inject at runtime. Treat 100/100/100 as the baseline for ad-free pages only.
|
|
@@ -34,6 +34,7 @@ export default {
|
|
|
34
34
|
]
|
|
35
35
|
)}
|
|
36
36
|
${callout('note', 'Run <code>mcp__chrome-devtools__lighthouse_audit</code> after every new page to verify all four scores are 100. Fix any failures before considering the task done.')}
|
|
37
|
+
${callout('warning', '<strong>Third-party ads caveat:</strong> Pages that load ad network scripts will not achieve 100 across all categories. Ad scripts introduce render-blocking JS, third-party cookies (Best Practices), and late-loading content that causes CLS. Reserving fixed space for ad slots reduces CLS but cannot fully compensate for what ad networks inject at runtime. Treat 100/100/100 as the baseline for ad-free pages only.')}
|
|
37
38
|
|
|
38
39
|
${section('streaming-ssr', 'Streaming SSR')}
|
|
39
40
|
<p>Pulse uses Node.js streams for SSR. The server sends the <code><head></code> and page shell immediately, before any async data resolves. Browsers start downloading CSS and fonts while the server fetches data — so the user sees a styled shell within milliseconds.</p>
|
package/package.json
CHANGED
package/public/.pulse-ui-version
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
0.2.
|
|
1
|
+
0.2.10
|
package/src/cli/dev.js
CHANGED
|
@@ -71,6 +71,16 @@ const PUBLIC_DIR = path.join(ROOT, 'public')
|
|
|
71
71
|
fs.copyFileSync(checklistSrc, checklistDst)
|
|
72
72
|
}
|
|
73
73
|
|
|
74
|
+
// Sync slash commands into .claude/commands/ so /pulse-dev etc. always exist
|
|
75
|
+
const commandsSrc = new URL('../agent/commands', import.meta.url).pathname
|
|
76
|
+
const commandsDst = path.join(ROOT, '.claude', 'commands')
|
|
77
|
+
if (fs.existsSync(commandsSrc)) {
|
|
78
|
+
fs.mkdirSync(commandsDst, { recursive: true })
|
|
79
|
+
for (const file of fs.readdirSync(commandsSrc).filter(f => f.endsWith('.md'))) {
|
|
80
|
+
fs.copyFileSync(path.join(commandsSrc, file), path.join(commandsDst, file))
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
74
84
|
console.log(` ✓ pulse-ui assets synced (v${pkgVersion})\n`)
|
|
75
85
|
})()
|
|
76
86
|
|
package/src/cli/index.js
CHANGED
|
@@ -289,7 +289,7 @@ async function runUpdate(root) {
|
|
|
289
289
|
const dst = path.join(publicDir, asset)
|
|
290
290
|
if (!fs.existsSync(src)) { missing.push(asset); continue }
|
|
291
291
|
fs.copyFileSync(src, dst)
|
|
292
|
-
updated.push(asset)
|
|
292
|
+
updated.push(`public/${asset}`)
|
|
293
293
|
}
|
|
294
294
|
|
|
295
295
|
// Sync agent checklist into .claude/
|
|
@@ -301,12 +301,23 @@ async function runUpdate(root) {
|
|
|
301
301
|
updated.push('.claude/pulse-checklist.md')
|
|
302
302
|
}
|
|
303
303
|
|
|
304
|
+
// Sync slash commands into .claude/commands/
|
|
305
|
+
const commandsSrc = new URL('../agent/commands', import.meta.url).pathname
|
|
306
|
+
const commandsDst = path.join(root, '.claude', 'commands')
|
|
307
|
+
if (fs.existsSync(commandsSrc)) {
|
|
308
|
+
fs.mkdirSync(commandsDst, { recursive: true })
|
|
309
|
+
for (const file of fs.readdirSync(commandsSrc).filter(f => f.endsWith('.md'))) {
|
|
310
|
+
fs.copyFileSync(path.join(commandsSrc, file), path.join(commandsDst, file))
|
|
311
|
+
updated.push(`.claude/commands/${file}`)
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
|
|
304
315
|
// Read the new version for the success message
|
|
305
316
|
const versionFile = path.join(publicDir, '.pulse-ui-version')
|
|
306
317
|
const version = fs.existsSync(versionFile) ? fs.readFileSync(versionFile, 'utf8').trim() : '?'
|
|
307
318
|
|
|
308
|
-
console.log(`\n⚡ Pulse
|
|
309
|
-
for (const f of updated) console.log(` ✓
|
|
319
|
+
console.log(`\n⚡ Pulse updated to ${version}\n`)
|
|
320
|
+
for (const f of updated) console.log(` ✓ ${f}`)
|
|
310
321
|
for (const f of missing) console.log(` ✗ ${f} not found in package`)
|
|
311
322
|
console.log()
|
|
312
323
|
}
|
package/src/cli/scaffold.js
CHANGED
|
@@ -85,6 +85,14 @@ ${port !== 3000 ? ` port: ${port},\n` : ''}}
|
|
|
85
85
|
// CLAUDE.md — in .claude/ so it's alongside Claude Code's own config, not cluttering the project root
|
|
86
86
|
write(targetDir, '.claude/CLAUDE.md', claudeMd(name))
|
|
87
87
|
|
|
88
|
+
// Slash commands — copied from src/agent/commands/ so scaffold and dev sync stay in lock-step
|
|
89
|
+
const commandsSrc = new URL('../agent/commands', import.meta.url).pathname
|
|
90
|
+
if (fs.existsSync(commandsSrc)) {
|
|
91
|
+
for (const file of fs.readdirSync(commandsSrc).filter(f => f.endsWith('.md'))) {
|
|
92
|
+
write(targetDir, `.claude/commands/${file}`, fs.readFileSync(path.join(commandsSrc, file), 'utf8'))
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
88
96
|
// settings.json — hooks that enforce correct agent behaviour
|
|
89
97
|
write(targetDir, '.claude/settings.json', JSON.stringify({
|
|
90
98
|
hooks: {
|
|
@@ -408,3 +416,4 @@ function write(dir, relPath, content) {
|
|
|
408
416
|
fs.mkdirSync(path.dirname(filePath), { recursive: true })
|
|
409
417
|
fs.writeFileSync(filePath, content, 'utf8')
|
|
410
418
|
}
|
|
419
|
+
|