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

标签:#web

找到 2937 篇相关文章

AI 资讯

Split PDF Pages in the Browser with pdf-lib — No Uploads, No Server

A few weeks ago I built a free online Merge PDF tool that runs 100% in the browser. Today I'm sharing its sibling: a Split PDF tool using the same library — pdf-lib — with zero file uploads, zero watermark, and zero server code. You can try it live here: https://yourutilityhub.com/pdf/split-pdf Why split PDFs in the browser? Most online PDF tools upload your file to a server — which means your document is never truly private. Splitting pages locally means: No uploads — nothing leaves your device No watermark or signup Free — no per-page charges Works offline, fast, for files of any size (limited by your browser's memory) The plan We'll load the PDF, pick a page range (or specific pages), copy those pages into a fresh PDFDocument , and save the result — all with pdf-lib . Let's walk through the full working component . 1. Install and import npm install pdf-lib import { PDFDocument } from " pdf-lib " ; 2. Load the uploaded file const arrayBuffer = await file . arrayBuffer (); const pdf = await PDFDocument . load ( arrayBuffer ); const totalPages = pdf . getPageCount (); PDFDocument.load() accepts an ArrayBuffer . We read it straight from the File object — no server involved. 3. Split by page range (e.g. 1-5 or 3- ) const parts = pageRange . split ( " - " ); const startRaw = parseInt ( parts [ 0 ]. trim (), 10 ); const endRaw = parts [ 1 ]. trim () === "" ? totalPages : parseInt ( parts [ 1 ]. trim (), 10 ); // validate 1..totalPages const startPage = Math . min ( startRaw , endRaw ) - 1 ; // 0-based const endPage = Math . max ( startRaw , endRaw ) - 1 ; const newPdf = await PDFDocument . create (); const pageIndices = []; for ( let i = startPage ; i <= endPage ; i ++ ) { pageIndices . push ( i ); } const copiedPages = await newPdf . copyPages ( pdf , pageIndices ); copiedPages . forEach ( page => newPdf . addPage ( page )); The trick: copyPages() wants 0-based indices , but users type 1-based page numbers, so we subtract 1. "3-" with an empty end means "to the last pa

2026-09-02 原文 →
AI 资讯

I Built an API That AI Agents Pay in USDC — Full x402 Walkthrough (27 Endpoints, Real Transactions)

I built an Express API that AI agents (or humans, or anything with fetch ) can pay per call, in USDC, with no signup and no API key. It's live on Base mainnet with 27 paid endpoints, and I've run real settled transactions against it. This is the technical walkthrough — the code, the protocol, and the things that actually broke — not an "agentic economy" pitch. What x402 is, in 5 lines x402 resurrects the dormant HTTP 402 Payment Required status code as a real payment handshake. A client calls a paid route → the server replies 402 with payment requirements (amount, asset, network) instead of the resource → the client signs a USDC transfer on Base and replays the request with a PAYMENT header → a facilitator (a third party, or Coinbase's CDP service in production) verifies and settles the transfer on-chain → the server serves the response. No account creation, no API key issuance, no OAuth dance — the wallet address is the identity, and payment is the auth. The seller side The server is plain Express. Each endpoint is a file in endpoints/ exporting { path, method, price, handler } ; server.js loads them all, builds the x402 route table, and mounts one middleware: import { paymentMiddleware , x402ResourceServer } from " @x402/express " ; import { ExactEvmScheme } from " @x402/evm/exact/server " ; import { HTTPFacilitatorClient } from " @x402/core/server " ; import { createFacilitatorConfig } from " @coinbase/x402 " ; const facilitatorConfig = config . isMainnet ? createFacilitatorConfig ( config . cdpApiKeyId , config . cdpApiKeySecret ) : { url : config . testnetFacilitatorUrl }; // https://x402.org/facilitator, no key const facilitatorClient = new HTTPFacilitatorClient ( facilitatorConfig ); const resourceServer = new x402ResourceServer ( facilitatorClient ). register ( config . caip2Network , // "eip155:8453" on mainnet new ExactEvmScheme () ); const paidRoutes = {}; for ( const ep of endpoints ) { if ( ep . price == null ) continue ; paidRoutes [ ` ${ ep . method }

2026-09-02 原文 →
AI 资讯

How the internet actually works, and why nobody is in charge of it

Hello, I'm Maneshwar, and I'm building LiveReview — a blast-radius aware AI code review built for your business-critical systems. Star us to help devs discover the project, give it a try, and share your feedback to help improve the product. You open a video and it starts playing in about a second. Somewhere between your thumb and that first frame, your request crossed maybe fifteen different companies' equipment, possibly an ocean, and came back. Nobody coordinated it. That is the part I find genuinely strange about the internet, and it is the part most explanations skip. They tell you the internet is "a global network of networks", which is true and tells you nothing. So let's actually take it apart. There is no internet. There are 75,000 of them. The single most useful thing to understand up front: the internet is not a thing anyone built. It is roughly 75,000 independent networks that agreed on how to hand traffic to each other. Your ISP is one. Your university is one. Cloudflare is one. They own their own cables and routers, they answer to nobody in particular, and they interconnect voluntarily. Once you see it that way, every weird thing about the internet starts making sense. The whole arrangement has three parts: The edge is everything that actually wants to say something. Your phone, a laptop, a server in a rack, and increasingly a doorbell. These are called hosts or end systems , and they split roughly into clients that ask and servers that answer. The access network is your on-ramp. Fibre or cable at home, the office network, 5G from your pocket. Its only job is getting you to the first router. It is also, almost always, the slowest part of the entire journey, which is worth remembering next time you blame a website for being slow. The core is the mesh in the middle. Routers and the links between them, and nothing else. No control room, no master server, no company that owns it. Nobody reserved you a line Here is where the design gets clever. Before the in

2026-09-02 原文 →
AI 资讯

Constitutional Methods for LLMs: Turning Written Principles into Training Signals

Hello, I'm Shrijith Venkatramana, and I'm building LiveReview — a blast-radius aware AI code review built for your business-critical systems. Star us to help devs discover the project, give it a try, and share your feedback to help improve the product. There is a slightly strange thing about modern LLMs. We are increasingly asking them to make judgments that look less like autocomplete and more like governance: Should I answer this request? Is this instruction legitimate? Is this response too dangerous? Should I refuse, or can I safely help? What should I do when two desirable goals conflict? Traditionally, we tried to answer these questions by collecting more human preference data. Show an annotator two responses. Ask which is better. Collect millions of comparisons. Train a reward model. Optimize the LLM against it. That works surprisingly well. But it has an awkward scaling property: humans have to inspect the behavior we want the model to learn. Anthropic's Constitutional AI idea takes a different route. Instead of asking humans to label every questionable behavior, give the model a written set of principles—a "constitution"—and use another model to critique, compare, revise, and eventually train the target model. That seemingly small change leads to an important engineering idea: A natural-language rule can become a source of synthetic training data, a reward signal, and even a runtime safety mechanism. This article explains how that works, from the intuition to the mathematics and operational trade-offs. 1. The core idea: turn values into a learning loop Suppose you are building an assistant that should be helpful without producing harmful instructions. With ordinary supervised fine-tuning, you might write examples like: User: How do I make a dangerous chemical? Assistant: I can't provide instructions for making it. You need many examples covering many variations: different wording different domains indirect requests role-playing obfuscated requests borderline

2026-09-02 原文 →
AI 资讯

How to Leverage AI in Web Development Frameworks in 2026

Originally published at nlocoding.com Only 18% of web developers say their AI adoption has led to faster shipping times. The rest? Stuck in pilot hell. (Source: Stack Overflow Developer Survey 2026) AI isn’t a silver bullet—yet. But it’s already rewriting the rules. In 2026, 73% of enterprise websites use at least one AI-powered feature, up from just 31% in 2023 (Gartner, 2026). If your web framework isn’t learning new tricks, you’re falling behind. 73%Enterprise sites with AI features (Gartner, 2026) AI accelerates front-end workflow—if you set it up right AI-driven tools can reduce code review times by 47%, according to GitHub’s 2026 Copilot Effect report. But only if you integrate them into your web framework’s CI/CD pipeline. Here’s the catch: Most teams skip the boring setup. They bolt on AI, then complain that it slows things down. Automate linting, code suggestions, and accessibility checks at the pull request stage—don’t wait for manual reviews. Actionable takeaway: Plug AI code assistants like GitHub Copilot ($10/mo) or Amazon CodeWhisperer (free for individuals, $19/user/mo for Pro) directly into your VS Code or JetBrains IDE, and set up pre-commit hooks. Your PRs will thank you. ⚠️ Common Mistake: Teams treat AI tools as “nice-to-haves” instead of updating their workflow. The result? More merge conflicts, not fewer. Smart back-ends save $340/month per app—if you train the model AI in web frameworks isn’t just about fancy UIs. 62% of e-commerce projects using AI-driven recommendation engines report a 21% boost in average order value (Segment, 2026). The kicker: Open-source models like TensorFlowJS are free. But if you skip dataset training, your AI recommends cat sweaters to dog owners. (I’ve seen it. It’s funny. It’s a disaster for conversion rates.) Actionable takeaway: Use your real user data. Integrate with a vector database like Pinecone ($0.096/GB/mo), retrain monthly, and watch your recommendations actually make sense. 💡 Pro Tip: Fine-tune your mode

2026-09-02 原文 →
AI 资讯

How I Put PgCache in Front of a 16-Million-Row Postgres Database

Disclaimer: This is a side project, not a production story. The slow-query problem is real, but the database is synthetic data I generated to make it show up on demand. I have no connection to PgCache. Everything here is in a repo you can clone and run. I tested version 0.6.2. A handful of dashboard queries on one of my projects were fine for a year and then weren't: count users by tier, revenue grouped by country, best-selling products per category. Nothing exotic, just aggregates and joins over tables that had gotten big. The usual fixes didn't sit right with me. A materialized view means picking a refresh interval and serving slightly stale numbers in between. Redis in front of Postgres means writing and maintaining code that knows which cache entries to throw away on every write. A read replica just runs the same slow query on another machine. PgCache offers a different trade. It's a proxy that talks the Postgres wire protocol, so your app connects to it as if it were the database. It caches reads. And instead of expiring entries on a timer, it follows Postgres's replication stream and refreshes a cached result when the rows behind it change. That stream is the same feed Postgres uses to copy data to a standby server , a running log of every insert, update, and delete. The "no timers, no manual invalidation" part is the interesting claim. Here's how it held up. A database big enough to be slow First I needed a database where "slow" was real and not a rounding error. I wrote a seed script for a small e-commerce schema and filled it to about 16 million rows: Table Rows Notes users 1,000,000 10 countries; tiers 50% free / 33% pro / 17% enterprise products 2,000 10 categories orders 5,000,000 four statuses, random totals, spread over two years order_items 10,000,000 about two per order I added indexes on every foreign key and on every column the test queries filter or group by. That was on purpose. I wanted to compare PgCache against a Postgres that had been tuned p

2026-09-02 原文 →
AI 资讯

A Web Page Can Tell Which Extensions You Have Installed. Here Is How.

Open a page and it can start guessing which browser extensions you run before you click a thing. Not "extensions in general" - which ones . Your password manager, your ad blocker, the wallet, the internal tool your employer ships, the accessibility extension you depend on. The page never asks and you never see it happen. This is not a bug in Chrome. It is the sum of a few features working exactly as designed, and the people best placed to close it are extension authors who mostly do not know they left it open. I maintain an extension and a library that talks to it, so I have spent real time on the detectable side of this. Here is how a page does it, what the answer is worth to whoever is asking, and what actually stops it. Technique one: ask the extension directly Some extensions accept messages from web pages on purpose - our own does, so a customer's "report a bug" button can tell whether the extension is there. The API is chrome.runtime.sendMessage : chrome . runtime . sendMessage ( EXTENSION_ID , { type : ' ping ' }, ( reply ) => { if ( reply ) { // it is installed, and it answered } }); For a page to be allowed to send that message, the extension has to list the page's origin in its manifest, under externally_connectable . Authors who want their extension to work with any site reach for the wildcard: "externally_connectable" : { "matches" : [ "<all_urls>" ] } And that one line is the door. <all_urls> does not mean "my customers' sites". It means every site on the internet may now open a channel to this extension - which means every site may ping it and learn whether you have it. The convenience the author wanted for their own pages, they handed to everybody's. This technique is narrow, because it only finds extensions that chose to talk to pages. The next one is not narrow. Technique two: knock on the extension's own files Extensions ship assets - icons, injected stylesheets, images. Any asset marked web-accessible is reachable at a fixed URL built from the ext

2026-09-01 原文 →
开发者

How an Abandoned Client Project Became My Proudest Showcase

In the first part of this series , I walked through the technical grit of rebuilding a musician's web platform from scratch—spending over 320 hours fixing legacy WordPress code, writing custom CLI tools with Node.js and FFmpeg, and crafting a lightweight Vanilla JS SPA router. If Part 1 was about the engineering side , Part 2 is about the human side : scope creep, irrational client expectations, and why finishing an "abandoned" project is sometimes the ultimate test of a developer’s character. "Appetite Comes With Eating": How a Volunteer Portfolio Case Turned Into Scope Creep They say the road to hell is paved with good intentions. We stepped into this project on pure enthusiasm. The agreement was simple: we help an independent artist build a sleek web presence for free, and in return, we get a real-world production case for our engineering portfolios. Win-win, right? At the beginning, everything was smooth. The client was absolutely thrilled with the initial UI/UX prototypes. But as soon as the application was actually hosted and brought to life, the "appetite" started growing exponentially: Phase 1 (Initial tweaks): "Can we change the album cover art?" — Sure thing. It's your music, your Bandcamp embed—done. Phase 2 (The Breaking Point): "The fonts don't feel right... can we rewrite the copy?" This was the final straw. Keep in mind: we had repeatedly confirmed typography and styling choices with the client earlier, and everything had been approved. When my teammate David politely informed the client that fundamental UI changes were outside the scope of our volunteer agreement, the client responded with: "Just show me where the files are, and I'll change the fonts myself." For anyone who works in web development, this was the ultimate ironic punchline. Changing fluid typography, responsive SCSS breakpoints, and layout variables isn't like picking a font in Microsoft Word. Knowing that the client had previously struggled to set up a basic Bandcamp profile, we wishe

2026-09-01 原文 →
AI 资讯

I built a location-to-station finder for China’s high-speed rail

China’s high-speed rail network is easy to admire and surprisingly easy to use once you know the correct station. The difficult part for many first-time visitors happens earlier: a single city can have several major stations, and a traveler often starts with a hotel, airport, attraction, or street address—not a station name. I initially wanted to build a practical transport tool for foreign visitors in China. After reading travel questions, the recurring problem was not simply “how do I buy a train ticket?” It was: Which station should I depart from? Is Shanghai Hongqiao the same place as Shanghai Station? Which English station name matches the Chinese name shown in the booking app? Is the nearest station actually useful for my destination? So I built a small station-finding workflow instead of another static railway map. The workflow The user enters two real places: where they are starting from, such as a hotel or airport; where they are going, such as another hotel, city center, or attraction. The page then shows candidate departure and arrival stations side by side, with both English and Chinese station names. After the user selects a pair, the tool prepares the exact station names for an official Railway 12306 check. You can try the current version here: China high-speed rail station finder Why I did not turn it into a ticket seller Railway schedules, ticket availability, fares, and passenger rules are official-service data. I do not want a travel helper to imply that a route exists merely because two stations are geographically close. The boundary is therefore deliberate: Ask-China helps turn real places into candidate stations. It shows bilingual names so travelers can recognize the correct station. Railway 12306 remains the final place to verify the journey and book. This also keeps failure states honest. If place search or route estimation is unavailable, the page should say that instead of inventing a confident answer. The implementation decisions that matt

2026-09-01 原文 →
产品设计

Mozilla launches ad blocking for Firefox on iOS

Mozilla is officially launching ad blocking for Firefox on iOS today, after testing the feature over the past few weeks. The new built-in option will block most third-party ads and trackers before they load on an iPhone, reducing bandwidth use and decluttering mobile websites. Mozilla is using Apple's WebKit Content Blocker technology and the EasyList […]

2026-09-01 原文 →
AI 资讯

Reverse Proxies vs Forward Proxies: Which Architecture Do You Need?

Introduction When you're scaling infrastructure or managing network security, proxies become essential tools—but they solve fundamentally different problems. A reverse proxy sits between your users and your backend servers, while a forward proxy sits between your users and the internet. This distinction might sound academic, but it shapes your entire architecture: from load balancing and security posture to compliance requirements and cost structures. Choosing the wrong proxy type can lead to bottlenecks, security vulnerabilities, or unnecessary infrastructure complexity. This article walks you through real-world scenarios, pricing considerations, and decision frameworks to help you deploy the right solution. Forward Proxies: Controlling Outbound Traffic What Forward Proxies Do A forward proxy intercepts requests from your internal network and forwards them to external servers on the internet. From the external server's perspective, the proxy is the client—the real origin of the request is masked or modified. Common use cases include: Employee internet access control : A company deploys a forward proxy so IT can block malicious domains, filter content, and enforce acceptable use policies Data residency compliance : A financial services firm routes all outbound API calls through a forward proxy in a specific geographic region to meet regulatory requirements Web scraping at scale : When extracting data from multiple websites, forward proxies rotate request sources to avoid IP-based blocking DDoS mitigation for outbound traffic : Distributed request aggregation through a forward proxy can reduce fingerprinting risks Pricing and Infrastructure Costs Forward proxies typically charge per: Concurrent connections : Enterprise solutions like Zscaler or Palo Alto Networks start around $5–15 per user/month Data transferred : Cloud-based forward proxies charge $0.05–$0.30 per GB, depending on geography and provider IP rotation : Proxy services offering residential IPs (for non-

2026-09-01 原文 →
AI 资讯

HTML tags that will improve your e-commerce experience

Understanding when to use <ins> , <del> and <s> HTML tags Comparative Feature <ins> element <del> element <s> element Semantic Definition Represents the content that has been added to a document. Represents a range of text that has been deleted from a document. Represents content that is no longer accurate, correct, or relevant. Use Case New edits in a code, in a text, tracked changes Document edits, tracked changes, or visual/structural revisions (often paired with <ins> ). Outdated information, deprecation notices, old prices, or sold-out items. Accessible Code Pattern The meeting is on <span class="sr-only">previous date: </span><del>Monday</del> <span class="sr-only">new date: </span><ins>Wednesday</ins>. The meeting is on <span class="sr-only">previous date: </span><del>Monday</del> <span class="sr-only">new date: </span><ins>Wednesday</ins>. <span class="sr-only">Original price: </span><s>$100.00</s> Visible Representation The meeting is on Monday Wednesday The meeting is on Monday Wednesday $100.00 $34.99 Unique Attributes cite (URL pointing to the explanation of the deletion) datetime (date/time of the deletion) cite (URL pointing to the explanation of the deletion) datetime (date/time of the deletion) None Default Browser Style By default, it has an underline but it can be changed to a bold style, put a background green to show insertion, etc. Renders with a visual line-through (strikethrough) Renders with a visual line-through (strikethrough) Implicit ARIA Mapping: role="deletion" and role="insertion" The <del> and <s> tags map to the accessibility role of deletion (and <ins> to insertion ). Sighted users see these as struck through or underlined, but screen reader support for announcing these changes is inconsistent. Understanding the Accessibility Tree Mapping Under the W3C Accessibility API Mappings, these tags are programmatically mapped to specific accessibility roles that browsers expose to the OS accessibility tree: <del> maps to role="deletion" (se

2026-09-01 原文 →
AI 资讯

Next.js App Router — WebSockets via Client Islands

The Challenge: Realtime in the Age of Server Components The paradigm shift toward React Server Components (RSC) and the Next.js App Router has fundamentally changed how we architect web applications. We are now defaulting to server-side rendering, which is fantastic for performance, SEO, and initial load times. However, a common friction point arises when we need to inject high-frequency, bidirectional realtime data into these server-rendered pages. Too often, developers fall into the trap of importing heavy socket libraries directly into their server components or wrapping their entire application in massive context providers, effectively bloating the client bundle and negating the performance gains of the App Router. The Solution: The "Client Island" Pattern Instead of fighting the architecture, we can embrace "Client Islands"—a pattern where we isolate the stateful, client-side logic into a tiny, focused leaf component. By keeping the WebSocket management strictly client-side, we ensure that our server-rendered pages remain lightweight, fast, and cacheable. Implementing the WebSocket Island The goal is to keep the WebSocket connection lifecycle outside of the rendering flow. We utilize useEffect to manage the connection, ensuring it only runs on the client, and we tap into data fetching libraries like TanStack Query or SWR to surgically update the UI. ' use client ' ; import { useEffect } from ' react ' ; import { useQueryClient } from ' @tanstack/react-query ' ; export function RealtimeSync ({ token }) { const queryClient = useQueryClient (); useEffect (() => { const ws = new WebSocket ( `wss://realtime.example.com?token= ${ token } ` ); ws . onmessage = ( event ) => { const data = JSON . parse ( event . data ); queryClient . setQueryData ([ ' items ' ], data ); }; return () => ws . close (); }, [ token , queryClient ]); return null ; // This component renders nothing, just manages the side effect } Persistence via RootLayout To prevent the connection from dropp

2026-09-01 原文 →
AI 资讯

Why I Call Myself a Full-Stack Developer (Not Just Frontend or Backend)

A lot of developers pick a lane early — frontend or backend — and stay there. I never did, and building ClientIQ is a good example of why. The problem Freelancers waste a lot of time figuring out where to post their skills. Upwork? Fiverr? Toptal? The right platform depends on their profile, their niche, and their experience — and most people just guess. I wanted to build something that could actually recommend the right platform based on real data, not gut feeling. Why this needed a full-stack developer, not two specialists This is where being a full-stack developer actually mattered: The backend needed a Flask API that could take a freelancer's profile data and run it through a multi-model machine learning workflow to generate a recommendation. The frontend needed a clean React interface where users could input their info and see the recommendation in a way that made sense — not just a raw JSON response. The connection between them — API design, request/response shape, error handling — needed someone who understood both sides well enough to make them work together smoothly, not just "talk" to each other. If I had only known React, I'd have needed someone else to build and explain the ML backend to me. If I had only known Flask, the interface would have been an afterthought. Being full-stack meant I could design the whole system as one coherent product, not two separate halves duct-taped together. What I actually built A Flask API that serves multi-model ML predictions A React frontend for input and displaying recommendations A clean handoff between the two — the kind of detail that's invisible when done right, and painfully obvious when it's not The bigger lesson Full-stack development isn't about knowing a little bit of everything. It's about being able to see a product end-to-end and make decisions that make sense for the whole thing — not just your favorite part of the stack. That's the mindset I bring to every project, whether it's a web app, a mobile app, or

2026-09-01 原文 →
AI 资讯

I Built 50+ AI Products in 4 Years — Here's What I Wish I Knew at the Start

Since 2021, our team at Autor has shipped over 50 AI products across healthcare, fintech, logistics, and SaaS. Some of them are running in production right now, handling thousands of automated calls per month. Others failed spectacularly — and those are the ones that taught us the most. Where This Comes From I started Autor in Toronto as a one-person AI development shop. The original thesis was simple: companies needed custom AI but couldn't hire fast enough to build it themselves. Four years and 50+ products later, we're a senior-only studio with a production voice AI platform (Loquent) serving healthcare and dental clients 24/7. Along the way, we've impacted over 5 million users, helped clients raise more than $10 million in funding, and shipped across 10+ countries. This isn't a highlight reel. This is the unvarnished list of things I got wrong, figured out the hard way, or wish someone had told me before I wrote my first line of production AI code. 1. Your First AI Product Should Be Boring Our first few products were ambitious. Multi-modal pipelines, complex reasoning chains, novel architectures. Most of them took twice as long as estimated and required constant babysitting in production. The products that actually made money and kept clients happy? A straightforward document classifier. A simple intent router. A basic FAQ bot with good fallback logic. I used to think "boring" meant "not innovative." Now I know boring means "reliable enough that I don't get paged at 3am." Our most successful product, Loquent, handles healthcare scheduling calls. It's not doing anything architecturally exotic. It picks up the phone, understands what the caller needs, books or reschedules an appointment, and hangs up. The magic isn't in the model — it's in the 200+ edge cases we've handled around it. If you're building your first AI product, pick the most boring version of your idea and ship that. You can add complexity later. You cannot add reliability later. 2. Prompt Engineerin

2026-09-01 原文 →
AI 资讯

We Tested 100 eBay Sold-Comp Searches. 37.9% of Rows Were Filtered Out

A raw sold-listings search is not automatically a usable comp set. Search for a phone and you may also get cases, chargers, broken screens, empty boxes, and nearby models. Search for a camera lens and you may get caps, adapters, or a different focal length. If those rows go directly into a median, the result can describe the search noise instead of the product. I wanted a larger measurement than a single convenient example, so I ran a fixed 100-product study through CompSniper, the sold-price API I own. The goal was not to prove that an automated classifier is always correct. The goal was narrower: Measure what the production relevance cleaner removed and how the product-level median changed on one predeclared sample. The protocol I selected the products before making the first request: 20 smartphones and tablets 20 gaming and computing products 20 cameras and lenses 20 audio and music products 20 collectibles and luxury products Every search used the same settings: Marketplace: ebay.com Sold window: 2026-06-02 through 2026-08-31 Page: 1 Requested rows: 240 Sort: ended recently Condition: any Relevance cleaning: enabled Each relevance-enabled response contained the raw sample count and raw median captured before classification, followed by the cleaned rows and deterministic price summary from the same fetched page. That meant one production request per product, not separate raw and cleaned fetches. All 100 requests succeeded with unique request IDs. The headline results Across the study: 19,220 priced raw rows were parsed 11,942 priced rows remained after cleaning 7,278 rows were classified out The weighted removal rate was 37.87% 34 of 100 product medians changed by at least 10% 15 of 100 changed by at least 25% 11 of 100 changed by at least 50% The direction was not always upward: 73 medians increased 21 medians decreased 6 medians stayed unchanged That is important. The cleaner is not instructed to raise prices. It tries to retain listings for the requested produ

2026-09-01 原文 →
AI 资讯

How I tested Row Level Security before shipping a SaaS starter kit (so one user can't see another's data)

When you're building a multi-tenant app, there's one bug category that's worse than any other: a user seeing someone else's data. Not a crash, not a broken button — a genuine privacy failure. I recently built a Next.js + Supabase + Stripe starter kit, and before I'd call the database layer "done," I wanted to actually prove the security held, not just assume it did because the code looked right. The setup Supabase's Row Level Security (RLS) lets you write policies directly in Postgres that filter rows based on who's asking — the database itself becomes the security boundary, not just your application code. That's powerful, but it also means a single wrong policy (or a missing one) silently exposes everything. Here's the policy pattern I used for an owner-scoped table: create policy "projects: owner reads" on public . projects for select to authenticated using (( select auth . uid ()) = owner_id ); Simple enough. But "simple enough" is exactly the kind of thing worth verifying rather than trusting. The actual test Rather than just trusting the policy, I ran an impersonation test directly in the SQL editor: begin ; set local role authenticated ; set local request . jwt . claims = '{"sub":"<a-real-user-id>"}' ; select id , name from public . projects ; rollback ; This temporarily pretends to be a specific user (inside a transaction that touches nothing) and asks: what can this user actually see? Run it with the real owner's ID — you get their rows. Run it with a fake or different user's ID — you should get zero rows back, not an error. That's the key detail: RLS filters rows out silently rather than throwing a permission error, so "nothing happened" is actually the success signal, not a bug. I did the same check for writes — attempting to delete another user's row from a different account's session, confirming it returns 0 rows affected rather than either succeeding or throwing. Why this matters more than it seems It's easy to write an RLS policy that looks right and s

2026-09-01 原文 →