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

标签:#webdev

找到 1514 篇相关文章

AI 资讯

--- title: Day 1: Starting My Web Dev Journey published: true description: Learning HTML from scratch ---

Hi everyone! I'm a tech enthusiast currently mastering web development and game development. I am building my foundation from scratch,learning on my phone with Sololearn and Mimo while writing my code completely on a tablet using an app called Acode . Why I'm Doing This I want to learn how to turn big ideas into reality, one line of code at a time. I'm starting with the absolute basics of the web: HTML. My First HTML Project Today, I built a multi-page setup right on my tablet. Here is the structure of my homepage ( index.html ): <!DOCTYPE html> <html lang= "en" > <head> <title> My First Blog Post </title> </head> <body> <h1> Day 1: Starting My Journey To Become A Web Developer </h1> <p> I officially started learning web development today! </p><h3> What I Learnt </h3><Some of the things I learnt today were: </ p ><ul><li> HTML code controls the structure of a webpage </li><li> HTML tags are used to add elements to a webpage </li><li> Elements like button and paragraph require container tags while elements like images and line break only require empty tags <li> Container tags consist of both opening and closing tags. </li><li> Some HTML tags known as Semantic tags </li></ul><h4> What I Built </h4><p> I started with my first project which is my portfolio website </p><h5> Looking Ahead </h5><p> Next I want to learn more on HTML and dive deeper to get a better understanding of HTML and later learn CSS and JavaScript to style and make my webpage more interactive <p> </body> </html> ``` What's Next? ​My next immediate goal is to learn more about HTML and to learn CSS so I can start styling these pages and making them look awesome. After that, I'll be diving into JavaScript and starting my first simple game development projects. ​I'm excited to document my progress here as I grow from a beginner into a software developer. If you have any tips for learning on a mobile device, let me know in the comments!

2026-07-14 原文 →
AI 资讯

My MCP Server Kept Crashing. Here's the Error Recovery Pattern That Saved It.

I spent three days wondering why my MCP server would just... stop. No crash logs. No error messages. Clients connected fine, then after a few hours, every tool call returned silence. Turns out the Model Context Protocol (MCP) spec doesn't force you to handle errors — it assumes you will. But the reference implementations are minimal. Your server starts healthy, then bit by bit, things go wrong. A network blip. A malformed tool argument. An external API timeout. And suddenly your AI agent is staring at a blank response. Here's the pattern I ended up with. It's not clever. It just works. The Fix Start with a wrapper around your tool handlers. Every MCP server framework has some kind of tool registration — this works for the official Python SDK, the TypeScript SDK, and most community frameworks: from mcp.server import Server from mcp.types import ErrorData , INTERNAL_ERROR , INVALID_PARAMS import traceback import json class ResilientMCPServer ( Server ): """ An MCP server that doesn ' t silently die. """ async def call_tool ( self , name : str , arguments : dict ): try : result = await super (). call_tool ( name , arguments ) return result except ( ConnectionError , TimeoutError ) as e : # Network-level issues — reconnect and retry self . _reconnect () return self . _error_response ( f " Connection lost while executing { name } : { e } " ) except ValueError as e : # Bad arguments from the client — tell them clearly return self . _error_response ( f " Invalid arguments for { name } : { e } " , code = INVALID_PARAMS ) except Exception as e : # Everything else — log, don't crash traceback . print_exc () return self . _error_response ( f " Tool { name } failed: { e } " , code = INTERNAL_ERROR ) def _error_response ( self , message : str , code : int = INTERNAL_ERROR ): return { " content " : [{ " type " : " text " , " text " : f " ERROR: { message } " }], " isError " : True } def _reconnect ( self ): """ Reset transport layer without restarting the server. """ # Your recon

2026-07-14 原文 →
AI 资讯

Building an AI-Powered Lead Qualification API with Next.js 15 and Gemini 3.5 Flash

Every business wants more leads. But the real challenge isn't generating them—it's identifying which leads deserve your team's attention first. Instead of manually reviewing every inquiry, we can build a simple AI-powered API that analyzes incoming leads and assigns a priority score automatically. In this article, I'll show a lightweight production-ready approach using Next.js 15 and Gemini 3.5 Flash. Project Structure app/ ├── api/ │ └── qualify/ │ └── route.ts ├── lib/ │ └── gemini.ts └── page.tsx API Route import { NextResponse } from "next/server"; export async function POST(req: Request) { const { company, message } = await req.json(); const prompt = ` Company: ${company} Message: ${message} Give: - Score (1-100) - Priority - Reason `; // Call Gemini API here return NextResponse.json({ success: true, score: 92, priority: "High" }); } Example Response { " score " : 92 , " priority " : " High " , " reason " : " Large company with a clear automation requirement. " } Now your CRM, chatbot, or automation workflow can instantly decide which leads should be contacted first. Why This Matters A simple AI scoring layer can help teams: Reduce manual lead review Respond faster to high-value prospects Prioritize enterprise customers Improve sales efficiency Save hours every week The best part is that this API can be connected to forms, chatbots, CRMs, or n8n workflows without changing your existing process. Production Tips Before deploying this to production, make sure you: Validate incoming requests Store API keys securely Add rate limiting Log AI responses for monitoring Cache repeated requests where appropriate Small improvements like these make a huge difference once traffic starts growing. Final Thoughts AI shouldn't replace your sales team—it should remove repetitive work so they can focus on conversations that actually matter. A lightweight lead qualification API is one of the fastest AI features you can add to an existing product, and it scales well as your business

2026-07-14 原文 →
AI 资讯

Add Arrow-Key Shortcuts to a Confirmation Dialog Without Breaking Accessibility

Two buttons in a confirmation dialog look simple: Cancel and Confirm. Keyboard behavior makes the component a small state machine. A recent MonkeyCode change gives us a concrete example. Issue #862 and PR #863 add these shortcuts to the slash-command confirmation: ArrowLeft -> focus Cancel ArrowRight -> focus Confirm The reviewed implementation at commit c58bcd4 moves focus through button refs. That is a useful extra interaction. It is not a replacement for the dialog's accessibility foundation. Keep the baseline first For an alert-style confirmation, users still need: an accessible name and description; focus moved inside when the dialog opens; Tab and Shift+Tab constrained to dialog controls; Escape to dismiss when cancellation is allowed; visible focus; focus returned to the trigger after close; actual buttons whose labels explain the actions. The WAI-ARIA Authoring Practices Alert Dialog Pattern describes the modal semantics and keyboard foundation. Left/right mapping is a product shortcut, not a required AlertDialog convention. That means we must not steal keys from the established behavior around it. Isolate the extra mapping The companion keyboard.mjs starts with a pure function: export function arrowAction ( key ) { if ( key === " ArrowLeft " ) return " cancel " ; if ( key === " ArrowRight " ) return " confirm " ; return null ; } The event handler ignores unrelated and modified keys: export function handleDialogArrow ( event , controls ) { const action = arrowAction ( event . key ); if ( ! action || event . altKey || event . ctrlKey || event . metaKey ) return false ; event . preventDefault (); controls [ action ]. focus (); return true ; } Notice what is absent: no handler for Tab , Shift+Tab , Escape , or Enter . The native <dialog> and buttons in the minimal demo retain their normal jobs. In a React component, use a well-tested modal/dialog primitive for focus containment and dismissal, then add this narrow handler to its content. A complete minimal dialo

2026-07-14 原文 →
开发者

I Added 200+ Languages to a Translator… Then Realized Language Wasn't the Hardest Part

I'll Be Honest: The Internet Already Has Translators I know. Language translation isn't a new idea. There are already huge translation platforms out there. So when I started working on a translator for my tools website, I wasn't thinking: "I'm going to reinvent translation." Not at all. My thought was much simpler: "Can I make quick translation feel less distracting?" My Frustration Was Actually Pretty Simple Sometimes I just need to translate text. That's it. I don't want to: Create an account Open five different menus Break a long text into tiny pieces Jump between multiple tools I want to paste the text... Choose a language... And get the translation. So I Built My Own Version 👉 https://allinonetools.net/language-translator/ The tool currently supports 200+ languages and language variations . You can: Detect the source language Select the target language Translate long text Upload text Use voice input Listen to the result Copy or share the translation And I wanted to keep the text experience simple without forcing users into tiny input limits. Just: Enter → Choose Language → Translate 200+ Languages Sounded Simple Until I Saw the List English. Hindi. Gujarati. Spanish. Arabic. These are the languages most people immediately think about. But then I started going through the full language list. Abkhaz. Acholi. Afar. Alur. Aymara. Baluchi. And many more. Honestly... I hadn't even heard of some of them before building this. That was probably my biggest learning moment. I Realized How Small My Own View of the Internet Was As a developer, it's easy to build around the languages we personally know. For me, seeing English, Hindi, and Gujarati feels normal. But the internet is much bigger than my own experience. Someone somewhere may be trying to understand a sentence in a language I've never even heard spoken. That changed how I looked at this tool. The Hard Part Wasn't Adding a Dropdown A dropdown with 200+ options looks impressive. But that's not the real problem. The

2026-07-14 原文 →
AI 资讯

Speed Test: I Found AI APIs 99% Cheaper Than Premium

Here's the thing: speed Test: I Found AI APIs 99% Cheaper Than Premium I have a confession: I've been overpaying for AI APIs for years. Like, embarrassingly overpaying. When I finally sat down and actually benchmarked 15 different models on speed and cost, I couldn't believe what I found. Some of the fastest models out there cost literal pennies per million tokens. Here's the thing — if you're still defaulting to whatever the big labs are pushing, you're leaving serious money on the table. So I spent a week running tests through Global API's infrastructure, hitting endpoints from multiple regions, and crunching numbers until my eyes hurt. What I discovered genuinely surprised me. Check this out: there's a model that pushes 80 tokens per second and costs $0.15 per million output tokens. Compare that to premium options charging $3.00/M and you'll understand why I had to write this down. Let me walk you through everything I found. Why I Even Started This Whole Thing My monthly AI bill got out of control. I'm running a few production apps that do text generation, summarization, and chat, and my December bill made me physically flinch. I knew there had to be faster, cheaper models hiding in the ecosystem — I just hadn't taken the time to actually measure them properly. That's the whole reason I ran these benchmarks. Not for clout, not for content marketing. Pure self-interest. I wanted to know where the actual sweet spots are. Where you get the best speed-per-dollar ratio. Where you can save 70%, 80%, even 99% without tanking your user experience. What I found was honestly kind of shocking. My Testing Setup (For the Nerds) I kept the methodology tight and consistent. Here's exactly how I ran everything: Date: May 20, 2026 Test regions: US East (Ohio) and Asia (Singapore) Prompt: "Explain recursion in 200 words" Output target: ~150 tokens per run Iterations: 10 runs each, averaged the results Streaming: Enabled via SSE Base URL: https://global-apis.com/v1 I measured two k

2026-07-14 原文 →
AI 资讯

A variable I'd refactored into one function — and kept referencing from another. Python's lazy evaluation hid it, and an AST test finally caught it

One day the browser automation flow started failing right after plugin updates with NameError: name 'plugin_form_selectors' is not defined in the post-update "residual check" step. The refactor that introduced this had landed back in v1.6.1. The error didn't surface until many rounds later. Reading the code, the cause is obvious in seconds — but nobody hit it for ages, because Python's lazy evaluation kept the leftover reference hidden until exactly the right execution path ran. This post walks through what the bug was and how we structurally prevented its kind via an AST static-analysis test. What happened — a reference that crossed a scope boundary browser_utils.py has two functions involved: run_browser_update_flow() , which orchestrates the whole update flow, and browser_update_remaining_plugins() , which handles only the plugin-update logic. The list of plugin-form selector candidates, plugin_form_selectors , used to be a local variable inside run_browser_update_flow() . In the v1.6.1 refactor — "let's split plugin update into its own function" — we created browser_update_remaining_plugins() and moved the plugin_form_selectors definition into it . # After v1.6.1 refactor def browser_update_remaining_plugins ( page , site , update_url ): plugin_form_selectors = [ # ← defined here ' #update-plugins-table-wrap form ' , ' form[name= " upgrade-plugins " ] ' , ' form[action*= " do-plugin-upgrade " ] ' , ' .plugins-php form ' , ] # ... update logic ... def run_browser_update_flow ( site , page ): # ... call to plugin updater ... browser_update_remaining_plugins ( page , site , update_url ) # ★ post-update "residual check" still uses the old local name for selector in plugin_form_selectors : # NameError if page . locator ( selector ). count () > 0 : pending_browser . append (...) The " after updating, make sure no plugin update forms are still visible " residual check stayed in run_browser_update_flow() . During the refactor, the call to extract this loop alongside the

2026-07-14 原文 →
AI 资讯

SilentShare — A Browser-Based Peer-to-Peer File Sharing App

Have you ever been in a computer lab, classroom, or office where you needed to quickly send a file between your phone and laptop? I run into this problem all the time. Sometimes there's no USB cable, no pendrive, Bluetooth is painfully slow, or uploading to cloud storage just to download the file on another device feels unnecessary. So I decided to build SilentShare . What is SilentShare? SilentShare is a browser-based peer-to-peer file sharing application that lets you instantly share: 📁 Files (up to 50 MB) 💻 Code snippets 📝 Text 🖼️ Images No installation. No account. No server storing your files. Your data goes directly from one device to another using WebRTC . Whether you're sending files from your phone to your laptop, between classmates, or across the internet, SilentShare keeps the process simple. Why I Built It I wanted something that: Opens instantly in any browser Doesn't require creating an account Doesn't upload files to someone else's server Works on desktop and mobile Feels lightweight and fast Instead of relying on cloud storage, I wanted the browser itself to become the transfer tool. Features ✨ Peer-to-peer file transfer using WebRTC 📂 File sharing up to 50 MB (including ZIP files) 🔒 Optional end-to-end encrypted rooms using AES-GCM 📷 QR code invitations with built-in camera scanner 📊 Live progress, transfer speed, ETA, pause & resume 🖼️ Preview support for: Images Audio Video PDFs 💻 Share code snippets with syntax highlighting 👥 Multi-user rooms (around 5 participants) 🌙 Dark & Light mode 📱 Installable as a Progressive Web App (PWA) How It Works Create a room Receive a random room code Share the code, QR code, or invite link Other devices join Start sharing instantly The files are transferred directly between devices instead of passing through a storage server. Privacy One of the goals of SilentShare was privacy. No user accounts No cloud storage No permanent database Nothing stored after the browser tab closes If you set a room password, all transf

2026-07-14 原文 →
AI 资讯

It works on my machine, but is it working for my users?

Every time I shipped something, the same thought hit me a few hours later: It works on my machine. It works in staging. But is it actually working for the people using it right now? I had analytics. I had a green dashboard. And I still had no honest answer to that question. Users would quietly leave, a button would silently break on Safari, a page would crawl on a mid-range Android, and I'd find out days later, if at all. That gap is what I ended up building HeronSignal to close. But before I talk about the tool, let me talk about the pain, because I think you've felt at least one version of it. The pain, depending on who you are If you're a vibe coder / solo builder You ship fast. Cursor, Claude, v0, a Vercel deploy, and it's live. Beautiful. Then… nothing. You have no idea what happens after "Deploy successful." Is the checkout button throwing an error on mobile? Is your landing page slow enough that half your visitors bounce before it paints? You don't know, because setting up "real" monitoring feels like a second job: a Datadog dashboard you'll never look at, a Sentry config you half-finish. So you just… hope. And hope is not a monitoring strategy. If you're an engineer Your problem isn't no data. It's too much . Ten dashboards, alert fatigue, a Sentry inbox with 400 issues where 390 are noise. Something's clearly wrong, but which thing actually matters? You spend your morning triaging instead of fixing. And when you finally pick an error, you get a stack trace with zero context: no idea what page it happened on, what the user was doing, or how to reproduce it. Triage is not the job. Fixing is the job. But the tools make you do the triage first. If you're a product person You can see in your funnel that people drop off at step 3. What you can't see is why . Was it a JS error? A slow page? A confusing layout? Your analytics tool tells you what happened but never why , and the engineering dashboards that might explain it are unreadable walls of numbers. So you gue

2026-07-14 原文 →
AI 资讯

The Librarian Pattern: websites you talk to instead of browse

This is a condensed version of my preprint ( DOI: 10.5281/zenodo.21345310 , CC BY 4.0). Reference implementation: askbar.pro . The library problem For thirty years the website has been a library: a visitor arrives with one question and is expected to find the answer themselves, navigating menus, pages, and filters. Visitors read a small fraction of site content. Most leave without doing the thing the site owner hoped for. Chat widgets bolted onto such sites change nothing: the maze remains, the widget just answers questions about the maze. The pattern The Librarian Pattern inverts the relationship. The site does not present itself; it asks what you need and assembles the answer. The bar as the primary interface. One persistent input, text and hold-to-talk voice. It replaces navigation. Scene reassembly (generative UI). The center of the screen is not a page but a scene, composed per recognized intent. Transitions morph rather than reload. A guide with a plan. The conversational layer is a consultant with a goal ladder, asking one next question, never presenting menus of three options. Two button systems. Global suggestion chips above the bar are visually separated from in-scene action cards. This prevents the "six buttons" degeneration of chat UIs. The static shadow. Every live scene has a server-rendered twin page: full text in the DOM, question-shaped headings, FAQ schema, llms.txt, freshness stamps. Humans get the agent; crawlers and AI answer engines get complete, citable pages, generated from the same content source. Structural GEO-readiness. Content already organized as questions and answers matches how generative engines retrieve and cite, by construction. The result that surprised me 24 hours after the discoverability layer went public, Yandex Alice (the largest Russian AI answer engine) began citing the reference implementation as its prime example for the "next-generation website" query, describing the mechanics correctly and distinguishing it from "a chat

2026-07-14 原文 →
AI 资讯

The Everyday Backend Engineer: Step 10 — The Observer Pattern

Welcome back to The Everyday Backend Engineer: Practical Design Patterns . In our last post, we made our core algorithms interchangeable using the Strategy Pattern. Today, we close out our design patterns roadmap with arguably the most native pattern in the entire Node.js ecosystem: The Observer Pattern . Let’s look at how to master event-driven decoupling to trigger secondary workflows seamlessly without bloat. 🔴 The Problem: Direct Inline Side-Effects Imagine you are writing a video processing engine or a simple order fulfillment system. When a specific event happens—such as an order being finalized—multiple unrelated departments want a piece of the action: The Notification Service needs to send an SMS and Email receipt. The Logistics Service needs to generate a warehouse fulfillment ticket. The Analytics Service needs to update marketing tracking boards. If you don't decouple these events, your primary execution service ends up managing a giant web of secondary micro-services: // ❌ Bad Practice: The primary service is drowning in secondary dependencies const EmailService = require ( ' ../services/email ' ); const WarehouseService = require ( ' ../services/warehouse ' ); const AnalyticsTracker = require ( ' ../services/analytics ' ); class OrderProcessor { async finalizeOrder ( order ) { console . log ( " Saving primary order to the database... " ); // Core business logic ends here // The codebase smell: Procedural cascading dependencies await EmailService . sendReceipt ( order . userEmail ); await WarehouseService . createShipment ( order . id ); await AnalyticsTracker . trackSale ( order . totalAmount ); } } module . exports = OrderProcessor ; Why does this slow your system down? Your core OrderProcessor is now structurally dependent on three separate systems. If the AnalyticsTracker throws a network timeout error or if the warehouse API changes its interface, your core transaction fails or hangs. Furthermore, adding a fourth side-effect (like an auditing logger

2026-07-14 原文 →
AI 资讯

Part 2: When Nobody Grades Their Own Homework

TL;DR Some things can't be checked with a number, like whether an animation feels right. So a second, read-only agent grades the first one against a written rubric it is not allowed to edit. In my run the reviewer rejected the builder three times, and the most interesting problem it caught was in the test evidence, not the code. In Part 1 I built a loop that chased a number, frames per second. But most of what we care about in software is not a number. "Does this region switch feel good?" has no assert. You cannot write expect(feelsRight).toBe(true) . So this part is about how you check quality when there is nothing to measure. The approach I used is a second agent that grades the first one against a written rubric. In my run the reviewer turned the builder down three times before it approved anything, and the most interesting problem it found was not in the code at all. A quick reminder of the definition, since this is Part 2 of 3: a loop is an external script that runs the agent, a separate check the agent cannot edit decides pass or fail, and it repeats until it passes or hits a limit. In Part 1 the check was a Playwright test. Here the check is another agent. The problem this loop solves In the browser you can switch regions, say from Tamil to Korean, which swaps out hundreds of posters at once. Done badly, the grid flashes blank and jumps around. Done well, it fades from one set to the next, keeps its layout, shows a loading state, and puts you back at the top. "Done well" is subjective, which is the kind of thing you cannot unit-test. So I wrote it down as a rubric and had a second agent apply it. The bar: a rubric a person owns The rubric is seven plain-English checks in a file, and the first line is the one that matters: Overall APPROVED requires every item PASS. This file is human-owned. Only a person changes the bar. The seven items are things like a crossfade instead of a flash, no layout shift, a visible loading state, posters that stay 2:3, and landing

2026-07-14 原文 →
AI 资讯

Part 3: A Loop Whose Job Is to Do Nothing

TL;DR This loop runs on a schedule and succeeds by doing nothing almost every night. The pass/fail check is plain deterministic code, with no AI in the decision. It can run entirely free on your own machine. Only the cloud/CI version needs a paid API key. Plus the one bug that broke all three loops. The first two loops in this series work the same way from your side: you start them and watch. This last one runs on a schedule, like a nightly job, while you are not looking. That changes what success even means. A scheduled maintenance loop is doing its job when it does nothing. It should run every night, find nothing wrong, cost almost nothing, and still be there on the night something actually breaks. This part covers that loop, the hook mechanism that the whole series relies on, and a bug that broke all three loops in the least convenient place possible. The definition one more time, since this is Part 3 of 3: a loop is a trigger that runs the agent, a check the agent cannot edit that decides pass or fail, and a repeat, or here a wait until the next run. The only new thing this time is the trigger. A timer starts it instead of you. The problem this loop solves The browser's poster data is baked ahead of time into JSON files and images. In a real deployment that data goes stale as films are added and metadata changes, so you want to regenerate it every so often and confirm it is still valid before it ships: on a timer -> regenerate the data -> validate it -> green ships, red shouts The gate: a plain check with no model in it The check is a Node script. For every region file it confirms three things and exits non-zero if any of them fail: it matches the expected JSON schema, it has at least the minimum film count, and every poster file it points to actually exists on disk. There is no language model in that list. The regeneration step might use Claude, but the decision about whether the data is good is plain, deterministic code. That is on purpose. You do not want the

2026-07-14 原文 →
AI 资讯

How We Built DJ ROOTS: An AI-Powered Music Recommendation Platform

🎧 DJ ROOTS – Building a Real-Time Collaborative Music Platform with Gesture Control Crowd Vibes. You Control. Music is one of the best ways to bring people together. However, during parties, college events, hostel gatherings, or study sessions, one common problem always exists— who gets to control the music? Usually, one person owns the playlist while everyone else keeps requesting songs. This often creates confusion, interruptions, and arguments over what should play next. Our team wanted to solve this problem by creating a platform where everyone in the room gets an equal voice. Welcome to DJ ROOTS . 🚨 The Problem Traditional music streaming at group events has several limitations: Only one person controls the playlist. Song requests are ignored or forgotten. No real-time collaboration. Existing queue systems don't truly represent the crowd's choice. There is no simple browser-based solution that works instantly without downloading an app. We wanted to build something that makes music democratic . 💡 Our Solution DJ ROOTS is a real-time collaborative DJ platform where anyone can join a room using a simple room code. Participants can: Create or join a music room Add songs using YouTube Upvote or downvote tracks Automatically reorder the queue based on crowd votes Watch every change happen instantly across all connected devices Let the host control playback using webcam hand gestures Instead of one person deciding the playlist, the entire crowd decides what plays next. 🛠 Tech Stack Frontend React 19 Vite Tailwind CSS v4 Framer Motion Three.js GSAP OGL Backend Node.js Express.js Database & Authentication Supabase PostgreSQL Supabase Authentication Supabase Realtime Computer Vision Google MediaPipe Gesture Recognizer Audio Pipeline yt-dlp youtube-dl-exec HTML5 Audio API Web Audio API Deployment Vercel (Frontend) ⚙️ How It Works Users create or join a room using a unique room code. Songs are added using a YouTube link or search. Song metadata is automatically fetched. E

2026-07-14 原文 →
AI 资讯

Building an Offline AI Note-Taking App with WebGPU

For the last few months, I’ve been obsessed with a specific problem: the friction between privacy and utility in modern AI tools. Most "private" AI solutions still rely on a local LLM running on your CPU or GPU via a heavy desktop application. They require installation, constant background processes, and often struggle with performance on older hardware. I wanted to see if we could do better. I wanted to see if we could run a capable language model entirely within the browser, using only the device’s hardware acceleration, with zero data leaving the machine. The result is PrivateScribe, a tool I built to handle note summarization, email drafting, and rewriting. But more importantly, it’s an experiment in what’s possible when you treat the browser not just as a display layer, but as a compute engine. The Wedge: WebGPU and True Offline The core constraint that drove this project was simple: nothing leaves the device. In the current landscape, "on-device AI" often means "installed on your device." This is fine for desktop apps, but it creates silos. You can’t easily share a workflow across a Chromebook, a Windows machine, and an iPad without installing three different native applications. By leveraging WebGPU, PrivateScribe runs entirely in the browser. This unlocks a few critical advantages: Zero Installation: Users open a URL and start working. No downloads, no permission dialogs for file system access beyond what’s needed for the session. Hardware Acceleration: WebGPU allows the browser to tap directly into the GPU. This is crucial for inference speed. A small model that runs in your browser can process text significantly faster than a CPU-bound implementation, especially on modern laptops with integrated graphics. True Offline Capability: Because the model weights are loaded locally via WebAssembly and the inference happens on-device, the app works completely offline. If you lose your internet connection in the middle of drafting an email, the AI doesn’t stop. It c

2026-07-13 原文 →
AI 资讯

Five ways your LLM cost tracking is lying to you

Your monthly OpenAI or Anthropic invoice tells you how much you spent. It doesn't tell you which feature spent it, which model, or why last Tuesday cost three times as much as Monday. So at some point you (or your team) will build a metering layer: wrap the client, read usage off the response, multiply by a price table, ship it to a database. I did exactly that over the past few months while building an LLM observability service, and my numbers were wrong in five different ways before they were right. Every one of these failures was silent. No exception, no alert, just numbers that were quietly too low or too high. This is the list I wish someone had handed me. Pitfall 1: Streaming responses quietly report zero tokens OpenAI's Chat Completions API returns no usage data at all for streaming requests unless you pass stream_options: { include_usage: true } . No error, no warning. The stream just never contains token counts. If your metering reads usage off the chunks, every streaming call gets recorded as 0 tokens, $0. And since chat UIs are almost always streaming, that's most of your traffic. This one bit me twice in the same audit. First finding: all streaming calls in my own dashboard were $0. Second, nastier finding: I had a budget-gate feature that blocks calls once spend crosses a limit, and it waved every streaming call straight through — because as far as it could tell, streaming was free. The fix is to inject the option in your wrapper when the caller didn't set it: let injected = false ; if ( params . stream && params . stream_options ?. include_usage === undefined ) { params = { ... params , stream_options : { ... params . stream_options , include_usage : true }, }; injected = true ; } But there's a trap inside the fix. With include_usage on, OpenAI appends one extra chunk at the end of the stream that carries usage and has an empty choices array . Any downstream code that does chunk.choices[0].delta — which is most example code on the internet — will throw

2026-07-13 原文 →
AI 资讯

Node.js Hackathon Backends: From Idea to Demo in Under an Hour

Hackathons are intense. You've got a brilliant idea, a tight deadline, and often, limited sleep. The last thing you want is to spend half your precious time wrestling with database boilerplate, ORM setup, or SQL query syntax. This guide will walk you through building a functional Node.js backend for your hackathon project, focusing on speed and minimal friction, so you can spend more time on your core idea. The Hackathon Backend Challenge Typically, setting up a database and its interaction layer involves several steps: Schema Definition: Deciding on tables/collections, fields, types, and relationships. ORM/Driver Setup: Installing and configuring your database driver or ORM (e.g., Mongoose, Sequelize). Model Creation: Translating your schema into code, often with verbose syntax. Query Writing: Crafting SELECT , INSERT , UPDATE , DELETE statements or ORM methods for every data operation. Debugging: Fixing typos, schema mismatches, and complex join logic. This process, while fundamental, eats up valuable time that could be spent on features, UI, or even sleep. For a hackathon, you need to iterate rapidly, and database interactions should be the least of your worries. Strategy 1: Embrace Simplicity For many hackathon projects, you don't need highly optimized, production-grade queries from day one. You need functional queries that work quickly. Focus on getting data in and out reliably. Strategy 2: Natural Language for Data Modeling Instead of writing verbose schema definitions, think about how you'd describe your data to a non-technical person. For example, if you're building a task management app, you might say: "We need a collection of tasks. Each task has a title, a description, a due date, and a status (like 'pending' or 'completed'). Each task belongs to one user." This natural language description contains all the essential information for a data model, including relationships and field types. Strategy 3: Expressive Querying Similarly, when you need to fetch dat

2026-07-13 原文 →
AI 资讯

React useOptimistic: Optimistic UI Patterns That Actually Work (2026)

The problem with most web UIs is the gap between user action and visible feedback. A user clicks "like" and waits 200-400ms for the server to respond before the button changes. That delay reads as slowness even when the server is fast. The network round-trip is the ceiling. Optimistic UI inverts this: assume the operation will succeed, update the UI immediately, then reconcile with the server response when it arrives. If the server fails, roll back. React 19's useOptimistic hook gives you this pattern with minimal boilerplate and automatic rollback built in. The API const [ optimisticState , addOptimistic ] = useOptimistic ( state , // the current "real" state — synced from server updateFn , // (currentState, optimisticValue) => newOptimisticState ) optimisticState — during a pending transition, reflects the optimistic update. Once the transition completes, it reverts to state addOptimistic(value) — triggers an optimistic update, must be called inside startTransition Pattern 1: Like Button ' use client ' import { useOptimistic , useTransition } from ' react ' import { toggleLike } from ' @/actions/likes ' type LikeState = { liked : boolean ; count : number } export function LikeButton ({ postId , initialLiked , initialCount }: { postId : string initialLiked : boolean initialCount : number }) { const [ isPending , startTransition ] = useTransition () const [ optimisticState , addOptimistic ] = useOptimistic < LikeState > ( { liked : initialLiked , count : initialCount }, ( current ) => ({ liked : ! current . liked , count : current . liked ? current . count - 1 : current . count + 1 , }) ) function handleToggle () { startTransition ( async () => { addOptimistic ( ' toggle ' ) // updates UI immediately await toggleLike ({ postId }) // syncs with server }) } return ( < button onClick = { handleToggle } disabled = { isPending } > < Heart className = { cn ( ' h-4 w-4 ' , optimisticState . liked && ' fill-red-500 text-red-500 ' ) } /> < span > { optimisticState . count }

2026-07-13 原文 →
AI 资讯

How a Simple Screen Share Feature Turned Into a WebRTC Rabbit Hole

Introduction I've spent way too much time trying to come up with some generic introduction for this story, but then I realized none of you probably want to read that anyway. So instead, I'll just jump straight into the story—which is why you're here in the first place. The day I received the requirements The story begins when I received the requirements for a new feature that allows Teachers to share their presentation to review slides before the Lecture begins, so we would have teachers aids using the web version and seeing a screenshare from the main pc powerpoint, at first I thought maybe we can use HLS or RTMP for this and be okay with the 3 seconds delay that it has, but then I continued reading the ticket, we also needed the user to move to the next and previous slides via the web application, which immediately threw my initial idea out of the window. This is because if the user needs to interact with the application there is no way it will be usable without almost immediate feedback. Since we needed to show this to the client quickly we had 2 weeks to implement this feature, so before I did anything, I stopped and started drafting a simple design doc, which besides the fancy name was really just a document with my raw notes taken from research and comparisons between different solutions. After spending some time doing research and looking into different architectures and engineering blogs from companies like Twitch, Slack and Discord, I narrowed the possibilities down to four common architectures used for this type of use case. Architecture Options P2P Mesh This approach revolved around a user establishing WebRTC connections with every other user in the room. Besides being difficult to manage in terms of connections and sessions, it had one fatal flaw: network and CPU overhead. If we had twenty users in the room, every participant would maintain nineteen separate peer connections while sending nineteen streams, quickly consuming both CPU and bandwidth. MCU (M

2026-07-13 原文 →
AI 资讯

Introducing InterceptX: The Ultimate Modern Alternative to ModHeader

Introducing InterceptX: The Ultimate Modern Alternative to ModHeader for HTTP Modifications As web developers, API engineers, and security auditors, we spend a significant portion of our time inspecting and tweaking HTTP traffic. For years, extensions like ModHeader have been the go-to utility for modifying request and response headers on the fly. However, as the browser extension landscape transitions fully to Manifest V3 —bringing stricter security, better performance, and tighter permission rules—many developers are looking for a modern, lightweight, and local-first alternative. Enter InterceptX . What is InterceptX? InterceptX is a high-performance, compact Chrome extension designed to give you complete control over browser network requests. Built from the ground up on Manifest V3 using the declarative declarativeNetRequest API, it is fast, secure, and preserves your battery life by running lightweight matching rules inside the browser engine itself. Whether you need to bypass CORS policies, simulate mobile user-agents, override security headers, or redirect API endpoints to your local development server, InterceptX does it all with a premium, glassmorphic UI. Key Features at a Glance If you are familiar with ModHeader, you will feel right at home with InterceptX—but with several modern upgrades: 1. Request & Response Header Modifications Inject, append, or strip headers on outgoing requests or incoming responses: Set : Override an existing header or add a new one (e.g., setting custom auth tokens or Origin ). Append : Append values to headers like Accept or Cookie . Remove : Completely strip headers (e.g., testing behaviors when header keys are omitted). 2. URL Redirections Need to test API endpoints or redirect files? InterceptX features a built-in regex redirect engine (using RE2 syntax). You can redirect matching patterns and even use capture groups (e.g., redirecting https://api.production.com/(.*) to http://localhost:3000/\1 ). 3. Granular URL & Domain Fil

2026-07-13 原文 →