AI 资讯
The Case of the Lying Clock: 5 Vue Mysteries Solved
Every detective has their cold cases. These are mine — five Vue concepts that confused me until I investigated them properly. Grab your magnifying glass. Case #1: The Lying Clock Imagine you set an alarm to go off every 60 seconds. You press start at 10:00:00. First alarm: 10:01:00 — perfect Second alarm: 10:02:00 — still good But your phone is also doing other things: checking email, refreshing weather, running background tasks. Sometimes it fires the alarm a tiny bit late. Third alarm: 10:03:01 (1 second late) Fourth alarm: 10:04:02 (2 seconds off now) Five hours later: your alarm fires at 15:05:12 when it should fire at 15:05:00 That gap growing bigger over time — that's drift . The timer slowly slides away from where it should be. Why Does This Happen? JavaScript runs on a single thread — it can only do one thing at a time. When a timer is supposed to fire, the browser puts it in a queue. But if the thread is busy doing something else, the timer waits. The MDN documentation for setTimeout lists several reasons timers fire late: Nested timeouts are throttled to a minimum of 4ms after 5 levels of nesting (per the HTML5 spec ) Background tabs are throttled to a maximum of once per second ( MDN : "timeouts are throttled to firing no more often than once per second (1000 ms) in inactive tabs") Chrome 88+ introduced intensive throttling for hidden pages: timers that have been hidden for more than 5 minutes are checked only once per minute Tracking scripts in Firefox get even more aggressive throttling: 10 second minimum in background tabs Does This Happen on New Devices Too? Yes, but less. Modern devices are faster, so the delay per tick is smaller — maybe 1-2 milliseconds instead of 10-20. But over hours, even 1ms per tick adds up. And background tab throttling happens on every device, no matter how fast — it's a browser policy, not a hardware limitation. Is This Common Knowledge? It's the kind of thing you learn when your boss says "why does the clock on our dashboa
AI 资讯
Architecting a Real-Time Collaborative Task Board
Building rich, collaborative web interfaces today requires much more than simply rendering components to the DOM. It demands rigorous planning around rendering performance, deterministic state management, and network resilience. In this article, I will break down the architectural decisions and trade-offs behind a real-time, enterprise-grade Kanban Board. Built with React 19, Vite, TypeScript, and Tailwind CSS, this application is designed to handle high data volumes via virtualization while maintaining a bulletproof, offline-first architecture. 🚀 Live Demo System Architecture: The Smart/Dumb Paradigm To guarantee scalability and testability, the application strictly adheres to the Container/Presentational (Smart/Dumb) design pattern. This ensures absolute separation of concerns. Containers (Smart): Orchestrate state access via Zustand, handle asynchronous actions, and manage event listeners. Presentational Components (Dumb): Pure, stateless functions exclusively concerned with UI rendering and accessibility. They receive data strictly via props. Unidirectional Data Flow: State mutations propagate downward from the global store, ensuring predictable render cycles. Here is the architectural topography of the system: Quality Attributes (NFRs) and Technical Decisions To ensure this MVP could scale into a production-ready product, the system was designed around strict Non-Functional Requirements (NFRs). Performance: DOM Virtualization & React 19 Paradigms Rendering 1,000+ DOM nodes concurrently destroys the framerate of standard React applications. We implemented client-side virtualization via @tanstack/react-virtual. By recycling DOM nodes and dynamically measuring element heights, the browser only renders the exact cards visible within the viewport, maintaining a steady 60fps during complex Drag-and-Drop operations. Furthermore, this codebase natively embraces React 19. It intentionally omits manual memoization (useMemo, useCallback, React.memo), relying entirely on t
开发者
Your `fetch()` in `beforeunload` is being silently dropped. Use `navigator.sendBeacon()`.
When a user closes a tab, submits a form, or clicks an external link, you often need to send one last...
开源项目
🔥 plankanban / planka - PLANKA is the Kanban-style project mastering tool for everyo
GitHub热门项目 | PLANKA is the Kanban-style project mastering tool for everyone | Stars: 12,331 | 10 stars today | 语言: JavaScript
开源项目
🔥 airbnb / javascript - JavaScript Style Guide
GitHub热门项目 | JavaScript Style Guide | Stars: 148,133 | 15 stars today | 语言: JavaScript
AI 资讯
The iOS Safari keyboard scroll bug, fixed with one line of CSS
If you build a full-screen mobile editor as a position: fixed overlay with a fixed toolbar on top and a nav bar on the bottom , iOS Safari will happily scroll your entire chrome off-screen the moment the soft keyboard opens — but only when the content is short . The fix isn't a JavaScript viewport dance. It's one line: .editor .ProseMirror { padding-bottom : 60vh ; } Give the inner scroll container something to scroll , and iOS keeps the scroll inside it instead of falling back to scrolling the document (which drags your "fixed" elements along). No html / body locking required. I hit this while building the mobile editor for PenPage , a local-first WYSIWYG markdown notes app (React + TipTap/ProseMirror). Everything below is verified on a real iOS device. The setup Picture a mobile note editor that takes over the whole screen: ┌──────────────────────────┐ │ Toolbar (absolute,top) │ ← stays put ├──────────────────────────┤ │ │ │ Editable content │ ← scrolls │ (overflow-y: auto) │ │ │ ├──────────────────────────┤ │ Nav bar (absolute,bottom)│ ← stays put └──────────────────────────┘ The outer container is position: fixed; inset: 0 . The toolbar and nav bar are position: absolute inside it. The middle is the only thing that scrolls. Standard app-shell layout. Works great on desktop and Android. The symptom Tap into the editor, the iOS keyboard slides up, and: Long document (taller than the viewport): perfect. The content scrolls under the keyboard, the toolbar and nav bar stay nailed in place. Short document (shorter than the viewport): broken. Trying to scroll drags the whole screen — toolbar and nav bar included — as if the entire fixed overlay were a normal scrolling page. That "only when short" detail is the whole story. The root cause This is the long tail of WebKit bug #191204 : when the soft keyboard appears, iOS Safari's layout viewport gets shorter than the visual viewport , and the document itself becomes scrollable by the keyboard's height. Worse, in that stat
AI 资讯
DASTAN The Taste of Home Every culture has a taste of home.
DASTAN — The Taste of Home 🍲 This is my submission for the Frontend Challenge – Comfort Food Edition, Perfect Landing. What I Built For this challenge, I wanted to create something that felt more like a story than a typical food website. That idea became DASTAN — The Taste of Home . “Dastan” means a story, and the concept behind the project is simple: food is rarely just food. A dish can remind us of a person, a place, a family gathering, or a moment we haven't thought about in years. DASTAN is a visual, editorial-style landing page that explores comfort food from different parts of the world through photography, cultural stories, ingredients, and the people behind the memories. The goal was to make the experience feel warm, premium, and personal from the moment someone opens the page. The Idea The line that shaped the whole design was: Every culture has a taste of home. I wanted the website to communicate that feeling without relying on a traditional recipe-blog layout. Instead, I treated each dish almost like a magazine story. You can discover dishes from different regions, read the story behind them, and explore how food connects people across cultures. The Design I went for an editorial-inspired visual direction rather than a conventional modern dashboard. The design uses: Warm cream backgrounds Deep charcoal sections Muted gold accents Large serif typography Editorial-style food photography Rounded cards Generous spacing Strong visual hierarchy Story-focused content Subtle borders and details I wanted the interface to feel like opening a beautifully designed food magazine. At the same time, I made sure the experience remains comfortable to use on smaller screens. What You'll Find 🌍 Global Comfort Food DASTAN brings together dishes and stories from different parts of the world. Examples include: Tonkotsu Ramen — Japan Hyderabadi Dum Biryani — India Kimchi Jjigae — Korea Lasagna alla Bolognese — Italy Lahori Chicken Karahi — Pakistan Each one is presented as more
AI 资讯
TypeScript 6.0 `--noPropertyAccessFromIndexSignature`: The Flag That Forces Honest API Contracts
TypeScript 6.0 --noPropertyAccessFromIndexSignature : The Flag That Forces Honest API Contracts This article was written with the assistance of AI, under human supervision and review. The Silent Type Hole in Your Codebase Most runtime property access errors stem from index signatures pretending to guarantee properties they don't. Teams define Record<string, T> or { [key: string]: T } for objects where specific properties might not exist, then access those properties with dot notation as if the type system proved their presence. The compiler stays silent. Production crashes follow when the property is undefined. The --noPropertyAccessFromIndexSignature flag eliminates this false confidence. When enabled, TypeScript prohibits dot notation for properties defined only through index signatures. The type system forces bracket notation instead, making the uncertainty explicit at every call site. This distinction is critical—it transforms implicit runtime failures into compile-time enforcement of honest contracts. When developers adopt this flag, the contract becomes explicit. Index signatures signal "this property might not exist" and the syntax enforces that uncertainty. Explicit properties signal "this property is guaranteed" and dot notation confirms the guarantee. The codebase gains honesty. Key Takeaways The --noPropertyAccessFromIndexSignature flag prevents dot notation on properties defined only through index signatures, forcing bracket notation that signals uncertainty. Index signatures ( [key: string]: T ) describe unknown property sets; explicit properties describe guaranteed contracts—the flag enforces this semantic difference. Enabling this flag exposes implicit runtime failures as compile errors, converting production crashes into immediate feedback during development. The migration path involves converting dot access to bracket notation for index-signature properties while keeping dot notation for explicit properties. Combining this flag with --noUncheckedInd
开发者
Still Warm: a museum where comfort food is the art
This is a submission for Frontend Challenge - Comfort Food Edition, Perfect Landing Most food...
AI 资讯
React 19's useFormStatus Fixed My Prop Drilling. Then It Sat There Returning False
Part 1 was about waiting well. Part 2 was about not waiting at all. This one is about a value I...
AI 资讯
Angular 22: The End of Boilerplate and the Consolidation of the Reactive Era
If you have been following the evolution of Google's framework over the last few years, you know it has been undergoing a silent reconstruction — piece by piece. With the release of Angular 22 on June 3, 2026, this reconstruction is no longer a promise and has become the standard. We are not looking at another batch of experimental features: we are looking at the consolidation of an entirely rethought ecosystem. For those who live and breathe enterprise applications, Clean Architecture, and Microfrontend ecosystems, this is the version that finally delivers what has been promised since Angular 16: an end-to-end reactive framework, zone-less by nature, and with much less ceremony along the way. The experiments are over. Below is what has actually changed — and what you need to do before running ng update . 📖 If you are just starting out: several technical terms in this article (change detection, Signals, SSR, dependency injection, microfrontends...) are explained in a glossary at the end. Read the article from end to end and use the glossary as a reference whenever you have a doubt. What Arrived in Angular 22 OnPush is the new default change detection (the old Default became Eager and is deprecated). Stable Resource API: resource , rxResource , and httpResource are ready for production. Stable Signal Forms: featuring the Submission API, dynamic schemas (Zod/Valibot), and interop with Reactive Forms. New @Service() decorator: shortening @Injectable({ providedIn: 'root' }) . injectAsync : for lazy dependency injection, with prefetch via onIdle . debounced : for native debounce in Signals/Resources. Incremental Hydration: enabled by default. HttpClient : uses FetchBackend by default ( withFetch() is deprecated). Important Router and bootstrap improvements designed for Microfrontends . 1. OnPush as the New Default Change Detection The moment the community has always asked for has arrived: ChangeDetectionStrategy.OnPush is now the default behavior for any new component. T
开发者
e.preventDefault() vs e.stopPropagation()
The easiest way to remember it: preventDefault() → stops the browser's default action. stopPropagation() → stops the event from moving through the DOM. event.preventDefault() It prevents the browser's built-in behavior associated with an event. Example: clicking a link. Google document.getElementById("link").addEventListener("click", (event) => { event.preventDefault(); }); Normally: Click ↓ Browser navigates to Google With preventDefault(): Click ↓ preventDefault() ↓ ❌ Browser does NOT navigate Common uses: // Form submission event.preventDefault(); // Link navigation event.preventDefault(); // Drag/drop browser behavior event.preventDefault(); event.stopPropagation() This prevents the event from bubbling up or capturing down through parent/child elements. Example: Click me parent.addEventListener("click", () => { console.log("Parent clicked"); }); child.addEventListener("click", (event) => { event.stopPropagation(); console.log("Button clicked"); }); Without stopPropagation(): Click Button ↓ Button handler ↓ Parent handler Output: Button clicked Parent clicked With stopPropagation(): Click Button ↓ Button handler ↓ stopPropagation() ↓ ❌ Parent handler doesn't receive the event The important difference Imagine: Like If you click the button: preventDefault() button.addEventListener("click", (event) => { event.preventDefault(); }); The event can still propagate: Button ↓ Anchor ↓ Card But the browser's default action (such as following the link) is prevented. stopPropagation() button.addEventListener("click", (event) => { event.stopPropagation(); }); The event doesn't continue through the DOM: Button ↓ ❌ Anchor/Card handlers But the browser's default behavior is not automatically cancelled. Can you use both? Yes. button.addEventListener("click", (event) => { event.preventDefault(); event.stopPropagation(); }); Now you're saying: Don't perform the browser's default action. Don't let this event reach other elements.
AI 资讯
Bug Smash: restoring dropped Gemini chat config in Sentry's JavaScript SDK
This is a submission for DEV's Summer Bug Smash: Clear the Lineup powered by Sentry. ...
AI 资讯
I built 109 tools that never touch a server - here is the architecture
I built 109 tools that never touch a server - here is the architecture Most "tools" sites you have used do this: You upload a file It goes to a server The server processes it You download the result Sometimes the server stores it. Sometimes it leaks. Sometimes it disappears with the company. I wanted something different. Every tool on korelyy.com runs 100% in your browser . Zero backend. Zero upload. Zero tracking. Here is the actual architecture, the real numbers after 90 days, and what I learned. What "no server" actually means For each of the 109 tools: The entire app is a static HTML + CSS + JS file It is served as-is from a CDN (Cloudflare Pages) All file processing happens in your browser via FileReader , canvas , Web Crypto API , or OffscreenCanvas Your file never leaves your device Closing the tab = the data is gone (no cookies, no localStorage, no account) This is not a marketing claim. It is verifiable: Open DevTools -> Network tab Use any tool that requires a file (image converter, JSON formatter, etc.) Reload. The only network request is for the static HTML/CSS/JS bundle. No fetch() to a server. No XHR . No upload. The file is read, processed in-memory, and downloaded. The 4 browser APIs that do 90% of the work When you remove a backend, you are left with the browser. The browser is more capable than most people think. 1. FileReader and URL.createObjectURL Read any file the user gives you: const file = document . querySelector ( ' input[type=file] ' ). files [ 0 ]; const url = URL . createObjectURL ( file ); const img = new Image (); img . onload = () => { // process image canvas . toBlob ( blob => { const downloadUrl = URL . createObjectURL ( blob ); // trigger download }); }; img . src = url ; Image conversion, PDF generation, audio trimming - all the same pattern. Read blob, process, create new blob, download. 2. crypto.subtle (Web Crypto API) Hashing, encryption, signing - all client-side: const hash = await crypto . subtle . digest ( ' SHA-256 ' , a
AI 资讯
What it took to move a collaborative browser IDE beyond process memory
The first collaboration model in CodeVerse was convincing in exactly the way a local demo needs to be convincing. Open two tabs. Join the same room. Type in one editor. Watch the other editor update. Then ask one unpleasant question: what happens when those two sockets land on different server instances? The answer was that the room stopped being a room. Each process had its own memory, its own presence list, and its own idea of the current files. A restart erased state. A reconnect could create a second identity. A load balancer could turn a working demo into two isolated conversations. This article is about the work that followed: moving CodeVerse from synchronized tabs to a collaboration path I could test across processes, recover after disconnects, and describe without pretending a local benchmark was a production capacity claim. The real boundary was not Socket.IO Socket.IO made connection handling and room fan-out approachable, but it did not decide where truth lived. That distinction matters. A room name inside one Socket.IO process is a routing convenience, not durable shared state. Once I wanted multiple application instances, I needed separate answers for four kinds of information: Document state — the convergent contents of every file. Room policy — organizer identity, edit permissions, active file, and revision. Presence — which sockets are here now, on which instance, with which effective role. Durability — what survives Redis expiry, application restarts, or a longer period of inactivity. CodeVerse now uses Yjs for convergent document updates, Redis for live distributed room state and pub/sub, and Supabase for durable room snapshots and membership data. Socket.IO remains the transport and fan-out layer. That separation was more important than any individual library choice. Redis does three different jobs It is easy to say “I added Redis” and leave the architecture vague. In CodeVerse, Redis has three explicit responsibilities. 1. Cross-instance fan-out
开源项目
🔥 polius / FileSync - Send files from one device to many in real-time.
GitHub热门项目 | Send files from one device to many in real-time. | Stars: 1,468 | 26 stars today | 语言: JavaScript
开源项目
🔥 bmad-code-org / BMAD-METHOD - Breakthrough Method for Agile Ai Driven Development
GitHub热门项目 | Breakthrough Method for Agile Ai Driven Development | Stars: 51,759 | 46 stars today | 语言: JavaScript
开源项目
🔥 chr0nzz / traefik-manager - A clean, self-hosted web UI for managing your Traefik revers
GitHub热门项目 | A clean, self-hosted web UI for managing your Traefik reverse proxy. | Stars: 1,207 | 31 stars today | 语言: JavaScript
AI 资讯
Adrak Chai & Samosa — Comfort Food Edition (Corporate Tech Office Tea Break)
This is a submission for Frontend Challenge - Comfort Food Edition, CSS Art . Inspiration In an Indian tech office, no product release, critical bug fix, or late-night deployment is complete without a 5-minute pantry chai break. A steaming clay Kulhad of Ginger Adrak Chai paired with crisp Garma-Garam Samosas is the ultimate comfort food that powers developers through endless coding sprints. This authentic workplace culture and rich street-food nostalgia inspired me to build a pure-CSS interactive art and corporate pantry scene. Demo Live Interactive Demo : Corporate Chai & Samosa Experience CodePen Embed : codepen.io GitHub Repository : Sayista-Yazdani/corporate-chai What I Built Adrak Chai & Samosa is an interactive web experience featuring: Pure CSS Hero Artwork : Handcrafted clay-textured Kulhad Chai cup with a shimmering tea surface, malai rim, and layered rising steam animations. Golden-brown samosas with crisp crimped edges, served on a traditional plate alongside mint and tamarind chutneys. Interactive Corporate Pantry Corner : Fully detailed tea kitchen equipped with a glowing gas stove, boiling tea saucepan with foam, spice jars ( Adrak , Elaichi , Chai Patti ), and stacked clay cups. 4 Distinct Characters : Rohan (Frontend Dev), Amit (Tech Lead), Priya (Product Manager), and Kaka (Pantry Specialist). Web Speech API & Audio Narration : Real voice speech synthesis with gender-matched voice profiles for each character. Character Gaze & Mouth Choreography : Characters automatically look toward whoever is currently speaking with dynamic gaze shifting, listening poses, and animated mouth movements. Journey & Tech Stack Technical Implementation CSS Artwork : Built entirely with CSS gradient meshes, polygon shapes, keyframe animations, and layered pseudo-elements ( ::before / ::after ). Audio Engine : Powered by native window.speechSynthesis with dynamic voice selection and text cleaning. State Management : Reactive data-speaker HTML attributes driving multi-char
AI 资讯
Data Scientist Learning JS: Promises and resolve()
Context: I'm a data scientist/analyst (in Python and R) learning development from scratch. Inevitably, I am learning these through the lens of what I already know. If you have a similar background and are a beginner developer, I hope these analogies help! Any comments, especially if you spot any misunderstanding, are appreciated. Commenting is caring <3 Motivation: I was building a mock data layer for a fitness social app — simulating what happens when users fetch new posts from a feed. The function needs to return mock posts after a delay, simulating a real network request. Working Code: `function fakeFetchPosts() { return new Promise((resolve) => { setTimeout(() => { resolve(posts); }, 2000); }); } async function main() { console.log("Fetching..."); const fetchedPosts = await fakeFetchPosts(); console.log("Fetched posts:", fetchedPosts); } main(); console.log("Sync code ran");` What do you expect to see as an output? I first confused the logic with blocking. For example, in webscraping, something like time.sleep() or Selenium's WebDriverWait(driver, 10).until(EC.presence_of_element_located(...)) . In this case, output will be Fetching..., Fetched posts: ..., then Sync code ran. However, the output gives Fetching..., Sync code ran, and then Fetched posts. In the former, the whole script (single thread) pauses and does nothing else until the wait ends or the condition is met. The latter is different in that the rest of your program keeps running during the wait, and thus the output where Sync code ran is printed first before the fetchedPosts. By the way, posts are arrays. const posts = [{ author: "j1wonkim", text: "Testing Physical", likes: 100, }, {author: "onewc0218", text: "Love love", likes: 55, }, {author: "gakbca", text: "You are good", likes: 10, } ];