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

标签:#web

找到 1693 篇相关文章

AI 资讯

Link or Button, that is the question.

What is a Link? Definition A link is an interactive element that redirects the user to a new location which can be another section inside the current page, modifying the URL with a # parameter, or a new page. It can be used to download a file. Once activated, it takes the user to the URL set in its href. The browser records that navigation in its history, so the user can return to the previous page using the back button. Semantic The elements needs the attribute href with a valid URL or an IDREF pointing to a section inside the current page to have the semantic value of a link, otherwise it will be considered as generic . <a href= "/URL" > Go to main page </a> Keyboard Interaction It can only be activated by pressing the key Enter . If the key Space is pressed while the focus is on the link, the page will scroll down. Screen Reader Interaction Screen Readers, generally, announce the links in the following way: Link, [accessible name of the link] . It is extremely important to provide a descriptive and correct accessible name to the element. Bad Practice It is completely unnaceptable, a bad practice and goes against the native behavior of the element, forcing it to behave as a button by doing the following: <a href= "javascript:void(0)" onclick= "openModal()" > Open Menu </a> <a href= "#" role= "button" onclick= "button()" > Link with role button </a> If you need to do this, it means that you need a link. What is a button? Definition A button is an interactive element that dispatches an action inside the page where it is located. It does not redirect the user to another place or location nor modifies the url. The actions that are being dispatched can be: open a modal, play a video, post a comment, etc. Semantic The button needs the attribute type with a value according to its action: - type="button" : it is used when the button does not have a default behavior. - type="submit" : it is used when the button sends information to a server. - type="reset" : it is used to

2026-06-22 原文 →
开发者

Enlace o botón, esa es la cuestión

¿Qué es un enlace? Definición Un link/enlace/elemento ancla es un elemento interactivo que redirecciona al usuario a una nueva ubicación la cual puede ser una página diferente, una ubicación distinta en la misma página (se modifica el URL en ese caso con un parametro # ) o también se puede utilizar para descagar un archivo, entre otras cosas. Al activarse, lleva al usuario a la URL definida en su href. El navegador guarda esa navegación en su historial, de modo que el usuario puede volver a la página anterior. Semántica Para que el elemento tenga carga semántica de elemento interactivo, tiene que si o si tener un atributo href con una URL válida o un IDREF que apunte a un elemento en la misma página, de lo contrario va a ser tratado como un elemento genérico . <a href= "/URL" > Ir a la página principal </a> Interacción con el teclado Solo se puede activar con la tecla Enter . Si se presiona la tecla Space mientras el foco esta en el enlace, la página va a scrollear hacia abajo. Interacción con lectores de pantalla Los lectores de pantalla, generalmente, anuncian el elemento de la siguiente manera: "Enlace, [Nombre accessible del enlace]" por lo cual es importante que el enlace tenga un nombre accesible pertinente y descriptivo. Malas prácticas Es totalmente inaceptable, una mala práctica y va en contra del funcionamiento nativo del elemento, forzar a un enlace a comportarse como un botón de la siguiente manera: <a href= "javascript:void(0)" onclick= "openModal()" > Abrir menu </a> <a href= "#" role= "button" onclick= "boton()" > Enlace con rol botón </a> Si necesitas hacerlo, quiere decir que necesitas un botón ¿Qué es un botón? Definición Un botón es un elemento interactivo que al ser cliqueado ejecuta una acción dentro de la página donde se encuentra. NO redirige al usuario a otro lugar, ni modifica la URL. Las acciones ejecutadas pueden ser abrir un modal, reproducir un vídeo, publicar un comentario, etc. Semántica El botón necesita el atributo type según la acci

2026-06-22 原文 →
AI 资讯

How to Reduced Load Time From 5 Seconds to 1 Second

The Problem: How Website Slow Performance Costs Businesses Revenue A slow website doesn't just frustrate users it actively costs businesses money. Every additional second of load time causes visitors to leave, damages your search engine rankings and directly reduces conversions. Research shows that pages taking 5 seconds to load have a bounce rate 75% higher than pages loading in 1 second. For e-commerce sites, this translates to thousands of dollars in lost sales monthly. Recently, we worked with a client experiencing exactly this problem. Their website averaged 5-second load times, resulting in high bounce rates, poor mobile performance and declining search visibility. They needed immediate action. The Initial Audit: Identifying Website Speed Bottlenecks Before implementing solutions, we performed a comprehensive website audit using industry-standard tools like Google PageSpeed Insights, GTmetrix and WebPageTest. Step 1: Image Optimization – The Biggest Win Images typically account for 50-80% of page weight. Optimizing images delivered the most dramatic performance improvements. What to do: Converted to Modern Formats – We converted all PNG and JPEG files to WebP format, which provides 25-35% better compression than traditional formats while maintaining visual quality. Aggressive Compression – Images were compressed using lossless and lossy techniques without perceptible quality loss to users. Implemented Lazy Loading – Below-the-fold images were set to load only when users scrolled near them, not on initial page load. Responsive Images – Different image sizes were served based on device screen size, so mobile users didn't download desktop-sized images. Step 2: Minifying and Deferring Code – Eliminating Render-Blocking Resources JavaScript and CSS files were creating significant render-blocking bottlenecks. What to do: Minified CSS and JavaScript – Removed unnecessary characters (spaces, comments, line breaks) from all CSS and JavaScript files. Removed Unused Code

2026-06-22 原文 →
AI 资讯

We built a free status monitor for 77 AI APIs. Here's what 6 weeks of data taught us.

Every AI developer has been here: your app is throwing 503s, users are pinging you, and you have 12 browser tabs open — OpenAI status page, Anthropic status page, the GitHub Copilot health page, three different Discord servers — trying to figure out is this me or is it them? That's the problem we set out to solve. Prismix aggregates status from 77 AI services in one place. Six weeks of running it in production taught us some things that might save you time. The problem is worse than you think AI APIs don't fail like traditional infrastructure. They fail in weird, partial ways: Degraded performance that passes your health checks but makes your product feel broken Regional outages — OpenAI US-East is down while EU is fine, so half your users are affected Silent rate-limit cascades — the API returns 429s but their status page says "operational" for another 20 minutes Incident lag — providers often post status updates 10–30 minutes after engineers are already aware The official status pages are optimistic by design. They're customer-facing communications tools, not real-time engineering dashboards. There's nothing wrong with this — but it means you need a different mental model for "is this service down?" What 77 status pages look like in aggregate When you watch 77 AI services simultaneously, patterns emerge fast. OpenAI is the most-watched service (and has the most incidents to watch). The pattern is almost always the same: investigating → identified → monitoring → resolved , typically in 45–90 minutes. The investigating phase is where most developers panic — it looks bad but usually resolves without action on your end. Anthropic runs noticeably clean compared to its API usage growth. Incidents are rarer and shorter. When they do happen, updates arrive faster than most providers. The long tail is interesting. Services like Replicate, Runway, ElevenLabs, and Suno have incident patterns that don't correlate with OpenAI at all. If you're routing across multiple providers

2026-06-22 原文 →
AI 资讯

I Built a Tool to Track Which World Cup Players Are Blowing Up on Social Media

Every World Cup there's a moment. Some player nobody outside their domestic league had heard of scores an absolute screamer in a knockout match, and by the time they've finished celebrating, their follower count is climbing like a rocket. I always found that fascinating, but I could never see it happening. By the time the "X gained 3M followers!" tweets show up, the surge is already over. So this tournament I built a little tracker that snapshots player follower counts on a schedule and shows me the growth curve in near real-time. Here's how it works. The problem with doing this "properly" My first instinct was the official APIs. That died fast. Instagram's Graph API won't give you follower counts for accounts you don't own. TikTok's Research API is academics-only and takes weeks of applications. X's API now starts at $100/month and climbs steeply from there. I just wanted public follower counts — numbers anyone can see by opening the app. I didn't want a data partnership and a legal review. I ended up using the SociaVault API , which wraps public profile data from each platform behind one key. One request, one credit, JSON back. The shared client Everything runs through one tiny helper: // Node 18+ has fetch built in const API_KEY = process . env . SOCIAVAULT_API_KEY ; const BASE = " https://api.sociavault.com " ; async function sv ( path , params ) { const url = new URL ( BASE + path ); Object . entries ( params ). forEach (([ k , v ]) => url . searchParams . set ( k , v )); const res = await fetch ( url , { headers : { " X-API-Key " : API_KEY } }); if ( ! res . ok ) throw new Error ( ` ${ res . status } ${ await res . text ()} ` ); return res . json (); } Grabbing follower counts across platforms Each platform nests the count slightly differently, so I use fallback chains to stay defensive: async function instagramFollowers ( username ) { const data = await sv ( " /v1/scrape/instagram/profile " , { username }); const p = data . data ?. user ?? data . data ?? data

2026-06-22 原文 →
AI 资讯

Diff Checker: a small tool that solves a specific problem

Code reviews, configuration changes, and debugging sessions demand precise understanding of what changed between two versions of text. Manual comparison of large blocks of code or configuration files is error-prone, and version control diffs don’t always provide a quick, focused view for sharing or verifying changes outside a repository. What it is Diff Checker is a browser-based text comparison tool that performs line-by-line analysis of two text blocks and highlights differences with color-coded visual indicators. It processes text entirely in the browser—part of the 200+ free tools on DevTools—meaning no data is uploaded or stored, a privacy‑first design. The interface uses a split‑pane layout: original text on the left, modified text on the right. As you paste or type, the comparison engine recalculates the diff in real time, marking added, removed, and changed segments so differences are immediately clear. Several configuration options tailor the analysis. Toggling whitespace sensitivity ignores differences in indentation or blank lines, useful when comparing code from teams with different formatting conventions. Case sensitivity can be turned off for text where capitalization inconsistencies are irrelevant. A swap button reverses the comparison direction with a single click, handy when the assignment of “original” and “modified” is accidentally reversed. How to use it Paste the original text into the left panel and the modified version into the right panel. The diff view updates instantly, so you don’t need to press a button to see changes. For code, the process is straightforward. Drop a baseline function on the left: function calculateTotal ( items ) { let total = 0 ; for ( let item of items ) { total += item . price ; } return total ; } And the updated version on the right: function calculateTotal ( items , taxRate = 0 ) { let total = 0 ; for ( let item of items ) { total += item . price * ( 1 + taxRate ); } return Math . round ( total * 100 ) / 100 ; } The

2026-06-22 原文 →
AI 资讯

Lorem Ipsum Generator: a small tool that solves a specific problem

Placeholder text is necessary scaffolding in web development, but ubiquitous Lorem ipsum can lead to design monotony and disconnect from project context. Developers building mockups, prototypes, or content-heavy interfaces often need filler text that matches the tone of the target application without introducing distracting Latin. What it is The Lorem Ipsum Generator is a browser-based tool that produces placeholder text in multiple styles, moving beyond classical Latin pseudo-text. It offers distinct variants: traditional Lorem ipsum, Hipster Ipsum with artisanal terminology, Corporate Speak filled with business jargon, and Pirate Ipsum with nautical themes. Each style maintains readability while providing vocabulary that aligns with the spirit of a given project. The generator is part of DevTools, a privacy-first collection of 200+ free browser tools where all processing happens locally—no signup, no tracking. Developers can configure generation parameters to specify the number of paragraphs, total word count, and whether to start with the familiar “Lorem ipsum dolor sit amet” opening. The output is plain text ready for pasting into HTML, design files, or CMS entries. How to use it The interface is a straightforward form: select a text style from the dropdown, then set the number of paragraphs or words you need. The tool generates the text instantly and provides a one-click copy button. <!-- Example output structure when pasting into HTML --> <div class= "content-area" > <p> Leverage agile frameworks to provide a robust synopsis for high level overviews... </p> <p> Iterative approaches to corporate strategy foster collaborative thinking... </p> </div> For typical workflows, 1–3 paragraphs suffice for article previews or body content. Headlines work well with 5–15 words, while navigation elements often need only 2–5 words. The quick copy functionality streamlines populating multiple content areas. Different styles suit different contexts: Corporate Speak makes busi

2026-06-22 原文 →
AI 资讯

Why My RAG App Kept Hallucinating (and How I Fixed It)

A few months ago I was demoing my RAG-powered support bot to a colleague, feeling pretty confident about it. Then it confidently told her our refund policy was “30 days, no questions asked.” Our actual policy is 14 days, with conditions. The bot didn’t hedge. It didn’t say “I’m not sure.” It just made it up and said it with the same calm tone it uses for everything else. That demo stung. RAG was supposed to fix hallucinations, not just relocate them. Here’s what I learned debugging it, roughly in the order I learned it. 1. My chunks were too big, and too dumb I was splitting documents by character count, 1000 chars with slight overlap. It felt efficient. It wasn’t. A single chunk often contained unrelated sections. For example, the end of a “Shipping Policy” and the start of a “Returns Policy” could sit together in the same block. So when the retriever saw a query about returns, it would grab that chunk and the model would blend both sections into one confident but wrong answer. Fix: I switched to semantic chunking based on headings and paragraphs instead of raw character limits. More work upfront, but it stopped feeding the model Frankenstein context. 2. I trusted top-k similarity way too much My retriever was pulling the top 3 chunks by cosine similarity and passing them straight into the prompt. The problem: “similar” is not the same as “relevant.” A chunk can be semantically close to the query but still not actually contain the answer. The model doesn’t know that, it just assumes everything in context is true. Fix: I added a reranking step using a cross-encoder and started logging retrieval scores properly. That alone made it obvious when the system had no real answer but was still trying to act confident. 3. I never told the model it was allowed to say “I don’t know” My prompt was basically: “Use the context to answer the question.” That’s it. No instruction on what to do when the context is insufficient. So the model did what LLMs do when under-specified: it f

2026-06-22 原文 →
AI 资讯

Understanding the Software Development Process: A Complete Guide from Concept to Deployment

Software has become the backbone of modern business operations, powering everything from customer-facing applications and e-commerce platforms to enterprise systems and cloud-based services. Behind every successful software product is a well-structured development process designed to ensure quality, scalability, security, and long-term maintainability. The Software Development Process, commonly referred to as the Software Development Life Cycle (SDLC), provides a systematic framework for transforming ideas into reliable software solutions. By following a defined methodology, organizations can reduce risks, optimize resources, improve collaboration, and deliver products that align with business objectives. This article explores the key stages of the software development process and highlights why each phase is essential to successful project delivery. What Is the Software Development Process? The software development process is a structured sequence of activities involved in designing, building, testing, deploying, and maintaining software applications. It serves as a roadmap that guides development teams from initial requirements gathering to ongoing support after deployment. A well-defined development process helps organizations: Improve project predictability and delivery timelines Reduce development and maintenance costs Enhance software quality and reliability Strengthen security and compliance Increase customer satisfaction Facilitate collaboration across teams Whether developing a small business application or a large-scale enterprise platform, a structured process is critical for achieving sustainable success. _ Phase 1: Requirements Gathering and Analysis_ Every successful software project begins with a clear understanding of business needs and user expectations. During this phase, stakeholders, business analysts, project managers, and development teams collaborate to identify: Business objectives Functional requirements Non-functional requirements User expe

2026-06-22 原文 →
AI 资讯

Browser Scroll Restoration Is Broken on SPAs. Here's How a Chrome Extension Fixes It.

Chrome has had scroll restoration support since 2015. You can even control it: history.scrollRestoration = 'manual' . But if you've ever tried to reliably restore a user's position on a React or Next.js app, you know it doesn't work the way you'd expect. Here's what breaks, why it breaks, and how a browser extension can sidestep the entire problem. What the Browser Actually Does The default behavior is history.scrollRestoration = 'auto' . When you navigate back to a page, the browser tries to scroll to where you were. This works fine for static pages. It falls apart for: SPAs where content is injected into the DOM after navigation Infinite scroll pages where the content at a given Y position changes depending on what was previously loaded Lazy-loaded images that push content down after the scroll restore fires The fundamental problem: the browser fires scroll restoration when the page HTML is parsed, not when the page content is fully rendered. A React app that loads a skeleton → fetches data → renders actual content will restore scroll into a partially-rendered DOM. The history.scrollRestoration = 'manual' Trap If you set manual , you own scroll restoration completely. Most Next.js apps do this. The typical approach: // Save position before navigation router . beforeEach (( to , from ) => { savedPositions [ from . path ] = window . scrollY ; }); // Restore after navigation router . afterEach (( to ) => { const position = savedPositions [ to . path ]; if ( position !== undefined ) { nextTick (() => window . scrollTo ( 0 , position )); } }); The nextTick is the problem. It fires after the Vue/React render cycle, but before async data fetching completes. The page renders empty containers, scroll restores to Y=800, then data loads and pushes everything down. User ends up at Y=800 in a now-different page position. The correct fix is to wait until the content that was at Y=800 actually exists. There's no clean hook for this — you'd need to observe the DOM until the expec

2026-06-22 原文 →
AI 资讯

5 Cookie Tricks for Debugging Auth Issues in Chrome (No More Creating Test Accounts)

Debugging authentication in web apps is painful. You need to test the same flow as five different user types — new visitor, returning user, admin, expired session, logged-out — and the easiest way is to constantly create new accounts or clear all your cookies and start over. There's a faster way. These five techniques use direct cookie manipulation to simulate any auth state without touching your database or creating dummy accounts. I use CookieJar for most of this — a free Chrome extension built natively on MV3 that gives you a proper UI for cookie editing. But I'll show you the underlying Chrome DevTools method too, so you understand what's actually happening. 1. Simulate a Logged-Out State Without Clearing Everything The naive approach: clear all cookies and reload. The problem: you just nuked your dev server session token, your local storage flags, your Stripe test mode cookie, and everything else you carefully set up. The targeted approach : identify and delete only the session/auth cookie. Most session cookies are named session , sid , auth_token , _session_id , or something close. In DevTools: Application → Cookies → [your domain] → find the session cookie → right-click → Delete With CookieJar: open the extension, search session , click the trash icon next to just that cookie. Your dev environment stays intact. The user state resets to logged-out. 2. Test the "Returning User" vs "New User" Path Without a Second Account Session cookies tell the server you're authenticated. But many apps use separate cookies to track whether a user has seen the onboarding flow, completed setup, or visited before. Look for cookies like onboarding_complete , setup_done , first_visit , or custom flags in your app code. To test the new user experience: Export your current cookies (CookieJar → Export → JSON format, or copy from DevTools) Delete the specific onboarding/first-visit flag cookie Reload and test the new user path Re-import or re-set the cookie to restore your state This

2026-06-22 原文 →
AI 资讯

The Invisible Duct Tape of the Internet: Backend Tools You Hear About But Never Fully Get

Hi 👋 fellow devs Sorry for such a big gap since my last article...... Life got a bit hectic, but I am finally back in action! You know how it goes. We spend so much of our energy obsessing over the flashy side of tech. We talk about gorgeous UI designs, smooth animations, and whatever frontend framework is trending on GitHub this week. But let’s be completely real for a second. What actually keeps your favorite apps from melting down when millions of people hit the refresh button at the exact same moment? That is exactly what we are going to unpack today. We are pulling back the curtain on the quiet, brilliant backstage crew of infrastructure tools. You see their logos all over tech Twitter and hear senior engineers drop their names in meetings like secret handshakes, but today, we are stripping away the corporate fluff. We will break down eight legendary backend technologies using conversational paragraphs and quick bullet points so you can finally master what they actually do. Let’s dive right in. 1. Redis Traditional databases live on hard drives. They are fantastic for keeping your data safe and organized permanently, but pulling data off a physical drive takes time. If your application has to wander deep into those database aisles to fetch the exact same piece of information every single second, your entire system starts to stall. To understand how Redis fixes this, imagine you are studying for a brutal exam. Your massive, 1,000-page textbook represents your main database. It holds every single answer, but flipping through the pages continuously is incredibly slow. Redis is the digital equivalent of writing the core formulas you need on a neon sticky note and taping it directly to your monitor. It keeps critical data sitting directly inside the system's lightning-fast short-term memory. You will typically find Redis stepping in to handle operations like: Session Management: Keeping users logged into an application without checking the main database on every cli

2026-06-22 原文 →
AI 资讯

Optimizing Django ORM Queries: A Practical Guide to select_related and prefetch_related

1. Introduction Django's ORM is one of its greatest strengths. It abstracts away raw SQL, lets you express database operations in clean Python, and gets you productive fast. But that convenience comes with a hidden cost: if you're not deliberate about how you fetch related objects, you'll silently generate far more queries than you intend — and you won't notice until your app slows to a crawl in production. The most common culprit is the N+1 query problem : a pattern where fetching a list of N objects triggers an additional query for each one, resulting in N+1 total round-trips to the database. At ten rows it's invisible. At ten thousand rows, it's a disaster. Django provides two tools to fix this: select_related and prefetch_related . This article explains how each one works internally, when to use which, and how to combine them effectively — with before/after examples and real query counts throughout. 2. Understanding the N+1 Problem Consider a simple blog with posts and authors. You want to render a list of posts, showing each post's title and its author's name. Models: # models.py from django.db import models class Author ( models . Model ): name : str = models . CharField ( max_length = 100 ) class Post ( models . Model ): title : " str = models.CharField(max_length=200) " author : Author = models . ForeignKey ( Author , on_delete = models . CASCADE , related_name = " posts " , ) The naive approach: # views.py from django.db import connection from .models import Post def list_posts () -> None : posts = Post . objects . all () # Query 1: fetch all posts for post in posts : print ( f " { post . title } by { post . author . name } " ) # ^^^ Query 2, 3, 4, ... N+1: one per post For 100 posts, this produces 101 queries . Django lazily fetches post.author the first time you access it on each object. Each access hits the database separately. You can verify this with django.db.connection.queries (requires DEBUG = True ): from django.db import connection , reset_queries

2026-06-22 原文 →
AI 资讯

Stop polling: real-time email and calendar webhooks with Nylas

If your integration polls Nylas every minute to check for new email, you're doing too much work and still getting stale data. Polling is a tax: you burn rate limit on requests that mostly return nothing, and a message that arrives at 12:00:05 doesn't reach your app until the next poll. Webhooks flip that around. Nylas pushes a notification to your endpoint the moment something happens — a message arrives, an event changes, a contact is created — and your app reacts in real time. This post walks the webhook surface from both sides: the HTTP API that registers and manages webhooks, and the Nylas CLI , which has genuinely useful tooling for the part everyone gets stuck on — verifying signatures and testing webhooks against local code. I work on the CLI, so the terminal commands below are the ones I run when I'm wiring up a webhook receiver. Triggers and destinations A webhook has two halves: the trigger types it listens for and the destination URL it pushes to. Trigger types are dotted event names like message.created , event.updated , and contact.created , grouped into categories — grant, message, thread, event, contact, calendar, folder, and notetaker. You subscribe one destination to as many triggers as you want. The CLI lists every available trigger so you don't have to guess the names: # All trigger types nylas webhook triggers # Only message-related triggers nylas webhook triggers --category message Webhooks are application-scoped, not grant-scoped: one webhook registered on your application receives notifications for every connected account, identified by the grant_id in each payload. See the notifications overview for the full event model. Before you begin You need a Nylas API key — webhook management is admin-level, so it uses the application's API key rather than a grant. You also need an HTTPS endpoint reachable from the public internet to receive the notifications. The CLI gets the key set up: nylas init # create an account, generate an API key For local de

2026-06-22 原文 →
AI 资讯

Kinde Is Missing from Mastra's Auth Lineup, So I Built the Provider

If you're building a SaaS AI agent product and you're already on Kinde, you already know the problem. Mastra is the TypeScript-first AI agent framework. It ships with official auth providers for Clerk, Auth0, Supabase, Firebase, WorkOS, and Better Auth. Kinde is not on that list. The obvious question is why not reach for one of those providers, since Auth0 is already there. Most developers who choose Kinde rely on far more than its login. Kinde ships with the organizational structures, permission systems, and monetization tools that products actually need, bringing auth, billing, feature flags, and multi-tenancy together in one platform. If you're building a B2B SaaS product on Kinde, you're using Kinde orgs to segment your customers, Kinde billing to manage subscriptions, and Kinde feature flags to gate features by plan. Switching to Auth0 or Clerk to support a Mastra agent would mean rebuilding all of that elsewhere, which is not a real option. That gap is the problem. You need Kinde to work with Mastra, and until now there was no clean way to connect them. That's why I built mastra-auth-kinde . What Mastra's auth system actually does When you add an auth provider to Mastra, it protects two things at once: all your API routes ( /api/agents/* , /api/workflows/* , and so on) and your Mastra Studio UI. Every request to a protected route goes through your provider before it reaches anything else. You extend Mastra's MastraAuthProvider base class and implement two methods: authenticateToken(token, request) verifies the JWT and returns the decoded user, or null if it fails authorizeUser(user, request) returns true to let the request through, or false for a 403 Mastra handles everything else: extracting the Bearer token from the Authorization header, calling your methods in order, and storing the verified user in the request context so your agents and tools can access it. Why Kinde specifically Beyond the billing and org story above, a few things make Kinde the right fit

2026-06-22 原文 →
AI 资讯

Building Margin: A Privacy-First News Reader Inside Chrome's Side Panel

I built a Chrome extension called Margin — a news reader that lives in the browser's side panel and shows one bite-sized story at a time, instead of an infinite-scroll feed. This is a build log: the decisions, the constraints that pushed back, and a couple of things I had to solve in slightly unusual ways. Why the side panel Chrome shipped chrome.sidePanel in MV3 a while back and most uses I saw were utility tools — note-taking, translation helpers. Nobody was using it for content consumption. News felt like a good fit: a side panel that stays open next to whatever you're working on, where you tap through headlines in a couple of minutes without leaving the page. The reading model is intentionally narrow: one card, one headline, one short summary, tap to read the full article at the source . No infinite scroll, no algorithmic feed. If you've used InShorts, the shape will be familiar. The stack Preact + Vite + @crxjs/vite-plugin . Preact because the side panel is a small UI surface and I didn't want React's weight for what's essentially a card stack and a settings screen. @crxjs/vite-plugin handles the MV3-specific build wiring (manifest generation, service worker loader, HMR for the extension context) that would otherwise be a lot of manual plumbing. The constraint that shaped onboarding chrome.sidePanel.open() requires a user gesture . You cannot call it from a background service worker on install — Chrome will throw. That one constraint shaped the whole first-run experience. My first instinct was "just auto-open the panel on install so people see it immediately." Doesn't work. The fix ended up being two-pronged: On chrome.runtime.onInstalled with reason === 'install' , open a real browser tab with a short walkthrough (find the icon → pin it → open the panel). The button on that page calls sidePanel.open() — valid, because the click is the gesture. The first time the panel itself is opened, show an in-panel welcome screen before onboarding, nudging the user to pin

2026-06-22 原文 →
AI 资讯

Precision Loss and Rounding Exploits in Financial Smart Contracts

A smart contract does not need an overflow, reentrancy bug, or broken access-control check to lose money. Sometimes, the exploit is hidden inside an ordinary division: uint256 result = amount * rate / SCALE; The expression looks harmless. It may even produce the expected answer in every unit test. But financial smart contracts operate with integer arithmetic. Fractions are discarded, rounding direction changes who receives value, and an error of one unit can be repeated across thousands of transactions. In a financial protocol, rounding is not merely a mathematical implementation detail. Rounding is a value-transfer policy. Every division should therefore answer three questions: Which direction does the calculation round? Which party benefits from that direction? Can the rounding advantage be repeated or amplified? This article examines the most dangerous precision problems in Solidity and the engineering patterns used to prevent them. Solidity Does Not Have Native Fixed-Point Arithmetic Most financial formulas use fractions: interest = principal × rate × time fee = amount × fee percentage shares = assets × total shares ÷ total assets collateral value = token amount × oracle price Solidity primarily performs these calculations with integers. For unsigned integers: uint256 result = 5 / 2; The result is: 2 The fractional component is discarded. For positive values, this behaves like rounding down: 2.5 → 2 This appears insignificant until the result represents: vault shares; debt; collateral; protocol fees; interest; rewards; liquidation bonuses; exchange rates; token prices. The lost fraction does not disappear economically. One party receives less value, while another party retains the remainder. Precision Loss Is Not Always Small Consider a protocol calculating a percentage: function calculateFee( uint256 amount, uint256 feeBps ) public pure returns (uint256) { return amount * feeBps / 10_000; } For a 0.3% fee: amount = 100 feeBps = 30 fee = 100 × 30 ÷ 10,000 fee =

2026-06-22 原文 →
开源项目

Setting up socket.io

This article covers what I learned or maybe didn't really learn. The Problem With Traditional HTTP Most web applications use HTTP. The flow looks like this: Client → Request → Server Client ← Response ← Server Once the server sends the response, the connection is closed. This works perfectly for: Authentication CRUD operations Fetching data Form submissions But what happens when the server needs to send information without being asked? For example: A new task is assigned Someone comments on a task A project status changes A teammate updates a board With traditional HTTP, the browser would need to keep asking: "Anything new?" "Anything new?" "Anything new?" This technique is called polling, and it's inefficient. That's where Socket.io comes in. What Socket.io Actually Does Socket.io creates a persistent connection between the client and server. Instead of repeatedly opening and closing connections, the connection stays alive. Now communication becomes two-way: Client ↔ Server The client can send data whenever it wants. The server can also send data whenever it wants. This is what makes real-time applications possible. Why Express Alone Isn't Enough One thing that confused me initially was why Socket.io couldn't simply be attached directly to my Express app. The answer lies in how Express works. When you write: app . listen ( 5000 ); Express creates the HTTP server internally. You don't have direct access to it. Socket.io, however, needs access to the raw HTTP server. So instead of: app . listen ( PORT ); The flow becomes: const httpServer = createServer ( app ); Then Socket.io attaches to that server: const io = new Server ( httpServer ); Finally: httpServer . listen ( PORT ); This architecture allows Socket.io and Express to share the same server. Understanding Events Socket.io is event-driven. Everything revolves around two methods: socket . emit () and socket . on () Think of them as: emit = send on = listen For example: Client: socket . emit ( " join-project " ,

2026-06-22 原文 →