The public brain of this project — what has been built, what is being built, what broke along the way, and what is still only a thought. Nothing here is behind a login.
a living chart of the xsantcastx universe
v2.2.1“Blueprint”built August 11, 2026
By The Numbers
Live Numbers
counted from the registry at build time, not from memory
126Free toolsall client-side, all free
258+SSR-prerendered pagesreal HTML for every route
14MCP tools for AI agentsnpm install -g xsantcastx-mcp-server
Hero carousel is visible on mobile again — it had been a 210px black void directly under the header on every phone
Cause: Angular scopes @keyframes names per component, but did not rewrite the animation reference inside the <=768px media query, so it pointed at a keyframes name that did not exist and the cards never left opacity: 0
Mobile now reuses the desktop keyframes and flattens the 3D tilt with transform: none !important, so there is only one keyframes name left to scope
v2.2.0BlueprintAugust 11, 2026
a11y overhaul — every interactive control now has an accessible name
Zero buttons without an accessible name site-wide; 82 that relied on a hover-only title tooltip now carry a real label, translated where the tooltip was
296 form controls wired to the labels that were only visually beside them — sliders and colour pickers used to announce as unnamed
Header logo is a real button, not a div with role="button", and shows a focus ring again
rel="noopener noreferrer" on all 64 links that open a new tab
Heading levels no longer skip from h1 to h3 on games, css-variables and pdf-generator
v2.1.0BlueprintAugust 11, 2026
Mobile navigation repaired — 44px tap targets, drawer sits flush under the header
Mobile performance — nine always-composited full-viewport layers down to five, all static
backdrop-filter disabled on mobile (was 300+ declarations, four stacked in the header alone)
/live and the header no longer overflow a 375px viewport
Every standalone control now meets the 44px touch minimum
v2.0.0BlueprintAugust 10, 2026
Blueprint public roadmap + dev log
i18n support (EN/ES)
Accessibility overhaul
Security hardening
126 tools
v1.0.0GenesisMarch 1, 2026
Initial launch
First 45 tools
Easter egg system
Dark theme
What We've Built
126+ Free Developer Tools
every star below is a working tool — no sign-up, no upload, no limits
no private backlog — this is the actual order of work
Now
shipping this cycle
Multi-language support (i18n)
building
Wiring every tool through TranslationService so the whole site reads in English and Spanish.
Accessibility audit
building
Labelled controls, real buttons, focus order and reduced-motion paths across all 126 tools.
Security hardening
building
Dependency vulnerability sweep, tightened Firestore rules and a stricter Content-Security-Policy.
Next
queued and specced
Regex Builder & Tester
planned
Build patterns visually, test against sample text, and export to JS, Python or Go.
HAR File Analyzer
planned
Drop a HAR export and get waterfall timings, payload sizes and slow-request callouts.
Liquid Glass CSS Studio
planned
Design frosted-glass surfaces with layered blur, tint and refraction — copy the CSS out.
Pro tier
planned
Optional paid tier via LemonSqueezy for heavier limits and saved workspaces. Free tools stay free.
Sponsored tool slots
planned
Clearly-labelled sponsorships on individual tool pages to keep the lights on without ads.
Later
ideas worth chasing
AI-powered tool suggestions
idea
Describe the problem in a sentence and get pointed at the right tool — or a new one worth building.
Community-built tools
idea
A contribution path so anyone can ship a tool into the registry with the cosmic shell for free.
API access
idea
Programmatic endpoints for the tools that make sense server-side, for scripts and CI pipelines.
Mobile app
idea
A PWA-first companion so the whole toolbox works offline on a phone.
Dev Log
Build In Public
the problems, the decisions and the mistakes — written down while they were fresh
Feature Launch
Shipping /blueprint meant publishing the backlog, the architecture decisions and the mistakes — including the ones not fixed yet.
Most side projects keep the roadmap in a private doc, and the public only ever sees the finished thing. That is comfortable, and it is also how a project quietly stops being accountable to anyone. If nobody knows what was promised, nothing was ever late.
So the roadmap moved onto the site. Three columns — Now, Next, Later — with a status badge on every card. The cost of that is real: once "Regex Builder & Tester" is sitting in the Next column with your name on it, you cannot silently decide it was never a good idea. You have to move it to Later and let people see it move.
The implementation is deliberately boring. Roadmap items, architecture decisions and these log entries are plain TypeScript arrays — no CMS, no database round-trip, no admin UI. Adding a roadmap item is a one-line edit that ships with the next deploy. The tool map is the one exception: it derives from TOOLS_REGISTRY at build time, so it is structurally impossible for the count on this page to drift from the tools that actually exist.
The part that matters most is the suggestion form at the bottom of the Contribute tab. A roadmap that only flows outward is a changelog with extra steps. The interesting version is the one where somebody reads the Later column, thinks "that is the wrong priority", and says so.
Blueprint
Build in Public
Roadmap
Feature Launch
Adding Spanish revealed that the hard part is not the strings in the templates — it is the English baked into every tool's output.
The site had a TranslationService and a language toggle from early on, but it only covered the chrome: nav, footer, hero copy. Every one of the 126 tools was still hardcoded English, which meant a Spanish-speaking visitor got a translated shell wrapped around an untranslated product.
The mechanical part went in batches — inject TranslationService, replace literals with translate('key') calls, add the EN and ES pairs. Roughly a dozen tools per commit, because a 126-file diff is a diff nobody reviews. Doing it in batches also meant each batch could be verified independently instead of discovering a systematic mistake at the end.
The interesting problem showed up about three batches in. A tool is not just labels. The CSS generators emit code comments. The validators emit error messages. The JSON tools emit type names and diff annotations. All of that is output, not UI, and none of it lives in a template where a find-and-replace can reach it. A translated button above an English error message arguably looks worse than leaving the whole thing in English.
The current position is a deliberate split: interface copy is translated, generated code output stays in English. Developers read English code comments regardless of what language they speak, and a Spanish comment inside a CSS snippet the user is about to paste into an English codebase is not a kindness. That line is a judgment call and it is the kind of thing worth arguing about — which is part of why it is written down here.
Still open: the tool titles and descriptions in the registry have optional titleKey and descriptionKey fields, but only a handful of tools populate them. Until every entry has them, the /tools grid is bilingual in patches.
i18n
Angular
TranslationService
Problem Solved
Twenty advisories closed across the app and Cloud Functions, one critical — plus the CSP finally dropped script-src 'unsafe-inline'.
The audit had been red for a while. Two separate surfaces, because this repo ships a Firebase Functions package with its own package.json: ten advisories in the app dependency tree, ten more in functions including one critical. The critical one was an SSRF in axios, fixed by moving to 1.15.0, alongside a moderate ReDoS in ajv.
Not everything had a clean upgrade path. Several advisories were in transitive dependencies of packages with no patched release, which is the usual dead end — you either fork the parent, drop the feature, or pin the transitive dep. Scoped npm overrides were the answer for the app tree: they let you force a patched version deep in the graph without waiting for every maintainer above it to cut a release. They are also a liability, because an override that outlives its advisory silently holds a package back. Each one is commented with the advisory it exists for.
The unglamorous half was deletion. Nine dependencies were in package.json that nothing imported — 92 packages once transitive deps were counted. Firebase turned out to be installed twice as two complete SDK copies, both bundled. Removing code you are not using is the highest-yield security work available, and it has none of the drama of a CVE.
Separately, the Content-Security-Policy finally dropped script-src 'unsafe-inline'. The blocker was always the two inline scripts in index.html — the cosmic engine bootstrap and the theme guard. Both now ship with SHA-256 hashes in the policy, which allows exactly those two scripts and nothing else an injection could add.
A caveat on the numbers, because audit counts are easy to inflate: npm audit reports advisories per dependency path, so the same underlying CVE can be counted many times over and a headline "closed N vulnerabilities" can be made almost arbitrarily large. Twenty is the count of distinct advisories across both trees. The metric actually worth tracking is simpler — zero advisories at moderate or above, checked in CI, every build.
Security
npm audit
CSP
Dependencies
Architecture
The framework bump was routine. Converting 126 components to standalone and rewriting 253 routes to loadComponent was not.
Angular 21.2.19 landed without much ceremony — the framework upgrade itself was close to a non-event, which is a genuine compliment to the Angular team's migration tooling. The real work was structural, and it was work this app had been deferring for a long time.
Every one of the 126 tool components was still declared in an NgModule. That is not wrong, but it meant the build had one enormous lazy chunk: visit any single tool and you downloaded all of them. The official `ng g @angular/core:standalone` schematic did the bulk of the conversion, and then 253 routes across the tools and embed routing modules were rewritten from `component:` to `loadComponent:`, preserving path, title and SEO data verbatim. `tools-page-components.module.ts` was deleted outright.
The result was a 3.7 MB single chunk splitting into 158 per-tool chunks of roughly 3–55 kB each. The largest is pdf-generator at 124 kB, and that is almost entirely jsPDF — a tool that needs a PDF library is going to carry a PDF library, and the point of the split is that the other 125 tools no longer carry it too.
Worth being honest about the baseline: the internal spec driving this work claimed main.js was 5.47 MB with 125 eagerly-loaded tool components. That was wrong. main.js was already 535 kB and the tools were already lazy — just batched into one chunk. The intent of the work (per-tool chunks) was right and got implemented; the "main.js drops to 270 kB" framing in the spec never applied to reality, because the initial bundle was never the problem. Initial bundle size is essentially unchanged, by design.
Prerendering now covers 265 routes. Every tool page, every top-level page, real HTML for all of them, generated at build time rather than rendered per request.
Angular
SSR
Standalone
Migration
Problem Solved
A cosmic starfield, a CSS planet and a particle canvas are lovely on a desktop GPU. On a mid-range Android they are a heater.
This site runs more than twenty simultaneous ambient systems: a particle constellation canvas, a drifting pulsar, a rotating alchemical sigil, a CSS-only lit planet with ring shadows, scroll-linked parallax, per-character heading animations, cursor trails. On a desktop with a discrete GPU that is a nice atmosphere. On a mid-range phone it is a frame-rate problem and a battery problem.
The first instinct — a single "is mobile, disable animations" kill switch — was the wrong shape and got removed. It produces a dead page on exactly the devices most visitors are using, and it treats a 2019 budget Android and a current iPhone Pro as the same machine. What replaced it is tiered. Canvas lite mode triggers on a compound signal: viewport ≤768px, OR hardwareConcurrency ≤4, OR deviceMemory ≤4. In lite mode device pixel ratio is capped at 1.5, particle density is halved, and the O(n²) constellation-line pass — which is the genuinely expensive part — is skipped entirely. Ripples and touch sparks stay, because those are the feedback a user actually notices.
On top of that sits a frame-time governor. It keeps a rolling 60-frame average, and when that average exceeds 12 ms it sheds 20% of the remaining particles, with a floor of 24 so the effect never fully dies. It is a feedback loop rather than a threshold, which means it degrades on devices nobody tested on, including ones that did not exist when the code was written.
One bug from this pass is worth recording because it is the kind that hides forever. A mobile rule setting the planet's surface drift to `animation-duration: 180s` had been in the stylesheet for months doing absolutely nothing — it was silently overridden by an `animation:` shorthand appearing later in source order, which resets duration. Nothing errored. The animation just ran at its desktop speed on every phone. Fixed with `!important`, matching the neighbouring mobile rules. Shorthand properties quietly clobbering longhands set earlier is a whole category of CSS bug that no tool warns about.
The honest limitation: all of the above was verified by static analysis and build output. No runtime profiling on real devices has happened yet. The acceptance criteria that need an actual browser — CLS under 0.02, 55fps under throttled scroll, no horizontal overflow between 320 and 768px, Safari mask-and-blend rendering — are unverified rather than passing, and they are sitting in the roadmap for that reason.
Performance
Mobile
Canvas
Animation
Problem Solved
A custom ErrorHandler stops SSR failures from breaking the build. That is a trade, not a fix — so it logs a grep-able trail.
Prerendering 265 routes at build time is great for SEO and awful for build stability. Any single component that touches `window` at the wrong moment, or hits an API that does not exist in Node, takes down the entire production build — and it takes it down with a stack trace pointing at the framework rather than at your component.
The response was a custom `SsrErrorHandler` in `app.server.module.ts`. It catches errors during server render and refuses to rethrow, so one bad component prerenders as a degraded page instead of failing 265 routes. That kept the deploy pipeline moving. It also means a component can be quietly broken on the server for weeks while every build reports success, which is a genuinely worse failure mode than a red build.
So the handler is built to leave a trail. Every swallowed error logs a single structured line: `[SSR-SWALLOWED] route=<route> kind=<kind> msg=<truncated>`. The message is truncated to 200 characters and whitespace-collapsed so it stays one grep-able line. Errors are bucketed into `NotYetImplemented` — Angular's marker for a browser-only API called during server render, which is common and usually benign — versus `Other`, which is everything genuinely worth looking at. Anything in the `Other` bucket also emits `[SSR-SWALLOWED-STACK]` with the top three stack frames, skipping the error header, because three frames is enough to identify the component and short enough to not drown the build log.
The point of that format is that it is machine-readable. A monitoring job greps build stderr for the prefix and reports counts per route, which turns "silent suppression" into "a number that should be zero and is currently not". Suppression without monitoring is just hiding bugs; suppression with a counter is a triage queue.
This is not where it should end up. The right end state is zero swallowed errors and a handler that rethrows. The current state is a build that ships and a log that tells you exactly how much debt is behind it.
SSR
Angular
Monitoring
Build
Agent Log
The catalog grew fast because of one file. Every tool is one registry entry, and that entry wires up six systems automatically.
Adding the first tools was slow in the way early work always is: a card on the landing page, an entry in the tools grid, a route with SEO metadata, a JSON-LD block, a related-tools mapping, a sitemap line. Six places to edit for one tool, and six places to forget.
TOOLS_REGISTRY collapsed that. One entry — id, title, description, route, category, tags, icons, feature bullets — and everything downstream derives from it. The landing page cards, the /tools galaxy map, the related-tools recommendations, the category filters, the tag-based constellation lines, and the count displayed on this very page all read from the same array. The registry is not a convenience; it is the reason the catalog could get to three digits without the metadata rotting.
That leaves the obvious risk, which is that 126 shallow tools is worse than 30 good ones. A spot-check sampled a dozen entries at random — meta-tag-generator, ts-playground, css-variables, email-deliverability-auditor, responsive-preview, base64-encoder, lorem-generator, snippet-manager, checklist, git-reference, hex-editor, morse-code. All had real implementations, between 107 and 677 lines of TypeScript each plus matching templates. No stubs, no placeholder pages. Three carried a handful of TODO markers, which is polish debt rather than a broken tool.
A sample of twelve is not an audit of 126, and the honest read is that a few tools are probably rougher than the rest. A full pass with fresh eyes is on the roadmap. But the structural claim holds: this is not a directory of empty pages with good SEO.
The other thing that made scale work is that every tool runs entirely in the browser. No server, no queue, no per-tool backend to operate. The marginal operational cost of tool 126 is the same as tool 2 — which is zero.
Registry
Automation
Scale
Architecture
Feature Launch
Fourteen of the tools now run inside Claude and any other MCP client, as a published npm package.
The tools were already pure functions with a UI bolted on. Base64 encoding, hash generation, JSON formatting, cron parsing — none of that needs a browser, it needs an input and an output. The Model Context Protocol turned out to be exactly the right shape for exposing them somewhere else.
Fourteen tools are packaged as `xsantcastx-mcp-server`, installable with `npm install -g xsantcastx-mcp-server`. It speaks MCP over stdio, which means it works with Claude Desktop, Claude Code, and any other MCP-compatible client without a per-client integration.
The design constraint carried straight over from the website: zero API calls, all local computation. An agent using this server is not sending your data anywhere, because there is nowhere for it to go — the whole thing runs on your machine. That is the same promise the site makes to a human in a browser, and it was worth keeping identical rather than quietly relaxing it for the agent case.
The interesting realisation is what this says about the tools themselves. A well-built utility has a UI-shaped surface and a function-shaped core, and if the core is clean it can be re-hosted almost for free. Repackaging fourteen tools was days of work, not months, entirely because none of them had business logic tangled into a component.
MCP
npm
AI Agents
Developer Tools
Feature Launch
A registry of 106 discoverable secrets, tracked per-visitor in localStorage and counted globally in Firestore.
A developer tools site has a retention problem baked into its value proposition: it works, you leave. That is the tool doing its job. The counter-move was to make the site worth poking at — not by getting in the way of the utility, but by rewarding the kind of curiosity that costs nothing to indulge.
There are 106 Easter eggs in a central registry — 4 global and 102 tool-specific. The tool-specific ones fire on doing something unexpected inside a tool rather than on finding a hidden button, which is the distinction that makes them feel earned instead of arbitrary. Discovery state persists per-visitor in localStorage under `easter-eggs-found`, and global discovery counts go to Firestore, so an egg can advertise how rare it is.
When one fires, a toast slides in with the egg name and a running X/106 progress count, then auto-dismisses after six seconds. Six seconds was tuned: long enough to read and register, short enough that it never becomes something you have to dismiss while working. Every one of them is skippable and none block input.
The heavier layer sits behind the global eggs. The Konami code, a hidden sigil in the corner, and a console command all toggle "ritual mode", which changes the site's palette and fades in an ambient five-oscillator Web Audio drone. That audio graph is lazily instantiated — a visitor who never triggers ritual mode never gets an AudioContext at all, which matters both for performance and for not being the site that makes noise at somebody in an open-plan office.
Whether this is a good use of engineering time on a utility site is a fair question. The argument for it: the tools are commodities and there are a hundred sites with a Base64 encoder. The thing that is not a commodity is being the one somebody remembers.
Easter Eggs
Engagement
Games
Firestore
Milestone
The founding constraints — free, no sign-up, nothing leaves the browser — and why each one was worth committing to before writing any code.
The site launched with 45 tools and three constraints that have not moved since: everything is free, nothing requires an account, and no data leaves the browser. Those were chosen deliberately at the start, because constraints adopted on day one are architecture and constraints adopted in month six are refactors.
The privacy one does the most work. Every tool runs client-side, which means you can paste a production config, a customer CSV or a JWT into any of them without a decision to make about whether you trust the operator. There is no upload, no logging, no retention — not as a policy you have to take on faith, but because there is no server in the path to do any of it.
That constraint pays for itself in ways that were not obvious upfront. No servers means no hosting costs that scale with usage, which is what makes "free forever" a sustainable claim rather than a runway problem. It means no queue, so results appear as you type. It means every tool keeps working if the backend is down, because there is no backend. And it made the MCP server possible two months later, essentially for free.
The visual direction — a cosmic universe with a drifting pulsar, constellation lines and hidden runes — was the other early commitment, and the more contested one. Developer tools trend toward austere and grey. The bet was that a utility site can be memorable without being less useful, and that the wrapper is not the product. Two constraints keep that bet honest: every animation over a second has a reduced-motion fallback, and nothing decorative is allowed to block or slow the thing you actually came to do.
Launch
Principles
Privacy
How It's Built
Architecture
the machinery under the nebula, and why it was picked
Global CDN, per-route cache headers, preview channels
◉
Angular SSR
258+ routes prerendered at build time
⬡
TypeScript
Strict mode, one registry as the single source of truth
⬢
Firestore
Changelog, suggestions and counters — schema-enforced in rules
✦
MCP Server
14 tools exposed to AI agents over stdio
Your data never leaves the tab. Nothing is uploaded, logged or retained, so you can paste a production config or a customer CSV without thinking twice. It also means there is no server to pay for and no queue to wait in — results land the moment you stop typing, and every tool keeps working if the backend is down.
Server-side rendering was non-negotiable: search engines need real HTML for every one of the tool pages, and Angular SSR prerenders them all at build time. Signals keep the heavier tools responsive without manual change-detection tuning, and standalone components let each tool ship as its own lazy chunk so visiting one tool never downloads the other 125.
A utility site is usually a place you leave as fast as you arrived. The hidden runes, the Konami code, the ritual mode and the drifting pulsar exist to make the site worth poking at — curiosity is what turns a one-off visit into a bookmark. They are all opt-in, respect prefers-reduced-motion, and never get in the way of the tool you actually came for.
Building in public keeps the plan honest. You can see what is genuinely in progress, what is only an idea, and what quietly got dropped — and you can push back on any of it. It also means the next tool is far more likely to be one somebody actually asked for.
Get Involved
Contribute
the next star in this universe could be yours
How the AI team works
Most of the day-to-day work on this site — new tools, refactors, accessibility fixes, dependency bumps — is done by autonomous AI agents working from the same public roadmap you are reading. They pick up scoped tasks, open branches, run the build and the type-checker, and push commits.
Nothing merges without passing a production build, and every change lands as an ordinary reviewable commit rather than a black box. The Dev Log tab is where the interesting runs get written up, including the ones that went sideways. If you want to see how the sausage is made, the git history and that log are the same story told at two zoom levels.
◆
Read the code
The whole site is on GitHub — Angular app, Cloud Functions, MCP server and all.