Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions .github/workflows/validate.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,22 @@ on:
env:
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true

permissions:
contents: read

jobs:
validate:
runs-on: ubuntu-latest
steps:
- 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

Expand Down
30 changes: 21 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
@@ -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`.

Expand All @@ -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`
Expand Down Expand Up @@ -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
Expand All @@ -63,27 +75,27 @@ 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

- editorial signal-desk shell rather than a generic directory layout
- 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.
Expand Down
50 changes: 49 additions & 1 deletion app.js
Original file line number Diff line number Diff line change
@@ -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) {
Expand All @@ -24,7 +70,7 @@ function initReveal() {
})
},
{
threshold: 0.16,
threshold: 0.02,
rootMargin: '0px 0px -8% 0px',
},
)
Expand Down Expand Up @@ -173,3 +219,5 @@ function initCatalogFilters() {

initReveal()
initCatalogFilters()
initMoodSwitcher()
initUtcClock()
132 changes: 85 additions & 47 deletions catalog/index.html
Original file line number Diff line number Diff line change
@@ -1,47 +1,39 @@
<!DOCTYPE html>
<html lang="en">
<html lang="en" class="mood-graphite">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>StackScout // Catalog</title>
<meta name="description" content="Searchable StackScout catalog of tracked ecosystem tools and lab products." />
<meta property="og:title" content="StackScout // Catalog" />
<meta property="og:description" content="Searchable StackScout catalog of tracked ecosystem tools and lab products." />
<title>Stack Scout // Top tools</title>
<meta name="description" content="Searchable Stack Scout catalog of tracked ecosystem tools and lab products." />
<meta property="og:title" content="Stack Scout // Top tools" />
<meta property="og:description" content="Searchable Stack Scout catalog of tracked ecosystem tools and lab products." />
<meta property="og:type" content="website" />
<meta name="theme-color" content="#0a100c" />
<meta name="theme-color" content="#14171c" />
<link rel="icon" type="image/svg+xml" href="../icon.svg" />
<link rel="apple-touch-icon" href="../icon.svg" />
<link rel="manifest" href="../manifest.json" />
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link href="https://fonts.googleapis.com/css2?family=Archivo:wght@400;500;600;700;800&family=Fraunces:opsz,wght,SOFT@9..144,500..800,50&family=IBM+Plex+Mono:wght@400;500;600&display=swap" rel="stylesheet" />
<link href="https://fonts.googleapis.com/css2?family=IBM+Plex+Mono:wght@400;500;600;700&family=Newsreader:ital,opsz,wght@0,6..72,400..800;1,6..72,400..800&display=swap" rel="stylesheet" />
<link rel="stylesheet" href="../styles.css" />
</head>
<body data-page="catalog" data-site-root="../">
<div class="atmosphere" aria-hidden="true">
<div class="atmosphere__grid"></div>
<div class="atmosphere__ring atmosphere__ring--one"></div>
<div class="atmosphere__ring atmosphere__ring--two"></div>
<div class="atmosphere__flare atmosphere__flare--acid"></div>
<div class="atmosphere__flare atmosphere__flare--ice"></div>
<div class="atmosphere__flare atmosphere__flare--ember"></div>
</div>
<div class="site-meta-bar">
<div class="site-meta-bar__inner">
<p class="site-meta-bar__issue">Issue 2026-04-25 // Curated public signal for builders</p>
<div class="site-meta-bar__tokens">
<span>No fake telemetry</span>
<span>Official sources first</span>
<span>Badges over fake scores</span>
</div>
</div>
</div>
<div class="ss-grain" aria-hidden="true"></div>
<header class="site-header">
<a class="site-brand" href="../">
<span class="site-brand__mark">S</span>
<span class="site-brand__wordmark">StackScout</span>
<span class="site-brand__mark" aria-hidden="true"></span>
<span class="site-brand__wordmark">Stack <span>Scout</span></span>
</a>
<nav class="site-nav" aria-label="Primary"><a href="../">Home</a><a href="./" aria-current="page">Catalog</a><a href="../categories/">Categories</a><a href="../updates/">Updates</a><a href="../radar/">Radar</a><a href="../collections/">Collections</a><a href="../method/">Method</a></nav>
<div class="site-header__right">
<nav class="site-nav" aria-label="Primary"><a href="../">Home</a><a href="./" aria-current="page">Top tools</a><a href="../categories/">Categories</a><a href="../updates/">Wire</a><a href="../radar/">Radar</a><a href="../collections/">Collections</a><a href="../method/">Sources &amp; method</a></nav>
<div class="mood-switcher" aria-label="Theme">
<button class="mood-switcher__button is-active" type="button" data-mood="graphite" aria-label="Graphite theme"></button>
<button class="mood-switcher__button" type="button" data-mood="midnight" aria-label="Midnight theme"></button>
<button class="mood-switcher__button" type="button" data-mood="obsidian" aria-label="Obsidian theme"></button>
<button class="mood-switcher__button" type="button" data-mood="slate" aria-label="Slate theme"></button>
<button class="mood-switcher__button" type="button" data-mood="carbon" aria-label="Carbon theme"></button>
</div>
</div>
</header>
<main class="page-shell">
<section class="hero hero--inner">
Expand Down Expand Up @@ -82,7 +74,7 @@ <h2>Make</h2>
<select id="scopeFilter">
<option value="">All</option>
<option value="ecosystem">Ecosystem</option>
<option value="lab">StackScout Lab</option>
<option value="lab">Stack Scout Lab</option>
</select>
</label>
<label class="filter-field">
Expand Down Expand Up @@ -135,7 +127,7 @@ <h2>Make</h2>
<strong>Agent-ready protocol surfaces</strong>
</a>
<a class="brief-link" href="./?scope=lab">
<span>StackScout Lab</span>
<span>Stack Scout Lab</span>
<strong>Clearly labelled in-house tools</strong>
</a>
<a class="brief-link" href="./?pricing=Usage-based">
Expand Down Expand Up @@ -499,9 +491,9 @@ <h3>Wrangler</h3>
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">
<div class="scout-card__topline">
<span class="pill pill--violet">StackScout Lab</span>
<span class="pill pill--violet">Stack Scout Lab</span>
<span class="pill pill--violet">Early but Promising</span>
</div>
<div class="signal-mark signal-mark--web-apps">
Expand All @@ -515,7 +507,7 @@ <h3>Canvas Planner</h3>
<div class="chip-row"><span class="chip chip--ink">campaign planning</span><span class="chip chip--ink">creative sequencing</span><span class="chip chip--ink">lightweight boards</span></div>
</div>
<div class="scout-card__meta">
<span>StackScout Lab</span>
<span>Stack Scout Lab</span>
<span>Experimental</span>
<span>11 Apr 2026</span>
</div>
Expand All @@ -533,9 +525,9 @@ <h3>Canvas Planner</h3>
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">
<div class="scout-card__topline">
<span class="pill pill--violet">StackScout Lab</span>
<span class="pill pill--violet">Stack Scout Lab</span>
<span class="pill pill--violet">Early but Promising</span>
</div>
<div class="signal-mark signal-mark--web-apps">
Expand All @@ -549,7 +541,7 @@ <h3>Signal Stack</h3>
<div class="chip-row"><span class="chip chip--ink">creator scheduling</span><span class="chip chip--ink">queue design</span><span class="chip chip--ink">platform planning</span></div>
</div>
<div class="scout-card__meta">
<span>StackScout Lab</span>
<span>Stack Scout Lab</span>
<span>Experimental</span>
<span>12 Apr 2026</span>
</div>
Expand All @@ -567,9 +559,9 @@ <h3>Signal Stack</h3>
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">
<div class="scout-card__topline">
<span class="pill pill--violet">StackScout Lab</span>
<span class="pill pill--violet">Stack Scout Lab</span>
<span class="pill pill--amber">Worth Watching</span>
</div>
<div class="signal-mark signal-mark--web-apps">
Expand All @@ -583,7 +575,7 @@ <h3>Strudel Studio</h3>
<div class="chip-row"><span class="chip chip--ink">browser music prototyping</span><span class="chip chip--ink">pattern-driven composition</span><span class="chip chip--ink">creative experiments</span></div>
</div>
<div class="scout-card__meta">
<span>StackScout Lab</span>
<span>Stack Scout Lab</span>
<span>Experimental</span>
<span>12 Apr 2026</span>
</div>
Expand All @@ -601,9 +593,9 @@ <h3>Strudel Studio</h3>
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">
<div class="scout-card__topline">
<span class="pill pill--violet">StackScout Lab</span>
<span class="pill pill--violet">Stack Scout Lab</span>
<span class="pill pill--violet">Early but Promising</span>
</div>
<div class="signal-mark signal-mark--desktop-apps">
Expand All @@ -617,7 +609,7 @@ <h3>SyncPad</h3>
<div class="chip-row"><span class="chip chip--ink">private notes</span><span class="chip chip--ink">local-first drafting</span><span class="chip chip--ink">multi-device ambition</span></div>
</div>
<div class="scout-card__meta">
<span>StackScout Lab</span>
<span>Stack Scout Lab</span>
<span>Experimental</span>
<span>12 Apr 2026</span>
</div>
Expand All @@ -632,13 +624,59 @@ <h3>SyncPad</h3>
</section>
</main>
<footer class="site-footer">
<div>
<p class="site-footer__brand">StackScout</p>
<p>Public tool intelligence for builders, operators, and curious system nerds.</p>
<div class="site-footer__marquee" aria-label="Stack Scout operating principles">
<div class="site-footer__marquee-track">
<span>No affiliate theatre</span>
<span>No fake scores</span>
<span>Official sources first</span>
<span>Used or vetted</span>
<span>Badges over decimal dust</span>
<span>Curated, not exhaustive</span>
<span>No affiliate theatre</span>
<span>No fake scores</span>
<span>Official sources first</span>
<span>Used or vetted</span>
<span>Badges over decimal dust</span>
<span>Curated, not exhaustive</span>
</div>
</div>
<div class="site-footer__grid">
<div>
<p class="site-footer__brand">Stack <span>Scout</span></p>
<p>A field log for builder tools, official sources, and the stack worth opening.</p>
</div>
<nav class="site-footer__links" aria-label="Main pages">
<span>Main</span>
<a href="../">Home</a>
<a href="./">Top tools</a>
<a href="../updates/">Wire</a>
<a href="../collections/">Collections</a>
</nav>
<nav class="site-footer__links" aria-label="Projects">
<span>Projects</span>
<a href="../radar/">Radar</a>
<a href="../method/">Sources &amp; method</a>
<a href="https://theairesourcehub.com/" target="_blank" rel="noreferrer">AI Resource Hub</a>
<a href="https://elusionworks.com/" target="_blank" rel="noreferrer">Elusion Works</a>
</nav>
<div class="site-footer__links">
<span>Contact</span>
<a href="https://koltregaskes.com/" target="_blank" rel="noreferrer">Kol Tregaskes</a>
<a href="https://github.com/koltregaskes/stackscout" target="_blank" rel="noreferrer">GitHub</a>
<a href="../method/">Method</a>
</div>
</div>
<div class="site-footer__estate" aria-label="Elusion Works umbrella">
<div>
<span>Umbrella home</span>
<a href="https://elusionworks.com/" target="_blank" rel="noreferrer">Elusion Works</a>
</div>
<p>The showcase for Kol's websites, tools, games, and web experiments.</p>
<a href="https://elusionworks.com/" target="_blank" rel="noreferrer">Visit Elusion Works -&gt;</a>
</div>
<div class="site-footer__meta">
<p>Updated 25 Apr 2026</p>
<p>Public site generation from the StackScout shared source layer.</p>
<p><span class="live-dot" aria-hidden="true"></span><span id="utcClock">Live UTC</span></p>
<p>Updated 25 May 2026 from the Stack Scout shared source layer.</p>
</div>
</footer>
<script src="../pwa.js"></script>
Expand Down
Loading