From 4f569b453b4a810d60f120e0001f3002f2086761 Mon Sep 17 00:00:00 2001 From: Kol Tregaskes Date: Mon, 25 May 2026 22:51:06 +0100 Subject: [PATCH] feat: implement Stack Scout zine redesign --- .github/workflows/validate.yml | 9 + README.md | 30 +- app.js | 50 +- catalog/index.html | 132 +++-- categories/apis/index.html | 100 ++-- categories/clis/index.html | 100 ++-- categories/desktop-apps/index.html | 106 ++-- categories/index.html | 104 ++-- categories/mcps/index.html | 100 ++-- categories/web-apps/index.html | 118 ++-- categories/web-services/index.html | 100 ++-- categories/websites/index.html | 100 ++-- collections/index.html | 108 ++-- content/stackscout/site-source.json | 20 +- content/stackscout/tools-source.json | 8 +- data/categories-manifest.json | 6 +- data/collections-manifest.json | 10 +- data/methodology-manifest.json | 8 +- data/page-registry.json | 12 +- data/radar-manifest.json | 6 +- data/tools-manifest.json | 16 +- data/updates-manifest.json | 6 +- index.html | 142 +++-- manifest.json | 2 +- method/index.html | 108 ++-- package.json | 5 +- pwa.js | 2 +- radar/index.html | 102 ++-- scripts/build-stackscout.js | 187 ++++--- scripts/refresh-stackscout.ps1 | 12 +- scripts/verify-launch-safety.js | 219 ++++++++ service-worker.js | 2 +- sitemap.xml | 56 +- styles.css | 781 ++++++++++++++++++++++++++- tools/anthropic-api/index.html | 102 ++-- tools/canvas-planner/index.html | 118 ++-- tools/gh-cli/index.html | 102 ++-- tools/github-mcp-server/index.html | 102 ++-- tools/hugging-face/index.html | 102 ++-- tools/make/index.html | 102 ++-- tools/n8n/index.html | 102 ++-- tools/openai-api/index.html | 102 ++-- tools/perplexity/index.html | 102 ++-- tools/playwright-mcp/index.html | 102 ++-- tools/signal-stack/index.html | 118 ++-- tools/strudel-studio/index.html | 112 ++-- tools/syncpad/index.html | 112 ++-- tools/wrangler/index.html | 102 ++-- updates/index.html | 104 ++-- 49 files changed, 3313 insertions(+), 1138 deletions(-) create mode 100644 scripts/verify-launch-safety.js diff --git a/.github/workflows/validate.yml b/.github/workflows/validate.yml index f4f5dc8..fd78f2f 100644 --- a/.github/workflows/validate.yml +++ b/.github/workflows/validate.yml @@ -9,6 +9,9 @@ on: env: FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true +permissions: + contents: read + jobs: validate: runs-on: ubuntu-latest @@ -16,6 +19,12 @@ jobs: - name: Checkout uses: actions/checkout@v6 + - name: Build generated site + run: npm run build:site + + - name: Run launch-safety checks + run: npm run check + - name: Check index.html exists and is non-empty run: test -s index.html diff --git a/README.md b/README.md index 4fd00e8..4a807b4 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ -# StackScout +# Stack Scout -`tools-hub` builds **StackScout**, the public-facing tools destination for curated builder tools, services, APIs, MCPs, and CLIs. +`stackscout` builds **Stack Scout**, the public-facing tools destination for curated builder tools, services, APIs, MCPs, and CLIs. This repo remains the GitHub Pages implementation base, but the visible product is no longer a simple internal "Tools Hub" brochure. The private operational console stays separate in `W:\Repos\_local\surfaces\tools-hub-local`. @@ -13,7 +13,7 @@ This repo remains the GitHub Pages implementation base, but the visible product ## Shared source layer -StackScout uses a shared source layer inside this repo: +Stack Scout uses a shared source layer inside this repo: - `content/stackscout/site-source.json` - `content/stackscout/tools-source.json` @@ -50,6 +50,18 @@ This regenerates: npm run check ``` +`npm run check` also runs the no-publish launch-safety gate: + +```bash +npm run verify:launch +``` + +That gate scans generated public output for local Windows paths and private surface markers, confirms the public file set exists, checks `.gitignore` still excludes local notes and env files, and verifies the `service-worker.js` cache name is not older than the generated issue date. + +GitHub Pages does not support custom response headers such as a Netlify `_headers` file. Keep browser hardening inside static HTML, conservative client code, and dependency-free scripts unless the site moves to a host that can set CSP/HSTS-style headers. + +Before a public refresh, bump `CACHE_NAME` in `service-worker.js` when generated public content advances. The launch-safety gate fails if the cache date is older than the visible issue date. + ## Refresh ```bash @@ -63,13 +75,13 @@ For unattended Windows refreshes without visible terminal focus theft, use the l ## Site structure - `Home` -- `Catalog` +- `Top tools` - `Tool Detail` - `Categories` -- `Updates` +- `Wire` - `Radar` - `Collections` -- `Method` +- `Sources & method` ## Launch surface highlights @@ -77,13 +89,13 @@ For unattended Windows refreshes without visible terminal focus theft, use the l - shareable catalog filters via URL query state - public dossier pages for every tracked tool - source-linked updates and visible freshness dates -- clearly labelled `StackScout Lab` subset for in-house tools +- clearly labelled `Stack Scout Lab` subset for in-house tools - installable static PWA shell for repeat visits ## Notes -- StackScout is curated ecosystem first. -- Our own tools are a clearly labelled `StackScout Lab` subset, not the whole point of the site. +- Stack Scout is curated ecosystem first. +- Our own tools are a clearly labelled `Stack Scout Lab` subset, not the whole point of the site. - Public verdicts use editorial badges, not fake numeric scoring. - Update items should prefer official release notes, changelogs, docs, blogs, and first-party repositories. - The catalog now keeps filter state in the URL so filtered views can be shared directly. diff --git a/app.js b/app.js index fefe7a6..72b8d41 100644 --- a/app.js +++ b/app.js @@ -1,5 +1,51 @@ document.body.classList.add('has-motion') +const MOOD_CLASSES = ['mood-graphite', 'mood-midnight', 'mood-obsidian', 'mood-slate', 'mood-carbon'] + +function initMoodSwitcher() { + const buttons = Array.from(document.querySelectorAll('[data-mood]')) + if (!buttons.length) { + return + } + + const storedMood = localStorage.getItem('stackscout:mood') + const initialMood = buttons.some((button) => button.dataset.mood === storedMood) ? storedMood : 'graphite' + + function applyMood(mood) { + document.documentElement.classList.remove(...MOOD_CLASSES) + document.documentElement.classList.add(`mood-${mood}`) + buttons.forEach((button) => { + const isActive = button.dataset.mood === mood + button.classList.toggle('is-active', isActive) + button.setAttribute('aria-pressed', String(isActive)) + }) + localStorage.setItem('stackscout:mood', mood) + } + + buttons.forEach((button) => { + button.addEventListener('click', () => applyMood(button.dataset.mood)) + }) + + applyMood(initialMood) +} + +function initUtcClock() { + const clock = document.getElementById('utcClock') + if (!clock) { + return + } + + function renderClock() { + const now = new Date() + const hours = String(now.getUTCHours()).padStart(2, '0') + const minutes = String(now.getUTCMinutes()).padStart(2, '0') + clock.textContent = `Live - ${hours}:${minutes} UTC` + } + + renderClock() + window.setInterval(renderClock, 30_000) +} + function initReveal() { const revealItems = Array.from(document.querySelectorAll('[data-reveal]')) if (!revealItems.length) { @@ -24,7 +70,7 @@ function initReveal() { }) }, { - threshold: 0.16, + threshold: 0.02, rootMargin: '0px 0px -8% 0px', }, ) @@ -173,3 +219,5 @@ function initCatalogFilters() { initReveal() initCatalogFilters() +initMoodSwitcher() +initUtcClock() diff --git a/catalog/index.html b/catalog/index.html index 2d9c3e8..5c4a8e6 100644 --- a/catalog/index.html +++ b/catalog/index.html @@ -1,47 +1,39 @@ - + - StackScout // Catalog - - - + Stack Scout // Top tools + + + - + - + - -
-
-

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

-
- No fake telemetry - Official sources first - Badges over fake scores -
-
-
+
@@ -82,7 +74,7 @@

Make

diff --git a/categories/apis/index.html b/categories/apis/index.html index 4d83e54..145d11d 100644 --- a/categories/apis/index.html +++ b/categories/apis/index.html @@ -1,47 +1,39 @@ - + - StackScout // APIs + Stack Scout // APIs - + - + - + - -
-
-

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

-
- No fake telemetry - Official sources first - Badges over fake scores -
-
-
+
@@ -131,13 +123,59 @@

Anthropic API

diff --git a/categories/clis/index.html b/categories/clis/index.html index 883eab2..c1f4070 100644 --- a/categories/clis/index.html +++ b/categories/clis/index.html @@ -1,47 +1,39 @@ - + - StackScout // CLIs + Stack Scout // CLIs - + - + - + - -
-
-

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

-
- No fake telemetry - Official sources first - Badges over fake scores -
-
-
+
@@ -131,13 +123,59 @@

Wrangler

diff --git a/categories/desktop-apps/index.html b/categories/desktop-apps/index.html index 9c5a59d..5391e8e 100644 --- a/categories/desktop-apps/index.html +++ b/categories/desktop-apps/index.html @@ -1,47 +1,39 @@ - + - StackScout // Desktop Apps + Stack Scout // Desktop Apps - + - + - + - -
-
-

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

-
- No fake telemetry - Official sources first - Badges over fake scores -
-
-
+
@@ -68,9 +60,9 @@

Desktop Apps

data-badge="Early but Promising" data-date="2026-04-12" data-priority="1" - data-search="SyncPad A private, desktop-first notes tool with live sync ambitions and a workflow that stays close to the operator. StackScout Lab The browser and client surfaces are healthier, but the Electron desktop verification path is still blocked by a GPU startup issue on the manager machine. notes desktop private sync knowledge"> + data-search="SyncPad A private, desktop-first notes tool with live sync ambitions and a workflow that stays close to the operator. Stack Scout Lab The browser and client surfaces are healthier, but the Electron desktop verification path is still blocked by a GPU startup issue on the manager machine. notes desktop private sync knowledge">
- StackScout Lab + Stack Scout Lab Early but Promising
@@ -84,7 +76,7 @@

SyncPad

private noteslocal-first draftingmulti-device ambition
- StackScout Lab + Stack Scout Lab Experimental 12 Apr 2026
@@ -97,13 +89,59 @@

SyncPad

diff --git a/categories/index.html b/categories/index.html index da0411d..70bbb47 100644 --- a/categories/index.html +++ b/categories/index.html @@ -1,47 +1,39 @@ - + - StackScout // Categories - - - + Stack Scout // Categories + + + - + - + - -
-
-

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

-
- No fake telemetry - Official sources first - Badges over fake scores -
-
-
+
@@ -184,13 +176,59 @@

Desktop Apps

diff --git a/categories/mcps/index.html b/categories/mcps/index.html index fc82736..8a410de 100644 --- a/categories/mcps/index.html +++ b/categories/mcps/index.html @@ -1,47 +1,39 @@ - + - StackScout // MCPs + Stack Scout // MCPs - + - + - + - -
-
-

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

-
- No fake telemetry - Official sources first - Badges over fake scores -
-
-
+
@@ -131,13 +123,59 @@

Playwright MCP

diff --git a/categories/web-apps/index.html b/categories/web-apps/index.html index 2487a5e..a756d06 100644 --- a/categories/web-apps/index.html +++ b/categories/web-apps/index.html @@ -1,47 +1,39 @@ - + - StackScout // Web Apps + Stack Scout // Web Apps - + - + - + - -
-
-

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

-
- No fake telemetry - Official sources first - Badges over fake scores -
-
-
+
@@ -68,9 +60,9 @@

Web Apps

data-badge="Early but Promising" data-date="2026-04-11" data-priority="1" - data-search="Canvas Planner A visual planning surface for boards, campaign flow, and creative work without the drag of a generic project manager. StackScout Lab The latest public-ready pass cleaned the browser surface and kept the board flow sharp without adding clutter. planning boards creative workflow pwa"> + data-search="Canvas Planner A visual planning surface for boards, campaign flow, and creative work without the drag of a generic project manager. Stack Scout Lab The latest public-ready pass cleaned the browser surface and kept the board flow sharp without adding clutter. planning boards creative workflow pwa">
- StackScout Lab + Stack Scout Lab Early but Promising
@@ -84,7 +76,7 @@

Canvas Planner

campaign planningcreative sequencinglightweight boards
- StackScout Lab + Stack Scout Lab Experimental 11 Apr 2026
@@ -102,9 +94,9 @@

Canvas Planner

data-badge="Early but Promising" data-date="2026-04-12" data-priority="1" - data-search="Signal Stack A publishing planner built around image, video, and queue workflows rather than generic social-media posting dashboards. StackScout Lab The recent execution pass made delivery truth more explicit, but live platform integrations still depend on real credentials and approvals. publishing scheduling creator workflow social"> + data-search="Signal Stack A publishing planner built around image, video, and queue workflows rather than generic social-media posting dashboards. Stack Scout Lab The recent execution pass made delivery truth more explicit, but live platform integrations still depend on real credentials and approvals. publishing scheduling creator workflow social">
- StackScout Lab + Stack Scout Lab Early but Promising
@@ -118,7 +110,7 @@

Signal Stack

creator schedulingqueue designplatform planning
- StackScout Lab + Stack Scout Lab Experimental 12 Apr 2026
@@ -136,9 +128,9 @@

Signal Stack

data-badge="Worth Watching" data-date="2026-04-12" data-priority="2" - data-search="Strudel Studio A browser-based music studio path that brings programmable patterns, scenes, and samples into a clearer public-facing workflow. StackScout Lab The takeover pass tightened the smoke runner and kept the product moving toward a more serious music workspace. music browser studio coding audio"> + data-search="Strudel Studio A browser-based music studio path that brings programmable patterns, scenes, and samples into a clearer public-facing workflow. Stack Scout Lab The takeover pass tightened the smoke runner and kept the product moving toward a more serious music workspace. music browser studio coding audio">
- StackScout Lab + Stack Scout Lab Worth Watching
@@ -152,7 +144,7 @@

Strudel Studio

browser music prototypingpattern-driven compositioncreative experiments
- StackScout Lab + Stack Scout Lab Experimental 12 Apr 2026
@@ -165,13 +157,59 @@

Strudel Studio

diff --git a/categories/web-services/index.html b/categories/web-services/index.html index 293e073..56ff97d 100644 --- a/categories/web-services/index.html +++ b/categories/web-services/index.html @@ -1,47 +1,39 @@ - + - StackScout // Web Services + Stack Scout // Web Services - + - + - + - -
-
-

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

-
- No fake telemetry - Official sources first - Badges over fake scores -
-
-
+
@@ -131,13 +123,59 @@

Make

diff --git a/categories/websites/index.html b/categories/websites/index.html index 03d642b..2107b21 100644 --- a/categories/websites/index.html +++ b/categories/websites/index.html @@ -1,47 +1,39 @@ - + - StackScout // Websites + Stack Scout // Websites - + - + - + - -
-
-

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

-
- No fake telemetry - Official sources first - Badges over fake scores -
-
-
+
@@ -131,13 +123,59 @@

Hugging Face

diff --git a/collections/index.html b/collections/index.html index 5867289..c4ad6eb 100644 --- a/collections/index.html +++ b/collections/index.html @@ -1,47 +1,39 @@ - + - StackScout // Collections - - - + Stack Scout // Collections + + + - + - + - -
-
-

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

-
- No fake telemetry - Official sources first - Badges over fake scores -
-
-
+
@@ -61,7 +53,7 @@

Shortlists with intent.

Use-case grouping

Best tools for creators

-

If you are building content systems, prototyping creative workflows, or stitching research into production, this is the first StackScout lane to start with.

+

If you are building content systems, prototyping creative workflows, or stitching research into production, this is the first Stack Scout lane to start with.

@@ -120,7 +112,7 @@

Best offline-friendly tools

Use-case grouping

-

From the StackScout Lab

+

From the Stack Scout Lab

These are not presented as the whole point of the site. They sit alongside the wider ecosystem and earn their place separately.

Canvas PlannerSignal StackStrudel StudioSyncPad @@ -131,13 +123,59 @@

From the StackScout Lab

diff --git a/content/stackscout/site-source.json b/content/stackscout/site-source.json index 466b707..654930a 100644 --- a/content/stackscout/site-source.json +++ b/content/stackscout/site-source.json @@ -1,11 +1,11 @@ { "brand": { - "name": "StackScout", - "tagline": "The public scout deck for serious builder tools.", - "description": "StackScout tracks the tools, services, APIs, MCPs, CLIs, and workbench apps worth a builder's attention.", - "heroEyebrow": "Curated ecosystem // tools, systems, and builder intelligence", - "heroTitle": "A cleaner way to track the tools actually shaping modern workflows.", - "heroLede": "StackScout is the public-facing scout deck for fast-moving builder infrastructure: websites, web services, APIs, MCPs, CLIs, and a smaller lab lane for the tools we are building ourselves. It is curated, selective, and designed to stay useful rather than exhaustive." + "name": "Stack Scout", + "tagline": "A field log for the AI stack.", + "description": "Stack Scout tracks the tools, services, APIs, MCPs, CLIs, and workbench apps worth a builder's attention.", + "heroEyebrow": "Today's lead // official sources first", + "heroTitle": "A field log for the tools worth opening.", + "heroLede": "Stack Scout is a selective, source-led zine for builder infrastructure: APIs, MCPs, CLIs, services, workbench apps, and the lab tools we are building ourselves. It is curated rather than exhaustive, with visible dates and editorial badges instead of fake precision." }, "home": { "featureSlugs": [ @@ -23,7 +23,7 @@ "creator-stack", "mcp-starters", "automation-apis", - "stackscout-lab" + "stackscout-lab" ] }, "categories": [ @@ -108,7 +108,7 @@ } ], "methodology": { - "thesis": "StackScout is a public guide, not a benchmark lab. We badge selectively, update from official sources where possible, and avoid pretending every fast-moving tool deserves a fixed numeric score.", + "thesis": "Stack Scout is a public guide, not a benchmark lab. We badge selectively, update from official sources where possible, and avoid pretending every fast-moving tool deserves a fixed numeric score.", "principles": [ { "title": "Curated over exhaustive", @@ -177,7 +177,7 @@ "slug": "creator-stack", "title": "Best tools for creators", "summary": "A practical mix for publishing, generation, research, and creative flow.", - "description": "If you are building content systems, prototyping creative workflows, or stitching research into production, this is the first StackScout lane to start with.", + "description": "If you are building content systems, prototyping creative workflows, or stitching research into production, this is the first Stack Scout lane to start with.", "items": [ "hugging-face", "perplexity", @@ -223,7 +223,7 @@ }, { "slug": "stackscout-lab", - "title": "From the StackScout Lab", + "title": "From the Stack Scout Lab", "summary": "A clearly labelled subset of the tools we are building ourselves.", "description": "These are not presented as the whole point of the site. They sit alongside the wider ecosystem and earn their place separately.", "items": [ diff --git a/content/stackscout/tools-source.json b/content/stackscout/tools-source.json index 3c915e1..f4f50a0 100644 --- a/content/stackscout/tools-source.json +++ b/content/stackscout/tools-source.json @@ -264,7 +264,7 @@ "category": "web-apps", "summary": "A visual planning surface for boards, campaign flow, and creative work without the drag of a generic project manager.", "officialUrl": "https://koltregaskes.github.io/canvas-planner/", - "publisher": "StackScout Lab", + "publisher": "Stack Scout Lab", "platforms": ["Web App", "PWA"], "pricing": "Free", "badge": "Early but Promising", @@ -289,7 +289,7 @@ "category": "web-apps", "summary": "A publishing planner built around image, video, and queue workflows rather than generic social-media posting dashboards.", "officialUrl": "https://koltregaskes.github.io/signal-stack/", - "publisher": "StackScout Lab", + "publisher": "Stack Scout Lab", "platforms": ["Web App"], "pricing": "Free", "badge": "Early but Promising", @@ -314,7 +314,7 @@ "category": "web-apps", "summary": "A browser-based music studio path that brings programmable patterns, scenes, and samples into a clearer public-facing workflow.", "officialUrl": "https://koltregaskes.github.io/strudel-studio/", - "publisher": "StackScout Lab", + "publisher": "Stack Scout Lab", "platforms": ["Web App", "PWA"], "pricing": "Free", "badge": "Worth Watching", @@ -339,7 +339,7 @@ "category": "desktop-apps", "summary": "A private, desktop-first notes tool with live sync ambitions and a workflow that stays close to the operator.", "officialUrl": "https://github.com/koltregaskes/syncpad", - "publisher": "StackScout Lab", + "publisher": "Stack Scout Lab", "platforms": ["Windows", "Desktop App", "Private Web Client"], "pricing": "Free", "badge": "Early but Promising", diff --git a/data/categories-manifest.json b/data/categories-manifest.json index c95c128..dc7e493 100644 --- a/data/categories-manifest.json +++ b/data/categories-manifest.json @@ -1,7 +1,7 @@ { - "title": "StackScout // Categories", - "generatedAt": "2026-04-25", - "updatedAt": "2026-04-25", + "title": "Stack Scout // Categories", + "generatedAt": "2026-05-25", + "updatedAt": "2026-05-25", "categories": [ { "slug": "websites", diff --git a/data/collections-manifest.json b/data/collections-manifest.json index 2b33a0a..0e6d713 100644 --- a/data/collections-manifest.json +++ b/data/collections-manifest.json @@ -1,13 +1,13 @@ { - "title": "StackScout // Collections", - "generatedAt": "2026-04-25", - "updatedAt": "2026-04-25", + "title": "Stack Scout // Collections", + "generatedAt": "2026-05-25", + "updatedAt": "2026-05-25", "collections": [ { "slug": "creator-stack", "title": "Best tools for creators", "summary": "A practical mix for publishing, generation, research, and creative flow.", - "description": "If you are building content systems, prototyping creative workflows, or stitching research into production, this is the first StackScout lane to start with.", + "description": "If you are building content systems, prototyping creative workflows, or stitching research into production, this is the first Stack Scout lane to start with.", "items": [ { "slug": "hugging-face", @@ -117,7 +117,7 @@ }, { "slug": "stackscout-lab", - "title": "From the StackScout Lab", + "title": "From the Stack Scout Lab", "summary": "A clearly labelled subset of the tools we are building ourselves.", "description": "These are not presented as the whole point of the site. They sit alongside the wider ecosystem and earn their place separately.", "items": [ diff --git a/data/methodology-manifest.json b/data/methodology-manifest.json index 815185c..5cf7354 100644 --- a/data/methodology-manifest.json +++ b/data/methodology-manifest.json @@ -1,8 +1,8 @@ { - "title": "StackScout // Methodology", - "generatedAt": "2026-04-25", - "updatedAt": "2026-04-25", - "thesis": "StackScout is a public guide, not a benchmark lab. We badge selectively, update from official sources where possible, and avoid pretending every fast-moving tool deserves a fixed numeric score.", + "title": "Stack Scout // Methodology", + "generatedAt": "2026-05-25", + "updatedAt": "2026-05-25", + "thesis": "Stack Scout is a public guide, not a benchmark lab. We badge selectively, update from official sources where possible, and avoid pretending every fast-moving tool deserves a fixed numeric score.", "principles": [ { "title": "Curated over exhaustive", diff --git a/data/page-registry.json b/data/page-registry.json index c9a1b85..e4ba728 100644 --- a/data/page-registry.json +++ b/data/page-registry.json @@ -1,6 +1,6 @@ { - "title": "StackScout // Page Registry", - "generatedAt": "2026-04-25", + "title": "Stack Scout // Page Registry", + "generatedAt": "2026-05-25", "pages": [ { "key": "home", @@ -10,7 +10,7 @@ }, { "key": "catalog", - "title": "Catalog", + "title": "Top tools", "summary": "Searchable, filterable catalog of tracked tools and lab products.", "href": "catalog/" }, @@ -22,7 +22,7 @@ }, { "key": "updates", - "title": "Updates", + "title": "Wire", "summary": "Recent public activity, releases, direction changes, and noteworthy platform moves.", "href": "updates/" }, @@ -40,7 +40,7 @@ }, { "key": "method", - "title": "Method", + "title": "Sources & method", "summary": "Public badge definitions, freshness rules, and editorial guardrails.", "href": "method/" }, @@ -123,7 +123,7 @@ }, { "key": "collection-stackscout-lab", - "title": "From the StackScout Lab", + "title": "From the Stack Scout Lab", "summary": "A clearly labelled subset of the tools we are building ourselves.", "href": "collections/index.html#stackscout-lab", "parent": "collections" diff --git a/data/radar-manifest.json b/data/radar-manifest.json index 9c3b710..2c299ca 100644 --- a/data/radar-manifest.json +++ b/data/radar-manifest.json @@ -1,7 +1,7 @@ { - "title": "StackScout // Radar", - "generatedAt": "2026-04-25", - "updatedAt": "2026-04-25", + "title": "Stack Scout // Radar", + "generatedAt": "2026-05-25", + "updatedAt": "2026-05-25", "items": [ { "title": "Azure MCP Server", diff --git a/data/tools-manifest.json b/data/tools-manifest.json index 9d4bbc9..28fa7b6 100644 --- a/data/tools-manifest.json +++ b/data/tools-manifest.json @@ -1,8 +1,8 @@ { - "title": "StackScout // Tools Manifest", - "generatedAt": "2026-04-25", - "updatedAt": "2026-04-25", - "summary": "Public-safe catalog for StackScout.", + "title": "Stack Scout // Tools Manifest", + "generatedAt": "2026-05-25", + "updatedAt": "2026-05-25", + "summary": "Public-safe catalog for Stack Scout.", "counts": { "total": 14, "ecosystem": 10, @@ -499,7 +499,7 @@ "category": "web-apps", "summary": "A visual planning surface for boards, campaign flow, and creative work without the drag of a generic project manager.", "officialUrl": "https://koltregaskes.github.io/canvas-planner/", - "publisher": "StackScout Lab", + "publisher": "Stack Scout Lab", "platforms": [ "Web App", "PWA" @@ -542,7 +542,7 @@ "category": "web-apps", "summary": "A publishing planner built around image, video, and queue workflows rather than generic social-media posting dashboards.", "officialUrl": "https://koltregaskes.github.io/signal-stack/", - "publisher": "StackScout Lab", + "publisher": "Stack Scout Lab", "platforms": [ "Web App" ], @@ -584,7 +584,7 @@ "category": "web-apps", "summary": "A browser-based music studio path that brings programmable patterns, scenes, and samples into a clearer public-facing workflow.", "officialUrl": "https://koltregaskes.github.io/strudel-studio/", - "publisher": "StackScout Lab", + "publisher": "Stack Scout Lab", "platforms": [ "Web App", "PWA" @@ -627,7 +627,7 @@ "category": "desktop-apps", "summary": "A private, desktop-first notes tool with live sync ambitions and a workflow that stays close to the operator.", "officialUrl": "https://github.com/koltregaskes/syncpad", - "publisher": "StackScout Lab", + "publisher": "Stack Scout Lab", "platforms": [ "Windows", "Desktop App", diff --git a/data/updates-manifest.json b/data/updates-manifest.json index dc7a94e..4ae33c6 100644 --- a/data/updates-manifest.json +++ b/data/updates-manifest.json @@ -1,7 +1,7 @@ { - "title": "StackScout // Updates", - "generatedAt": "2026-04-25", - "updatedAt": "2026-04-25", + "title": "Stack Scout // Updates", + "generatedAt": "2026-05-25", + "updatedAt": "2026-05-25", "summary": "Public-safe activity stream seeded from official or first-party sources.", "items": [ { diff --git a/index.html b/index.html index df3e469..ccc9d71 100644 --- a/index.html +++ b/index.html @@ -1,54 +1,46 @@ - + - StackScout // Home - - - + Stack Scout // Home + + + - + - + - -
-
-

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

-
- No fake telemetry - Official sources first - Badges over fake scores -
-
-
+
-

Curated ecosystem // tools, systems, and builder intelligence

-

A cleaner way to track the tools actually shaping modern workflows.

-

StackScout is the public-facing scout deck for fast-moving builder infrastructure: websites, web services, APIs, MCPs, CLIs, and a smaller lab lane for the tools we are building ourselves. It is curated, selective, and designed to stay useful rather than exhaustive.

+

Today's lead // official sources first

+

A field log for the tools worth opening.

+

Stack Scout is a selective, source-led zine for builder infrastructure: APIs, MCPs, CLIs, services, workbench apps, and the lab tools we are building ourselves. It is curated rather than exhaustive, with visible dates and editorial badges instead of fake precision.

-

StackScout works best when you enter through a workflow lane, not a random pile of names.

+

Stack Scout works best when you enter through a workflow lane, not a random pile of names.

@@ -585,9 +577,9 @@

A clearly labelled subset of our own tools.

data-badge="Early but Promising" data-date="2026-04-11" data-priority="1" - data-search="Canvas Planner A visual planning surface for boards, campaign flow, and creative work without the drag of a generic project manager. StackScout Lab The latest public-ready pass cleaned the browser surface and kept the board flow sharp without adding clutter. planning boards creative workflow pwa"> + data-search="Canvas Planner A visual planning surface for boards, campaign flow, and creative work without the drag of a generic project manager. Stack Scout Lab The latest public-ready pass cleaned the browser surface and kept the board flow sharp without adding clutter. planning boards creative workflow pwa">
- StackScout Lab + Stack Scout Lab Early but Promising
@@ -601,7 +593,7 @@

Canvas Planner

campaign planningcreative sequencing
- StackScout Lab + Stack Scout Lab Experimental 11 Apr 2026
@@ -619,9 +611,9 @@

Canvas Planner

data-badge="Early but Promising" data-date="2026-04-12" data-priority="1" - data-search="Signal Stack A publishing planner built around image, video, and queue workflows rather than generic social-media posting dashboards. StackScout Lab The recent execution pass made delivery truth more explicit, but live platform integrations still depend on real credentials and approvals. publishing scheduling creator workflow social"> + data-search="Signal Stack A publishing planner built around image, video, and queue workflows rather than generic social-media posting dashboards. Stack Scout Lab The recent execution pass made delivery truth more explicit, but live platform integrations still depend on real credentials and approvals. publishing scheduling creator workflow social">
- StackScout Lab + Stack Scout Lab Early but Promising
@@ -635,7 +627,7 @@

Signal Stack

creator schedulingqueue design
- StackScout Lab + Stack Scout Lab Experimental 12 Apr 2026
@@ -653,9 +645,9 @@

Signal Stack

data-badge="Worth Watching" data-date="2026-04-12" data-priority="2" - data-search="Strudel Studio A browser-based music studio path that brings programmable patterns, scenes, and samples into a clearer public-facing workflow. StackScout Lab The takeover pass tightened the smoke runner and kept the product moving toward a more serious music workspace. music browser studio coding audio"> + data-search="Strudel Studio A browser-based music studio path that brings programmable patterns, scenes, and samples into a clearer public-facing workflow. Stack Scout Lab The takeover pass tightened the smoke runner and kept the product moving toward a more serious music workspace. music browser studio coding audio">
- StackScout Lab + Stack Scout Lab Worth Watching
@@ -669,7 +661,7 @@

Strudel Studio

browser music prototypingpattern-driven composition
- StackScout Lab + Stack Scout Lab Experimental 12 Apr 2026
@@ -687,9 +679,9 @@

Strudel Studio

data-badge="Early but Promising" data-date="2026-04-12" data-priority="1" - data-search="SyncPad A private, desktop-first notes tool with live sync ambitions and a workflow that stays close to the operator. StackScout Lab The browser and client surfaces are healthier, but the Electron desktop verification path is still blocked by a GPU startup issue on the manager machine. notes desktop private sync knowledge"> + data-search="SyncPad A private, desktop-first notes tool with live sync ambitions and a workflow that stays close to the operator. Stack Scout Lab The browser and client surfaces are healthier, but the Electron desktop verification path is still blocked by a GPU startup issue on the manager machine. notes desktop private sync knowledge">
- StackScout Lab + Stack Scout Lab Early but Promising
@@ -703,7 +695,7 @@

SyncPad

private noteslocal-first drafting
- StackScout Lab + Stack Scout Lab Experimental 12 Apr 2026
@@ -733,7 +725,7 @@

Useful starting packs.

Use-case grouping

-

From the StackScout Lab

+

From the Stack Scout Lab

These are not presented as the whole point of the site. They sit alongside the wider ecosystem and earn their place separately.

Canvas PlannerSignal StackStrudel StudioSyncPad @@ -789,13 +781,59 @@

From the StackScout Lab

diff --git a/manifest.json b/manifest.json index 1b43cbc..b7e1209 100644 --- a/manifest.json +++ b/manifest.json @@ -1,5 +1,5 @@ { - "name": "StackScout", + "name": "Stack Scout", "short_name": "Scout", "description": "A curated public guide to the builder tools, services, APIs, MCPs, and CLIs worth following.", "start_url": "./", diff --git a/method/index.html b/method/index.html index bdbfcd3..8b44939 100644 --- a/method/index.html +++ b/method/index.html @@ -1,54 +1,46 @@ - + - StackScout // Method - - - + Stack Scout // Sources & method + + + - + - + - -
-
-

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

-
- No fake telemetry - Official sources first - Badges over fake scores -
-
-
+

Method

Editorial judgment with visible guardrails.

-

StackScout is a public guide, not a benchmark lab. We badge selectively, update from official sources where possible, and avoid pretending every fast-moving tool deserves a fixed numeric score.

+

Stack Scout is a public guide, not a benchmark lab. We badge selectively, update from official sources where possible, and avoid pretending every fast-moving tool deserves a fixed numeric score.

@@ -56,7 +48,7 @@

Editorial judgment with visible guardrails.

Principles

-

How StackScout decides.

+

How Stack Scout decides.

@@ -157,13 +149,59 @@

Verdict language

diff --git a/package.json b/package.json index 8e4d22d..b8fa461 100644 --- a/package.json +++ b/package.json @@ -2,10 +2,11 @@ "name": "stackscout-site", "version": "0.1.0", "private": true, - "description": "Static build pipeline for the StackScout public tools destination.", + "description": "Static build pipeline for the Stack Scout public tools destination.", "scripts": { "build:site": "node scripts/build-stackscout.js", "refresh:site": "powershell -NoProfile -ExecutionPolicy Bypass -File ./scripts/refresh-stackscout.ps1", - "check": "node --check scripts/build-stackscout.js && node --check app.js && node --check pwa.js" + "check": "node --check scripts/build-stackscout.js && node --check app.js && node --check pwa.js && node --check service-worker.js && node --check scripts/verify-launch-safety.js && node scripts/verify-launch-safety.js", + "verify:launch": "node scripts/verify-launch-safety.js" } } diff --git a/pwa.js b/pwa.js index 839a601..07788f9 100644 --- a/pwa.js +++ b/pwa.js @@ -12,7 +12,7 @@ async function registerStackScoutServiceWorker() { scope: siteRoot, }) } catch (error) { - console.error('StackScout service worker registration failed.', error) + console.error('Stack Scout service worker registration failed.', error) } } diff --git a/radar/index.html b/radar/index.html index 8f2697e..aad5067 100644 --- a/radar/index.html +++ b/radar/index.html @@ -1,54 +1,46 @@ - + - StackScout // Radar + Stack Scout // Radar - + - + - + - -
-
-

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

-
- No fake telemetry - Official sources first - Badges over fake scores -
-
-
+

Radar

Interesting is not the same as ready.

-

Radar is where StackScout puts genuinely interesting systems that still need more evidence before they become default recommendations.

+

Radar is where Stack Scout puts genuinely interesting systems that still need more evidence before they become default recommendations.

@@ -120,13 +112,59 @@

GitHub skills ecosystem

diff --git a/scripts/build-stackscout.js b/scripts/build-stackscout.js index 7019eb2..250398c 100644 --- a/scripts/build-stackscout.js +++ b/scripts/build-stackscout.js @@ -11,15 +11,15 @@ const PRIVATE_PREVIEW_EXPORT_CANDIDATES = [ const BUILD_NOW = new Date() const GENERATED_AT = BUILD_NOW.toISOString().slice(0, 10) const GENERATED_AT_ISO = BUILD_NOW.toISOString() -const PUBLIC_BASE_URL = 'https://koltregaskes.github.io/tools-hub/' +const PUBLIC_BASE_URL = 'https://koltregaskes.github.io/stackscout/' const STATIC_PAGES = [ ['home', 'Home', 'Editorial front door, featured tools, categories, updates, and the lab subset.', 'index.html'], - ['catalog', 'Catalog', 'Searchable, filterable catalog of tracked tools and lab products.', 'catalog/index.html'], + ['catalog', 'Top tools', 'Searchable, filterable catalog of tracked tools and lab products.', 'catalog/index.html'], ['categories', 'Categories', 'Landing page for websites, web services, APIs, MCPs, CLIs, and app lanes.', 'categories/index.html'], - ['updates', 'Updates', 'Recent public activity, releases, direction changes, and noteworthy platform moves.', 'updates/index.html'], + ['updates', 'Wire', 'Recent public activity, releases, direction changes, and noteworthy platform moves.', 'updates/index.html'], ['radar', 'Radar', 'The worth-watching layer for tools and systems that are not yet full recommendations.', 'radar/index.html'], ['collections', 'Collections', 'Curated use-case groupings that make the catalog easier to navigate.', 'collections/index.html'], - ['method', 'Method', 'Public badge definitions, freshness rules, and editorial guardrails.', 'method/index.html'], + ['method', 'Sources & method', 'Public badge definitions, freshness rules, and editorial guardrails.', 'method/index.html'], ].map(([key, title, summary, outputPath]) => ({ key, title, summary, outputPath })) const BADGE_ORDER = ['Recommended', 'Specialist Pick', 'Worth Watching', 'Early but Promising'] const CATEGORY_LABELS = { @@ -195,7 +195,7 @@ function scopeTone(scope) { function buildPageRegistry(tools, categories, collections) { return { - title: 'StackScout // Page Registry', + title: 'Stack Scout // Page Registry', generatedAt: GENERATED_AT, pages: [ ...STATIC_PAGES.map((page) => ({ @@ -231,10 +231,10 @@ function buildPageRegistry(tools, categories, collections) { function buildToolManifest(tools, categories) { return { - title: 'StackScout // Tools Manifest', + title: 'Stack Scout // Tools Manifest', generatedAt: GENERATED_AT, updatedAt: GENERATED_AT, - summary: 'Public-safe catalog for StackScout.', + summary: 'Public-safe catalog for Stack Scout.', counts: { total: tools.length, ecosystem: tools.filter((tool) => tool.scope === 'ecosystem').length, @@ -247,7 +247,7 @@ function buildToolManifest(tools, categories) { function buildCategoriesManifest(categories, tools) { return { - title: 'StackScout // Categories', + title: 'Stack Scout // Categories', generatedAt: GENERATED_AT, updatedAt: GENERATED_AT, categories: categories.map((category) => ({ @@ -260,7 +260,7 @@ function buildCategoriesManifest(categories, tools) { function buildUpdatesManifest(updates, toolIndex) { return { - title: 'StackScout // Updates', + title: 'Stack Scout // Updates', generatedAt: GENERATED_AT, updatedAt: GENERATED_AT, summary: 'Public-safe activity stream seeded from official or first-party sources.', @@ -274,7 +274,7 @@ function buildUpdatesManifest(updates, toolIndex) { function buildMethodologyManifest(site) { return { - title: 'StackScout // Methodology', + title: 'Stack Scout // Methodology', generatedAt: GENERATED_AT, updatedAt: GENERATED_AT, thesis: site.methodology.thesis, @@ -288,7 +288,7 @@ function buildMethodologyManifest(site) { function buildCollectionsManifest(collections, toolIndex) { return { - title: 'StackScout // Collections', + title: 'Stack Scout // Collections', generatedAt: GENERATED_AT, updatedAt: GENERATED_AT, collections: collections.map((collection) => ({ @@ -304,7 +304,7 @@ function buildCollectionsManifest(collections, toolIndex) { function buildRadarManifest(radar) { return { - title: 'StackScout // Radar', + title: 'Stack Scout // Radar', generatedAt: GENERATED_AT, updatedAt: GENERATED_AT, items: radar, @@ -315,7 +315,7 @@ function buildPublishingPreview(tools, updates, categories) { return { generatedAt: GENERATED_AT, generatedAtIso: GENERATED_AT_ISO, - title: 'StackScout public export preview', + title: 'Stack Scout public export preview', catalogCount: tools.length, updateCount: updates.length, categoryCount: categories.length, @@ -392,7 +392,7 @@ function renderToolCard(tool, outputPath, compact = false) { data-priority="${escapeHtml(String(BADGE_ORDER.length - BADGE_ORDER.indexOf(tool.badge)))}" data-search="${escapeHtml([tool.name, tool.summary, tool.publisher, tool.latestTrackedChange, tool.tags.join(' ')].join(' '))}">
- ${escapeHtml(tool.scope === 'lab' ? 'StackScout Lab' : 'Ecosystem')} + ${escapeHtml(tool.scope === 'lab' ? 'Stack Scout Lab' : 'Ecosystem')} ${escapeHtml(tool.badge)}
@@ -520,61 +520,101 @@ function renderNav(currentKey, outputPath) { function renderDocument({ title, description, currentKey, outputPath, content }) { const homeHref = outputHref(outputPath, 'index.html') const siteRoot = homeHref === './' ? './' : homeHref + const sourceHref = outputHref(outputPath, 'method/index.html') + const rootClass = 'mood-graphite' return ` - + - ${escapeHtml(title)} + ${escapeHtml(title.replaceAll('StackScout', 'Stack Scout'))} - + - + - + - -
-
-

Issue ${escapeHtml(GENERATED_AT)} // Curated public signal for builders

-
- No fake telemetry - Official sources first - Badges over fake scores -
-
-
+
${content}
-
- -

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

+ + +
@@ -596,7 +636,7 @@ function renderHome(site, tools, updates, categories, collections, outputPath) { const labCount = labTools.length return renderDocument({ - title: 'StackScout // Home', + title: 'Stack Scout // Home', description: site.brand.description, currentKey: 'home', outputPath, @@ -625,9 +665,9 @@ function renderHome(site, tools, updates, categories, collections, outputPath) {

${escapeHtml(spotlightUpdate?.title || 'Fresh public movement')}

${escapeHtml(spotlightUpdate?.summary || site.brand.description)}

- ${escapeHtml(spotlightTool?.name || 'StackScout')} + ${escapeHtml(spotlightTool?.name || 'Stack Scout')} ${escapeHtml(spotlightUpdate ? formatDate(spotlightUpdate.publishedAt) : formatDate(GENERATED_AT))} - ${escapeHtml(spotlightUpdate?.sourceLabel || 'StackScout')} + ${escapeHtml(spotlightUpdate?.sourceLabel || 'Stack Scout')}
-

StackScout works best when you enter through a workflow lane, not a random pile of names.

+

Stack Scout works best when you enter through a workflow lane, not a random pile of names.

${categories.map((category) => renderCategoryCard(category, tools.filter((tool) => tool.category === category.slug), outputPath)).join('')} @@ -804,8 +844,8 @@ function renderCatalog(tools, categories, outputPath) { const newestTracked = [...tools].sort((left, right) => right.lastUpdatedAt.localeCompare(left.lastUpdatedAt))[0] return renderDocument({ - title: 'StackScout // Catalog', - description: 'Searchable StackScout catalog of tracked ecosystem tools and lab products.', + title: 'Stack Scout // Top tools', + description: 'Searchable Stack Scout catalog of tracked ecosystem tools and lab products.', currentKey: 'catalog', outputPath, content: ` @@ -847,7 +887,7 @@ function renderCatalog(tools, categories, outputPath) { - StackScout Lab + Stack Scout Lab Clearly labelled in-house tools @@ -925,7 +965,7 @@ function renderCatalog(tools, categories, outputPath) { function renderToolDetail(tool, relatedTools, toolUpdates, outputPath) { return renderDocument({ - title: `StackScout // ${tool.name}`, + title: `Stack Scout // ${tool.name}`, description: tool.summary, currentKey: 'catalog', outputPath, @@ -933,7 +973,7 @@ function renderToolDetail(tool, relatedTools, toolUpdates, outputPath) {
- ${escapeHtml(tool.scope === 'lab' ? 'StackScout Lab' : 'Ecosystem')} + ${escapeHtml(tool.scope === 'lab' ? 'Stack Scout Lab' : 'Ecosystem')} ${escapeHtml(tool.badge)} ${escapeHtml(tool.maturity)}
@@ -971,7 +1011,7 @@ function renderToolDetail(tool, relatedTools, toolUpdates, outputPath) {

Why it matters

-

StackScout verdict

+

Stack Scout verdict

@@ -1039,8 +1079,8 @@ function renderToolDetail(tool, relatedTools, toolUpdates, outputPath) { function renderCategoriesIndex(categories, tools, outputPath) { return renderDocument({ - title: 'StackScout // Categories', - description: 'All public StackScout lanes in one place.', + title: 'Stack Scout // Categories', + description: 'All public Stack Scout lanes in one place.', currentKey: 'categories', outputPath, content: ` @@ -1062,7 +1102,7 @@ function renderCategoriesIndex(categories, tools, outputPath) { function renderCategoryDetail(category, tools, outputPath) { return renderDocument({ - title: `StackScout // ${category.title}`, + title: `Stack Scout // ${category.title}`, description: category.description, currentKey: 'categories', outputPath, @@ -1090,8 +1130,8 @@ function renderCategoryDetail(category, tools, outputPath) { function renderUpdates(updates, toolIndex, outputPath) { return renderDocument({ - title: 'StackScout // Updates', - description: 'Recent public activity from the StackScout cohort.', + title: 'Stack Scout // Wire', + description: 'Recent public activity from the Stack Scout cohort.', currentKey: 'updates', outputPath, content: ` @@ -1111,7 +1151,7 @@ function renderUpdates(updates, toolIndex, outputPath) { function renderRadar(site, outputPath) { return renderDocument({ - title: 'StackScout // Radar', + title: 'Stack Scout // Radar', description: 'Worth-watching tools and systems that are not yet full recommendations.', currentKey: 'radar', outputPath, @@ -1120,7 +1160,7 @@ function renderRadar(site, outputPath) {

Radar

Interesting is not the same as ready.

-

Radar is where StackScout puts genuinely interesting systems that still need more evidence before they become default recommendations.

+

Radar is where Stack Scout puts genuinely interesting systems that still need more evidence before they become default recommendations.

@@ -1132,8 +1172,8 @@ function renderRadar(site, outputPath) { function renderCollections(collections, toolIndex, outputPath) { return renderDocument({ - title: 'StackScout // Collections', - description: 'Curated collections that group the StackScout catalog by real use case.', + title: 'Stack Scout // Collections', + description: 'Curated collections that group the Stack Scout catalog by real use case.', currentKey: 'collections', outputPath, content: ` @@ -1153,8 +1193,8 @@ function renderCollections(collections, toolIndex, outputPath) { function renderMethod(site, outputPath) { return renderDocument({ - title: 'StackScout // Method', - description: 'How StackScout curates, badges, and updates public entries.', + title: 'Stack Scout // Sources & method', + description: 'How Stack Scout curates, badges, and updates public entries.', currentKey: 'method', outputPath, content: ` @@ -1170,7 +1210,7 @@ function renderMethod(site, outputPath) {

Principles

-

How StackScout decides.

+

How Stack Scout decides.

@@ -1239,7 +1279,8 @@ ${routes.map((route) => ` ${PUBLIC_BASE_URL}${route}`).jo } function main() { - const privatePreviewExport = resolveWritableExternalPath(PRIVATE_PREVIEW_EXPORT_CANDIDATES) + const privatePreviewExport = + process.platform === 'win32' ? resolveWritableExternalPath(PRIVATE_PREVIEW_EXPORT_CANDIDATES) : null 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 +1295,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')) @@ -1297,7 +1340,7 @@ function main() { writeFile('sitemap.xml', buildSitemap(sitemapRoutes)) console.log( - `StackScout build complete. Generated ${tools.length} tool pages, ${categories.length} category pages, and ${updates.length} updates.`, + `Stack Scout build complete. Generated ${tools.length} tool pages, ${categories.length} category pages, and ${updates.length} updates.`, ) } diff --git a/scripts/refresh-stackscout.ps1 b/scripts/refresh-stackscout.ps1 index 2ee63e4..fe3be49 100644 --- a/scripts/refresh-stackscout.ps1 +++ b/scripts/refresh-stackscout.ps1 @@ -25,7 +25,7 @@ foreach ($candidate in $privateDataDirCandidates) { } if (-not $privateDataDir) { - throw 'Unable to resolve a writable private data directory for StackScout refresh status.' + throw 'Unable to resolve a writable private data directory for Stack Scout refresh status.' } $statusFile = Join-Path $privateDataDir 'stackscout-refresh-status.json' @@ -123,19 +123,19 @@ function Invoke-RefreshStep { } } -Write-RefreshStatus -State 'running' -Message 'StackScout refresh started.' -Extra @{ +Write-RefreshStatus -State 'running' -Message 'Stack Scout refresh started.' -Extra @{ lastSuccessAt = $previousLastSuccessAt } Push-Location $repoRoot try { - Invoke-RefreshStep -Label 'Build StackScout' -ScriptBlock { + Invoke-RefreshStep -Label 'Build Stack Scout' -ScriptBlock { & node 'scripts/build-stackscout.js' } if (-not $SkipCheck) { - Invoke-RefreshStep -Label 'Check StackScout' -ScriptBlock { + Invoke-RefreshStep -Label 'Check Stack Scout' -ScriptBlock { & cmd /c 'npm run check' } } @@ -145,13 +145,13 @@ try { $categoriesManifest = Read-JsonFile -Path $categoriesManifestFile if (-not $toolsManifest) { - throw 'StackScout refresh completed but tools-manifest.json could not be read.' + throw 'Stack Scout refresh completed but tools-manifest.json could not be read.' } $durationStopwatch.Stop() $completedAt = (Get-Date).ToUniversalTime().ToString('o') - Write-RefreshStatus -State 'ok' -Message 'StackScout refresh completed successfully.' -Extra @{ + Write-RefreshStatus -State 'ok' -Message 'Stack Scout refresh completed successfully.' -Extra @{ completedAt = $completedAt lastSuccessAt = $completedAt durationMs = [int][Math]::Round($durationStopwatch.Elapsed.TotalMilliseconds) diff --git a/scripts/verify-launch-safety.js b/scripts/verify-launch-safety.js new file mode 100644 index 0000000..282dedd --- /dev/null +++ b/scripts/verify-launch-safety.js @@ -0,0 +1,219 @@ +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', +] +const MONTH_NUMBERS = { + Jan: '01', + Feb: '02', + Mar: '03', + Apr: '04', + May: '05', + Jun: '06', + Jul: '07', + Aug: '08', + Sep: '09', + Oct: '10', + Nov: '11', + Dec: '12', +} + +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(/Updated ([0-9]{1,2}) (Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec) ([0-9]{4})/) + if (!issueMatch) { + return new Date().toISOString().slice(0, 10) + } + + return `${issueMatch[3]}-${MONTH_NUMBERS[issueMatch[2]]}-${issueMatch[1].padStart(2, '0')}` +} + +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() + if (cacheDateMatch[1] < issueDate) { + throw new Error(`CACHE_NAME ${cacheName} is older than visible generated date ${issueDate}.`) + } + + 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 } +} + +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(`Stack Scout launch safety passed: ${publicFiles.length} public files scanned, CACHE_NAME=${freshness.cacheName}.`) +} + +try { + main() +} catch (error) { + console.error(`Stack Scout launch safety failed: ${error.message}`) + process.exit(1) +} diff --git a/service-worker.js b/service-worker.js index b4064f1..bcf97f5 100644 --- a/service-worker.js +++ b/service-worker.js @@ -1,4 +1,4 @@ -const CACHE_NAME = 'stackscout-v1' +const CACHE_NAME = 'stackscout-2026-05-25' const APP_SHELL = [ '', 'index.html', diff --git a/sitemap.xml b/sitemap.xml index ce2b1b3..fcb4802 100644 --- a/sitemap.xml +++ b/sitemap.xml @@ -1,31 +1,31 @@ - https://koltregaskes.github.io/tools-hub/ - https://koltregaskes.github.io/tools-hub/catalog/ - https://koltregaskes.github.io/tools-hub/categories/ - https://koltregaskes.github.io/tools-hub/updates/ - https://koltregaskes.github.io/tools-hub/radar/ - https://koltregaskes.github.io/tools-hub/collections/ - https://koltregaskes.github.io/tools-hub/method/ - https://koltregaskes.github.io/tools-hub/categories/websites/ - https://koltregaskes.github.io/tools-hub/categories/web-services/ - https://koltregaskes.github.io/tools-hub/categories/apis/ - https://koltregaskes.github.io/tools-hub/categories/mcps/ - https://koltregaskes.github.io/tools-hub/categories/clis/ - https://koltregaskes.github.io/tools-hub/categories/web-apps/ - https://koltregaskes.github.io/tools-hub/categories/desktop-apps/ - https://koltregaskes.github.io/tools-hub/tools/perplexity/ - https://koltregaskes.github.io/tools-hub/tools/hugging-face/ - https://koltregaskes.github.io/tools-hub/tools/n8n/ - https://koltregaskes.github.io/tools-hub/tools/make/ - https://koltregaskes.github.io/tools-hub/tools/openai-api/ - https://koltregaskes.github.io/tools-hub/tools/anthropic-api/ - https://koltregaskes.github.io/tools-hub/tools/github-mcp-server/ - https://koltregaskes.github.io/tools-hub/tools/playwright-mcp/ - https://koltregaskes.github.io/tools-hub/tools/gh-cli/ - https://koltregaskes.github.io/tools-hub/tools/wrangler/ - https://koltregaskes.github.io/tools-hub/tools/canvas-planner/ - https://koltregaskes.github.io/tools-hub/tools/signal-stack/ - https://koltregaskes.github.io/tools-hub/tools/strudel-studio/ - https://koltregaskes.github.io/tools-hub/tools/syncpad/ + https://koltregaskes.github.io/stackscout/ + https://koltregaskes.github.io/stackscout/catalog/ + https://koltregaskes.github.io/stackscout/categories/ + https://koltregaskes.github.io/stackscout/updates/ + https://koltregaskes.github.io/stackscout/radar/ + https://koltregaskes.github.io/stackscout/collections/ + https://koltregaskes.github.io/stackscout/method/ + https://koltregaskes.github.io/stackscout/categories/websites/ + https://koltregaskes.github.io/stackscout/categories/web-services/ + https://koltregaskes.github.io/stackscout/categories/apis/ + https://koltregaskes.github.io/stackscout/categories/mcps/ + https://koltregaskes.github.io/stackscout/categories/clis/ + https://koltregaskes.github.io/stackscout/categories/web-apps/ + https://koltregaskes.github.io/stackscout/categories/desktop-apps/ + https://koltregaskes.github.io/stackscout/tools/perplexity/ + https://koltregaskes.github.io/stackscout/tools/hugging-face/ + https://koltregaskes.github.io/stackscout/tools/n8n/ + https://koltregaskes.github.io/stackscout/tools/make/ + https://koltregaskes.github.io/stackscout/tools/openai-api/ + https://koltregaskes.github.io/stackscout/tools/anthropic-api/ + https://koltregaskes.github.io/stackscout/tools/github-mcp-server/ + https://koltregaskes.github.io/stackscout/tools/playwright-mcp/ + https://koltregaskes.github.io/stackscout/tools/gh-cli/ + https://koltregaskes.github.io/stackscout/tools/wrangler/ + https://koltregaskes.github.io/stackscout/tools/canvas-planner/ + https://koltregaskes.github.io/stackscout/tools/signal-stack/ + https://koltregaskes.github.io/stackscout/tools/strudel-studio/ + https://koltregaskes.github.io/stackscout/tools/syncpad/ diff --git a/styles.css b/styles.css index 8442938..4c98f42 100644 --- a/styles.css +++ b/styles.css @@ -320,7 +320,7 @@ h3, .lead { margin: 0; font-family: "Fraunces", Georgia, serif; - letter-spacing: -0.035em; + letter-spacing: 0; } h1 { @@ -914,3 +914,782 @@ h3 { transform: none; } } + +/* Stack Scout zine refined system */ +:root { + --ink: #ede5d3; + --muted: #7d8086; + --rule: rgba(237, 229, 211, 0.18); + --rule-strong: rgba(237, 229, 211, 0.45); + --zine-max: min(1320px, calc(100vw - 40px)); + --zine-pad: clamp(18px, 4vw, 56px); + --text: var(--ink); + --soft: var(--muted); + --line: var(--rule); + --line-strong: var(--rule-strong); + --acid: var(--accent); + --ice: var(--accent); + --ember: var(--accent); + --violet: var(--accent); +} + +html.mood-graphite { + --bg: #14171c; + --accent: #6dbab1; +} + +html.mood-midnight { + --bg: #0f1622; + --accent: #7fb8d2; +} + +html.mood-obsidian { + --bg: #0a0c0f; + --accent: #6dd5b8; +} + +html.mood-slate { + --bg: #1a1d22; + --accent: #8ec2a8; +} + +html.mood-carbon { + --bg: #181b22; + --accent: #88bdd1; +} + +html { + color-scheme: dark; + background: var(--bg); +} + +body { + color: var(--ink); + background: var(--bg); + font-family: "Newsreader", Georgia, serif; + transition: background 500ms ease, color 400ms ease; +} + +body::selection, +::selection { + background: var(--accent); + color: var(--bg); +} + +body::after, +.ss-grain { + content: ""; + position: fixed; + inset: 0; + z-index: 1; + pointer-events: none; + opacity: 0.035; + mix-blend-mode: overlay; + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)' opacity='0.5'/%3E%3C/svg%3E"); +} + +a { + text-decoration-thickness: 1px; + text-underline-offset: 0.18em; +} + +.atmosphere, +.site-meta-bar { + display: none; +} + +.site-header, +.page-shell, +.site-footer { + width: var(--zine-max); + position: relative; + z-index: 2; +} + +.site-header { + top: auto; + position: relative; + display: flex; + justify-content: space-between; + align-items: baseline; + gap: 28px; + margin: 0 auto; + padding: 30px 0 16px; + border: 0; + border-bottom: 1.5px solid var(--rule-strong); + border-radius: 0; + background: transparent; + box-shadow: none; + backdrop-filter: none; +} + +.site-brand { + gap: 12px; +} + +.site-brand__mark { + width: 10px; + height: 10px; + border: 0; + border-radius: 999px; + background: var(--accent); + box-shadow: none; + transform: translateY(-2px); +} + +.site-brand__wordmark, +.site-footer__brand { + font-family: "Newsreader", Georgia, serif; + font-size: clamp(1.8rem, 3vw, 2.25rem); + font-weight: 700; + letter-spacing: 0; + line-height: 1; + text-transform: none; +} + +.site-brand__wordmark span, +.site-footer__brand span { + color: var(--accent); + font-style: italic; +} + +.site-header__right { + display: inline-flex; + align-items: center; + gap: 28px; + min-width: 0; +} + +.site-nav { + gap: 22px; +} + +.site-nav a, +.site-header__utility { + min-height: auto; + padding: 4px 0 5px; + border: 0; + border-bottom: 2px solid transparent; + border-radius: 0; + background: transparent; + color: var(--muted); + font-family: "IBM Plex Mono", monospace; + font-size: 0.72rem; + font-weight: 500; + letter-spacing: 0.16em; + text-transform: uppercase; +} + +.site-nav a:hover, +.site-nav a:focus-visible, +.site-nav a[aria-current="page"], +.site-header__utility:hover, +.site-header__utility:focus-visible { + color: var(--ink); + border-color: var(--accent); + background: transparent; + transform: none; +} + +.mood-switcher { + display: inline-flex; + align-items: center; + gap: 9px; +} + +.mood-switcher__button { + width: 15px; + height: 15px; + padding: 0; + border: 1px solid var(--rule-strong); + border-radius: 999px; + background: var(--accent); + cursor: pointer; +} + +.mood-switcher__button[data-mood="graphite"] { + background: #6dbab1; +} + +.mood-switcher__button[data-mood="midnight"] { + background: #7fb8d2; +} + +.mood-switcher__button[data-mood="obsidian"] { + background: #6dd5b8; +} + +.mood-switcher__button[data-mood="slate"] { + background: #8ec2a8; +} + +.mood-switcher__button[data-mood="carbon"] { + background: #88bdd1; +} + +.mood-switcher__button.is-active { + outline: 2px solid color-mix(in srgb, var(--accent) 55%, transparent); + outline-offset: 3px; +} + +.page-shell { + margin: 0 auto; + padding: 28px 0 72px; +} + +h1, +h2, +h3, +.hero h1, +.hero h2, +.section-head h2, +.scout-card h3 { + color: var(--ink); + font-family: "Newsreader", Georgia, serif; + letter-spacing: 0; +} + +h1, +.hero h1 { + max-width: 12ch; + font-size: clamp(4rem, 10vw, 7.2rem); + font-weight: 700; + line-height: 0.95; +} + +.hero__lede, +.section-copy, +.summary, +.card-note, +.content-panel p, +.text-list, +.site-footer p { + color: var(--muted); + font-family: "Newsreader", Georgia, serif; + line-height: 1.55; +} + +.eyebrow, +.label, +.pill, +.chip, +.token, +.hero-panel__meta, +.scout-card__meta, +.catalog-results, +.site-footer__links span, +.site-footer__meta, +.site-footer__marquee { + font-family: "IBM Plex Mono", Consolas, monospace; + letter-spacing: 0.16em; + text-transform: uppercase; +} + +.eyebrow, +.label { + color: var(--accent); + font-weight: 700; +} + +.hero, +.section-block, +.content-panel, +.catalog-panel, +.hero-panel, +.scout-card, +.signal-chip, +.brief-link, +.tool-detail-panel { + border-radius: 0; + background: transparent; + box-shadow: none; +} + +.hero, +.section-block { + padding: 30px 0; + border: 0; + border-top: 1px solid var(--rule-strong); +} + +.hero:first-child { + border-top: 0; +} + +.hero--home, +.hero--launch { + display: grid; + grid-template-columns: minmax(0, 1.35fr) minmax(320px, 0.85fr); + gap: clamp(28px, 5vw, 58px); + align-items: start; +} + +.hero--inner, +.hero--detail { + display: grid; + grid-template-columns: minmax(0, 1fr) minmax(260px, 0.42fr); + gap: clamp(20px, 4vw, 40px); + padding: 20px 0 18px; +} + +.hero--inner h1, +.hero--detail h1 { + max-width: none; + font-size: clamp(2.4rem, 5vw, 4rem); + line-height: 1; +} + +.hero--inner .hero__lede, +.hero--detail .hero__lede { + max-width: 760px; +} + +.hero__copy { + display: flex; + flex-direction: column; + gap: 16px; +} + +.hero__rail { + display: grid; + gap: 18px; +} + +.hero-panel, +.catalog-panel, +.content-panel { + padding: 16px 0; + border: 0; + border-top: 1px solid var(--rule-strong); +} + +.hero-panel__meta, +.scout-card__meta { + color: var(--muted); + font-size: 0.68rem; +} + +.hero-stat-grid { + display: grid; + grid-template-columns: repeat(2, minmax(0, 1fr)); + gap: 14px; +} + +.hero-stat-tile, +.hero-stat, +.metric-row, +.method-note, +.catalog-results { + padding: 0; + border: 0; + background: transparent; +} + +.hero-stat-tile { + border-top: 1px dashed var(--rule); + padding-top: 12px; +} + +.hero-stat-tile span, +.hero-stat span, +.metric-row span { + color: var(--muted); + font-family: "IBM Plex Mono", Consolas, monospace; + font-size: 0.68rem; + letter-spacing: 0.14em; + text-transform: uppercase; +} + +.hero-stat-tile strong, +.hero-stat strong, +.metric-row strong { + color: var(--accent); + font-family: "Newsreader", Georgia, serif; + font-size: clamp(2rem, 5vw, 3.2rem); + line-height: 1; +} + +.button { + min-height: auto; + width: auto; + padding: 0 0 4px; + border: 0; + border-bottom: 1px solid currentColor; + border-radius: 0; + background: transparent; + color: var(--ink); + font-family: "Newsreader", Georgia, serif; + font-size: 1rem; + font-weight: 650; + text-decoration: none; +} + +.button--primary { + color: var(--accent); +} + +.button--ghost { + color: var(--muted); +} + +.button:hover, +.button:focus-visible { + color: var(--accent); + background: transparent; + border-color: var(--accent); + transform: none; +} + +.hero__actions, +.hero__command-row, +.chip-row, +.token-list { + gap: 14px; +} + +.token, +.chip, +.pill, +.tool-filter-link, +select, +input[type="search"] { + border: 1px solid var(--rule); + border-radius: 999px; + background: transparent; + color: var(--muted); +} + +.token--link:hover, +.token--link:focus-visible, +.pill--green, +.pill--blue, +.pill--amber, +.pill--violet { + color: var(--accent); + border-color: var(--accent); + background: color-mix(in srgb, var(--accent) 10%, transparent); +} + +.signal-strip, +.home-split, +.tool-detail-grid, +.catalog-layout, +.content-grid, +.category-grid { + gap: clamp(22px, 4vw, 38px); +} + +.signal-strip { + padding: 18px 0 28px; + border-top: 1px solid var(--rule-strong); +} + +.signal-chip { + min-height: auto; + padding: 0 0 0 16px; + border: 0; + border-left: 1px solid var(--rule); +} + +.card-grid { + gap: 0; +} + +.card-grid--featured, +.card-grid--catalog, +.activity-grid { + display: grid; + grid-template-columns: 1fr; +} + +.scout-card { + display: grid; + gap: 12px; + padding: 18px 0; + border: 0; + border-top: 1px dashed var(--rule); +} + +.scout-card:first-child { + border-top-style: solid; + border-top-color: var(--rule-strong); +} + +.scout-card:hover { + transform: none; +} + +.scout-card:hover::before { + opacity: 0; +} + +.scout-card__topline { + justify-content: flex-start; +} + +.signal-mark { + display: none; +} + +.scout-card h3 { + font-size: clamp(1.35rem, 3vw, 2.15rem); + line-height: 1.08; +} + +.scout-card__actions { + justify-content: flex-start; +} + +.section-head { + gap: 28px; + align-items: end; +} + +.section-head h2 { + font-size: clamp(2.2rem, 6vw, 4.4rem); + font-style: italic; + line-height: 0.98; +} + +.catalog-layout { + display: grid; + grid-template-columns: minmax(220px, 0.35fr) minmax(0, 1fr); +} + +.catalog-sidebar { + position: sticky; + top: 20px; + align-self: start; +} + +.catalog-toolbar, +.filter-grid { + display: grid; + gap: 12px; +} + +input[type="search"], +select { + width: 100%; + min-height: 42px; + padding: 0 14px; + outline: none; + color: var(--ink); +} + +input[type="search"]:focus, +select:focus { + border-color: var(--accent); +} + +.brief-link { + padding: 12px 0; + border: 0; + border-top: 1px dashed var(--rule); +} + +.text-list li { + border-color: var(--rule); +} + +.site-footer { + display: block; + margin: 0 auto; + padding: 0 0 30px; + border: 0; + border-top: 1.5px solid var(--rule-strong); +} + +.site-footer__marquee { + width: 100%; + margin: 0; + padding: 12px 0; + overflow: hidden; + border-bottom: 1px solid var(--rule); + color: var(--ink); + font-size: 0.68rem; +} + +.site-footer__marquee-track { + display: flex; + width: max-content; + gap: 28px; + white-space: nowrap; + animation: ss-marquee-scroll 38s linear infinite; +} + +.site-footer__marquee:hover .site-footer__marquee-track { + animation-play-state: paused; +} + +.site-footer__marquee span::before { + content: "x "; + color: var(--accent); +} + +.site-footer__grid { + display: grid; + grid-template-columns: minmax(0, 1.2fr) repeat(3, minmax(150px, 1fr)); + gap: clamp(22px, 4vw, 40px); + padding: 26px 0; +} + +.site-footer__brand { + margin: 0 0 8px; +} + +.site-footer__links { + display: grid; + align-content: start; + gap: 9px; +} + +.site-footer__links span, +.site-footer__estate span { + color: var(--accent); + font-size: 0.68rem; + font-weight: 700; +} + +.site-footer a { + color: var(--muted); + text-decoration: none; +} + +.site-footer a:hover, +.site-footer a:focus-visible { + color: var(--accent); +} + +.site-footer__estate { + display: grid; + grid-template-columns: minmax(160px, 0.8fr) minmax(240px, 1.5fr) auto; + gap: 22px; + align-items: center; + padding: 22px 0; + border-top: 1px solid var(--rule); +} + +.site-footer__estate a:first-of-type { + display: block; + margin-top: 6px; + color: var(--ink); + font-family: "Newsreader", Georgia, serif; + font-size: clamp(1.4rem, 3vw, 2rem); + font-weight: 700; +} + +.site-footer__estate > a { + color: var(--accent); + font-family: "IBM Plex Mono", Consolas, monospace; + font-size: 0.72rem; + letter-spacing: 0.14em; + text-transform: uppercase; + white-space: nowrap; +} + +.site-footer__meta { + display: flex; + justify-content: space-between; + gap: 18px; + padding-top: 14px; + border-top: 1px solid var(--rule); + color: var(--muted); + font-size: 0.68rem; +} + +.live-dot { + display: inline-block; + width: 8px; + height: 8px; + margin-right: 8px; + border-radius: 999px; + background: var(--accent); + animation: ss-pulse 2.4s ease-in-out infinite; +} + +@keyframes ss-marquee-scroll { + from { + transform: translateX(0); + } + + to { + transform: translateX(-50%); + } +} + +@keyframes ss-pulse { + 0%, + 100% { + opacity: 0.4; + transform: scale(0.9); + } + + 50% { + opacity: 1; + transform: scale(1.15); + } +} + +@media (max-width: 980px) { + .site-header, + .site-header__right { + align-items: flex-start; + flex-direction: column; + } + + .site-nav { + width: 100%; + } + + .hero--home, + .hero--launch, + .hero--inner, + .hero--detail, + .catalog-layout, + .home-split, + .tool-detail-grid, + .site-footer__grid, + .site-footer__estate { + grid-template-columns: 1fr; + } + + .catalog-sidebar { + position: static; + } + + h1, + .hero h1 { + max-width: none; + } +} + +@media (max-width: 640px) { + :root { + --zine-max: min(100vw - 24px, 1320px); + } + + .site-nav a, + .site-header__utility, + .button { + width: auto; + justify-content: flex-start; + } + + .site-nav { + gap: 14px; + } + + .mood-switcher { + flex-wrap: wrap; + } + + .hero, + .section-block { + padding: 24px 0; + } + + .site-footer__meta { + flex-direction: column; + } +} diff --git a/tools/anthropic-api/index.html b/tools/anthropic-api/index.html index 04c0cb6..00f4859 100644 --- a/tools/anthropic-api/index.html +++ b/tools/anthropic-api/index.html @@ -1,47 +1,39 @@ - + - StackScout // Anthropic API + Stack Scout // Anthropic API - + - + - + - -
-
-

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

-
- No fake telemetry - Official sources first - Badges over fake scores -
-
-
+
@@ -85,7 +77,7 @@

Anthropic API

Why it matters

-

StackScout verdict

+

Stack Scout verdict

@@ -267,13 +259,59 @@

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..30981ec 100644 --- a/tools/canvas-planner/index.html +++ b/tools/canvas-planner/index.html @@ -1,53 +1,45 @@ - + - StackScout // Canvas Planner + Stack Scout // Canvas Planner - + - + - + - -
-
-

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

-
- No fake telemetry - Official sources first - Badges over fake scores -
-
-
+
- StackScout Lab + Stack Scout Lab Early but Promising Experimental
@@ -64,7 +56,7 @@

Canvas Planner

Publisher - StackScout Lab + Stack Scout Lab

Web App / Web Apps

@@ -85,7 +77,7 @@

Canvas Planner

Why it matters

-

StackScout verdict

+

Stack Scout verdict

@@ -169,9 +161,9 @@

What sits nearby.

data-badge="Early but Promising" data-date="2026-04-12" data-priority="1" - data-search="Signal Stack A publishing planner built around image, video, and queue workflows rather than generic social-media posting dashboards. StackScout Lab The recent execution pass made delivery truth more explicit, but live platform integrations still depend on real credentials and approvals. publishing scheduling creator workflow social"> + data-search="Signal Stack A publishing planner built around image, video, and queue workflows rather than generic social-media posting dashboards. Stack Scout Lab The recent execution pass made delivery truth more explicit, but live platform integrations still depend on real credentials and approvals. publishing scheduling creator workflow social">
- StackScout Lab + Stack Scout Lab Early but Promising
@@ -185,7 +177,7 @@

Signal Stack

creator schedulingqueue design
- StackScout Lab + Stack Scout Lab Experimental 12 Apr 2026
@@ -203,9 +195,9 @@

Signal Stack

data-badge="Early but Promising" data-date="2026-04-12" data-priority="1" - data-search="SyncPad A private, desktop-first notes tool with live sync ambitions and a workflow that stays close to the operator. StackScout Lab The browser and client surfaces are healthier, but the Electron desktop verification path is still blocked by a GPU startup issue on the manager machine. notes desktop private sync knowledge"> + data-search="SyncPad A private, desktop-first notes tool with live sync ambitions and a workflow that stays close to the operator. Stack Scout Lab The browser and client surfaces are healthier, but the Electron desktop verification path is still blocked by a GPU startup issue on the manager machine. notes desktop private sync knowledge">
- StackScout Lab + Stack Scout Lab Early but Promising
@@ -219,7 +211,7 @@

SyncPad

private noteslocal-first drafting
- StackScout Lab + Stack Scout Lab Experimental 12 Apr 2026
@@ -233,13 +225,59 @@

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..4ce2c98 100644 --- a/tools/gh-cli/index.html +++ b/tools/gh-cli/index.html @@ -1,47 +1,39 @@ - + - StackScout // GitHub CLI + Stack Scout // GitHub CLI - + - + - + - -
-
-

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

-
- No fake telemetry - Official sources first - Badges over fake scores -
-
-
+
@@ -85,7 +77,7 @@

GitHub CLI

Why it matters

-

StackScout verdict

+

Stack Scout verdict

@@ -233,13 +225,59 @@

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..9729a00 100644 --- a/tools/github-mcp-server/index.html +++ b/tools/github-mcp-server/index.html @@ -1,47 +1,39 @@ - + - StackScout // GitHub MCP Server + Stack Scout // GitHub MCP Server - + - + - + - -
-
-

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

-
- No fake telemetry - Official sources first - Badges over fake scores -
-
-
+
@@ -85,7 +77,7 @@

GitHub MCP Server

Why it matters

-

StackScout verdict

+

Stack Scout verdict

@@ -267,13 +259,59 @@

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..5cec48b 100644 --- a/tools/hugging-face/index.html +++ b/tools/hugging-face/index.html @@ -1,47 +1,39 @@ - + - StackScout // Hugging Face + Stack Scout // Hugging Face - + - + - + - -
-
-

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

-
- No fake telemetry - Official sources first - Badges over fake scores -
-
-
+
@@ -85,7 +77,7 @@

Hugging Face

Why it matters

-

StackScout verdict

+

Stack Scout verdict

@@ -267,13 +259,59 @@

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..b6ee64d 100644 --- a/tools/make/index.html +++ b/tools/make/index.html @@ -1,47 +1,39 @@ - + - StackScout // Make + Stack Scout // Make - + - + - + - -
-
-

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

-
- No fake telemetry - Official sources first - Badges over fake scores -
-
-
+
@@ -85,7 +77,7 @@

Make

Why it matters

-

StackScout verdict

+

Stack Scout verdict

@@ -267,13 +259,59 @@

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..6bf8067 100644 --- a/tools/n8n/index.html +++ b/tools/n8n/index.html @@ -1,47 +1,39 @@ - + - StackScout // n8n + Stack Scout // n8n - + - + - + - -
-
-

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

-
- No fake telemetry - Official sources first - Badges over fake scores -
-
-
+
@@ -85,7 +77,7 @@

n8n

Why it matters

-

StackScout verdict

+

Stack Scout verdict

@@ -267,13 +259,59 @@

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..e4b7c25 100644 --- a/tools/openai-api/index.html +++ b/tools/openai-api/index.html @@ -1,47 +1,39 @@ - + - StackScout // OpenAI API + Stack Scout // OpenAI API - + - + - + - -
-
-

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

-
- No fake telemetry - Official sources first - Badges over fake scores -
-
-
+
@@ -85,7 +77,7 @@

OpenAI API

Why it matters

-

StackScout verdict

+

Stack Scout verdict

@@ -301,13 +293,59 @@

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..56142c2 100644 --- a/tools/perplexity/index.html +++ b/tools/perplexity/index.html @@ -1,47 +1,39 @@ - + - StackScout // Perplexity + Stack Scout // Perplexity - + - + - + - -
-
-

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

-
- No fake telemetry - Official sources first - Badges over fake scores -
-
-
+
@@ -85,7 +77,7 @@

Perplexity

Why it matters

-

StackScout verdict

+

Stack Scout verdict

@@ -233,13 +225,59 @@

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..525d96f 100644 --- a/tools/playwright-mcp/index.html +++ b/tools/playwright-mcp/index.html @@ -1,47 +1,39 @@ - + - StackScout // Playwright MCP + Stack Scout // Playwright MCP - + - + - + - -
-
-

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

-
- No fake telemetry - Official sources first - Badges over fake scores -
-
-
+
@@ -85,7 +77,7 @@

Playwright MCP

Why it matters

-

StackScout verdict

+

Stack Scout verdict

@@ -267,13 +259,59 @@

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..890b1a4 100644 --- a/tools/signal-stack/index.html +++ b/tools/signal-stack/index.html @@ -1,53 +1,45 @@ - + - StackScout // Signal Stack + Stack Scout // Signal Stack - + - + - + - -
-
-

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

-
- No fake telemetry - Official sources first - Badges over fake scores -
-
-
+
- StackScout Lab + Stack Scout Lab Early but Promising Experimental
@@ -64,7 +56,7 @@

Signal Stack

Publisher - StackScout Lab + Stack Scout Lab

Web App / Web Apps

@@ -85,7 +77,7 @@

Signal Stack

Why it matters

-

StackScout verdict

+

Stack Scout verdict

@@ -147,9 +139,9 @@

What sits nearby.

data-badge="Early but Promising" data-date="2026-04-11" data-priority="1" - data-search="Canvas Planner A visual planning surface for boards, campaign flow, and creative work without the drag of a generic project manager. StackScout Lab The latest public-ready pass cleaned the browser surface and kept the board flow sharp without adding clutter. planning boards creative workflow pwa"> + data-search="Canvas Planner A visual planning surface for boards, campaign flow, and creative work without the drag of a generic project manager. Stack Scout Lab The latest public-ready pass cleaned the browser surface and kept the board flow sharp without adding clutter. planning boards creative workflow pwa">
- StackScout Lab + Stack Scout Lab Early but Promising
@@ -163,7 +155,7 @@

Canvas Planner

campaign planningcreative sequencing
- StackScout Lab + Stack Scout Lab Experimental 11 Apr 2026
@@ -181,9 +173,9 @@

Canvas Planner

data-badge="Worth Watching" data-date="2026-04-12" data-priority="2" - data-search="Strudel Studio A browser-based music studio path that brings programmable patterns, scenes, and samples into a clearer public-facing workflow. StackScout Lab The takeover pass tightened the smoke runner and kept the product moving toward a more serious music workspace. music browser studio coding audio"> + data-search="Strudel Studio A browser-based music studio path that brings programmable patterns, scenes, and samples into a clearer public-facing workflow. Stack Scout Lab The takeover pass tightened the smoke runner and kept the product moving toward a more serious music workspace. music browser studio coding audio">
- StackScout Lab + Stack Scout Lab Worth Watching
@@ -197,7 +189,7 @@

Strudel Studio

browser music prototypingpattern-driven composition
- StackScout Lab + Stack Scout Lab Experimental 12 Apr 2026
@@ -211,13 +203,59 @@

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..e3f09bb 100644 --- a/tools/strudel-studio/index.html +++ b/tools/strudel-studio/index.html @@ -1,53 +1,45 @@ - + - StackScout // Strudel Studio + Stack Scout // Strudel Studio - + - + - + - -
-
-

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

-
- No fake telemetry - Official sources first - Badges over fake scores -
-
-
+
- StackScout Lab + Stack Scout Lab Worth Watching Experimental
@@ -64,7 +56,7 @@

Strudel Studio

Publisher - StackScout Lab + Stack Scout Lab

Web App / Web Apps

@@ -85,7 +77,7 @@

Strudel Studio

Why it matters

-

StackScout verdict

+

Stack Scout verdict

@@ -169,9 +161,9 @@

What sits nearby.

data-badge="Early but Promising" data-date="2026-04-12" data-priority="1" - data-search="Signal Stack A publishing planner built around image, video, and queue workflows rather than generic social-media posting dashboards. StackScout Lab The recent execution pass made delivery truth more explicit, but live platform integrations still depend on real credentials and approvals. publishing scheduling creator workflow social"> + data-search="Signal Stack A publishing planner built around image, video, and queue workflows rather than generic social-media posting dashboards. Stack Scout Lab The recent execution pass made delivery truth more explicit, but live platform integrations still depend on real credentials and approvals. publishing scheduling creator workflow social">
- StackScout Lab + Stack Scout Lab Early but Promising
@@ -185,7 +177,7 @@

Signal Stack

creator schedulingqueue design
- StackScout Lab + Stack Scout Lab Experimental 12 Apr 2026
@@ -233,13 +225,59 @@

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..8506e6e 100644 --- a/tools/syncpad/index.html +++ b/tools/syncpad/index.html @@ -1,53 +1,45 @@ - + - StackScout // SyncPad + Stack Scout // SyncPad - + - + - + - -
-
-

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

-
- No fake telemetry - Official sources first - Badges over fake scores -
-
-
+
- StackScout Lab + Stack Scout Lab Early but Promising Experimental
@@ -64,7 +56,7 @@

SyncPad

Publisher - StackScout Lab + Stack Scout Lab

Desktop App / Desktop Apps

@@ -85,7 +77,7 @@

SyncPad

Why it matters

-

StackScout verdict

+

Stack Scout verdict

@@ -147,9 +139,9 @@

What sits nearby.

data-badge="Early but Promising" data-date="2026-04-11" data-priority="1" - data-search="Canvas Planner A visual planning surface for boards, campaign flow, and creative work without the drag of a generic project manager. StackScout Lab The latest public-ready pass cleaned the browser surface and kept the board flow sharp without adding clutter. planning boards creative workflow pwa"> + data-search="Canvas Planner A visual planning surface for boards, campaign flow, and creative work without the drag of a generic project manager. Stack Scout Lab The latest public-ready pass cleaned the browser surface and kept the board flow sharp without adding clutter. planning boards creative workflow pwa">
- StackScout Lab + Stack Scout Lab Early but Promising
@@ -163,7 +155,7 @@

Canvas Planner

campaign planningcreative sequencing
- StackScout Lab + Stack Scout Lab Experimental 11 Apr 2026
@@ -177,13 +169,59 @@

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..6f22718 100644 --- a/tools/wrangler/index.html +++ b/tools/wrangler/index.html @@ -1,47 +1,39 @@ - + - StackScout // Wrangler + Stack Scout // Wrangler - + - + - + - -
-
-

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

-
- No fake telemetry - Official sources first - Badges over fake scores -
-
-
+
@@ -85,7 +77,7 @@

Wrangler

Why it matters

-

StackScout verdict

+

Stack Scout verdict

@@ -233,13 +225,59 @@

Playwright MCP

-
- -

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

+ + +
diff --git a/updates/index.html b/updates/index.html index 3f33b57..fdc4b3e 100644 --- a/updates/index.html +++ b/updates/index.html @@ -1,47 +1,39 @@ - + - StackScout // Updates - - - + Stack Scout // Wire + + + - + - + - -
-
-

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

-
- No fake telemetry - Official sources first - Badges over fake scores -
-
-
+
@@ -320,13 +312,59 @@

Wrangler 4.58.0 improved command grouping and auth ergonomics

-
- -

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

+ + +