今日已更新 50 条资讯 | 累计 24336 条内容
关于我们

标签:#webdev

找到 1741 篇相关文章

AI 资讯

Beyond Marketing Myths: Proxy Network Performance Benchmarks & Reliability Auditing in Production

Hey Dev Community, If you are running enterprise-scale web scrapers, pricing monitors, or data ingestion pipelines for LLMs, you’ve probably spent sleepless nights dealing with network latency and sudden 403 blocks. When choosing an infrastructure partner, every provider pitches the same script: "99.9% uptime guarantees, millions of residential IPs, and lightning-fast response times." But in the trenches of real-world data collection, we all know that marketing numbers rarely match production reality. Last quarter, my team ran an exhaustive infrastructure audit to compare proxy providers pricing performance and infrastructure stability. If you want to dive straight into our live dataset, telemetry scripts, and interactive monitoring utilities, you can check out the full workbench at ProxyVero . Here is a technical breakdown of how we built our benchmarking matrix, and the architectural gaps we discovered across mainstream enterprise proxy services. 📊 1. The Core Metrics: Uptime vs. Success Rates The biggest lie in the networking industry is confusing Server Uptime with Request Success Rate . A proxy gateway server can maintain a 99.9% uptime while the underlying residential peer network is failing 20% of your data collection requests due to strict target WAFs or high peer churn. When conducting our proxy providers uptime guarantees performance benchmarks , we evaluated three core parameters: TCP Handshake Latency : The time it takes to establish a connection with the proxy endpoint. TTFB (Time to First Byte) : Critical for parsing dynamic JavaScript targets. HTTP Status Code Reliability : Tracking the exact ratio of 200 OK vs. 403 Forbidden / 429 Too Many Requests . ⚖️ 2. The Big Three: Oxylabs vs Bright Data vs SmartProxy Comparison To provide an objective proxy network performance benchmarks comparison , we deployed standard headless browser worker instances (Playwright/Puppeteer) routed through different enterprise gateways. Below is a high-level summary of our a

2026-06-25 原文 →
AI 资讯

How I built an end-to-end encrypted pastebin (and why the server can’t read your text)

got annoyed that pastebin and similar sites log everything and keep your text forever, so i built one where the server literally cant read what you paste. heres how the encryption actually works and what i learned building it the problem most paste sites work like this: you type something, it goes to their server as plain text, and it sits in their database. they can read it. their employees can read it. anyone who breaches them can read it. and a lot of them keep it forever even after you think its gone. i didnt want to just promise not to look at your stuff. i wanted it so that i cant look even if i wanted to. the idea: encrypt before it leaves the browser the trick is that all the encryption happens on your side, in the browser, before anything gets sent. the server only ever sees scrambled bytes. the key never touches the server at all, it lives in the part of the url after the # , which browsers dont send in requests. so the flow is basically: you paste text browser generates a random key text gets encrypted with that key only the encrypted blob goes to the server the key gets stuck in the link after a # whoever opens the link decrypts it locally the actual code modern browsers have the Web Crypto API built in, so you dont need any library for this. heres the encrypt part, stripped down: \ `js async function encrypt(text) { const key = await crypto.subtle.generateKey( { name: "AES-GCM", length: 256 }, true, ["encrypt", "decrypt"] ); const iv = crypto.getRandomValues(new Uint8Array(12)); const encoded = new TextEncoder().encode(text); const ciphertext = await crypto.subtle.encrypt( { name: "AES-GCM", iv }, key, encoded ); // export the key so we can put it in the url const rawKey = await crypto.subtle.exportKey("raw", key); return { ciphertext, iv, rawKey }; } ` \ the ciphertext and iv go to the server. the rawKey gets base64'd and dropped into the link after the # . decrypting is just the same thing in reverse with crypto.subtle.decrypt . the thing that tripped

2026-06-25 原文 →
AI 资讯

I built a $0.0005 screenshot cropper that saves AI agents 95% on vision LLM costs

If you're building AI agents that work with browser screenshots, you already know the pain. You take a full 1920×1080 screenshot, pass it to GPT-4o or Claude, and watch your token bill climb — while the model downscales the image anyway and blurs the exact text you needed it to read. There's a better way. The problem Vision LLMs are expensive for two reasons when you feed them full screenshots: Token cost — a full screenshot can cost 10–20x more tokens than a small crop Accuracy loss — models internally downscale large images, blurring fine text, labels, and UI elements But your agent already knows where to look. Browser automation tools like Playwright and Puppeteer give you getBoundingClientRect() — the exact pixel coordinates of any element on screen. So why are you sending the whole screenshot? The solution I built a stateless pay-per-use API that takes a screenshot and pixel coordinates, and returns just the cropped element as a lossless PNG — ready to pass directly to your vision LLM. POST /crop { "image" : "<base64 screenshot>" , "x" : 120 , "y" : 45 , "width" : 640 , "height" : 80 } Returns: { "success" : true , "data" : { "base64" : "iVBORw0KGgo..." , "mime" : "image/png" , "width" : 640 , "height" : 80 , "bytes" : 4821 } } A 4KB crop instead of a 2MB screenshot. Same information. 95% fewer tokens. How payment works Here's where it gets interesting. The API uses the x402 payment protocol — HTTP's long-dormant 402 Payment Required status code, finally put to use. There are no API keys. No accounts. No subscriptions. The agent pays $0.0005 USDC per crop on Base L2 automatically. The flow: 1. Agent POSTs to /crop (no payment header) ← 402 with payment instructions in headers 2. Agent transfers 0.0005 USDC to recipient wallet on Base (near-zero gas, ~2 second settlement) 3. Agent POSTs again with x-payment-tx-hash header ← 200 with cropped PNG The entire exchange happens inside the HTTP request cycle. No human intervention. No billing dashboard. The money lands

2026-06-25 原文 →
AI 资讯

Building a Real-Time World Cup 2026 Bracket Predictor with Vanilla JS and GitHub Actions

Introduction With the World Cup 2026 group stage reaching its climax, football fans worldwide are speculating about who will make it to the finals. To make this experience interactive, I built a fully dynamic World Cup 2026 Bracket Simulator. Instead of just letting users click and choose winners, this app dynamically calculates ELO win probabilities and probabilistically generates realistic match scores (including extra time and penalties) based on team ratings. It also syncs with live match data in real-time. Live URL: https://worldcup-predict2026.github.io/champion/ Tech Stack: Vanilla JS, CSS3 (3D parallax), GitHub Actions, Python, football-data.org API Core Features & Technical Implementation ELO-Based Win Probability & Score Simulation Each team in the database is assigned an ELO-based strength rating. When a user runs the AI auto-prediction, the script calculates win probability and generates a realistic scoreline. Here is the goal roll algorithm (Poisson-like simulation) implemented in Vanilla JS: javascript function generateMatchScore(team1, team2, winner) { if (team1 === "TBD" || team2 === "TBD" || !winner) return null; const s1 = teamStrengths[team1] || 70; const s2 = teamStrengths[team2] || 70; const winnerIsTeam1 = (winner === team1); const strengthDiff = Math.abs(s1 - s2); const baseGoalExpected = 1.1; const bonusGoal = Math.min(1.8, strengthDiff / 12.0); // Goal weight based on ELO difference const rollGoals = (lambda) => { let L = Math.exp(-lambda); let k = 0; let p = 1.0; do { k++; p *= Math.random(); } while (p > L && k < 10); return k - 1; }; let gWin = 0; let gLose = 0; const r = Math.random(); if (r < 0.75) { // Regular time win (90 mins) gLose = rollGoals(baseGoalExpected); gWin = gLose + 1 + rollGoals(0.7 + bonusGoal); return winnerIsTeam1 ? ${gWin} - ${gLose} : ${gLose} - ${gWin} ; } else if (r < 0.92) { // Extra time win (AET) const normalGoals = rollGoals(baseGoalExpected); gLose = normalGoals; gWin = normalGoals + 1; return winnerIsTeam1 ?

2026-06-25 原文 →
AI 资讯

How Be Recommended by Inithouse Scores AI Visibility 0 to 100 Across ChatGPT, Perplexity, Claude and Gemini

Your product might rank on page one of Google and still be invisible to AI. When someone asks ChatGPT "what's the best project management tool for small teams," does your product show up? For most SaaS companies under 50 employees, the answer is no. At Inithouse, we built Be Recommended to answer that question with a number: a single AI visibility score from 0 to 100 that tells you exactly where you stand across four major AI engines. Here is how the scoring works under the hood. What the score measures The Be Recommended score captures how often, how prominently, and how positively AI engines mention your product when users ask category-relevant questions. A score of 0 means no AI engine mentions you at all. A score of 100 means every tested prompt across all four engines names your product as a top recommendation. The four engines we test against: ChatGPT (OpenAI), Perplexity , Claude (Anthropic), and Gemini (Google). Step 1: Prompt generation We start by building a bank of 50+ real prompts that a potential customer would actually type into an AI assistant. These are not keyword-stuffed test queries. They mirror how real people ask for recommendations. For a CRM product, that looks like: "What CRM should a 10-person startup use?" "Best alternatives to Salesforce for small businesses" "Compare CRM tools with good API integration" "Which CRM has the best free tier in 2026?" We group prompts into three categories: direct (user names the product category), comparative (user asks for alternatives or comparisons), and situational (user describes a problem without naming a category). Each category tests a different signal: brand recognition, competitive positioning, and contextual relevance. Step 2: Multi-engine querying Each prompt gets sent to all four AI engines through their APIs. We capture the full response text, not just a yes/no for whether your product appeared. The raw responses go into a structured analysis pipeline. We run queries from neutral accounts with n

2026-06-25 原文 →
AI 资讯

How to Get Your First Tool Online

TL;DR - A finished app that only runs on one laptop is a private demo. Getting it online means connecting three things: a place to store the code (version control), a place to run it (a host), and an address people can type (a domain). The same AI tool that helped build the app can walk a beginner through all three, often without ever opening a terminal. An important step you don’t want to skip is the security check before going live, because the fastest way to ruin a launch is to ship with the database wide open. So you’ve done it. You built your first tool. And it works. The button does the thing. Now’s the moment. It’s time to get your tool online, but how? A project running on a laptop is real, but it lives in exactly one place, the machine it was built on. Nobody else can open it. Getting that project online is its own small skill, separate from building, and it trips up more beginners than the building did. A new coder can finish a working photo booth app in an afternoon and still have no idea how to hand it to a friend short of pulling up the GitHub link while sitting together over coffee. The good news is that the part that used to eat a whole weekend now takes a conversation. Three Things Every App Needs to Go Live Almost every deployment, whatever the tool, comes down to three things working together. Version control: This is a place to store the code and track every change made to it. For most people that means GitHub, which we’ve talked about before. The same way Google Docs keeps a version history, GitHub keeps one for a project. This piece does not re-explain it; the GitHub walkthrough covers the whole thing. A host: A host is really just a computer that stays powered on and connected to the internet with a public address of its own. When a visitor types in the app's address, their browser sends a request across the internet to that machine, the machine runs the code, and it sends the finished page back. A laptop was quietly doing both jobs during the

2026-06-25 原文 →
AI 资讯

You don't need NextJS: here's why

This is the public, sanitized version of an internal proposal I wrote to move our production app off Next.js. Next.js is the default answer to "I want to build a React app." It's a great framework. But default and necessary aren't the same word. The gap between them quietly cost us speed, debuggability, and a surprising amount of cross-team friction. We were building an authenticated, data-heavy product: dashboards, filters, charts. Almost every screen lived behind a login and updated in response to clicks. For that shape of app, server-side rendering wasn't buying us much, and it was charging us a lot. First, the only question that matters The right architecture depends on what you're building. Content-first: Marketing sites, blogs, storefronts, docs. Mostly public, SEO matters, lots of static content. SSR/SSG is a genuinely great fit. Use Next.js. Seriously. Application-first: Internal tools, dashboards, admin panels, SaaS consoles. Behind auth, highly interactive, bottlenecked by your API and DB — not by React rendering. Put an application-first product on a content-first framework and you pay for machinery you never use. That was us. What SSR actually cost us Production debugging got harder Server-rendered errors don't map cleanly to the components you wrote, so root-causing took longer every single time. Client-side, the error happens in the browser with a stack trace that points at your component. Boring and fast to fix. Server components fought our tests You can't cleanly unit test a server component that renders other server components. Tools like React Testing Library expect renderable elements, not the serialized output a server component produces. We ended up making design choices purely to stay testable. Tail wagging the dog. Authentication became a distributed-systems problem This was a big one. If you gate protected pages on the server, the server must read and validate the token on every request, then propagate auth state through hydration. That singl

2026-06-25 原文 →
AI 资讯

Stop Hand-Designing Open Graph Images: Automate Link Previews for Every Page

Open Graph images are the single biggest factor in whether your shared links look credible or broken. Yet most sites ship one generic image on every page because making a unique one by hand is tedious. Here is a more sustainable approach: treat preview images as generated data, not hand-made design. The problem, concretely When you share a link, the receiving platform reads your page's og:image meta tag and renders a card. If that tag is missing, points to a low-res logo, or is the same image on all 200 pages, your links look generic in every feed, Slack channel, and group chat. Studies of social sharing consistently show that posts with a clear, relevant preview image get meaningfully more engagement than those without. The reason teams skip it is not ignorance. It is friction. Opening a design tool, duplicating a template, swapping the title text, exporting at the right dimensions, and uploading the file takes 10 to 20 minutes per page. Nobody keeps that up across a real publishing schedule. So the back catalog stays bare and new posts get whatever the default is. The insight: it is template work Look at a typical preview card and ask what actually changes between pages. Usually just the title, maybe the author and a category tag. The layout, background, logo, and fonts are constant. That is the textbook definition of a job you should template once and generate programmatically, not redo by hand each time. How to solve it The cleanest pattern is to generate the image at build time or on first request, then cache it. Conceptually: // During your build or in an API route async function getOgImage ( post ) { const params = new URLSearchParams ({ title : post . title , author : post . author , tag : post . category , }); // Returns a ready Open Graph image URL return `https://getcardforge.dev/api/card? ${ params } ` ; } // In your page head // <meta property="og:image" content={getOgImage(post)} /> You can build this yourself with a headless browser plus an HTML templ

2026-06-25 原文 →
AI 资讯

How I built a Minecraft server list that ranks by real player votes (not bots)

Hi, I'm Hugo. I built MinecraftServers-List.com — a Minecraft server directory that ranks servers by genuine player votes and uptime. Why I built it Most existing Minecraft server lists have the same problem: the rankings are easily gamed. Server owners run scripts to inflate their vote counts, and players searching for a good server end up with a list that reflects who has the best bots, not which servers are actually worth playing on. I wanted to fix that. What makes it different Vote integrity — votes are tied to real player sessions and IP validation, making bot voting significantly harder Uptime monitoring — servers that go offline lose ranking visibility automatically Player reviews — verified players can leave reviews with star ratings, giving prospective players real signal Java & Bedrock — both editions listed and filterable by gamemode, version, and country The tech stack Built with TanStack Start (React SSR), Supabase for the database, and deployed on Cloudflare Workers. The SSR approach was important for SEO — server listing pages need to be fully rendered for Googlebot to index individual server pages properly. What I've learned so far Getting a new directory site indexed by Google is genuinely hard. The challenge isn't technical — it's convincing Google that hundreds of server listing pages are individually worth indexing when they all share a similar template structure. The solution has been enriching each server page with structured data (VideoGame schema with AggregateRating), genuine user reviews, and making sure every page has a meaningfully unique meta description generated from real server data — version, gamemode, player count, country. Still a work in progress but the site is live, servers are actively listed, and players are voting daily. Try it If you run a Minecraft server, you can list it free at https://minecraftservers-list.com If you're looking for a server to join, the SMP list and survival list are good starting points. Happy to answe

2026-06-25 原文 →
AI 资讯

Your structured data is probably broken, and your crawler isn't telling you

Most on-page audits catch the obvious stuff: a missing title here, a duplicate meta description there. The thing that quietly costs you rich results is structured data that exists but is invalid, and most flat-list crawlers either skip it or bury it. Here is why it happens and how to catch it. The problem, concretely You add FAQ schema to a product page to win that expandable rich result in Google. You paste a JSON-LD block into the head, ship it, and move on. Six weeks later the rich result never showed up, and nobody knows why. The usual culprits are small and silent: A @type that does not match the content (FAQPage with no mainEntity ). A required property missing ( acceptedAnswer without text ). A trailing comma or a stray character that makes the JSON parse fail entirely. Schema that contradicts what is actually on the page, which Google can flag as spammy and ignore. None of these throw a visible error. The page renders fine. The schema is just dead weight, and a standard "issues" crawl that only counts titles and headings walks right past it. How to catch it First, validate the JSON itself. A block that does not parse is invisible to search engines. Even a quick local check surfaces the dumb-but-fatal errors: // Pull every JSON-LD block and check it parses + has a @type const blocks = [... document . querySelectorAll ( ' script[type="application/ld+json"] ' )]; blocks . forEach (( b , i ) => { try { const data = JSON . parse ( b . textContent ); if ( ! data [ " @type " ]) console . warn ( `Block ${ i } : missing @type` ); } catch ( e ) { console . error ( `Block ${ i } : invalid JSON ->` , e . message ); } }); If that logs an error, the schema was never going to work, no matter how perfect the markup looked. Second, check required properties for the specific type you are using. FAQPage needs mainEntity with Question items, each carrying an acceptedAnswer . Article needs headline , author , and datePublished . Validating "it parsed" is not the same as "it is c

2026-06-25 原文 →
AI 资讯

The New Standard for NPM Package Discovery: Deep Dive into LibPilot

As web developers, engineering workflows are heavily dependent on the NPM registry. However, the traditional process of searching, auditing, and integrating packages remains highly fragmented. Developers are routinely forced to hop between npmjs.com, GitHub source repositories, and external documentation tabs simply to verify bundle sizes, check dependency trees, or generate setup boilerplate. Following a strong reception on LinkedIn, X, and Facebook, the Motion Mind Team has introduced LibPilot to the dev.to community. LibPilot is not a traditional registry interface; it is an AI-powered search engine and discovery hub engineered to index, track, and analyze over 4,000,000 NPM packages in real time. Here is an architectural breakdown of how LibPilot restructures package exploration for modern developers and autonomous AI code agents. Intent-Based Discovery and Global Search Architecture Traditional search engines require users to input the exact name or strict keyword of a library. LibPilot introduces a dual-input architecture on its home page to eliminate this constraint: Direct Registry Querying: Users can input full or partial package names into the global search bar to instantly surface clean, structured, and typed suggestions directly from the live NPM ecosystem database. Contextual AI Recommendations: For scenarios where the ideal package is unknown, developers can type out a complete description of their project architecture or system constraints (for example: "a lightweight, typed state management engine that handles server-side rendering natively"). LibPilot's internal AI agent processes the functional requirements and suggests production-ready libraries suited for that stack. Continuous Context AI and Interactive Onboarding A core goal of the platform is reducing developer friction and maintaining deployment momentum. LibPilot transitions static package documentation into an interactive environment: Unlimited AI Chat Architecture: Once a library is select

2026-06-24 原文 →
AI 资讯

Legacy code não envelhece como vinho: quanto mais espera, pior fica

Semana passada eu passei três horas debugando um bug que deveria levar 20 minutos. O problema? Um módulo de validação escrito em 2019 que ninguém mexe "porque funciona". Spoiler: não funcionava mais, e quando finalmente abri o arquivo, encontrei um // TODO: refactor this datado de 2020. Por que legacy vira bola de neve A indústria trata código legado como se fosse dívida técnica opcional — algo que você paga "quando tiver tempo". Mas código legado se comporta mais como mofo: se espalha, contamina áreas adjacentes, e quanto mais você ignora, mais cara fica a limpeza. O ciclo é previsível: você herda um projeto ou feature antiga, vê que está "meio bagunçado mas roda", adiciona sua feature com um if a mais, e segue em frente. Seis meses depois, outra pessoa faz o mesmo. Um ano depois, aquele arquivo tem 800 linhas, cinco níveis de if aninhados, e zero testes. Ninguém mais entende o fluxo completo, então cada mudança vira uma sessão de especulação: "se eu mexer aqui, quebra ali?" O custo real de esperar Esse código "que funciona" tem um custo oculto que aparece em três formas: Velocidade de desenvolvimento despenca. Features que deveriam levar dois dias levam uma semana porque você passa mais tempo entendendo o contexto do que escrevendo código novo. Bugs aumentam exponencialmente. Código sem testes e com lógica embolada é um gerador de regressões. Você corrige um edge case e quebra outro que nem sabia que existava. Onboarding vira tortura. Novo dev no time? Boa sorte explicando por que aquele service tem três formas diferentes de fazer autenticação, ou por que a mesma validação está copiada em sete lugares. Sinais de que você está sentado em cima de uma bomba Nem todo código antigo é legacy tóxico. Aqui estão os red flags que indicam que você precisa agir agora: // Red flag #1: comentários mentirosos ou inúteis function processPayment ( order ) { // Process the payment const user = order . user ; // TODO: fix this later // HACK: don't touch this, breaks prod if ( user

2026-06-24 原文 →
AI 资讯

How to Fetch Real-Time Options Chain Data in Python (Without Paying $99/mo)

If you've ever tried to pull live options data into a Python script, you've probably hit the same wall I did: the cheapest real-time providers start at $99/mo. Here's how to do it for $20/mo — or free if you stay within 1,000 credits/day. What You'll Need Python 3.8+ requests library ( pip install requests ) An API key from market-option.com (free tier available, no card required) Fetching a Full Options Chain import os import requests API_KEY = os . environ [ " MARKET_OPTIONS_KEY " ] BASE_URL = " https://market-option.com/api/v1 " def get_chain ( ticker : str ) -> list [ dict ]: res = requests . get ( f " { BASE_URL } /options/chain/ { ticker } " , params = { " apiKey " : API_KEY }, ) res . raise_for_status () return res . json ()[ " results " ] contracts = get_chain ( " SPY " ) print ( f " { len ( contracts ) } contracts returned " ) print ( contracts [ 0 ]) Each contract in results looks like this: { "details" : { "contract_type" : "call" , "strike_price" : 530 , "expiration_date" : "2026-01-17" , "ticker" : "O:SPY260117C00530000" }, "last_quote" : { "bid" : 3.45 , "ask" : 3.50 , "midpoint" : 3.475 }, "greeks" : { "delta" : 0.42 , "gamma" : 0.031 , "theta" : -0.18 , "vega" : 0.29 }, "implied_volatility" : 0.182 , "open_interest" : 12418 } Filtering by Expiration and Strike def get_near_the_money ( ticker : str , expiration : str , spot : float , width : float = 0.05 ): """ Return contracts within ±width% of spot price. """ contracts = get_chain ( ticker ) low = spot * ( 1 - width ) high = spot * ( 1 + width ) return [ c for c in contracts if c [ " details " ][ " expiration_date " ] == expiration and low <= c [ " details " ][ " strike_price " ] <= high ] atm = get_near_the_money ( " SPY " , " 2026-01-17 " , spot = 530 ) for c in atm : print ( c [ " details " ][ " strike_price " ], c [ " details " ][ " contract_type " ], c [ " last_quote " ][ " bid " ], c [ " greeks " ][ " delta " ], ) Scanning for High IV Contracts def high_iv_scan ( ticker : str , iv_threshold :

2026-06-24 原文 →
AI 资讯

Stokado: A Zero-Dependency Proxy Wrapper That Makes Browser Storage Feel Like a Plain Object

If you've shipped anything to the browser, you've used localStorage . And if you've used it for more than five minutes, you've also written this exact line more times than you'd like to admit: const user = JSON . parse ( localStorage . getItem ( ' user ' ) || ' null ' ) The Web Storage API has aged remarkably well for something so small, but it carries three persistent pain points that every frontend codebase ends up papering over by hand. Pain point #1: everything is a string. localStorage.setItem('count', 0) doesn't store the number 0 — it stores the string "0" . Read it back and typeof is "string" . Booleans become "true" / "false" , Date objects collapse into ISO strings (if you're lucky) or "[object Object]" (if you're not), and undefined becomes the literal string "undefined" . So every project grows a thin serialization layer of JSON.parse / JSON.stringify wrappers, plus a pile of defensive try/catch blocks for the day a malformed value sneaks in. Pain point #2: the API is verbose and stringly-typed. getItem , setItem , removeItem — three method calls and a string key for what is conceptually just reading and writing a property. It reads nothing like the rest of your code. Pain point #3: reactivity is broken in the tab you actually care about. The native storage event only fires in other tabs of the same origin. The tab that performed the write never hears about it. So if you want to react to your own storage changes — the overwhelmingly common case — the platform gives you nothing. Stokado is a small, zero-dependency library that addresses all three by wrapping any storage object in a Proxy . It's framework-agnostic, TypeScript-friendly, and works equally well with localStorage , sessionStorage , cookies, async backends like localForage, and a handful of mini-program runtimes. This article walks through what it actually does, feature by feature, with runnable code. Quick start npm install stokado import { createProxyStorage } from ' stokado ' const storage =

2026-06-24 原文 →
AI 资讯

I ran one API response through two JSON-to-Zod converters. One silently turned every field into z.string().

You have an API response. You want a Zod schema. So you paste the JSON into a JSON-to-Zod converter, copy the output, and ship it. Here's the trap: a lot of those converters infer basic types only . Your email , your uuid , your url , your ISO timestamp — they all come out as z.string() . The schema compiles, the types look right, and your validator quietly accepts "not-an-email" , "ftp://nope" , and "2026-99-99" forever. I wanted to see exactly how much gets lost, so I ran the same payload through two tools and diffed the output. Everything below is real, copy-pasteable output — nothing edited. The input A pretty ordinary user object: { "id" : "3f2a9c1e-5b7d-4e8a-9f1c-2d3e4f5a6b7c" , "email" : "ada@example.com" , "website" : "https://ada.dev" , "age" : 34 , "rating" : 4.7 , "created_at" : "2026-03-04T10:15:30Z" , "is_active" : true , "address" : { "city" : "Lyon" , "zip" : "69001" }, "tags" : [ "early-adopter" , "beta" ] } Tool 1 — json-to-zod (npm) const user = z . object ({ id : z . string (), email : z . string (), website : z . string (), age : z . number (), rating : z . number (), created_at : z . string (), is_active : z . boolean (), address : z . object ({ city : z . string (), zip : z . string () }), tags : z . array ( z . string ()), }); Structurally correct. But every meaningful field is a bare z.string() / z.number() . This schema will happily validate email: "lol" and created_at: "yesterday" . Tool 2 — TypeMorph import { z } from " zod " ; export const userAddressSchema = z . object ({ city : z . string (), zip : z . string (). regex ( /^ [ A-Z0-9 ][ A-Z0-9 \s\-]{1,8}[ A-Z0-9 ] $/i ), }); export type UserAddress = z . infer < typeof userAddressSchema > ; export const userSchema = z . object ({ id : z . uuid (), email : z . email (), website : z . url (), age : z . number (). int (). min ( 0 ). max ( 150 ), rating : z . number (). min ( 0 ). max ( 5 ), created_at : z . iso . datetime (), is_active : z . boolean (), address : userAddressSchema , tags :

2026-06-24 原文 →
AI 资讯

TypeScript Tips That Actually Matter in Real Projects (including the satisfies operator)

Most TypeScript tutorials teach you the language. This article teaches you how to use it. There's a difference. The language has hundreds of features. A real project uses maybe twenty of them regularly, and about eight of them make up the difference between TypeScript that fights you and TypeScript that helps you. These are those eight. Each one comes from a pattern I've seen repeatedly in real codebases: first as an antipattern, then as a realization, then as a habit. The goal isn't to show off advanced type gymnastics. It's to show you the specific things that make your code safer, more readable, and less painful to maintain. TL;DR Most TypeScript pain comes from fighting the type system instead of working with it, any , manual casting, and loose types are the usual culprits. A small set of features, discriminated unions, utility types, satisfies , as const , generics, solve the majority of real-world typing problems. The best TypeScript isn't the most complex. It's the most precise. Table of Contents Tip 1: Use Discriminated Unions Instead of Optional Fields Tip 2: Stop Writing Types Twice with Utility Types Tip 3: Use satisfies to Validate Without Losing Inference Tip 4: Use as const for Literal Types That Don't Drift Tip 5: Write Type Guards Instead of Casting Tip 6: Use Generics to Write Functions Once Tip 7: Use ReturnType and Parameters to Stay in Sync Tip 8: Use unknown Instead of any for External Data Honorable Mentions Final Thoughts Tip 1: Use Discriminated Unions Instead of Optional Fields This is the tip that changes how you model data in TypeScript. Once you see it, you'll spot the antipattern everywhere. The antipattern // ❌ A type that tries to represent multiple states with optional fields interface ApiResponse { data ?: User error ?: string isLoading : boolean } The problem: this type allows impossible states. Nothing stops you from having both data and error set at the same time, or neither set, or isLoading: false with no data and no error . The

2026-06-24 原文 →
AI 资讯

Why I Stopped Picking AI Models by Hype and Started Picking by Speed

Why I Stopped Picking AI Models by Hype and Started Picking by Speed Three months ago I almost lost a $14,000 retainer because my chatbot felt sluggish. The client didn't say "your TTFT is too high." They said "it feels dumb." That's freelancer code for "users are bouncing and I'm about to find someone else." I rebuilt that bot in a weekend using a model I'd never even heard of six weeks earlier, dropped average response time from 1.4 seconds to under 300ms, and the client renewed for another six months. That single pivot paid for my rent. So I went down a rabbit hole. I ran the same speed test on every model I could get my hands on through Global API's unified endpoint. Fifteen models. Same prompt. Same regions. Ten iterations each. I'm writing this up because if you're billing by the hour or running a side hustle on a shoestring, speed isn't a vanity metric — it's a profit metric. Let me show you what I found. The Setup (How I Actually Ran the Tests) I'm not a researcher with a rack of GPUs. I'm a guy with a M2 MacBook, a $19/mo Hetzner box, and a stopwatch in the form of Python's time.perf_counter() . Here's how I kept it honest. Date window: All tests run on May 20, 2026 Regions tested: US East (Ohio) and Asia (Singapore) Prompt used: "Explain recursion in 200 words" — boring on purpose, because boring prompts are where most apps actually live Output length: Roughly 150 tokens per run Iterations: 10 runs per model per region, average recorded Streaming: Yes, SSE throughout Endpoint: Global API at https://global-apis.com/v1 I measured two things: TTFT (time to first token — the lag before the user sees anything move) and sustained tokens per second (how fast the words actually arrive after that). Both matter. TTFT is the "is this thing broken?" feeling. Tokens per second is the "is this thing fast?" feeling. Here's the script I used, stripped down to the essentials: import time import requests from statistics import mean API_KEY = " your-global-api-key " BASE_URL

2026-06-24 原文 →
AI 资讯

The SEC has a free financial data API that nobody talks about

Every quarterly earnings number for every US public company going back to 2009 is sitting in a free, well-documented JSON API run by the US government. No API key. No rate limit for normal use. No paywall. Almost nobody in the dev community seems to know it exists. It's at data.sec.gov , and it's the same data Bloomberg charges $24k/year for. What's in it The SEC requires all US-listed companies to file financial reports in XBRL — a structured XML format where every number is tagged with a standardised concept name. The EDGAR system has been collecting these since around 2009. The companyfacts endpoint exposes all of it as clean JSON: GET https://data.sec.gov/api/xbrl/companyfacts/CIK{cik}.json Where CIK is the company's SEC identifier (10 digits, zero-padded). For Apple, that's 0000320193 . The response is a large JSON object with every concept the company has ever reported, broken down by period. The other endpoint you need is the ticker-to-CIK map: GET https://www.sec.gov/files/company_tickers.json This gives you a flat list of all US-listed companies with their CIK, ticker, and name. Load it once and cache it. One gotcha: concept names vary by company Companies don't all use the same GAAP concept names to report the same thing. Apple reports revenue as RevenueFromContractWithCustomerExcludingAssessedTax . Older companies use Revenues . Some use SalesRevenueNet . If you just look up one concept name, you'll get blanks for most companies. The fix is a concept alias map: try each name in order, use the first one that has data. const CONCEPT_MAP : Record < string , string [] > = { revenue : [ ' Revenues ' , ' RevenueFromContractWithCustomerExcludingAssessedTax ' , ' RevenueFromContractWithCustomerIncludingAssessedTax ' , ' SalesRevenueNet ' , ' SalesRevenueGoodsNet ' , ], netIncome : [ ' NetIncomeLoss ' , ' NetIncomeLossAvailableToCommonStockholdersBasic ' , ' ProfitLoss ' , ], operatingCashFlow : [ ' NetCashProvidedByUsedInOperatingActivities ' , ' NetCashProvidedB

2026-06-24 原文 →
AI 资讯

MongoDB Indexes Finally Clicked for Me: Understanding Indexes, Compound Indexes & the Prefix Rule 🚀

While working on a MERN project, I came across these indexes: transactionSchema . index ({ user : 1 , date : - 1 }); transactionSchema . index ({ user : 1 , type : - 1 }); transactionSchema . index ({ user : 1 , category : - 1 }); My first reaction was: "Why are we creating 3 different indexes for the same schema? Isn't one index enough?" At that time, my understanding was: "Indexes help MongoDB find records faster." Which is true, but it wasn't enough to explain why multiple indexes existed for the same collection. That simple doubt led me down a rabbit hole of learning about indexes, compound indexes, how MongoDB stores them, and the famous Prefix Rule. Here's what I learned. What is an Index? Imagine a collection with millions of transactions. db . transactions . find ({ user : " Aarthi " }); Without an index, MongoDB may need to inspect every document until it finds the matching records. This is called a Collection Scan . Think of it like searching for a chapter in a book without a table of contents. You'd have to flip through page after page until you find it. An index works like a book's table of contents. Instead of scanning every document, MongoDB can jump directly to the relevant records. Example: db . transactions . createIndex ({ user : 1 }); Now MongoDB can quickly locate all transactions belonging to a specific user. What is a Compound Index? A compound index contains multiple fields. Example: db . transactions . createIndex ({ user : 1 , date : - 1 }); This means MongoDB organizes the index by: user └── date Conceptually, it looks something like: Aarthi 2025-08-10 2025-08-09 2025-08-08 John 2025-08-10 2025-08-05 The data is first grouped by user , and within each user, it is ordered by date . Now queries like: db . transactions . find ({ user : " Aarthi " }). sort ({ date : - 1 }); become very efficient. MongoDB can jump directly to Aarthi's records and retrieve them in date order. The Prefix Rule: The Concept That Finally Made It Click Consider this i

2026-06-24 原文 →
AI 资讯

10 Free PDF Tools Every Developer Should Bookmark in 2026

PDF work shows up in dev life more often than we'd like to admit — exporting docs, compressing build artifacts, merging client deliverables, or converting a spec sheet someone sent as a scanned PDF into something you can actually search. Paid suites like Adobe Acrobat are overkill for most of these one-off tasks. Here are 10 free, no-signup tools that get the job done, ranked roughly by how often you'll reach for them. 1. ToolTiny — PDF to Word/Excel/PowerPoint ToolTiny converts PDFs into editable DOCX, XLSX, or PPTX files directly in the browser, alongside the usual merge/split/compress/watermark/password toolkit. No account, no watermark on output. What's actually useful for dev workflows: it handles presentation-style PDFs (think exported slide decks or design-heavy one-pagers) reasonably well — most converters flatten these into a single unreadable text blob, but ToolTiny keeps the layout intact while still giving you editable text. Good for the "client sent a PDF, I need it as a Word doc by EOD" scenario. 2. Smallpdf The OG in this space. Smallpdf's PDF-to-Word conversion is excellent at preserving layout — it renders the page as a background image and overlays editable text boxes at the correct coordinates, which is why it handles complex layouts better than most. Free tier caps you at 2 tasks/day though. 3. iLovePDF Similar feature set to Smallpdf, slightly more generous free tier. Their "Organize PDF" drag-and-drop page reordering is one of the smoother UX implementations out there if you need to quickly reshuffle a multi-doc PDF before sending it out. 4. PDF24 A German tool that's been around forever and quietly does everything — OCR, forms, signing, comparison. Less polished UI than the others but the OCR accuracy on scanned technical docs is genuinely strong. 5. Stirling-PDF If you want something self-hosted, Stirling-PDF is the open-source answer. It's a Docker container you spin up yourself, giving you a full PDF toolkit (split, merge, compress, OCR, wa

2026-06-24 原文 →