AI 资讯
How I Built a Browser-Based File Compression Tool for India Using Canvas API and pdf-lib — No Backend Needed
I built ResizeKB — a free image and PDF resizer built specifically for Indian users. 25+ tools. Zero server uploads. Pure HTML, CSS, JavaScript. Here's how and why. The Problem Every Indian applying for government jobs, exams, or bank accounts hits the same wall — portals with strict KB limits rejecting documents. UPSC wants photo under 300KB. SSC wants under 50KB. Banks need Aadhaar PDF under 500KB. Every portal is different. Every rejection wastes someone's time and opportunity. Most people have no idea how to resize to an exact KB. They either give up or use random tools that upload their Aadhaar and PAN card to unknown servers. I built a tool that solves this in one click — with zero server upload. The Tech Stack No framework. No backend. No database. Canvas API for image processing pdf-lib for PDF compression Vanilla JavaScript only Cloudflare Pages for hosting — free, global CDN, auto deploys from GitHub Total infrastructure cost: ₹1,162 per year for the domain. Everything else free. Image Compression — The Binary Search Algorithm The core challenge is compressing to an exact KB target without over-compressing. Most tools use a fixed quality setting like 60% which destroys image quality. The right approach is binary search on JPEG quality: javascriptasync function compressToTargetSize(file, targetKB) { const targetBytes = targetKB * 1024; let low = 0.1; let high = 1.0; let result = null; const img = await loadImage(file); const canvas = document.createElement('canvas'); canvas.width = img.width; canvas.height = img.height; const ctx = canvas.getContext('2d'); ctx.drawImage(img, 0, 0); while (high - low > 0.01) { const mid = (low + high) / 2; const blob = await canvasToBlob(canvas, 'image/jpeg', mid); if (blob.size <= targetBytes) { result = blob; low = mid; } else { high = mid; } } return result; } This finds the highest quality setting that still hits your target KB. Result is the sharpest possible image at that file size — never over-compressed. PDF Compress
AI 资讯
How a Slow Office VPN Led Me to File a US Patent
This is the story of how a mundane complaint — "the VPN is slow" — turned into a US patent application. Not a granted patent. An application . I want to be precise about that from the start, because the distance between the two is the whole point of this post. It started with a slow VPN The company I work for had an internal VPN that everyone routed through. It lived in the Tokyo office, it was old, and it was not something I built. Then the complaints started arriving — from a lot of people, all saying the same thing: it's slow. I work from Thailand most of the time. That detail matters. If that aging box in Tokyo had fallen over, I would have been the person furthest from the power button, in the worst position to fix it. A slow VPN is annoying. An unreachable VPN, when you're a few thousand kilometers away, is a real problem. So I started moving it to the cloud. I stood up a WireGuard VPN — modern, fast, and something I could actually reason about and operate remotely instead of inheriting a black box. Down the WireGuard rabbit hole Around that time I was deep into building my own iPhone apps. So the cloud migration turned into a personal project on the side: I built my own server and wired WireGuard into an iPhone app of my own. And to do that properly, I started studying how WireGuard actually works under the hood — the Noise protocol, the handshake, the key exchange. That study is where everything else came from. I wasn't trying to invent anything. I was just trying to understand the thing I was now responsible for. The SYN flood that primed my brain Not long before, the same company had been hit with a SYN flood attack. If you've dealt with one, you know it lodges the mechanics of connection handshakes firmly in your head — the back-and-forth, the round trips, the cost of every "hello" before any real data moves. So I had handshakes on the brain. And then, reading through how WireGuard establishes a session, a thought stopped me: Wait — does it really handsha
AI 资讯
Perl 🐪 Weekly #776 - Learning Perl
Originally published at Perl Weekly 776 Hi there, Recently, I came across an article, The Day I Decided Never to Learn Python by Randal L. Schwartz . Well, Randal doesn't need an introduction. He took us back to 2001 , the same era when I first started learning Perl in 1999. He was a major guiding force during my early programming days. Last week, I joined a live session by Gabor focussed on FalkorDB . It was fun watching him code and talk while I sat back as a silent spectator. You can learn a lot just by watching how he approaches coding. It reminded me of many years ago when I did pair programming with him and submitted a pull request to the Dancer2 project. Those were the golden days, when I had so much energy and time. That being said, I am still actively learning Perl and discovering how to do new things with it. These concepts may not be new to everyone, but they are new to me. For example, I recently played with GraphQL for the first time, and I've also been experimenting with RAG and JSON-RPC . I have shared my recent experiments down below. The process of learning never stops. A few days ago, I noticed an update for HTTP::Message v7.02 . Since it was released by Olaf Alders , I was curious to see what had changed. It turned to be something, I hadn't realised for all these years. While I am well-acquainted with HTTP methods like GET, POST, and PUT, I didn't know "0" could actually be a valid HTTP method name if you wanted it to be. This release added support for exactly that, thanks to contributor, Karen Etheridge . Amidst all of this, I am still trying to find time for my upcoming book on DBIx::Class . I recently shared a blog post demonstrating the power of DBIC components, and I am trying my best not to lose focus. You might find that this edition is full of my own personal posts, as there was unfortunately very little community news to report this week. Regardless, I hope you enjoy the rest of the newsletter. -- Your editor: Mohammad Sajid Anwar. Announ
AI 资讯
Typed Eloquent boundaries without building a second ORM
Most Laravel teams do not need to "fix" Eloquent. They need to stop letting raw model state leak too far into code that makes real business decisions. That is the practical version of this debate. Typed objects around Eloquent can be a big improvement, but only when they are used as boundaries . If you push the pattern too far, you end up with a second object model shadowing the first one. At that point you are not improving Laravel. You are building a parallel ORM that adds mapping code, cognitive load, and friction on every change. So the right question is not, "Should we replace Eloquent with typed objects?" The right question is, where does untyped Eloquent stop being cheap? Once you frame it that way, the migration path becomes much clearer. Keep Eloquent where it is good at persistence, hydration, scopes, relationships, and query composition. Introduce typed objects where the shape is messy, the values carry business meaning, or invalid combinations are too easy to represent. That is the version that pays off. The Core Recommendation If you only remember one thing from this article, make it this: add typed boundaries around unstable or meaningful data, not around every model . That usually means one of four cases: a JSON column that multiple parts of the app interpret differently domain values like money, status, addresses, or billing configuration data crossing from Eloquent into services, jobs, or integrations code paths where stringly typed state has already caused confusion or bugs Everything else should be guilty until proven useful. This is where a lot of teams go wrong. They see a good example of typed objects and immediately generalize it into an architecture rule. Then every model gets a FooData , FooView , FooState , FooRecord , and FooMapper . The app becomes more "designed" and less understandable. A Laravel codebase does not get better because it has more classes. It gets better because responsibility becomes clearer . Why Raw Eloquent Starts Hurt
AI 资讯
BTC collateral vaults: how an agent posts native Bitcoin against an obligation without a custodian
Most "Bitcoin in DeFi" stories quietly route through a custodian or a wrapped representation. You send BTC somewhere, someone (or some bridge multisig) holds it, and you get an IOU on another chain. That works until the thing holding your BTC is the thing that fails. For an autonomous agent that has to post collateral against an obligation it can't babysit, "trust the custodian" is exactly the assumption we're trying to delete. This post is about the alternative: a BTC collateral vault where native Bitcoin backs an obligation on another chain, the release is gated by a hashlock, and the worst case is a refund — not a loss. It's one of the primitives underneath Hashlock's settlement layer. I'll walk through the timelock ordering that makes it safe, the Bitcoin script that enforces it, and the failure modes you design around. Honest status up front: this is signet-validated, not BTC mainnet . The problem in one sentence An agent wants to commit BTC as collateral backing an action on Ethereum — settling a forward, anchoring one leg of a multi-leg trade, guaranteeing a payout — such that the BTC is released to the counterparty only if the corresponding obligation on Ethereum is fulfilled, and returns to its owner if it isn't. No third party should ever be able to hold, freeze, or abscond with the BTC in between. That's a cross-chain conditional. Bitcoin can't read Ethereum state, and Ethereum can't read Bitcoin's. The only thing both chains can independently verify is a hash preimage. So the entire construction hangs on one shared secret. The shared secret, and why timelock order is the whole game Both legs lock to the same hash H = SHA256(s) . Whoever knows the preimage s can claim. The instant s is revealed on one chain to claim a coin, it's public, and the other party copies it to claim the other coin. That's the atomic part: one preimage unlocks both legs or neither. The danger isn't the hash. It's time . If both legs had the same expiry, the party who knows the sec
开发者
I Built 25 Free Financial Calculators — No Ads, No Signup, Just Tools
Two weeks ago I shared a collection of 6 financial calculators. The response was incredible, so I kept building. Today, fi-calc.com has 25 completely free calculators covering every major personal finance need: 🏠 Housing • Mortgage Calculator (full PITI + amortization schedule + pie chart) • Rent vs Buy Calculator • House Affordability Calculator • Refinance Calculator 💰 Investing & Retirement • Compound Interest Calculator • Investment Return Calculator • Future Value & Present Value Calculators • ROI Calculator • Retirement Savings Calculator • 401(k) Calculator • FIRE Calculator (Financial Independence) 💳 Debt & Loans • Loan Comparison Calculator • Auto Loan Calculator • Student Loan Calculator • Credit Card Payoff Calculator • Debt Payoff Calculator (Avalanche method) 📊 Everyday Finance • Budget Planner (50/30/20 rule) • Savings Goal Calculator • Inflation Calculator • Salary & Take-Home Pay Calculator • Net Worth Calculator • Currency Converter (15+ currencies) • CD Calculator • Sales Tax Calculator ✨ Tech Stack • Pure vanilla HTML/CSS/JS — no frameworks • Chart.js for animated interactive charts • Responsive design (mobile-friendly) • All calculations run client-side in your browser • No data collection, no accounts, no cookies 🔗 Give it a try: fi-calc.com The entire site is free and open. I built it because I was tired of calculator sites with paywalls, signup walls, and bloated ad experiences. Would love feedback from the community! What other calculators should I build next?
AI 资讯
My company packaged 12 years of my experience into an AI Skill, then laid me off. When it crashed, the CTO called at 5x my salary.
A story about knowledge extraction, Kafka consumer rebalance, and what happens when a company...
开发者
All the Ways Europe Is Ditching American Technology
A WIRED timeline shows how dozens of governments, companies, and other organizations across Europe are moving, or planning to shift, away from US Big Tech.
开发者
The 20 Best Vibe Coding Tools in 2026 (Honest Reviews, Real Pricing)
The way developers write software has genuinely changed. Not incrementally — fundamentally. A year...
AI 资讯
Napkin Math
personalized AI food journal + nutrition coach Discussion | Link
AI 资讯
Building a spaced repetition system that adapts to user pace in real-time (Kotlin/Compose)
I built a flashcard app for interview prep and wanted to share some of the more interesting technical problems I ran into. The app has 1500+ questions across DSA and System Design, and the core challenge was: how do you order cards intelligently without it feeling robotic? Problem 1: Slot Assignment for Spaced Repetition Standard SR (like Anki) just shows the most overdue card next. That works for vocabulary but feels terrible for algorithms because you get 3 Hard questions in a row and want to quit. My approach: generate a target difficulty pattern (Easy, Medium, Easy, Medium, Hard, repeat) based on a 40/40/20 distribution, then assign due cards to matching-difficulty slots. Most-overdue cards get placed first within their tier. Unseen cards fill remaining slots. This means a Hard card that's overdue still lands in a Hard slot, not position 1. You get difficulty variety while still seeing overdue cards at the right time. fun assignSlots(pool: List<Question>, dueCards: List<ProgressEntity>): List<Question> { val pattern = generatePattern(size = pool.size, distribution = "40/40/20") val dueByDifficulty = dueCards.groupBy { it.difficulty } val result = Array<Question?>(pattern.size) { null } // Place due cards in matching slots, most overdue first for ((difficulty, cards) in dueByDifficulty) { val sorted = cards.sortedBy { it.nextReviewDate } val availableSlots = pattern.indices.filter { pattern[it] == difficulty && result[it] == null } sorted.zip(availableSlots).forEach { (card, slot) -> result[slot] = findQuestion(card, pool) } } // Fill remaining with unseen // ... } Problem 2: Re-ranking after every swipe without jank After each swipe, the deck needs to re-rank. But the top visible card (position 0) is already animating into view, so you can't move it. Solution: lock position 0, re-rank positions 1+, then check for constraint violations across the boundary (e.g., if locked card is Hard and new position 1 is also Hard, swap position 1 with the first non-Hard card d
AI 资讯
Tab Vacuum - click once to remove every duplicate Chrome tab and auto-group the rest by website
I had 4 Chrome windows with ~80 tabs each, mostly duplicates of the same Stack Overflow page. Tried OneTab (saves to a list - not what I wanted) and Workona (cloud sync, overkill). So I wrote ~50 lines of vanilla JS. Click the toolbar icon → every duplicate tab across every window is removed (matched by URL) → survivors merge into one window → remaining tabs auto-group by hostname (collapsed). Two permissions: tabs, tabGroups. No background activity, no server, no analytics. Whole source is in the README so you can audit it before installing. Chrome Web Store: https://chromewebstore.google.com/detail/tab-vacuum/apdjhdjcejehjiomcolfgfgjhaedoieb GitHub: https://github.com/mayhsundar/tab-vacuum Please give your comments submitted by /u/mayhsundar [link] [留言]
AI 资讯
I Built a Quote Generator Because Sometimes Finding the Right Words Is Hard
The Problem Wasn't Writing It was starting. Sometimes I wanted: A social media caption A motivational quote A writing prompt A meaningful message But my mind would go completely blank. Not because I had nothing to say. Because: Coming up with the right words at the right moment is surprisingly difficult. We've All Done This Open a new tab. Search: "Motivational quotes" "Success quotes" "Life quotes" "Funny quotes" Scroll for 10 minutes. Copy one. Close the tab. Why I Built This Tool So I built something simple: 👉 https://allinonetools.net/quote-generator-tool/ A tool that instantly generates quotes across different categories. Whether you need: Motivation Success Life Leadership Creativity Social media inspiration You can generate quotes in seconds. No signup. No setup. Just: Click → Generate → Use What I Realized People don't always look for quotes because they need content. Often they're looking for: A different perspective. A good quote can do something interesting. It can say in one sentence what takes us paragraphs to explain. The Surprising Part The most popular quotes are rarely complicated. They're simple. Short. Easy to remember. Yet somehow they stick with us for years. Why Quotes Still Matter In a world full of endless content: Attention is limited Time is limited Patience is limited A strong quote delivers an idea instantly. That's powerful. The Problem With Searching Manually Most quote websites feel: Cluttered Slow Full of ads Hard to browse And sometimes you spend more time searching than actually reading. What I Focused On I wanted the experience to feel: Fast Clean Inspiring Fun to explore Because finding inspiration shouldn't require effort. What Surprised Me After building it: Some people used it for: Social posts Presentations Daily motivation Writing inspiration But one thing surprised me most. People kept generating quote after quote. Not because they needed one. Because they enjoyed discovering them. The Real Insight Sometimes tools aren't abo
AI 资讯
Day 28 — 🔭 Monitoring & Observability Part One
In Modern Time applications are no longer simple monolithic systems. Today organizations run: Microservices Kubernetes Containers Serverless Functions Multi-Cloud Platforms Distributed Systems As infrastructure becomes more distributed, troubleshooting becomes significantly harder. A single user request may travel through: Frontend ↓ API Gateway ↓ Microservice A ↓ Microservice B ↓ Database When something breaks, the biggest challenge becomes: "What exactly happened?" This is where Observability becomes critical. 🔗 Resources ** Support the Journey on GitHub: If you're following along, consider starring and forking the repo:** https://github.com/17J/30-Days-Cloud-DevSecOps-Journey What is Observability? Observability is the ability to understand the internal state of a system by analyzing the data it produces. In simple words: Can we understand what is happening inside our systems? Observability helps engineers answer: Why is the application slow? Which service is failing? Which request caused the issue? What changed recently? Where is latency occurring? Without observability: Problem Exists ↓ Guessing Begins With observability: Problem Exists ↓ Evidence Available ↓ Faster Resolution Why Observability Matters Modern cloud-native systems generate enormous amounts of data. Example: 100 Microservices ↓ Millions of Requests ↓ Thousands of Containers Traditional monitoring alone is no longer sufficient. Organizations need: Visibility Insights Correlation Root Cause Analysis Observability provides all of them. Monitoring vs Observability Many people confuse monitoring and observability. Monitoring asks: What is wrong? Observability asks: Why is it wrong? Example: Monitoring: CPU Usage = 95% Observability: Which service? Which request? Which dependency? Which deployment caused it? Observability provides context. The Three Pillars of Observability Modern observability is built on three primary pillars. Metrics Logs Traces Or: Monitoring Logging Tracing Together they provide a
AI 资讯
🎥AI Chat, AI Cheering Messages, and Animation Editor Hyper (AI Avatar v10: VS Code and Chrome Extension)
Intro AI Avatar is a completely free app that lets your VRoid (VRM) 3D avatar animate in...
AI 资讯
Odysseus: The Self-Hosted AI Workspace That Bundles Everything (59k ⭐)
I Tried PewDiePie's Open-Source AI Workspace. It's Actually Good. Yes, that PewDiePie. Felix Kjellberg (110M YouTube subscribers) spent late 2025 building a home AI lab — 8 modified RTX 4090s, 256GB of VRAM, running on Arch Linux. He called it "The Swarm." He crashed it running 64 models in parallel. The web frontend he built for it? He open-sourced it. Called it Odysseus . It hit 59,000 GitHub stars fast. I dug into the code expecting a glorified Ollama wrapper. It's not. What it actually is Odysseus isn't just another chat UI. It bundles things no other self-hosted tool does in one place: Chat — local or cloud models (Ollama, vLLM, llama.cpp, OpenAI, OpenRouter, GitHub Copilot) Agent mode — shell, files, web, MCP tools, per-tool toggles Cookbook — scans your GPU, recommends models that actually fit, downloads and serves them in one click Deep Research — multi-step web research that writes you a cited report Email — IMAP/SMTP with AI triage, auto-tagging, draft replies Calendar — CalDAV sync with Radicale, Nextcloud, Apple, Fastmail Memory — persistent, evolving across all your conversations No cloud account. No telemetry. MIT license. Everything lives in your data/ folder. The Cookbook is the standout feature Every other self-hosted UI assumes you already know what model to run. Odysseus doesn't. It scans your hardware, scores 270+ models against your actual VRAM, and gives you a one-click download-and-serve. It understands GGUF vs FP8 vs AWQ. It picks the right backend (vLLM, llama.cpp, Metal on Apple Silicon). Downloaded models persist in a volume — no re-downloading after container restarts. For someone who wants local AI but finds the ecosystem confusing, this is the most accessible on-ramp that currently exists. The code is better than the meme suggests The README has a little ASCII bear face. Don't let it fool you. The entry point app.py is 1,092 lines of real production thinking. A few things that stood out: The .env loader handles Windows BOM silently: loa
AI 资讯
Migrating a Real App to Swift 6: Data Races, a Dependency I Had to Evict, and the Compiler That Wouldn't Let Me Lie
Let me start with a confession: I have been writing concurrent code since the only tool in the box was a mutex and a prayer. After a decade of Swift I feel suspicion of any code that touches two threads and claims to be fine. So when Swift 6 showed up promising to prove my concurrency correct at compile time, I had two reactions at once. The grizzled half of me said "sure, kid." The other half — the half that has spent actual weekends chasing a heisenbug that only reproduced on a customer's M1 under sync load — said "...please. Please be real." This is the story of moving Ditto Edge Studio — a SwiftUI debug-and-query tool for the Ditto edge database — to Swift 6's strict concurrency mode. It's a real app: SQLCipher persistence, an embedded MCP server, a SpriteKit presence graph, live sync over Bluetooth and WebSocket. Not a to-do list. The kind of app where concurrency bugs hide in the cracks and wait for a demo. Spoiler: it was worth it. It was also more work than the WWDC talk implied, and the most valuable thing the compiler did happened in the one place I told it to stop looking. Let me show you. First, the Wall: A Dependency That Wasn't Coming to Swift 6 Here's the thing nobody warns you about. Swift 6 language mode isn't really a per-file setting. Your code can be immaculate — every actor isolated, every Sendable accounted for — and you'll still be stuck, because one dependency that isn't Swift 6-ready can hold your entire module hostage. Mine was a code editor. I'd been using a popular SwiftUI editor package for the DQL query editor, and it transitively pulled in a syntax-highlighting library. Both were lovely. Both were also written for a more innocent time, and neither was going to compile under Swift 6 strict concurrency without upstream changes that weren't happening on my timeline. I had the usual three options, and I want to be honest about how tempting the cowardly ones were: Pin the dependency and leave the whole app at Swift 5. Free today, expensive
AI 资讯
I Wrote 50 Claude Code Prompts and Used Them for a Week -- Here's What Actually Works
Last week I did something dumb: I sat down and wrote 50 Claude Code prompts in one sitting. Halfway through I was sure most of them would never get used. But I finished, pushed them to GitHub, and made myself use them for an entire week -- no ad-hoc prompting allowed. The result surprised me. Some skills were life-changing. Others were useless. Here is the honest breakdown. The Methodology I categorized the 50 skills into 5 types: Analysis (12), Generation (14), Debugging (8), Planning (10), Maintenance (6). Rule: every time I hit a task, I must use a skill file or admit I did not have one. The 7 That Actually Saved Me Hours 1. Code Review Assistant (saved ~3h) This was the biggest surprise. I usually review PRs by gut feel -- scan the diff, look for obvious bugs, approve. The Code Review skill forced me to be systematic: On a 400-line PR it caught 2 security issues I would have missed. That alone justified the experiment. 2. Bug Investigator (saved ~2h) Instead of pasting errors and asking "why?", this skill forces you to provide: error message, file context, hypothesis. 3. Dependency Audit (saved ~1h) Scanned a 3-year old Node project. Found 2 CVEs, 8 unused devDependencies (21 MB). 4. Auto Commit Messages (saved ~30m) Saves 2 minutes per commit. Over 15 commits in a week that is 30 minutes. 5. Test Generator (saved ~2h) Generates 5-8 test cases per function in seconds. 6. Refactoring Planner (saved ~1h) Reads the function, identifies extraction candidates, outputs a dependency-ordered plan. 7. Performance Audit (saved ~30m) Found an unoptimized 3 MB hero image and a render-blocking script. The Ones I Never Touched About 8 out of 50 were "not this week" -- Database Migrations, API Documentation, CI/CD Pipeline. What I Learned The ROI is in the analysis skills. Code review, bug investigation, dependency audit -- these are high-judgment tasks where Claude thoroughness beats speed. Skills are habit, not technology. The hardest part was not writing the prompts -- it w
AI 资讯
🚀 Rebuilding My Android App with Jetpack Compose: The Mailfo v2.0 Journey
Hey DEV community! 👋 I just completely rebuilt and launched Mailfo v2.0 , an privacy-focused temporary disposable email app for Android[cite: 1, 2]. The first version got the job done, but it lacked the fluid user experience, offline reliability, and sleek UI that modern mobile apps need. I decided to tear it down and rewrite it from scratch using Jetpack Compose , Room DB , and modern Android architecture[cite: 1]. Here is a breakdown of what went into the rebuild, why privacy tools like this are essential, and what's new[cite: 1]. 🛡️ Why Use a Temporary Disposable Email? We’ve all been there: you want to download a single source-code snippet, test a new app, or sign up for a one-time service, but you don't want your primary inbox flooded with endless marketing spam[cite: 1]. A disposable email address acts as your personal buffer[cite: 1]. It protects your personal data, prevents tracker exposure, and keeps your real inbox clean[cite: 1]. ⚠️ Pro-tip: Mailfo is designed strictly for low-risk temporary email needs[cite: 1]. Do not use disposable email addresses for banking, legal accounts, or primary account recoveries[cite: 1]! 🛠️ The Tech Stack & Architecture Upgrades Moving from version 1.0 to 2.0 meant migrating away from legacy views to a fully declarative UI workflow[cite: 1, 2]. UI/UX Architecture: Built entirely with Jetpack Compose for smooth performance, a modern look, and native Light, Dark, and System theme switching[cite: 1]. Navigation: Implemented an intuitive bottom navigation system dividing the app into distinct Home, Inbox, and Profile tabs[cite: 1]. Caching & Offline Stability: Integrated a local Room SQLite database to cache inbox summaries and message data[cite: 1]. This guarantees instantaneous screen transitions without annoying network loading spinners[cite: 1]. ✨ Key Features in Mailfo v2.0 Custom & Random Email Generator: Instantly spin up a completely randomized address or build a custom email username using multiple searchable domains[ci
AI 资讯
Backstage vs Port vs Cortex: When to Stop Self-Hosting
Backstage won the developer portal war and most teams running it still failed. Spotify's open-source framework, now a CNCF project, holds about 89% of the IDP market, runs at more than 3,400 organizations, and serves over two million developers outside Spotify. That is a decisive victory by any market-share metric. Then you find the number nobody puts on a keynote slide: the average internal adoption rate of a self-hosted Backstage instance sits around 10%. Most teams stand up a portal, demo it to leadership, and watch it quietly fail to become the thing engineers open every morning. So the slogan making the rounds in platform circles this year, "DIY is dead," is aimed at the exact tool that dominates the category. That sounds like a contradiction. It isn't. It's a math problem about where a small platform team's hours actually go. The 89% that doesn't mean what you think Framework market share and developer adoption are two different scoreboards, and Backstage is winning one while losing the other. Winning the framework war means a lot of organizations chose Backstage as the thing to build on. It says nothing about whether developers inside those organizations use the resulting portal. The honest read of the data is grim: teams "burn out on maintenance before delivering features developers actually want," and 56% of Backstage adopters name upgrades as their single biggest pain point. Not catalog design, not plugin gaps. Upgrades. The treadmill of keeping a fast-moving framework current is the thing that eats the year. I've watched this pattern up close on infra teams that had every reason to succeed. The portal goes live, gets a round of applause, and then the catalog data goes stale because nobody owns the integrations, the scorecards never get wired to real ownership data, and three months later the platform engineers are spending their sprints chasing a plugin that broke on the latest bump. The portal became the project instead of the platform. That is the failu