AI 资讯
The part of a PaaS you use most should have the least power — so I built Mooring
I have a folder on my laptop called side-projects . Most of them are Dockerized. Most of them will never see more than a handful of users. And for years, every one of them hit the same wall: getting the thing onto a cheap VPS without losing a weekend — and copy-pasting my own past mistakes forward every single time. Here's the opinion that eventually turned into a project: the part of a PaaS you touch most often should hold the least power over your server. Think of a deploy tool as two planes. There's a read plane — dashboards, logs, container health, the stuff you stare at — where you spend most of your time and which is your most exposed surface. And there's a write plane — deploy, restart, the actions that actually change the system — which is rare and should be gated. My frustration was that the thing I looked at all day and the thing that could rewrite my box tended to sit on the same pile of privilege. So I built Mooring to keep those two planes apart. It's an early, solo project, and this post is me showing it and asking for eyes on it. The mental model The whole thing, end to end: Install it as an unprivileged systemd service (not root). Connect a git repo. Write one mooring.yaml . Click Deploy. That's the loop. Everything below is what's underneath it. What it is Mooring is a small, security-first, self-hosted control plane for Docker — a tiny PaaS. You point it at a git repo, describe your app once, and it deploys and runs your containers on your own server. Same territory as Coolify, Dokku, CapRover, and Kamal — all genuinely good work. The difference I care about is the posture underneath. It ships as one static, CGO-free Go binary . It runs as an unprivileged systemd service — not root. State lives in SQLite (the pure-Go modernc driver). Every asset is embedded with go:embed , so there's no node_modules , no asset pipeline, nothing to build on the box. To be honest about the neighborhood: setting up a self-hosted PaaS, these tools tend to want broad ac
AI 资讯
I built a daily Linux documentation site
I built a daily Linux documentation site I created this site because I've noticed that Linux documentation is generally confusing. What is xybss? xybss is a simple site that publishes Linux documentation every day. No ads No tracking No JavaScript Just plain HTML docs I add at least one new command every day. Who is it for? Beginners learning Linux Anyone who needs a quick reference People who want simple, clean docs Current content Right now, the site covers basic commands like ls and rm. More commands are added daily. Check it out 👉 https://xybss.github.io Feedback is welcome
AI 资讯
A 20-year-old HCI paper, resurrected as a Chrome extension
I missed the tiny "x" on a browser tab again today. Meant to close it, switched to it instead. Aiming a one-pixel pointer at an eleven-pixel checkbox is basically microsurgery, and somewhere along the way we all just accepted that. Here's the strange part: HCI research solved this twenty years ago. It just never shipped. The paper In 2005, Grossman and Balakrishnan published The Bubble Cursor at CHI. The whole idea fits in one sentence: Make the cursor's hit area a dynamic circle that always contains exactly one target. That turns out to be the same thing as always selecting the target nearest to the pointer. Picture the screen divided into Voronoi cells, one per clickable thing, and the cursor picking the owner of whatever cell it's currently in. The clever part is what it refuses to do. Naive "gravity" cursors snap to every link on the way to the one you actually want, and they get stuck. The bubble cursor grabs exactly one target by definition. The moment a second target becomes nearer, it switches. So it stays calm on link-dense pages, and the paper showed significant speedups in controlled experiments. Twenty years later our cursors are still naked, so I built it as a Chrome extension. It's called MagPoint . The core is about 30 lines A content script collects clickable elements ( a[href] , button , input , ARIA roles and so on) and, every frame, picks the one with the smallest point-to-rectangle distance: function pointToRect ( x : number , y : number , r : DOMRect ): number { const dx = Math . max ( r . left - x , 0 , x - r . right ); const dy = Math . max ( r . top - y , 0 , y - r . bottom ); return Math . hypot ( dx , dy ); } Clicks that land in the empty space near a captured element get re-routed to it. Past a max radius of 120px the magnet lets go, and empty-space clicks behave like the normal web. It also stands down while you type or select text, because getting yanked toward a link mid-sentence would be infuriating. The rule that kept me sane: the vis
AI 资讯
Scaling Terraform Infrastructure Beyond a Single Team
When a single engineer manages all the Terraform in an organisation, everything is simple. One repo, one state, one pipeline, one set of credentials. There's no coordination overhead because there's no one to coordinate with. That stops working the moment a second team needs to deploy infrastructure. And by the time you have three or four teams — networking, platform, application, security — the single-team model is actively slowing everyone down. This guide covers what breaks, how teams typically work around it, and how to set up a structure where each team owns their slice of infrastructure independently. What breaks State lock contention Terraform's state locking is per-state. When the networking team is running terraform plan , the application team's pipeline is blocked — even though they're changing completely unrelated resources. The more teams share a state, the more time everyone spends waiting. Blast radius A junior engineer deploying a new application service shouldn't be able to accidentally destroy the VPC. But if application resources and networking resources share a state, a single misconfigured terraform apply can touch anything. Code review catches some of this. Not all of it. Credential sprawl A shared pipeline needs credentials for everything — the networking team's Azure subscription, the application team's AWS account, the security team's DNS provider. Every team's secrets end up in one CI environment, accessible to anyone who can trigger a run. This fails most compliance audits. Approval bottlenecks In many organisations, one person or a small group gatekeeps all infrastructure changes. Every PR needs their review. Every apply needs their approval. The gatekeeper becomes a bottleneck not because they're slow, but because they're a single point of serialisation for all infrastructure work. Backend access as implicit access control Terraform has no built-in concept of per-team or per-workspace permissions. All workspaces in a backend share the sam
AI 资讯
Managing Terraform Across Multiple Cloud Providers
Most organisations don't live in a single cloud. You might run compute in AWS, DNS in Cloudflare, identity in Azure AD, and logging in GCP. Terraform handles each provider fine on its own, but the moment you need to coordinate across providers the tooling fights you. This guide walks through the common pain points of multi-cloud Terraform setups and the approaches teams use to cope — then shows how Snap CD makes cross-cloud dependency management a solved problem. Where it gets difficult Credential sprawl Each cloud provider has its own authentication mechanism. AWS uses IAM roles and access keys. Azure uses service principals and managed identities. GCP uses service accounts and workload identity federation. A single Terraform state that spans providers needs credentials for all of them — which means your CI runner or developer workstation holds keys to everything. That's a security problem. A compromised CI pipeline with AWS and Azure credentials exposes both clouds simultaneously. And it's an operational problem — rotating credentials means updating every pipeline that touches that state. This problem compounds at scale: Terraform couples provider processes tightly to credentials , so managing hundreds of accounts across clouds means spawning thousands of provider processes, which quickly becomes unmanageable. Provider version conflicts Terraform providers are versioned independently. Upgrading the AWS provider to fix a bug in aws_eks_cluster shouldn't require you to also test a new version of the Azure provider. But when they share a state, a terraform init -upgrade pulls new versions for everything, and a regression in one provider blocks all deployments. Terraform also lacks built-in support for instantiating multiple providers with a loop and passing providers to modules in for_each , making multi-cloud configurations especially verbose and repetitive. Blast radius across clouds A misconfigured terraform apply in a single-cloud state damages resources in one c
AI 资讯
Agentic payments: your AI agent can pay - but can it get paid?
Everyone is building rails for AI agents to spend money. Google's AP2 gives agents payment mandates. Coinbase's x402 pattern turns HTTP 402 into machine-to-machine micropayments. Agent wallets are everywhere. But watch what agents actually do all day in 2026: they build products. A Lovable app in an evening. A SaaS in Cursor over a weekend. And every one of those products eventually needs the thing no spending protocol covers — accepting money. The wall every agent hits Here's a session I've watched a hundred times: ➜ ~ claude "finish my app" ✓ scaffold — Next.js + Tailwind ✓ UI — components & design system ✓ UX — onboarding flow polished ✓ auth — Google sign-in wired ✓ database — schema + migrations ✓ deploy — production live ▸ application is almost ready… ✗ missing: payments And then the agent — which just shipped a full product in one session — tells you: "To accept payments you need a merchant account. Traditional PSP onboarding requires a compliance review — expect to wait at least a week for approval." An app built in an evening, waiting 7 days for permission to charge £1. That's not risk management. That's a workflow designed when software took months to ship, and nobody went back to fix it. Your other options aren't better: no company? The classic path detours through Stripe Atlas ($500) and an IRS EIN wait that stretches to weeks for non-US founders — before you can even apply . Software's bottleneck has moved — from writing code to accepting payments. What "agent-native" means on the merchant side The spending side got protocols. The earning side needs four properties: 1. Machine-readable everything. Docs an agent consumes in one pass — llms.txt , agents-first API references. The integrating developer is increasingly not a human. 2. Provisioning tools, not just management tools. Stripe's MCP server can operate an account you already have — customers, refunds, invoices. The agent-native question is one level deeper: create the account. 3. Progressive KYB. G
AI 资讯
You Can't Review an Agent. You Can Review a Plan.
A harness for AI-era Terraform. I'm building one. For a while now I've been developing a harness for infrastructure-as-code as a private SDK and compiler — the layer that sits between whoever proposes a change (a person, an agent, CI) and whatever actually reaches production. This post isn't the tool. It's the thinking underneath it, and the few pieces I've become most convinced by while building it. (Notes from inside the work — where I've landed so far, not advice.) The problem that sent me down this road is easy to state and easy to underrate. A version of it happened recently. An agent fixed some Terraform; the PR read clean — tidy diff, sensible resource names, a plan output that looked exactly like what I'd asked for. It got approved. And then, at apply time, a different plan ran than the one that was reviewed: apply had re-planned against state that moved in between, and the diff that touched production wasn't quite the diff anyone had read. Nothing broke, that time. But that near-miss is the whole reason the harness exists. Because the danger was never "the agent writes bad HCL." Agents write perfectly good HCL; I let them. The danger is the distance between the plan a human reviewed and the plan that actually runs — and once agents are the ones proposing changes at volume, that distance is the thing I most want to nail shut. Where I've landed for now (and expect to keep revising): What AI-era IaC needs isn't AI that can apply . It's a structure where every change — human or agent — is evaluated at the same boundary , and only a reviewed plan ships. The unit of trust isn't the agent. It's a specific, reviewed plan , bound byte for byte. You can't review an agent. You can only review a plan. Instructions to an agent can be broken. A CI gate can't be talked out of it. Put guidance in the prompt; put the guarantee in the gate. Terraform/OpenTofu don't go away. You wrap them in a harness; you don't replace them. Your repo has non-human authors now For years IaC
AI 资讯
How I Cut Our AI API Bill by 95% — The Engineering Playbook
How I Cut Our AI API Bill by 95% — The Engineering Playbook When our finance lead forwarded me the AWS bill for March, I almost choked on my coffee. We were a team of nine engineers shipping AI features, and somehow we'd burned through enough on inference to cover two salaries. The worst part? I hadn't even noticed because the charges were scattered across OpenAI, Anthropic, and a couple of side experiments. That's the moment I decided to actually treat LLM spending like a real infrastructure problem instead of a credit card swipe. What follows is the playbook I wish I'd had on day one. These aren't theoretical tips — they're the exact moves I made across three products to get our run-rate down to roughly 5% of where it started, without shipping worse software. The Harsh Truth About Model Defaults Here's the dirty secret nobody tells you in the LLM hype cycle: most teams default to the most famous model for every single call. GPT-4o for everything. Claude Sonnet for everything. Then they wonder why their "simple AI feature" costs them a kidney. The model selection decision is where I recovered the majority of my budget. When you look at it rationally, the gap between the flagship tier and the cheap-tier models is absurd for tasks that don't require frontier reasoning. This is the matrix I landed on, and it still governs our routing today: Task What I Used To Use What I Use Now Cost Cut Simple chat GPT-4o ($10/M out) DeepSeek V4 Flash ($0.25/M) 97.5% Classification GPT-4o-mini ($0.60/M) Qwen3-8B ($0.01/M) 98.3% Code generation GPT-4o ($10/M) DeepSeek Coder ($0.25/M) 97.5% Summarization GPT-4o ($10/M) Qwen3-32B ($0.28/M) 97.2% Translation GPT-4o ($10/M) Qwen-MT-Turbo ($0.30/M) 97% I want you to really sit with the classification row. Qwen3-8B at $0.01 per million output tokens. That's sixty times cheaper than GPT-4o-mini. For a binary sentiment classifier, the accuracy difference in my benchmarks was under 1.5 percentage points. The ROI math isn't even close. The code
AI 资讯
Self-Hosting Like a Pro, Part 1: Hardening a Fresh Ubuntu VPS
This is the first article in a four-part series where I document how I turned a 10€/month VPS into a production-grade platform hosting my portfolio, a university group webapplication and a SaaS product, all isolated from each other with Kubernetes. In this part, we take a fresh Ubuntu server and lock it down properly before installing anything else. Why bother with hardening? The moment your VPS gets a public IP address, it starts receiving attacks. Not "might receive", it starts . Within minutes, automated bots will probe port 22, try root:root , admin:admin123 and thousands of other credential combinations. If you skip this step and jump straight to deploying your apps, you are building on sand. The good news: an hour of work is enough to eliminate the vast majority of these threats. Here is what we will set up: A non-root user with sudo privileges SSH key authentication, with passwords and root login disabled UFW as a simple, effective firewall Fail2ban to ban brute-force attackers automatically Automatic security updates What you need A fresh VPS running Ubuntu 24.04 LTS or newer. I use a Hostinger KVM 2 (2 vCPU, 8 GB RAM, 100 GB NVMe), but any provider works: Hetzner, DigitalOcean, OVH, Contabo. The root password or SSH key your provider gave you. A terminal on your local machine (macOS, Linux, or WSL on Windows). Throughout this tutorial, replace YOUR_SERVER_IP with your server's IP address and deploy with the username you want to use. Step 1: First login and system update Connect as root for the first and last time: ssh root@YOUR_SERVER_IP Update everything before touching anything else: apt update && apt upgrade -y apt autoremove -y If a kernel update was installed, reboot now: reboot Wait a minute, then reconnect. Step 2: Create a non-root user Working as root is like driving without a seatbelt: fine until it isn't. One mistyped rm -rf and the party is over. Create a dedicated user: adduser deploy Choose a strong password (you will still need it for sudo ,
AI 资讯
What I Learned After Building AI Systems Across Multiple Brands
One of the biggest misconceptions about AI is that every project is unique. At first glance, it certainly feels that way. One project is a chatbot. Another is an AI-powered search system. Another automates documentation. Another generates code. But after building AI systems across multiple brands and initiatives, I started noticing something surprising. The technology changes. The business domain changes. The users change. The underlying principles rarely do. Here are some of the biggest lessons I've learned. 1. AI Doesn't Fix Broken Systems Many teams believe AI will solve operational problems. In reality, AI usually exposes them. If documentation is inconsistent, AI becomes inconsistent. If data is outdated, AI produces outdated answers. If workflows are unclear, automation becomes unreliable. One of the biggest lessons I've learned is this: AI amplifies the quality of your existing systems. It rarely compensates for poor foundations. That's why I spend far more time understanding processes than choosing models. 2. Simplicity Beats Complexity Every new AI framework looks exciting. Agents. Memory. Planning. Reflection. Tool calling. Multi-agent orchestration. I've experimented with many of these approaches, but one principle keeps proving itself. The simplest solution that solves the problem is usually the best solution. A straightforward workflow is often easier to: Build Test Maintain Scale Explain Complexity should be introduced only when it delivers clear value. 3. Prompt Libraries Are More Valuable Than Individual Prompts When I first started using AI, I wrote prompts from scratch. Eventually I realized I was solving the same problems repeatedly. Now I build prompt libraries. Instead of creating new prompts every day, I improve existing ones. This creates consistency across projects. If you're interested in how I manage this, I recently shared the system I use to organize more than 10,000 prompts across different projects. The shift from individual prompts to
产品设计
What Happens When Everyone Can Build Apps But Nobody Understands Them?
Alright, real talk moment. Last week I watched someone with zero coding background build a fully...
AI 资讯
Presentation: Practical Robustness: Going Beyond Memory Safety in Rust
Andy Brinkmeyer shares how engineering leaders and architects can use Rust to build failure-proof systems. Moving beyond memory safety, he explains how ownership, enums, and the typestate pattern embed complex runtime protocols into compile-time checks. Learn to eliminate entire classes of bugs, manage real-world resources safely, and maximize codebase robustness effortlessly. By Andy Brinkmeyer
开发者
My rate limiter was doing exactly what I told it to do. That was the problem.
I had a /image endpoint capped at 3 requests per minute. Simple express-rate-limit, keyed by IP,...
AI 资讯
Decoupling Async State from UI Lifecycles
In my previous articles, I’ve consistently emphasized a core architectural principle: once the render layer no longer dictates the entire data flow, the boundaries between State, Derived State, and Effects become critical. When we fall into the habit of stuffing every UI-affecting variable into generic "state," the system quickly loses its semantic structure. In modern frontend applications, this architectural gap becomes most glaring when dealing with asynchronous work. Async data is never merely "a value that will appear in the future." It carries complex semantics regarding its source, temporal validity, cancellation, error recovery, and invalidation. If these semantics aren't modeled explicitly, they inevitably get pushed down into the UI framework’s lifecycle—indirectly patched together through component mounts, effect dependencies, and callback guards. This brings us to the core question of this article: What does a system lose when the correctness of async work is forced to depend on the UI lifecycle? We are all incredibly familiar with this pattern: const data = await fetchSomething () setState ( data ) Or, using a standard UI framework hook: useEffect (() => { let cancelled = false fetchSomething (). then ( result => { if ( ! cancelled ) { setData ( result ) } }) return () => { cancelled = true } }, []) There is nothing inherently wrong with this code for simple use cases. It’s intuitive and perfectly aligns with how Promises are designed to work: trigger the operation, wait for the resolution, and write the result back into state. However, this mental model has a subtle downside. It encourages us to think of async work as simply calling setState after a Promise resolves. That may hold up for simple screens, but as an application grows, the model starts to expose structural problems. Promise Only Describes Completion, Not Ownership A Promise solves a very specific problem: A piece of work will complete in the future, and it will either succeed or fail. It c
AI 资讯
How I Built a Secondhand Clothes Marketplace for Kisumu, Kenya — As a First-Year Developer
A few months ago I didn't know much about coding. Today I have a full stack marketplace running with a real API, a live database, user authentication, image uploads, messaging and a React frontend. The Idea Kisumu has a huge secondhand clothes market. Mitumba is everywhere — Kibuye market, roadside stalls, WhatsApp groups. But there is no dedicated digital platform for it. If you want to sell a jacket in Kondele you have no easy way to reach buyers in your area. If you want to find size L shoes in CBD you have to physically go and look. I wanted to build something that solved a real local problem. Not another todo app. Not another weather app. Something that could actually help people in my city. That is how Kisumu Marketplace was born. The Tech Stack I Chose I built the backend in Go using the Gin framework. The database is PostgreSQL hosted on Neon.tech — a free cloud database that saved me more than once when my laptop broke. Authentication uses JWT tokens and bcrypt for password hashing. Images are uploaded to Cloudinary. The frontend is React with Tailwind CSS. I chose Go because Zone 01 teaches it and I wanted to go deep on one language rather than shallow on many. I chose PostgreSQL because it is the industry standard and learning it properly matters. I chose React because it is the most in-demand frontend framework and I wanted to build something real with it. What I Learned I learned Go from scratch while building this. I learned React from scratch while building this. I learned PostgreSQL, JWT, bcrypt, Cloudinary, Tailwind, axios, React Router and more — all by needing them for this project. The most valuable thing I learned is that you understand something properly only when you build with it. Reading about JWT is nothing like debugging a 401 Unauthorized error at midnight. I also learned that documentation is a skill. Writing this article, explaining how things work, is making me understand my own project better.
开源项目
Ship multi-language audio in HLS: author the manifest, wire the hls.js switcher
📦 Code: github.com/USER/hls-multi-audio - replace before publishing TL;DR We'll add a working language picker to an HLS player. The hard part isn't the dropdown, it's the manifest. We'll author alternate audio with EXT-X-MEDIA audio groups, package it correctly, debug the classic "zero audio tracks" bug, and wire a switcher on hls.js v1.7 . Adaptive video, captions, the whole pipeline already works. Now someone wants an English/Spanish audio toggle. In HLS, "which audio can the viewer pick" is decided at packaging time and written into the master playlist. The player just displays it. Let's build it in that order. 1. Understand the structure (audio groups) HLS decouples video variants from audio renditions: Each audio rendition is an #EXT-X-MEDIA:TYPE=AUDIO entry pointing at its own media playlist. Renditions are bundled into a named audio group via GROUP-ID . Each video variant ( #EXT-X-STREAM-INF ) references a group with AUDIO="..." . A correct master playlist: #EXTM3U #EXT-X-VERSION:6 #EXT-X-MEDIA:TYPE=AUDIO,GROUP-ID="aud",NAME="English",LANGUAGE="en",DEFAULT=YES,AUTOSELECT=YES,CHANNELS="2",URI="audio/en.m3u8" #EXT-X-MEDIA:TYPE=AUDIO,GROUP-ID="aud",NAME="Espanol",LANGUAGE="es",DEFAULT=NO,AUTOSELECT=YES,CHANNELS="2",URI="audio/es.m3u8" #EXT-X-STREAM-INF:BANDWIDTH=2128000,CODECS="avc1.640028,mp4a.40.2",AUDIO="aud" video/720p.m3u8 #EXT-X-STREAM-INF:BANDWIDTH=1128000,CODECS="avc1.640020,mp4a.40.2",AUDIO="aud" video/480p.m3u8 Every attribute earns its place: LANGUAGE - BCP-47 code, used for the label. DEFAULT - plays when the viewer has no preference. AUTOSELECT - may be auto-picked from the OS language. CHANNELS - needed so the player can reason about stereo vs surround. BANDWIDTH on each video variant must include the audio group's bitrate , or your ABR logic works from a wrong total. 2. Author the renditions with FFmpeg Extract/encode each language's audio, then package. First, encode video-only and audio-only renditions: # video only (no audio), two ladder rungs
AI 资讯
Benchmark NVENC vs CPU transcoding (and find your real break-even) with FFmpeg
📦 Code: github.com/USER/nvenc-vs-cpu-bench - replace before publishing TL;DR A GPU encodes faster than a CPU, but "faster" and "cheaper" are different claims. We'll build a small FFmpeg + VMAF harness that times software (libx264/SVT-AV1) against hardware (h264_nvenc/av1_nvenc), then plug the results into a dollars-per-encoded-minute formula so you find your break-even instead of trusting a benchmark blog. We're using FFmpeg 7.1.x (current stable line) and an NVIDIA GPU with NVENC. Same approach works for Intel QSV ( *_qsv ) and AMD AMF ( *_amf ) if you swap the encoder names. Why this isn't obvious NVENC is a fixed-function hardware block, not "the GPU doing x264 in parallel." It's extremely fast and barely touches the CPU, but it exposes fewer rate-control knobs and gives up a little compression efficiency versus a slow software preset. The gap has narrowed a lot, but it's still there at the quality-obsessed end. So the decision is per-job, and it comes down to one number: dollars per encoded minute = (instance $/hr) ÷ (minutes encoded/hr) . GPU instances cost more per hour but encode many streams in parallel, so the answer depends on whether you can keep the encoder saturated. Let's measure instead of argue. 1. Set up the encoders Three contenders. One representative source file (use real footage, not a synthetic clip). # software H.264, quality-leaning preset ffmpeg -y -i source.mp4 -c :v libx264 -preset slow -crf 21 -an out_cpu.mp4 # NVENC H.264, quality-tuned ffmpeg -y -hwaccel cuda -i source.mp4 -c :v h264_nvenc -preset p6 -tune hq \ -rc vbr -cq 23 -an out_gpu.mp4 # AV1: software (SVT-AV1) vs hardware (needs Ada / RTX 40+) ffmpeg -y -i source.mp4 -c :v libsvtav1 -preset 6 -crf 30 -an out_svtav1.mp4 ffmpeg -y -hwaccel cuda -i source.mp4 -c :v av1_nvenc -preset p5 -cq 30 -an out_av1nvenc.mp4 💡 Tip: -preset p1 (fastest) through -preset p7 (slowest/highest quality) for NVENC. p6 / p7 is where it competes on quality; p1 - p3 is where it competes on raw throughput.
AI 资讯
5 video APIs compared on what's included before you pay extra (2026)
📦 Code: github.com/USER/video-api-bench - replace before publishing TL;DR The per-minute delivery rate is the easiest number to compare and the least useful. The real cost lives in encoding, analytics, and the player. This post compares Mux, Cloudflare Stream, api.video, FastPix, and AWS on what each includes by default, then gives you a tiny script to benchmark upload and time-to-ready on your own files so you stop trusting marketing pages. I have shipped video on four managed APIs across three jobs, and every single time the invoice surprised someone. Not because the delivery rate was wrong, but because encoding, analytics, and the player turned out to be separate line items on some platforms and free on others. Let's compare the parts that don't show up in the headline number. ⚠️ Note: pricing pages move. Everything here was checked in June 2026; verify the links before quoting numbers. 1. Encoding: free or metered? This is the widest spread in the whole comparison. Platform Encoding Delivery Storage Cloudflare Stream Free $1 / 1,000 min delivered $5 / 1,000 min stored api.video Free (unlimited) $0.0017 / min $0.00285 / min FastPix Free on standard plan ~$0.00096 / min @1080p Per-minute, tiered Mux Metered per minute Per minute Per minute AWS (DIY) Per minute (MediaConvert) Per GB (CloudFront) Per GB (S3) If your catalog is upload-heavy (lots of assets encoded once, watched rarely), metered encoding is not a rounding error. It can flip which platform is cheapest, even when the delivery rates look identical. 2. Analytics: included or a $499 floor? QoE analytics is the feature teams forget to price until playback breaks in production. Platform QoE analytics Entry cost FastPix (Video Data) Session-level, 50+ signals/session Free up to 100K views/month Mux (Mux Data) Mature, broad device SDKs $499/month (Media plan, 1M views, +$0.50/1K) Cloudflare Stream Basic Included, limited depth api.video Available Usage-based AWS Build it yourself (CloudWatch + logs) Engineerin
AI 资讯
I Ran a Technical SEO Audit for Five Days: the Gates Mattered More Than the Five Fixes
Plenty of SEO audits end with a single tool report. You run Lighthouse, screenshot Search Console coverage, save a "12 issues found" panel, and call it done. The trouble is that most audits finished that way silently revert within three months. Someone publishes a new post, refactors a component, swaps a font, and the issue quietly comes back. Nobody notices. Over the last five days I actually audited my four-language blog (ko/ja/en/zh, 298 posts per language). Five items, all fixed. But what I really want to talk about isn't what I fixed. It's that the five fixes mattered less than the build gates that keep them from ever returning. An audit should be a loop, not an event. Why a one-report audit always comes back Most technical SEO issues aren't "the code is wrong." They're "an invariant was never enforced anywhere." Take a clear rule: a published post must not link internally to a draft. Obvious enough. But if a human has to remember that every time, then the moment a recommendation generator pulls in one draft slug, a 404 is born. The report catches that 404 and shows it to you, but it does nothing to prevent the next one. So I ran the audit as a three-step loop. Measure. Fix the biggest item first. Then turn that item into a checker and nail it to the build . Skip the third step and the first two become a chore you repeat every six months. Once a gate is in place, the same class of problem makes npm run build fail. A pipeline enforces the rule, not human memory. This isn't a new invention. It's the same logic by which tests prevent bug regressions, applied to the content and markup layer. It's just oddly rare in SEO, where most teams leave "SEO checks" as a quarterly manual task. The five items I actually ran over five days Measurement first. Each item got a before/after in numbers, not a vibe that "things feel better" but reproducible figures. (The raw log of all five lives on the improvement history page too.) Date Item Before After Gate 07-02 relatedPosts int
AI 资讯
My AI agent tried to ship a mistake we'd already reverted
A month ago we added a card_token column to the users table so a background job could retry failed Pro charges. It lasted about two days. Storing card data in your own database drops you into PCI-DSS (the compliance standard that kicks in the moment card data touches your systems), so we pulled it and moved to Stripe-managed payment methods. Last week the charges started failing again. New Claude Code session, no memory of any of that. Its plan? Add a card_token column to users and retry. I don't really blame the agent. It had the context the first time and it was right. The problem is that context died when the session closed. That's the part I never see mentioned about building with agents: the code sticks around, the reasoning doesn't. People leave a trail without trying. A commit message, a PR comment, the Slack thread before it. Agents don't, and the prompt that explained everything is gone by morning. So I built Selvedge to hold onto the reasoning. What happened the second time Selvedge is a local MCP server the agent calls as it works. There's a four-line block in our CLAUDE.md that says, roughly: before you touch an entity, check if we've been here before. $ selvedge prior-attempts users.card_token users.card_token Prior attempt 28 days ago ( reverted after 2 days ) Reasoning Added to store card tokens for one-click retries. Outcome REVERTED — kept card data out of our own DB to stay clear of PCI-DSS scope ; moved to Stripe-managed methods. So it didn't add the column. It charged off_session against the saved Stripe PaymentMethod instead. Charge retried, no card data in our database, done. We paid for that lesson once. How it works The agent writes down why live, in the moment, from the same context that made the change. That's the whole trick. A lot of the "git blame for AI" tools take your diff afterward and ask a second model to explain it. That's a guess. It reads well, but you can't really build on it. Selvedge stores what the agent actually meant, in i