diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..419d8e3 --- /dev/null +++ b/.env.example @@ -0,0 +1,4 @@ +# Optional local-only export targets. +# Leave unset in public CI and ordinary GitHub Pages builds. +STACKSCOUT_PRIVATE_EXPORT_DIR= +STACKSCOUT_PRIVATE_STATUS_DIR= diff --git a/.github/workflows/validate.yml b/.github/workflows/validate.yml new file mode 100644 index 0000000..27d4ace --- /dev/null +++ b/.github/workflows/validate.yml @@ -0,0 +1,22 @@ +name: Validate + +on: + pull_request: + push: + branches: + - main + - design/zine-prototype-2026-05 + workflow_dispatch: + +jobs: + validate: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - uses: actions/setup-node@v4 + with: + node-version: '20' + + - run: npm run build:site + - run: npm run check diff --git a/.gitignore b/.gitignore index 4bfa471..7cc533a 100644 --- a/.gitignore +++ b/.gitignore @@ -1,15 +1,19 @@ # Local planning and working notes .local/ local-hub/ +design/ PLAN.md TODO.local.md TASKS.local.md *.local.md +CLAUDE-HANDOFF-*.md notes-local/ planning-local/ .local-notes/ # Local screenshots and scratch files +.serve.log +.serve.err.log tmp-*.png tmp-*.jpg tmp-*.jpeg diff --git a/DESIGN-2026-05-zine.md b/DESIGN-2026-05-zine.md new file mode 100644 index 0000000..934c166 --- /dev/null +++ b/DESIGN-2026-05-zine.md @@ -0,0 +1,224 @@ +# Stack Scout — Design specification + +**Status:** Round 03 — page-by-page prototype, ready for Claude Code build +**Owner:** Kol +**Designer pass:** Claude (Anthropic) +**Last updated:** 19 May 2026 + +The prototype that this document describes lives at `StackScout Prototype.html` with all components under `wireframes/`. The existing `stackscout/` codebase (vanilla HTML + `styles.css` + `app.js` driven by JSON manifests) is the production target — this design replaces the chrome and IA of that codebase but keeps the shared source layer underneath. + +--- + +## 1. Identity + +| | | +|---|---| +| **Name** | Stack Scout (two words, not "StackScout") | +| **Tagline** | _A field log for the AI stack._ (Used sparingly — not in every header.) | +| **Tone** | Editorial · independent · used-not-listed · sharp without being shouty | +| **Mood** | Dark editorial. Closer to a printed broadsheet at night than a SaaS dashboard. | +| **What it is not** | A directory · an aggregator · "Product Hunt for AI" · ad-funded | + +The page identifies the site to the reader with the wordmark + accent dot in the masthead. No issue numbers in the masthead (these belonged to a previous round and have been removed). The tagline appears only on the Subscribe and Sources pages where it earns its place. + +--- + +## 2. Information architecture + +Top-level navigation, left to right in the masthead: + +| Slug | Label | What it is | +|---|---|---| +| `home` | Home | Front page — cycling lead news, the day's wire, the setlist of upcoming releases, the weekly stance. | +| `releases` | Releases | Every shipping date being tracked. Toggles between **List** view (grouped by window) and **Calendar** view (3-month strip). Filter rail at the top. | +| `wire` | Wire | 48-hour activity stream from primary sources. Filter rail at the top. | +| `list` | Top tools | A short, opinionated ranked list. Curated, not algorithmic. Filtered by editorial verdict. | +| `subscribe` | Subscribe | Email signup + past-issue archive. | + +Footer-only entry point (not in the top nav): + +| `sources` | Sources & method | Where the data comes from + what "Verified / Window / Confirmed / Shipped" mean. | + +### Page-shape contract (non-home pages) + +Every non-home page begins with: + +1. `"]} rightSlot={…}>` — a narrow strip with a breadcrumb on the left and a stat/clock/view-toggle on the right. +2. A 22px-padded filter rail (where relevant). +3. A hairline ``. +4. The content list. + +**Non-home pages do not get a hero block.** The breadcrumb + filter rail is the chrome; the data is the content. (This was a Round 02 mistake — the hero box on Releases and Wire wasted vertical space.) + +--- + +## 3. Visual system + +### 3.1 Palette + +Five **mood** palettes, swap-able from the toolbar in the masthead top-right. The toggle changes only `background` and `accent`. Everything else is fixed across moods so nothing flickers on swap. + +| ID | Name | Background | Accent | Use | +|---|---|---|---|---| +| `graphite` | Graphite | `#14171c` | `#6dbab1` | **Default.** Warm charcoal + dusty teal. | +| `midnight` | Midnight | `#0f1622` | `#7fb8d2` | Cool blue-black + steel. | +| `obsidian` | Obsidian | `#0a0c0f` | `#6dd5b8` | Near-black + mint. Darkest option. | +| `slate` | Slate | `#1a1d22` | `#8ec2a8` | Warm grey + sage. | +| `carbon` | Carbon | `#181b22` | `#88bdd1` | Deep blue-grey + powder blue. | + +Fixed across all moods: + +```css +--ink: #ede5d3; /* cream body text */ +--muted: #7d8086; /* metadata, captions */ +--rule: rgba(237,229,211,0.18); /* dashed hairlines */ +--rule-strong: rgba(237,229,211,0.45); /* solid hairlines, primary divisions */ +``` + +The accent is reserved for: hero verb (e.g. _without the wobble_), active nav underline, active filter pill, hover stripes, sparkline bars, the subscribe button, list-page rank numbers, calendar release dots, the live-pulse dot, and `::selection`. Nothing else. + +### 3.2 Type + +| Role | Family | Notes | +|---|---|---| +| Display + body | **Newsreader** | Variable, italic supported. Used for everything that reads like prose. | +| Captions / labels / nav / marquee / mono | **IBM Plex Mono** | All caps, ~0.16–0.22em letter-spacing. The other voice of the site. | + +There is no third font. Headings are weight 500–700, italic when emphatic. Body sizes scale from 14px (Lede small) to 96px (page hero). Bigger heroes use Newsreader Italic for the highlighted verb only. + +### 3.3 Structure + +- **No boxed containers.** Sections divide on whitespace + hairline rules. +- **No coloured cards.** No drop shadows. +- **One accent per page.** Everything else stays in the cream/muted scale. +- **Sources visible.** Every release and wire item must show its primary source. +- **No fake decimal scores.** Verdicts are editorial labels: _Recommended · Worth watching · Specialist pick · Shipped_. +- **Filter pills, not chiclets.** Round 999, 1px border, accent fill at 10% opacity when active. + +--- + +## 4. Interactions & motion + +Every animation lives in `wireframes/zine-shell.jsx` (` + + + + +
+ + + +
+ +
+ + +
+ + +
+
+ + +
+

Lead · cycling

+

 

+

 

+
+
+ + +
+ +
+ + +
+ Also today ▾ +
+ OpenAI ships smaller-model price drop across the API tier. + OpenAI release notes · 14:20 UTC +
+
+ Cursor 2.5 changelog confirms multi-window edit reviews in stable. + Cursor changelog · 12:08 UTC +
+
+ Suno v5.5 lifts the loop-token cap; longer-form clips now in beta. + Suno blog · 09:47 UTC +
+
+ +
+ + +
+
+

Setlist · next ninety days

+ All releases → +
+
+
+ +
+ + +
+
+

+ + Wire · last 48 hours +

+ All wire → +
+
+
+ + +
+

+ This week we are with small models that ship
+ and against roadmap theatre. +

+ +
+
+ + +
+ +
+
+ + + + + + + + + +
+
+

+ Phase 2 of the build wires this page to content/stackscout/tools-source.json. + List view groups by release window; calendar view is a 3-month strip. See KOL-540 (TBC) for the plumbing ticket. +

+
+ + +
+ +
+

+ Phase 2 wires this page to content/stackscout/updates-source.json with query-string filters. +

+
+ + +
+ +
+

+ Phase 2 reads the manual rank field in tools-source.json. + Filter rail: All / Recommended / Worth watching / Specialist pick. +

+
+ + +
+ +
+

+ Phase 2 wires the email form to the chosen subscribe endpoint and renders the past-issue archive + from updates-source.json grouped by week. +

+
+
+ +
+ + + + + + + + + + diff --git a/radar/index.html b/radar/index.html index 8f2697e..09f4b2c 100644 --- a/radar/index.html +++ b/radar/index.html @@ -28,7 +28,7 @@
-

Issue 2026-04-25 // Curated public signal for builders

+

Issue 2026-06-04 // Curated public signal for builders

No fake telemetry Official sources first @@ -125,7 +125,7 @@

GitHub skills ecosystem

Public tool intelligence for builders, operators, and curious system nerds.

diff --git a/scripts/build-stackscout.js b/scripts/build-stackscout.js index 7019eb2..c0e604e 100644 --- a/scripts/build-stackscout.js +++ b/scripts/build-stackscout.js @@ -4,10 +4,6 @@ const path = require('path') const ROOT_DIR = path.resolve(__dirname, '..') const SOURCE_DIR = path.join(ROOT_DIR, 'content', 'stackscout') const DATA_DIR = path.join(ROOT_DIR, 'data') -const PRIVATE_PREVIEW_EXPORT_CANDIDATES = [ - 'W:\\Repos\\_local\\surfaces\\tools-hub-local\\data\\stackscout-publishing.json', - '\\\\nas_storage_1\\Workspaces\\Repos\\_local\\surfaces\\tools-hub-local\\data\\stackscout-publishing.json', -] const BUILD_NOW = new Date() const GENERATED_AT = BUILD_NOW.toISOString().slice(0, 10) const GENERATED_AT_ISO = BUILD_NOW.toISOString() @@ -54,17 +50,16 @@ function writeExternalJson(absolutePath, value) { fs.writeFileSync(absolutePath, `${JSON.stringify(value, null, 2)}\n`, 'utf8') } -function resolveWritableExternalPath(candidates) { - for (const candidate of candidates) { - try { - ensureParent(candidate) - return candidate - } catch (error) { - continue - } +function resolvePrivatePreviewExportPath() { + if (process.env.STACKSCOUT_PRIVATE_EXPORT_FILE) { + return path.resolve(process.env.STACKSCOUT_PRIVATE_EXPORT_FILE) } - throw new Error(`Unable to resolve writable external path from candidates: ${candidates.join(', ')}`) + if (process.env.STACKSCOUT_PRIVATE_EXPORT_DIR) { + return path.join(path.resolve(process.env.STACKSCOUT_PRIVATE_EXPORT_DIR), 'stackscout-publishing.json') + } + + return null } function escapeHtml(value) { @@ -1239,7 +1234,7 @@ ${routes.map((route) => ` ${PUBLIC_BASE_URL}${route}`).jo } function main() { - const privatePreviewExport = resolveWritableExternalPath(PRIVATE_PREVIEW_EXPORT_CANDIDATES) + const privatePreviewExport = resolvePrivatePreviewExportPath() const site = readJson('site-source.json') const tools = readJson('tools-source.json') const updates = readJson('updates-source.json').sort((a, b) => b.publishedAt.localeCompare(a.publishedAt)) @@ -1254,7 +1249,9 @@ function main() { writeJson('data/methodology-manifest.json', buildMethodologyManifest(site)) writeJson('data/collections-manifest.json', buildCollectionsManifest(collections, toolIndex)) writeJson('data/radar-manifest.json', buildRadarManifest(site.radar)) - writeExternalJson(privatePreviewExport, buildPublishingPreview(tools, updates, categories)) + if (privatePreviewExport) { + writeExternalJson(privatePreviewExport, buildPublishingPreview(tools, updates, categories)) + } writeFile('index.html', renderHome(site, tools, updates, categories, collections, 'index.html')) writeFile('catalog/index.html', renderCatalog(tools, categories, 'catalog/index.html')) diff --git a/scripts/refresh-stackscout.ps1 b/scripts/refresh-stackscout.ps1 index 2ee63e4..8765129 100644 --- a/scripts/refresh-stackscout.ps1 +++ b/scripts/refresh-stackscout.ps1 @@ -6,29 +6,24 @@ param( $ErrorActionPreference = 'Stop' $repoRoot = (Resolve-Path (Join-Path $PSScriptRoot '..')).Path -$privateDataDirCandidates = @( - 'W:\Repos\_local\surfaces\tools-hub-local\data', - '\\nas_storage_1\Workspaces\Repos\_local\surfaces\tools-hub-local\data' -) $privateDataDir = $null -foreach ($candidate in $privateDataDirCandidates) { - try { - if (-not (Test-Path $candidate)) { - New-Item -ItemType Directory -Path $candidate -Force | Out-Null - } +$privateDataDirInput = if ($env:STACKSCOUT_PRIVATE_STATUS_DIR) { + $env:STACKSCOUT_PRIVATE_STATUS_DIR +} elseif ($env:STACKSCOUT_PRIVATE_EXPORT_DIR) { + $env:STACKSCOUT_PRIVATE_EXPORT_DIR +} else { + $null +} - $privateDataDir = (Resolve-Path $candidate).Path - break - } catch { - continue +if ($privateDataDirInput) { + if (-not (Test-Path $privateDataDirInput)) { + New-Item -ItemType Directory -Path $privateDataDirInput -Force | Out-Null } -} -if (-not $privateDataDir) { - throw 'Unable to resolve a writable private data directory for StackScout refresh status.' + $privateDataDir = (Resolve-Path $privateDataDirInput).Path } -$statusFile = Join-Path $privateDataDir 'stackscout-refresh-status.json' +$statusFile = if ($privateDataDir) { Join-Path $privateDataDir 'stackscout-refresh-status.json' } else { $null } $toolsManifestFile = Join-Path $repoRoot 'data\tools-manifest.json' $updatesManifestFile = Join-Path $repoRoot 'data\updates-manifest.json' $categoriesManifestFile = Join-Path $repoRoot 'data\categories-manifest.json' @@ -38,10 +33,13 @@ $durationStopwatch = [System.Diagnostics.Stopwatch]::StartNew() function Read-JsonFile { param( - [Parameter(Mandatory = $true)] [string]$Path ) + if (-not $Path) { + return $null + } + if (-not (Test-Path $Path)) { return $null } @@ -82,6 +80,10 @@ function Write-RefreshStatus { $payload[$entry.Key] = $entry.Value } + if (-not $statusFile) { + return + } + $directory = Split-Path -Parent $statusFile if (-not (Test-Path $directory)) { New-Item -ItemType Directory -Path $directory -Force | Out-Null diff --git a/scripts/verify-launch-safety.js b/scripts/verify-launch-safety.js new file mode 100644 index 0000000..505473f --- /dev/null +++ b/scripts/verify-launch-safety.js @@ -0,0 +1,208 @@ +const fs = require('fs') +const path = require('path') + +const ROOT_DIR = path.resolve(__dirname, '..') +const PUBLIC_ENTRIES = [ + 'index.html', + 'catalog', + 'categories', + 'collections', + 'data', + 'method', + 'radar', + 'tools', + 'updates', + 'app.js', + 'pwa.js', + 'service-worker.js', + 'manifest.json', + 'styles.css', + 'sitemap.xml', + 'icon.svg', +] +const REQUIRED_PUBLIC_FILES = [ + 'index.html', + 'catalog/index.html', + 'categories/index.html', + 'collections/index.html', + 'data/page-registry.json', + 'data/tools-manifest.json', + 'data/updates-manifest.json', + 'data/categories-manifest.json', + 'data/methodology-manifest.json', + 'data/collections-manifest.json', + 'data/radar-manifest.json', + 'method/index.html', + 'radar/index.html', + 'updates/index.html', + 'app.js', + 'pwa.js', + 'service-worker.js', + 'manifest.json', + 'styles.css', + 'sitemap.xml', + 'icon.svg', +] +const TEXT_EXTENSIONS = new Set(['.css', '.html', '.js', '.json', '.svg', '.txt', '.xml']) +const PRIVATE_PATTERNS = [ + { label: 'Windows drive path', pattern: /\b[A-Z]:[\\/][^\s"'<>)]*/i }, + { label: 'UNC path', pattern: /\\\\[A-Za-z0-9._-]+[\\/][^\s"'<>)]*/i }, + { label: 'local-only surface marker', pattern: /\b(?:tools-hub-local|LOCAL-ONLY|_local)\b/i }, + { label: 'private operations wording', pattern: /\b(?:manager inbox|review evidence|session state)\b/i }, +] +const REQUIRED_GITIGNORE_PATTERNS = ['.env', '.env.*', '*.local.md', '.local/', 'local-hub/'] +const REQUIRED_APP_SHELL_ENTRIES = [ + '', + 'index.html', + 'catalog/', + 'categories/', + 'updates/', + 'radar/', + 'collections/', + 'method/', + 'styles.css', + 'app.js', + 'pwa.js', + 'manifest.json', + 'icon.svg', + 'data/page-registry.json', + 'data/tools-manifest.json', + 'data/updates-manifest.json', + 'data/categories-manifest.json', + 'data/methodology-manifest.json', + 'data/collections-manifest.json', + 'data/radar-manifest.json', +] + +function readText(relativePath) { + return fs.readFileSync(path.join(ROOT_DIR, relativePath), 'utf8') +} + +function exists(relativePath) { + return fs.existsSync(path.join(ROOT_DIR, relativePath)) +} + +function walk(relativePath) { + const absolutePath = path.join(ROOT_DIR, relativePath) + if (!fs.existsSync(absolutePath)) { + return [] + } + + const stat = fs.statSync(absolutePath) + if (stat.isDirectory()) { + return fs.readdirSync(absolutePath).flatMap((entry) => walk(path.join(relativePath, entry))) + } + + return [relativePath] +} + +function collectPublicTextFiles() { + return PUBLIC_ENTRIES.flatMap(walk).filter((file) => TEXT_EXTENSIONS.has(path.extname(file).toLowerCase())) +} + +function extractIssueDate() { + const indexHtml = readText('index.html') + const issueMatch = indexHtml.match(/Issue (\d{4}-\d{2}-\d{2})/) + if (!issueMatch) { + throw new Error('index.html does not contain a generated issue date.') + } + + return issueMatch[1] +} + +function extractCacheName() { + const serviceWorker = readText('service-worker.js') + const cacheMatch = serviceWorker.match(/const CACHE_NAME = ['"]([^'"]+)['"]/) + if (!cacheMatch) { + throw new Error('service-worker.js does not declare CACHE_NAME.') + } + + return cacheMatch[1] +} + +function assertNoPrivateLeaks(files) { + const leaks = [] + + for (const file of files) { + const text = readText(file) + for (const { label, pattern } of PRIVATE_PATTERNS) { + if (pattern.test(text)) { + leaks.push(`${file}: ${label}`) + } + } + } + + if (leaks.length) { + throw new Error(`Public output contains private/local markers:\n${leaks.join('\n')}`) + } +} + +function assertRequiredFiles() { + const missing = REQUIRED_PUBLIC_FILES.filter((file) => !exists(file)) + if (missing.length) { + throw new Error(`Missing required public files:\n${missing.join('\n')}`) + } +} + +function assertServiceWorkerFreshness() { + const serviceWorker = readText('service-worker.js') + const cacheName = extractCacheName() + const cacheDateMatch = cacheName.match(/^stackscout-(\d{4}-\d{2}-\d{2})$/) + if (!cacheDateMatch) { + throw new Error(`CACHE_NAME must use stackscout-YYYY-MM-DD format; found ${cacheName}.`) + } + + const issueDate = extractIssueDate() + const cacheDate = cacheDateMatch[1] + if (cacheDate < issueDate) { + throw new Error(`CACHE_NAME ${cacheName} is older than generated issue date ${issueDate}. Bump service-worker.js before refresh.`) + } + + const missingShellEntries = REQUIRED_APP_SHELL_ENTRIES.filter((entry) => !serviceWorker.includes(`'${entry}'`)) + if (missingShellEntries.length) { + throw new Error(`service-worker.js is missing app-shell entries:\n${missingShellEntries.join('\n')}`) + } + + return { cacheName, issueDate } +} + +function assertGitignoreKeepsPrivateNotesOut() { + const gitignore = readText('.gitignore') + const missing = REQUIRED_GITIGNORE_PATTERNS.filter((entry) => !gitignore.includes(entry)) + if (missing.length) { + throw new Error(`.gitignore is missing private/local exclusions:\n${missing.join('\n')}`) + } +} + +function assertReadmeDocumentsLaunchGate() { + const readme = readText('README.md') + const requiredPhrases = [ + 'npm run verify:launch', + 'GitHub Pages does not support custom response headers', + 'service-worker.js', + ] + const missing = requiredPhrases.filter((phrase) => !readme.includes(phrase)) + if (missing.length) { + throw new Error(`README.md is missing launch-safety guidance:\n${missing.join('\n')}`) + } +} + +function main() { + assertRequiredFiles() + const publicFiles = collectPublicTextFiles() + assertNoPrivateLeaks(publicFiles) + const freshness = assertServiceWorkerFreshness() + assertGitignoreKeepsPrivateNotesOut() + assertReadmeDocumentsLaunchGate() + + console.log( + `StackScout launch safety passed: ${publicFiles.length} public files scanned, CACHE_NAME=${freshness.cacheName}, issue=${freshness.issueDate}.`, + ) +} + +try { + main() +} catch (error) { + console.error(`StackScout launch safety failed: ${error.message}`) + process.exit(1) +} diff --git a/service-worker.js b/service-worker.js index b4064f1..9ff0fb2 100644 --- a/service-worker.js +++ b/service-worker.js @@ -1,4 +1,4 @@ -const CACHE_NAME = 'stackscout-v1' +const CACHE_NAME = 'stackscout-2026-06-04' const APP_SHELL = [ '', 'index.html', diff --git a/tools/anthropic-api/index.html b/tools/anthropic-api/index.html index 04c0cb6..6c325c3 100644 --- a/tools/anthropic-api/index.html +++ b/tools/anthropic-api/index.html @@ -28,7 +28,7 @@
-

Issue 2026-04-25 // Curated public signal for builders

+

Issue 2026-06-04 // Curated public signal for builders

No fake telemetry Official sources first @@ -272,7 +272,7 @@

n8n

Public tool intelligence for builders, operators, and curious system nerds.

diff --git a/tools/canvas-planner/index.html b/tools/canvas-planner/index.html index 55a6ab8..ae35bd4 100644 --- a/tools/canvas-planner/index.html +++ b/tools/canvas-planner/index.html @@ -28,7 +28,7 @@
-

Issue 2026-04-25 // Curated public signal for builders

+

Issue 2026-06-04 // Curated public signal for builders

No fake telemetry Official sources first @@ -238,7 +238,7 @@

SyncPad

Public tool intelligence for builders, operators, and curious system nerds.

diff --git a/tools/gh-cli/index.html b/tools/gh-cli/index.html index aaa32b4..5c1cfd6 100644 --- a/tools/gh-cli/index.html +++ b/tools/gh-cli/index.html @@ -28,7 +28,7 @@
-

Issue 2026-04-25 // Curated public signal for builders

+

Issue 2026-06-04 // Curated public signal for builders

No fake telemetry Official sources first @@ -238,7 +238,7 @@

Wrangler

Public tool intelligence for builders, operators, and curious system nerds.

diff --git a/tools/github-mcp-server/index.html b/tools/github-mcp-server/index.html index 9210494..02f9e15 100644 --- a/tools/github-mcp-server/index.html +++ b/tools/github-mcp-server/index.html @@ -28,7 +28,7 @@
-

Issue 2026-04-25 // Curated public signal for builders

+

Issue 2026-06-04 // Curated public signal for builders

No fake telemetry Official sources first @@ -272,7 +272,7 @@

Wrangler

Public tool intelligence for builders, operators, and curious system nerds.

diff --git a/tools/hugging-face/index.html b/tools/hugging-face/index.html index 2148d98..86dfd96 100644 --- a/tools/hugging-face/index.html +++ b/tools/hugging-face/index.html @@ -28,7 +28,7 @@
-

Issue 2026-04-25 // Curated public signal for builders

+

Issue 2026-06-04 // Curated public signal for builders

No fake telemetry Official sources first @@ -272,7 +272,7 @@

GitHub MCP Server

Public tool intelligence for builders, operators, and curious system nerds.

diff --git a/tools/make/index.html b/tools/make/index.html index 9237f3e..1fa84c1 100644 --- a/tools/make/index.html +++ b/tools/make/index.html @@ -28,7 +28,7 @@
-

Issue 2026-04-25 // Curated public signal for builders

+

Issue 2026-06-04 // Curated public signal for builders

No fake telemetry Official sources first @@ -272,7 +272,7 @@

Anthropic API

Public tool intelligence for builders, operators, and curious system nerds.

diff --git a/tools/n8n/index.html b/tools/n8n/index.html index 2c19820..d0e28ca 100644 --- a/tools/n8n/index.html +++ b/tools/n8n/index.html @@ -28,7 +28,7 @@
-

Issue 2026-04-25 // Curated public signal for builders

+

Issue 2026-06-04 // Curated public signal for builders

No fake telemetry Official sources first @@ -272,7 +272,7 @@

Anthropic API

Public tool intelligence for builders, operators, and curious system nerds.

diff --git a/tools/openai-api/index.html b/tools/openai-api/index.html index cc6fb3b..e1f2e5d 100644 --- a/tools/openai-api/index.html +++ b/tools/openai-api/index.html @@ -28,7 +28,7 @@
-

Issue 2026-04-25 // Curated public signal for builders

+

Issue 2026-06-04 // Curated public signal for builders

No fake telemetry Official sources first @@ -306,7 +306,7 @@

Playwright MCP

Public tool intelligence for builders, operators, and curious system nerds.

diff --git a/tools/perplexity/index.html b/tools/perplexity/index.html index 646703b..b08afcb 100644 --- a/tools/perplexity/index.html +++ b/tools/perplexity/index.html @@ -28,7 +28,7 @@
-

Issue 2026-04-25 // Curated public signal for builders

+

Issue 2026-06-04 // Curated public signal for builders

No fake telemetry Official sources first @@ -238,7 +238,7 @@

OpenAI API

Public tool intelligence for builders, operators, and curious system nerds.

diff --git a/tools/playwright-mcp/index.html b/tools/playwright-mcp/index.html index 1e4bf30..462b6c3 100644 --- a/tools/playwright-mcp/index.html +++ b/tools/playwright-mcp/index.html @@ -28,7 +28,7 @@
-

Issue 2026-04-25 // Curated public signal for builders

+

Issue 2026-06-04 // Curated public signal for builders

No fake telemetry Official sources first @@ -272,7 +272,7 @@

Anthropic API

Public tool intelligence for builders, operators, and curious system nerds.

diff --git a/tools/signal-stack/index.html b/tools/signal-stack/index.html index e1697fc..e942688 100644 --- a/tools/signal-stack/index.html +++ b/tools/signal-stack/index.html @@ -28,7 +28,7 @@
-

Issue 2026-04-25 // Curated public signal for builders

+

Issue 2026-06-04 // Curated public signal for builders

No fake telemetry Official sources first @@ -216,7 +216,7 @@

Strudel Studio

Public tool intelligence for builders, operators, and curious system nerds.

diff --git a/tools/strudel-studio/index.html b/tools/strudel-studio/index.html index e2544b5..992e2a4 100644 --- a/tools/strudel-studio/index.html +++ b/tools/strudel-studio/index.html @@ -28,7 +28,7 @@
-

Issue 2026-04-25 // Curated public signal for builders

+

Issue 2026-06-04 // Curated public signal for builders

No fake telemetry Official sources first @@ -238,7 +238,7 @@

OpenAI API

Public tool intelligence for builders, operators, and curious system nerds.

diff --git a/tools/syncpad/index.html b/tools/syncpad/index.html index e597110..b1e7bc2 100644 --- a/tools/syncpad/index.html +++ b/tools/syncpad/index.html @@ -28,7 +28,7 @@
-

Issue 2026-04-25 // Curated public signal for builders

+

Issue 2026-06-04 // Curated public signal for builders

No fake telemetry Official sources first @@ -182,7 +182,7 @@

Canvas Planner

Public tool intelligence for builders, operators, and curious system nerds.

diff --git a/tools/wrangler/index.html b/tools/wrangler/index.html index 9de4afd..1695a79 100644 --- a/tools/wrangler/index.html +++ b/tools/wrangler/index.html @@ -28,7 +28,7 @@
-

Issue 2026-04-25 // Curated public signal for builders

+

Issue 2026-06-04 // Curated public signal for builders

No fake telemetry Official sources first @@ -238,7 +238,7 @@

Playwright MCP

Public tool intelligence for builders, operators, and curious system nerds.

diff --git a/updates/index.html b/updates/index.html index 3f33b57..e9d626f 100644 --- a/updates/index.html +++ b/updates/index.html @@ -28,7 +28,7 @@
-

Issue 2026-04-25 // Curated public signal for builders

+

Issue 2026-06-04 // Curated public signal for builders

No fake telemetry Official sources first @@ -325,7 +325,7 @@

Wrangler 4.58.0 improved command grouping and auth ergonomics

Public tool intelligence for builders, operators, and curious system nerds.