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

标签:#webdev

找到 1518 篇相关文章

AI 资讯

Your SaaS Mascot Should Do More Than Just Sit There

Interactive Rive mascots can react, think, talk, and connect to real AI, SaaS, web, and mobile products. Your SaaS Mascot Should Do More Than Just Sit There 👀 A lot of products have mascots. They look great on landing pages. Maybe they wave. Maybe they blink. Maybe there is a small looping animation. And that's it. But I think a product mascot can do much more. What if your mascot actually knew what was happening inside your product? That's the idea I've been exploring with Mascot Engine . I don't just want to animate characters. I want to build interactive mascot systems that connect to real products . From a mascot animation to a product system Imagine you're building an AI app. A user opens the app. The mascot is idle . The user sends a message. The mascot starts thinking . The AI begins responding. The mascot switches to talking . The task completes. The mascot celebrates . Something goes wrong? The mascot reacts to the error . The flow could look like this: User Action ↓ Product State ↓ Runtime Input ↓ Rive State Machine ↓ Mascot Reaction This isn't a video. It isn't a GIF. It isn't a pre-rendered animation playing randomly. The product controls the mascot at runtime. That's where things become interesting. A mascot can understand product states Well... not literally understand them 😄 The application still owns the logic. But we can expose a small runtime contract from the Rive file. For example: emotion = 2 isTalking = true lookX = 40 lookY = -10 celebrate = trigger error = false The developer controls these values from the application. The Rive State Machine handles the character behavior. The application controls what happened . The mascot system controls how the character reacts . I really like this separation. Why I use Rive for interactive mascots Traditional animation tools are great for videos and motion design. But product animation has different requirements. The character needs to react to application events. The animation may need runtime values. De

2026-07-13 原文 →
AI 资讯

The monitoring agent that cannot be told what to do

Here is a design decision we made early, wrote into the architecture as an invariant, and have refused to revisit since: our agent accepts no commands. Not "we don't currently use that feature" — the hub has no way to tell an installed agent to do anything at all. No remote execution, no self-update, no "collect this for us right now". It sends data outward, and that is the entire surface. This is not a limitation we are working around. It is the product. And it costs us features that customers ask for, which is exactly why it is worth explaining. The uncomfortable arithmetic of remote control Any tool that can update a plugin across fifty client sites is, by construction, a tool that can execute code on fifty client sites. Any dashboard that can restart a service on your server holds, somewhere, a credential that lets it in. This is not a flaw in those products — it is what they are for. You cannot automate a repair without the power to perform it. But that power has an owner, and the owner has a login, and the login has a support team, and somewhere in that chain there is a version of the software with a bug in it. When the tool is compromised, the blast radius is not the tool. It is every machine the tool could reach. The industry has already run this experiment at scale. In July 2021, attackers exploited a vulnerability in a widely used remote monitoring and management platform. They did not break into a single company — they broke into the thing that had access to the companies. Roughly sixty managed service providers were hit, and through them, an estimated 800 to 1,500 downstream businesses were encrypted in a single weekend, with a $70 million ransom demand attached. Read that shape again, because it is the whole argument: the victims did nothing wrong. They had bought a well-known product from a serious vendor and installed it exactly as instructed. Their compromise arrived through the door they had deliberately, sensibly, contractually left open — the one

2026-07-13 原文 →
AI 资讯

Building a Three.js 3D Product Configurator for WooCommerce: 4 Things I Didn't Expect

Most WooCommerce product pages still show the same thing stores have shown for 20 years: a handful of flat photos. I spent the last few months building Noorifa, a plugin that replaces that with an interactive Three.js viewer — customers rotate the model, zoom in, and switch colors/materials on specific meshes in real time, synced to the store's actual WooCommerce variations. The 3D rendering part was the easy 20%. The other 80% was a series of small, specific problems that don't show up in a Three.js tutorial. Here are four of them. 1. A directional light rig can't light a face it can't see Early on, customers rotating a table model would find the underside of the tabletop rendering near-black — no matter how far I pushed the light intensity. The rig at the time was a single key light plus a hemisphere ambient: scene . add ( new THREE . HemisphereLight ( 0xffffff , 0x444444 , 1.2 ) ); const keyLight = new THREE . DirectionalLight ( 0xffffff , 1.2 ); keyLight . position . set ( 3 , 5 , 4 ); scene . add ( keyLight ); The bug was geometric, not a brightness problem: keyLight sits above the model, so its light direction only reaches surfaces whose normal faces back toward it. A downward-facing surface — the underside of an overhanging tabletop — can't receive any direct contribution from a light positioned above it, at any intensity. Cranking the brightness slider was scaling a number that was multiplying against zero. The fix was closer to actual three-point studio lighting: key, fill, and rim from above for shape and separation, plus a dedicated light from below, and a brighter hemisphere ground color to approximate bounced light: scene.add( new THREE.HemisphereLight( 0xffffff, 0x888888, 1.1 * brightness ) ); const keyLight = new THREE.DirectionalLight( 0xffffff, 1.1 * brightness ); keyLight.position.set( 3, 5, 4 ); const fillLight = new THREE.DirectionalLight( 0xffffff, 0.5 * brightness ); fillLight.position.set( -4, 2, 3 ); const rimLight = new THREE.DirectionalLigh

2026-07-13 原文 →
AI 资讯

I scanned 15 public Lovable apps. 40% load their database in the browser.

No hacking — a passive scan only looks at what your browser already downloads when it opens a page. Here's what I found: 6 of 15 load their Supabase database directly client-side. The public API key sits in the page source. That's fine if Row-Level Security is configured right — but it's one wrong setting away from "anyone can read the whole table." 14 of 15 ship no Content-Security-Policy — a simple, high-value hardening against script injection, almost always missing. Is this theoretical? No. Two apps I audited with the owner's permission: A social app: the profiles table — user names, cities, and a password hash — readable by a logged-out stranger. Closed in an afternoon. A paid learning app: 155 paid study sheets and 4,872 answers were readable by anyone, with no account and no subscription — its entire paid catalogue, a single API call away. The paywall lived only in the front-end; the database served everything to everyone. Loading Supabase in the browser isn't the mistake. Not enforcing access in the database (RLS) is. And the tools you build with won't tell you — they'll happily ship it. If you built something on Lovable / Bolt / Replit with real users (or paying ones), it's worth 60 seconds to check what a stranger can already see. I made a free tool that runs the surface check (passive, no signup): sealdy.dev Happy to answer questions on how RLS leaks happen and how to lock them down.

2026-07-13 原文 →
AI 资讯

The Developer's Guide to Picking the Right Coding LLM at Scale

The Developer's Guide to Picking the Right Coding LLM at Scale Six months ago, I was staring at our monthly AI bill — $14,000 and climbing fast. We were using the "premium" model for everything, including trivial code completions. That night, I built a small internal benchmark to figure out which models actually earn their cost. What I learned reshaped how we think about AI tooling, vendor lock-in, and what "production-ready" really means. Here's the raw truth from my testing rig, what we shipped, and how we cut costs by 70% without touching output quality. Why I Stopped Trusting Default Recommendations Every vendor says their model is the best. Every benchmark site ranks things differently. Most "best of" lists are either sponsored or built on vibes. I needed numbers that matched my actual workflow: generating Python services, debugging JavaScript race conditions, implementing TypeScript algorithms, and reviewing Go for security. So I took ten models, threw identical prompts at them, and scored them myself. No vendor PR. No cherry-picked examples. Just the same five tasks, run the same way, scored on the same rubric. Here are the ten models I tested, with their output pricing per million tokens — because at scale, that's the metric that decides whether your AI strategy is viable or a margin killer. Model Provider Output $/M DeepSeek V4 Flash DeepSeek $0.25 DeepSeek Coder DeepSeek $0.25 Qwen3-Coder-30B Qwen $0.35 DeepSeek V4 Pro DeepSeek $0.78 DeepSeek-R1 DeepSeek $2.50 Kimi K2.5 Moonshot $3.00 GLM-5 Zhipu $1.92 Qwen3-32B Qwen $0.28 Hunyuan-Turbo Tencent $0.57 Ga-Standard GA Routing $0.20 Before you ask: yes, I tested against the originals. I also tested against Global API's unified routing layer, which lets you hit any of these through one endpoint. More on that later — it became the architectural decision that actually saved us. My Benchmark Methodology (No Marketing Fluff) I built five tasks that mirror what my engineers actually do every week. Not synthetic acad

2026-07-13 原文 →
AI 资讯

How I Built a GeoGuessr Game for Super Mario Odyssey

I wanted to build something different from the usual fan project. Instead of recreating gameplay, I asked a different question: How well do players actually remember the worlds of Super Mario Odyssey? The result is OdysseyGuessr, a browser game inspired by GeoGuessr. Players receive a screenshot from one of the game's Kingdoms and must place a marker on the correct location. Every meter counts. The project includes: Browser-based gameplay Single-player with customizable rounds Real-time multiplayer with a 5,000 HP battle system Community-submitted locations Admin moderation tools One of the biggest challenges wasn't the gameplay—it was collecting interesting locations that were difficult but still fair. Watching players confidently choose the wrong cliff or rooftop has been surprisingly entertaining. If you're interested in browser games or Nintendo fan projects, I'd love to hear your feedback. Play here: https://odyssey-guessr.lovable.app OdysseyGuessr is an unofficial fan project and is not affiliated with Nintendo.

2026-07-13 原文 →
AI 资讯

The One DevOps Metric Every Solo Developer Ignores

What’s up everyone! Back again for my daily drop. We talk a lot about deployment frequency and lead time for changes, but if you're a solo dev or part of a small team building something like LaunchAlly , there’s one metric that rules them all: Time to Recovery (TTR) from a bad push. When you're marketing, coding, and handling support all at once, a broken main branch is a massive bottleneck. Here is my quick tip for today: Invest 20 minutes into setting up strict automated rollbacks . If a deployment fails health checks, let the system revert it instantly without your intervention. Spend lots of hours working today...happy to go to bed now:) What’s your go-to strategy for handling failed deployments on the fly?

2026-07-13 原文 →
AI 资讯

Passion Edition

Submission: Edu-Insight Assistant What I build I built the Edu-Insight Assistant, a tool designed for educators to bridge the gap between complex school management data and actionable insights. It allows teachers to query students performance data using natural language, turning educational evaluation into a conversation rather than a manual data-processing task. Demo 🔗 Link: Passion-challenge How I Built It I utilized Next.js for a responsive, performant frontend and hooked it up to Google Gemini 3.5 API. The core logic involves a server-side API route that takes a teacher's natural language questions, prompt Gemini to generate the necessary SQL, and execute that query against a database. This architecture makes data exploration accessible to non-technical educators. Prize Categories: - Best Use of Google AI : Leveraged Gemini 3.5 Flash for natural language-to-SQL translation and result interpretation. - Best Use of Snowflake: Designed with an extensible data layer ready for production-scale analytical workloads in Snowflake.

2026-07-12 原文 →
AI 资讯

Blocking AI crawlers earns you nothing. Here's how to price them instead

Disallow: GPTBot is a wall. Walls don't pay rent, and the crawlers that matter most either ignore them or route around them. If your content is worth training on, the interesting question isn't "how do I keep the bots out" — it's "what do they owe me, and how do I say so in a way a machine can read." That's what RSL (Really Simple Licensing) is for. It shipped 1.0 in December 2025 with around 1,500 publishers behind it — Reddit, Yahoo, Quora, O'Reilly, Medium, Vox. This post is a from-scratch walkthrough of what the format actually is, the six places you can put it, the one mistake that makes crawlers silently ignore your terms, and where the declaration stops and enforcement begins. No tooling required to follow along — it's all plain XML and HTTP. The format is an XML vocabulary, not a config file An RSL document says: for this content, here's what's permitted, what's prohibited, and what it costs. Minimal example: <?xml version="1.0" encoding="UTF-8"?> <rsl xmlns= "https://rslstandard.org/rsl" max-age= "7" > <content url= "/" > <license> <permits type= "usage" > search </permits> <prohibits type= "usage" > ai-train </prohibits> <payment type= "crawl" > <amount currency= "USD" > 0.015 </amount> </payment> </license> </content> </rsl> Read it out loud: search engines may index this; training on it is prohibited; if you want to crawl it anyway, the rate is $0.015. usage tokens include search , ai-train , ai-use (inference/grounding), and a few more. You can scope rules by user and geo too. One rule that trips people up: prohibition wins . If the same token shows up under both permits and prohibits , the content is prohibited. Don't try to express "allowed except for X" by listing X in both — just prohibit X. The namespace is the thing crawlers actually key on The single most common way to publish RSL that quietly does nothing: getting the namespace wrong. It must be exactly: xmlns="https://rslstandard.org/rsl" http instead of https , a trailing slash, or a plausible

2026-07-12 原文 →
AI 资讯

Every AI tool, agent, and site builder a developer should know in 2026

hi, i am Aniruddha Adak, a full-stack developer from kolkata who spends way too much time building things with ai tools, shipping apps, and reading way too many github readmes at 2 am. i built 27 apps in 45 days using no-code and ai tools last year. that experience taught me one thing very clearly: the landscape of ai tooling for developers is moving insanely fast, and it is genuinely hard to keep up. so i sat down and did something about it. this is my deep research post on every ai tool, agent, builder, reviewer, and framework that developers, software engineers, and ai engineers should actually know about right now. i have organized it into categories so you can find what you need quickly. no fluff. just the tools, their sites, and what they do. why i wrote this i keep seeing developers waste time because they do not know the right tool exists. someone is manually reviewing pull requests for a week straight, not knowing coderabbit exists. someone else is hand-writing supabase schemas when emergent can do it in seconds. another person is spending days on a landing page when v0 can scaffold it in one prompt. this post is my attempt to fix that. i went through github repositories, dev communities, product hunt launches, and research aggregators to compile this. it is long. that is intentional. bookmark it. section 1: ai-native ides these are not just editors with a chatbot plugged in. these are environments built from the ground up around how language models think and work. tool site what it does cursor https://www.cursor.com forked vscode, codebase-aware context windows, multi-file edits with copilot-style background indexing windsurf https://windsurf.com cascade ai agent that writes files, runs terminal checks, and fixes things in real-time zed https://zed.dev built in rust with gpui, super low latency, native multiplayer coding support replit https://replit.com cloud ide with a full autonomous agent that runs inside serverless virtual workspaces google antigravit

2026-07-12 原文 →
AI 资讯

🧩 Runtime Snapshots #19 - We Opened the Format.

Most things that ship under "browser MCP" are the same thing wearing different names: an autonomous agent with a do-anything tool, pointed at your browser, told to figure it out. The pitch is capability. The unspoken cost is that a runtime which can do anything can be steered into doing anything. We just published the opposite, and we published it in the open. github.com/e2llm/e2llm-sifr is now the canonical home for SiFR - the format spec, the taxonomy, the MCP server manifest, real page captures, per-client configs, and the model skill. MIT-licensed. The capture engine and the server stay a hosted product; the format and the interface are open. This post is about why that split is the whole point. E2LLM is not an agent This comes first because everything else follows from it. An agent decides and acts on its own. It plans, it loops, it takes steps toward a goal with you out of the path. That autonomy is the feature - and it is also the attack surface. A runtime that can do anything is a runtime that can be talked into anything. E2LLM is a perception layer, not an agent. It gives whatever model you already use senses for the browser: structured sight, and a small set of narrow, individually-gated actuators. It does not plan, does not loop, does not decide. Your model does the reasoning. E2LLM reports what a page is and carries out one explicit instruction at a time. Nothing runs while you look away. Perception substrate versus autonomous runtime. That line is the design, not a disclaimer on top of it. What SiFR is - and the three things it isn't SiFR (Salience-Indexed Flat Relations) is the capture format at the center of E2LLM. From a distance it can look like a tidy DOM dump or an accessibility tree. Mechanically it is neither, and the difference is the entire value. Not a DOM dump. A dump serializes the tree as-is: everything, in document order, noise included. SiFR selects and ranks. It scores every node by salience, drops scaffolding, and flattens the survivor

2026-07-12 原文 →
AI 资讯

I built two Next.js 15 + Tailwind v4 templates with zero extra dependencies — here's what I learned

Earlier this month I shipped two premium templates — a SaaS landing page and a developer portfolio. Not a startup, not a SaaS, just templates. This post is about the two constraints I built them under, why they made the code better, and a few things I learned launching as a solo dev with zero audience. Constraint 1: zero dependencies beyond next, react, and tailwind Open the package.json of most templates and you'll find 20+ packages: icon libraries, animation libraries, carousel plugins, UI kits, utility libraries. Every one of them is a version conflict waiting to happen for the buyer, and most are replaceable with a few lines of code in 2026. What I used instead: Icons → inline SVG components. An icon component is ~10 lines. You need maybe 15 icons for a landing page. Animations → plain CSS. Scroll-blur navbars, gradient glows, an animated "typing" terminal — all doable with keyframes and transitions. No framer-motion. The dashboard mockup in the hero → pure CSS. Divs, borders, gradients. It looks like a product screenshot but it's ~80 lines of JSX and weighs nothing. Result: both templates land at ~100KB first-load JS, npm install takes seconds, and there is nothing to break when Next.js 16 arrives. Constraint 2: every piece of content in ONE typed config file The thing I hated most about templates I've used: content is smeared across 30 components. Changing a headline means hunting through JSX. So both templates keep all content in a single file — lib/content.ts for the landing page, site.config.ts for the portfolio. Headlines, nav, pricing tiers, testimonials, project lists, even the lines that animate in the fake terminal. Components are pure renderers of that config's TypeScript type. Two things surprised me here: TypeScript becomes your content linter. Forget an alt text, malform a link, give a pricing tier three features when the type expects a non-empty array — the build fails. Content mistakes surface at compile time. It forces better component design. W

2026-07-12 原文 →
AI 资讯

I Love Fragrances, So I Built a 6-Game Arcade + Concierge About My Obsession

Hi, my name's Ibrahim, I'm a university student, and I have a problem: I love fragrances way more than my bank account loves me for it. It started small, the way these things always do. A cheap Middle Eastern attar someone gave me as a gift, the kind that costs less than a coffee but somehow smells like it belongs in a much fancier bottle. Then another. Then I started actually reading about notes, pyramids, accords, sillage, the whole rabbit hole. Fast forward through a lot of saved-up allowance and skipped nights out, and I've now got about 20 bottles on my shelf. Mostly affordable Middle Eastern gems (some of them genuinely punch way above their price), with a small handful of designer pieces I saved up for and treat like trophies. If you're a fellow fragrance enthusiast, you already know the feeling: you don't just "wear" a scent, you collect them, you study them, you have opinions about whether a note is top, heart, or base and you will absolutely fight someone about it. That obsession is basically the entire reason this project exists. So when I saw the DEV Weekend Challenge's "Passion" prompt, there was only one thing I could possibly build. What I built: recommendmeafragrance recommendmeafragrance is a browser arcade for fragrance nerds: six small daily games built around real perfume data (notes, brands, years, price tiers), plus an AI Concierge you can actually talk to about what you're in the mood for. Every game feeds into a personal "shelf" that tracks which fragrances you've discovered, plus streaks so you have a reason to come back tomorrow. Here's the tour. 🧪 Scentle: Wordle, but for your nose A new fragrance is picked every day (the same one for everyone, worldwide, no matter your timezone). You get 6 guesses, and after each one you get Wordle style feedback: was the brand exact or just the same house family, did the real answer come out earlier or later than your guess, is it pricier or cheaper, same gender, same concentration, how many notes do you

2026-07-12 原文 →
AI 资讯

roaster0: I Let Gemini Read My GitHub and It Destroyed Me (Then Redeemed Me)

This is a submission for Weekend Challenge: Passion Edition (#weekendchallenge #devchallenge #ai #googleai #gemini #webdev #showdev) What if your GitHub could roast you harder than your teammates ever would — and then remind you why you keep building? What I Built 🔥 roaster0 — an AI that roasts your GitHub profile, then redeems you. Drop in any public GitHub username and it pulls your real repo data — commit habits, abandoned projects, lazy repo names, language choices — and turns it into a savage, hyper-specific roast using Gemini's structured output and multimodal reasoning. Then it ends with one sincere, earned compliment pulled from something genuinely good in your data. The idea started from a simple thought: your GitHub is an involuntary diary of what you were obsessed with. The eleven repos with no description. The final-v2-FINAL commit. The side project you lived and breathed for three weeks in March before abandoning it. That's passion — messy, obsessive, usually invisible unless someone points a spotlight at it. There's also a second mode, 🎭 Roast Anything : submit a name, bio, links, and/or images, and Gemini reads all of it — text, links, photos — to generate the same experience for anyone, not just developers. Demo 🔗 Live app: roaster0.netlify.app Try it on any public GitHub username, or switch to Roast Anything mode and paste in a bio + an image to see the multimodal analysis at work. Once your roast is generated, you can: 🔊 Listen to it — full audio narration via Web Speech API, paced and pitched differently depending on roast intensity 🖼️ Download the card — every roast renders as a shareable PNG on HTML5 Canvas, ledger-paper aesthetic, ready to post 📋 Share the record — copy a formatted text version straight to clipboard for any platform A couple of examples from testing: GitHub mode — roasted DEV's own founder using nothing but his real public repo data: (screenshot: Ben Halpern roast card — graveyard count, repo names like oceanic-giraffe and test

2026-07-12 原文 →
AI 资讯

Generate TypeScript Types from JSON (and where the auto-generators trip up)

You've got a JSON API response and you want TypeScript interfaces for it. Here's how to generate them fast — and where the auto-generators quietly get it wrong. The fast path Paste your JSON, get interfaces: { "id" : 1 , "name" : "Ada" , "roles" : [ "admin" ], "profile" : { "active" : true } } → interface Root { id : number ; name : string ; roles : string []; profile : Profile ; } interface Profile { active : boolean ; } jsonviewertool.com/json-to-typescript does this in the browser (client-side), nesting objects into their own interfaces. Where generators trip up A generator only sees the ONE sample you give it, which causes predictable gaps: Nullable fields. If your sample has "avatar": null , the generator infers null — but the real type is probably string | null . Feed it a populated sample, or fix it by hand. Empty arrays. "tags": [] infers any[] — the element type is unknowable from an empty array. Optional fields. A field missing from your sample won't appear at all. If the API sometimes omits middleName , mark it middleName?: string . Unions. A status that's "active" in your sample becomes string , not the literal union "active" | "banned" | "pending" . Narrow it manually for the safety. Numbers that are really enums or IDs. "currency": 840 types as number ; you may want an enum or branded type. When to use a schema instead If the JSON has a JSON Schema or OpenAPI spec, generate types from that ( json-schema-to-typescript , openapi-typescript ) — it encodes nullability, optionality, and unions the raw sample can't. Sample-based generation is for quick throwaway typing; schema-based is for anything you'll maintain. Rule of thumb Generate from a sample to skip the boilerplate, then read every field — the generator gives you a draft, not a contract. Nullability and optional fields are where the runtime bugs hide.

2026-07-12 原文 →
AI 资讯

How I Built ProjectHub: An Embeddable AI Recruiter Assistant That Runs on Free Tiers

I built a chat widget for my portfolio. One script tag, drop it on a page, and recruiters can ask questions about my projects, my AWS internship, what I actually know, and what kind of roles I'm looking for. I named the assistant Scout. <script src= "https://bradleymatera.github.io/ProjectHub/ProjectHub.js" ></script> That's the whole pitch from the outside. What it took to get there is a lot messier than one script tag suggests. The current version has a vanilla JS frontend, a Node backend on a Google Cloud e2-micro VM, a knowledge base pulled from GitHub, a network of free LLM providers, a response cache, per-tab memory, safety checks, a self-improvement loop, and an analytics dashboard. It also has six test suites and more documentation than I expected. The one rule I kept coming back to: it had to stay useful without me paying for AI traffic. Why I built this in the first place My portfolio is scattered. Projects live on GitHub, demos live on various subdomains, blog posts are on the site, certifications are listed somewhere, and my actual AWS internship experience is explained in a few different places. A motivated recruiter could piece it all together, but most recruiters are not motivated. They are busy. I realized I was asking them to do homework. That seemed backwards. So I thought, what if they could just ask? Scout is supposed to answer straight questions like "What is Bradley's strongest project?" or "Does he actually have production AWS experience?" or "What does he want to be paid?" It doesn't pretend to be me, doesn't inflate my title, and doesn't try to sell me as a senior engineer when I'm not one. It just answers from verified stuff. The architecture Three layers. Site loads one script. The script hits the backend. The backend either answers from the knowledge base or falls through to free LLM providers. flowchart TD A[Website or portfolio] -->|loads one script| B[ProjectHub widget on GitHub Pages] B -->|POST /api/chat| C[Node.js API on a GCP e2-mi

2026-07-12 原文 →
AI 资讯

What actually crosses the React Server Component boundary

Everyone can type "use client" . Almost nobody can say what survives the trip across it — and then something breaks: next build dies at prerender, the error names no file and no import chain, and the prop that killed it was an arrow one level down inside an object called options . Here's the uncomfortable secret: the boundary is one serializer . React walks every prop you hand a client component, encodes each value it has a branch for, and throws on the first one it doesn't. This post reads those branches out of React 19's Flight source — one file, no framework — and shows the two traps that pass code review and fail the build anyway. What crosses A prop is legal if the serializer has a branch for it. Everything else falls into one prototype check and throws. The whole contract fits on a screen: // app/page.tsx — a Server Component. Every comment is the serializer's verdict. export default function Page () { return ( < Chart title = "Q3" data = { { rows : [ 1 , 2 , 3 ] } } when = { new Date () } seen = { new Set ([ 1 ]) } index = { new Map () } rows = { fetchRows () } // an un-awaited Promise; the client calls use(rows) bytes = { new Uint8Array ( 8 ) } // ArrayBuffer, DataView, every typed array upload = { new File ([], ' a.csv ' ) } // there is no File branch — a File is a Blob form = { new FormData () } stream = { new ReadableStream () } kind = { Symbol . for ( ' chart ' ) } // global symbols cross; Symbol('chart') throws Slot = { Legend } // a client component: a function, and a client reference save = { saveRow } // a "use server" function: a server reference err = { new Error ( ' boom ' ) } // crosses — and arrives empty in production // no branch — every one of these throws at render match = { /q3/ } href = { new URL ( ' https://x.dev ' ) } cache = { new WeakMap () } user = { new User ( ' ada ' ) } bare = { Object . create ( null ) } onPick = { ( id ) => select ( id ) } /> ); } Four of those lines are the ones people get wrong: new Error() crosses, and product

2026-07-12 原文 →