AI 资讯
Designing Upload Expiration as a Recoverable State
Signed upload sessions expire. Event contribution windows close. Storage reservations are reclaimed. These are normal lifecycle events, but many interfaces reduce all of them to “Upload failed.” A better protocol makes expiration explicit and recoverable where policy allows it. Distinguish three clocks An upload workflow usually has at least three deadlines: the event contribution window; the server-side upload intent expiry; the short-lived storage credential expiry. They should not share one timestamp. The event may accept contributions until midnight while a credential lasts five minutes and an intent can be renewed for an hour. Return the clocks in the session response with server time: { "serverNow" : "2026-07-17T18:00:00Z" , "eventClosesAt" : "2026-07-18T00:00:00Z" , "intentExpiresAt" : "2026-07-17T19:00:00Z" , "credentialExpiresAt" : "2026-07-17T18:05:00Z" } The client can display useful warnings without trusting its own clock for authorization. Model expiration by state A credential expiring during transfer is different from an intent expiring before completion. Use stable reasons: credential_expired -> request renewal intent_expired -> reconcile committed parts, then renew or restart event_closed -> stop new work, preserve local recovery guidance Do not automatically restart from byte zero. First ask the control plane which parts were committed and whether the original object key remains valid. Renew narrowly A renewal endpoint should accept the upload ID and prove continuity with the guest session. It rechecks event state, file policy, rate limits, and committed size. The response returns a new credential for the same object. Do not let the browser extend an intent indefinitely. Define a maximum session age and a bounded number of renewals. Long uploads may receive a larger initial policy based on file size and observed throughput. Handle the closing boundary fairly Decide what happens to an upload already transferring when the event window closes. Reasona
AI 资讯
Memory-Safe Media Preflight in Mobile Browsers
Client-side media preflight can improve an upload experience, but it can also crash the page before the network request begins. A twelve-megapixel JPEG may be only four megabytes on disk and tens of megabytes after decoding. Creating several full-size canvases at once is enough to exhaust memory on older phones. Preflight is policy, not editing Decide what the browser must prove before transfer. Useful checks include file count, compressed byte size, declared type, readable dimensions, and a conservative duration limit for video. Avoid mandatory re-encoding unless the product truly needs it. Every transformation adds CPU time, memory pressure, battery use, and another failure mode. Process one file at a time A file picker may return twenty items. Do not decode all of them to build previews. Maintain a queue with one active decode on constrained devices and at most two on stronger ones. for ( const file of files ) { const result = await inspect ( file ); renderResult ( result ); await yieldToMainThread (); } The UI can list filenames immediately while dimensions and thumbnails arrive progressively. Prefer metadata over full pixels Use createImageBitmap with resize hints when supported. It can decode away from the main rendering path and avoid a full-resolution canvas for a small preview. const bitmap = await createImageBitmap ( file , { resizeWidth : 640 , resizeQuality : ' medium ' }); Always close bitmaps after drawing. Revoke object URLs when the component unmounts. Small leaks become large when guests select and remove files repeatedly. Handle orientation and color carefully Modern browsers generally honor EXIF orientation when decoding, but behavior differs across APIs and older engines. Test portrait photographs from real iOS and Android devices. Do not strip metadata silently if the original is supposed to remain untouched; upload the source file and treat the preview as disposable UI. Color differences between the preview and exported original are usually les
AI 资讯
React Native Interview Handbook — Part 8 of 10: Code Output Challenges
This is Part 8 of 10 , a bonus practice article with 70 code-output challenges . Each challenge asks you to predict the result before revealing the answer and reasoning. Complete series This Dev.to series has five core handbook articles plus five focused practice extras. Open the series page to move through the complete reading order: Part 1: JavaScript — core handbook, questions 1–120 Part 2: React — core handbook, questions 121–220 Part 3: React Native — core handbook, questions 221–420 Part 4: Performance & Architecture — core handbook, questions 421–560 Part 5: Senior & System Design — core handbook, questions 561–719 Part 6: Output-Based JavaScript Practice — bonus practice article Part 7: Coding Interview Practice — bonus practice article Part 8: Code Output Challenges — bonus practice article Part 9: Current React Native Interview Questions — new high-frequency practice article Part 10: Project & Production Interviews — senior project ownership and real-production practice How to use this challenge set Read the code, state the exact output or error, then explain the language rule. Do not run the snippet until you have committed to an answer. For React Native interviews, connect the JavaScript behavior to rendering, state updates, list handling, or the JavaScript thread when relevant. Skills tested Hoisting, scope, closures, and this Arrays, conditions, references, object behavior, and loose versus strict equality Promises, timers, async / await , and microtasks Common JavaScript patterns used in React and React Native interviews Code output challenges Challenge 1. Block-scoped counter Predict the exact output before opening the answer. let total = 0 ; for ( let i = 0 ; i < 3 ; i ++ ) { total += i ; } console . log ( total ); Answer and explanation Expected output: 3 Why: The loop adds 0, 1, and 2. Challenge 2. var callback loop Predict the exact output before opening the answer. for ( var i = 0 ; i < 3 ; i ++ ) { setTimeout (() => { console . log ( i ); }, 0
AI 资讯
Resumable Browser Uploads for Crowded Event Networks
Event uploads fail differently from normal office uploads. A wedding guest may move between venue Wi-Fi and mobile data, lock the phone while a video is transferring, or close the browser as soon as the progress bar reaches 100%. Hundreds of devices can share one access point, and users rarely wait around to diagnose an error. The usual POST request plus optimistic success toast is not enough. A reliable browser flow needs a small protocol that distinguishes local preparation, network transfer, server acceptance, media processing, and final availability. This article describes a platform-neutral design for that protocol. The five states users actually experience Model each file as a durable state machine: selected -> preparing -> transferring -> accepted -> processing -> ready Add terminal or recoverable branches: preparing -> rejected_local transferring -> paused | retryable_error | expired accepted -> processing_error processing -> ready | processing_error The key distinction is between transferring and accepted . The browser may have sent every byte while the server has not yet committed the upload. Showing “done” at that boundary creates the most frustrating failure: the guest deletes the original, but the organizer never receives it. Give every file a client-generated identity Create an upload ID before the first network request. A UUID is sufficient when combined with the event identifier: const uploadId = crypto . randomUUID (); const uploadIntent = { uploadId , eventId , name : file . name , size : file . size , type : file . type , lastModified : file . lastModified , }; Send that identity when creating the server-side upload session. If the browser retries after a timeout, the server returns the existing session instead of creating a duplicate. This is idempotency at the workflow level. A guest can tap “retry” without having to understand whether the first request reached the server. Separate the control plane from file bytes Use a small JSON API for sessi
AI 资讯
React Native Interview Handbook — Part 7 of 10: Coding Interview Practice
This is Part 7 of 10 , a bonus practice article containing 75 coding interview questions drawn from the React Native Interview Handbook. It covers the implementation tasks commonly used in JavaScript and React Native rounds, from string and array problems to hooks, FlatList , asynchronous work, caching, retries, and native modules. Complete series This Dev.to series has five core handbook articles plus five focused practice extras. Open the series page to move through the complete reading order: Part 1: JavaScript — core handbook, questions 1–120 Part 2: React — core handbook, questions 121–220 Part 3: React Native — core handbook, questions 221–420 Part 4: Performance & Architecture — core handbook, questions 421–560 Part 5: Senior & System Design — core handbook, questions 561–719 Part 6: Output-Based JavaScript Practice — bonus practice article Part 7: Coding Interview Practice — bonus practice article Part 8: Code Output Challenges — bonus practice article Part 9: Current React Native Interview Questions — new high-frequency practice article Part 10: Project & Production Interviews — senior project ownership and real-production practice How to answer coding questions Before coding, clarify inputs, output, edge cases, platform constraints, time complexity, space complexity, cancellation, and test coverage. Start with a correct readable solution, then optimize only when the constraint justifies it. Topics covered Strings, arrays, maps, sets, recursion, and algorithmic complexity Debounce, throttle, memoization, deep cloning, and polyfills Custom hooks, API state, error boundaries, and React rendering FlatList pagination, pull to refresh, search, and offline retry Promises, timeouts, concurrency limits, and exponential backoff Caching, EventEmitter, Pub/Sub, LRU design, and native module boundaries Interview coding checklist Confirm assumptions before writing code. State time and space complexity. Handle empty input, invalid input, and duplicate values deliberately
AI 资讯
React Native Interview Handbook — Part 6 of 10: Output-Based JavaScript Practice
This is Part 6 of 10 , a bonus practice article containing 191 output-based JavaScript interview questions . It includes 111 questions drawn from the React Native Interview Handbook plus 80 additional questions on the JavaScript behavior interviewers commonly test in React Native rounds: hoisting, scope, closures, arrays, objects, functions, coercion, conditions, Promises, and the event loop. Complete series This Dev.to series has five core handbook articles plus five focused practice extras. Open the series page to move through the complete reading order: Part 1: JavaScript — core handbook, questions 1–120 Part 2: React — core handbook, questions 121–220 Part 3: React Native — core handbook, questions 221–420 Part 4: Performance & Architecture — core handbook, questions 421–560 Part 5: Senior & System Design — core handbook, questions 561–719 Part 6: Output-Based JavaScript Practice — bonus practice article Part 7: Coding Interview Practice — bonus practice article Part 8: Code Output Challenges — bonus practice article Part 9: Current React Native Interview Questions — new high-frequency practice article Part 10: Project & Production Interviews — senior project ownership and real-production practice How to use this guide Before opening an answer, state the exact output first. Then explain the rule that causes it: evaluation order, scope, coercion, reference identity, prototype lookup, or microtask scheduling. Run the snippet only after committing to an answer. Topics covered Hoisting, Temporal Dead Zone, var , let , const , and function declarations Scope, closures, this , arrow functions, call , apply , and bind Arrays, sparse arrays, map , reduce , sort , slice , splice , and mutation Objects, references, shallow copies, prototypes, getters, and property lookup Conditions, truthiness, equality, nullish coalescing, and type coercion Promises, async / await , microtasks, timers, and error recovery React and React Native rendering behavior, state updates, effects,
AI 资讯
I Built a VS Code Extension to Upload Code Snippets to PasteDB in One Click 🚀
I created the official PasteDB VS Code extension that lets you upload your current file or selected code directly from Visual Studio Code. It includes secure API key storage, customizable upload settings, recent paste history, automatic language detection, and instant shareable links. In this post, I'll explain how it works, how to install it, and the challenges I faced while building it. More Info View on Marketplace
开源项目
🔥 microsoft / monaco-editor - A browser based code editor
GitHub热门项目 | A browser based code editor | Stars: 46,370 | 10 stars today | 语言: JavaScript
开源项目
🔥 sohzm / cheating-daddy - a free and opensource app that lets you gain an unfair advan
GitHub热门项目 | a free and opensource app that lets you gain an unfair advantage | Stars: 5,473 | 57 stars today | 语言: JavaScript
AI 资讯
WebGPU Explained: The Browser’s New Graphics and Compute Engine
A practical introduction to WebGPU, WGSL, render pipelines, compute shaders, and the future of high-performance graphics on the web. Your browser can stream 4K video, run a complete code editor, render complex 3D scenes, and host multiplayer games. But for years, web developers accessed the GPU through an API based on an older generation of graphics programming. WebGPU changes that contract. WebGPU is not simply a faster version of WebGL. It is a new approach to graphics and parallel computation on the web—one built around explicit pipelines, modern GPU architecture, compute shaders, predictable resource management, and a shader language designed specifically for the browser. This article expands on the progression presented in the uploaded High Performance Graphics: Introduction to WebGPU material: why WebGPU matters, how it differs from WebGL, how WGSL works, how the rendering pipeline is constructed, and how compute shaders extend the GPU beyond graphics. WebGPU is not WebGL 3.0 This is the first mental model to correct. WebGPU does not build on WebGL. WebGL exposes a browser-friendly version of the OpenGL ES programming model. WebGPU instead uses concepts associated with modern GPU APIs and provides a portable abstraction over the graphics capabilities available on the user’s system. WebGPU and WGSL are W3C standards for accessing GPU acceleration from web applications. The API supports both graphics rendering and general-purpose parallel computation. ( W3C ) WebGL │ └── OpenGL ES-style state machine WebGPU │ ├── Explicit pipelines ├── Explicit resource bindings ├── Command encoding ├── Compute shaders └── Modern GPU execution model The difference is architectural, not cosmetic. In WebGL, you frequently change global rendering state and then issue a draw call. In WebGPU, you describe the pipeline and resources more explicitly, record commands, and submit those commands to the GPU. WebGL mental model Change state ↓ Change more state ↓ Bind resources ↓ Draw WebGPU
AI 资讯
Why Static Accessibility Scanners Miss What AI Agents Hit
This button passes every automated accessibility scan we've thrown at it: <button class= "btn-primary" type= "button" > Check availability </button> And it breaks every AI agent that tries to book a room through it. The markup is clean: a real <button> , a proper accessible name from its text content, an explicit type . Nothing to flag. The failure isn't in the button, it's in what happens after the click. And no static scanner ever clicks. What a scanner actually sees Static accessibility scanners evaluate the DOM at a point in time. Usually the initial render: HTML parsed, framework hydrated, nothing interacted with. They check that state against WCAG rules, missing alt text, contrast ratios, label associations, heading order. That's genuinely useful. It's also a photograph of a lobby, when the task happens in the hallways. Here's what never appears in the initial DOM of a typical booking flow: The date picker that mounts when the check-in field receives focus The error message injected after a failed form submit The room-selection modal that opens on "Check availability" The loading state between "Book now" and the confirmation A scanner reports zero issues on all of these, for the simple reason that at scan time, none of them exist. What an agent actually traverses An AI agent completing a booking doesn't evaluate a snapshot. It walks the flow: reads the accessibility tree, decides on an action, performs it, waits for the interface to respond, reads the tree again. Every state transition is a place where the tree can lie to it. Let's look at three patterns we keep finding in real audits. All three pass static scans. All three stop an agent. 1. The modal that exists on screen but not in the tree { isOpen && ( < div className = "modal-overlay" > < div className = "modal" > < h2 > Select your room </ h2 > < RoomList rooms = { available } /> </ div > </ div > )} Visually: a modal. In the accessibility tree: a div soup appended somewhere in the body, with no role="di
开发者
How I Built a Cute Virtual Pet Game with HTML, CSS, and JavaScript 🐹
Hi everyone! I’m a developer at the beginning of my journey, and I’ve just finished working on a small project that brought me a lot of joy: Capybara Game. It’s a cute game where you feed your capybara and improve her happiness level. You can choose between 5 different types of food or pick your own snack. If the capybara likes the snack, her happiness level rises; if she doesn't like it, the happiness level falls. Your progress is saved automatically. Keep in mind that your capybara gets hungry over time, so make sure to check back and feed her regularly! I went for a minimalist, cozy design. The interface is clean and intuitive, focusing on a relaxing user experience that lets the player focus entirely on the capybara. I built this project using HTML, CSS, and JavaScript. Hope you're interested in playing! You can do it here: Play the game here I’d love to hear your thoughts! If you have any ideas for new features or if you find any bugs, feel free to let me know in the comments.
AI 资讯
How to Gate Your CI Pipeline on Quantum Vulnerability — with quantum-audit
Part 3 of the quantum-audit series. Part 1 | Part 2 * 🌐 Tool: quantum-audit-site.vercel.app Most security tools tell you there's a problem. Then you close the tab and forget about it. The only way to actually fix that is to make the problem block your deployment . quantum-audit exits with a non-zero code when it finds critical quantum-vulnerable cryptography. That means you can drop it into any CI pipeline and have it fail the build automatically. Here's how. The exit code behaviour npx quantum-audit . echo $? # 0 = no critical findings, 1 = critical findings found Exit 0 — no critical findings (safe to deploy) Exit 1 — critical findings detected (block the build) Medium findings (SHA-256, AES-128) don't fail the build — they appear in the output as warnings but don't block deployment. Only CRITICAL findings (RSA, ECDSA, secp256k1) cause a non-zero exit. GitHub Actions Add this to your .github/workflows/ci.yml : name : CI on : push : branches : [ main ] pull_request : branches : [ main ] jobs : quantum-audit : runs-on : ubuntu-latest steps : - name : Checkout uses : actions/checkout@v4 - name : Setup Node.js uses : actions/setup-node@v4 with : node-version : ' 20' - name : Run quantum-audit run : npx quantum-audit . If your project uses ethers , web3 , elliptic , or any other ECDSA/RSA library — the step will fail and your PR cannot be merged until the finding is addressed. JSON output for custom reporting Need to parse the results programmatically? Use the --json flag: npx quantum-audit . --json Output: { "project" : "my-dapp" , "score" : 60 , "grade" : "C — Moderate Exposure" , "findings" : [ { "algorithm" : "ECDSA (secp256k1) signing" , "risk" : "critical" , "weight" : 40 , "file" : "package.json" , "line" : null , "source" : "ethers" }, { "algorithm" : "SHA-256 (crypto.createHash)" , "risk" : "medium" , "weight" : 8 , "file" : "src/utils/hash.js" , "line" : 14 } ] } You can pipe this into a Slack notification, a dashboard, or a custom reporting step. Slack notif
AI 资讯
Experiments with On-device AI — What building on Gemini Nano actually teaches you
Chrome ships a real LLM inside the browser now — Gemini Nano, exposed through a handful of built-in...
AI 资讯
Beyond login: encrypting data with passkeys and WebAuthn PRF
Originally published at daniel-yang.com . I've been using passkeys for a while now, and at some point I noticed an extension in the WebAuthn spec that almost nobody talks about: PRF. It lets a website ask your authenticator to evaluate a pseudo-random function during login. Deterministic output, 32 bytes, keyed to that specific credential, never leaves your browser. That's an encryption key. Sitting inside the same ceremony everyone already uses for login. So I built pknotes to see how far the idea goes: an end-to-end encrypted notes app with no master password anywhere. Your passkey unlocks your notes in the literal, cryptographic sense. This post is the architecture writeup. There's a live demo if you'd rather poke it first (notes wiped daily). One ceremony, two jobs A normal passkey login proves who you are and nothing else. With the PRF extension, the same ceremony does double duty: The server verifies the WebAuthn assertion. That's login. The client reads the PRF output from the same response and derives a key from it. That's decryption. The server never sees the PRF bytes. They're returned to client-side JavaScript only, after user verification (Face ID, Touch ID, PIN), and only for the requesting origin. Requesting it looks like this: const credential = await navigator . credentials . get ({ publicKey : { challenge , userVerification : ' required ' , extensions : { prf : { eval : { first : new TextEncoder (). encode ( ' pknotes/prf-eval/v1 ' ) } }, }, }, }); const prfOutput = credential . getClientExtensionResults (). prf . results . first ; // 32 bytes, deterministic for this credential + this input, never sent anywhere The key hierarchy Raw PRF output shouldn't encrypt data directly, and you also want to be able to add and remove devices without re-encrypting everything. So there's a small hierarchy: Passkey PRF output │ HKDF-SHA256 ▼ KEK (key-encryption key, exists only in browser memory) │ unwraps ▼ Master key (random AES-256, generated once at signup) │
开源项目
🔥 fleetbase / fleetbase - Modular logistics and supply chain operating system (LSOS)
GitHub热门项目 | Modular logistics and supply chain operating system (LSOS) | Stars: 2,098 | 43 stars today | 语言: JavaScript
开源项目
🔥 schlagmichdoch / PairDrop - PairDrop: Transfer Files Cross-Platform. No Setup, No Signup
GitHub热门项目 | PairDrop: Transfer Files Cross-Platform. No Setup, No Signup. | Stars: 10,914 | 107 stars today | 语言: JavaScript
开源项目
🔥 mm7894215 / TokenTracker - Local-first AI token usage & cost tracker for 27 coding tool
GitHub热门项目 | Local-first AI token usage & cost tracker for 27 coding tools — with a desktop pet, 4 widgets, achievements, native macOS/Windows apps, and a one-command CLI. Never reads prompts. | Stars: 1,018 | 12 stars today | 语言: JavaScript
开源项目
🔥 wwebjs / whatsapp-web.js - A WhatsApp client library for NodeJS that connects through t
GitHub热门项目 | A WhatsApp client library for NodeJS that connects through the WhatsApp Web browser app | Stars: 22,200 | 12 stars today | 语言: JavaScript
AI 资讯
5 Things I Learned Building a Chrome Extension That Watches ChatGPT, Claude & Gemini
I spent the last few months building a Chrome extension that detects HTML code blocks inside ChatGPT, Claude, and Gemini and lets you deploy them straight to a live URL. The "deploy" part turned out to be the easy 20%. The hard 80% was reliably watching three completely different, constantly-changing chat UIs without breaking every other week. Here's what actually taught me something. 1. MutationObserver is non-negotiable, but it will still lie to you None of these chat apps render the full response at once — they stream tokens in, which means the DOM you're watching is incomplete almost every time your observer fires. My first version tried to detect a finished <pre><code> block the moment it appeared. Result: I was grabbing HTML mid-stream, cut off halfway through a <div> . What actually worked was debouncing on DOM stability instead of DOM presence: let debounceTimer ; const observer = new MutationObserver (() => { clearTimeout ( debounceTimer ); debounceTimer = setTimeout ( scanForCodeBlocks , 600 ); }); observer . observe ( document . body , { childList : true , subtree : true }); 600ms of "nothing changed" turned out to be a much more reliable signal than "the tag now exists." Not elegant, but it works across all three sites' streaming speeds. 2. Every AI chat UI restructures its DOM without telling you ChatGPT, Claude, and Gemini all ship frequent frontend updates, and none of them are obligated to keep a stable class name for you to hook into. I initially selected code blocks by class name ( .language-html , .hljs , etc.) and had selectors silently break in production within two weeks of launch. What's held up better: matching on structural patterns instead of class names — a <pre> containing a <code> whose text content starts with <!DOCTYPE or <html . It's slower to write the first time, but it doesn't care what CSS class the framework decided to use this month. 3. "Detect the code" is easy. "Detect the right code" is the actual problem A single AI response