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

标签:#react

找到 304 篇相关文章

AI 资讯

Full-Stack Architecture Patterns That Actually Survive Production

Every full-stack tutorial ends the same way: a working app, a happy demo, and zero mention of what happens six months later when your "simple" CRUD app has 40 endpoints, three types of caching, and a frontend team that's afraid to touch the API layer. This post isn't about picking a framework. It's about the architectural decisions that quietly determine whether your app is pleasant to work on in year two — or a slow-motion disaster. 1. Stop treating your API layer as an afterthought A huge number of full-stack apps start with the frontend calling the backend directly, endpoint by endpoint, with no shared contract. It works fine at 5 endpoints. At 50, nobody remembers which fields are optional, which ones changed last sprint, or why the mobile app is still sending the old shape. Two things fix this early: A single source of truth for your API contract. Whether that's OpenAPI, GraphQL SDL, or even just shared TypeScript types in a monorepo package, the goal is the same: one place where "what does this endpoint return" is answered definitively. Generated clients over hand-written fetch calls. If you're writing fetch('/api/users/' + id) by hand in more than one place, you've already created a maintenance liability. Tools like openapi-typescript-codegen or a tRPC setup remove an entire category of bugs. // Instead of this scattered everywhere: const res = await fetch ( `/api/users/ ${ id } ` ); const user = await res . json (); // type: any, hope for the best // This, generated from your contract: const user = await api . users . getById ( id ); // fully typed, autocomplete works 2. Decide where your business logic lives — before you have 30 files that disagree The classic failure mode: business logic scattered across route handlers, database triggers, frontend validation, and a couple of "utils" files nobody wants to open. Every rule ends up implemented two or three times, slightly differently. Pick one layer to own the rules. A common, boring, effective pattern: Contr

2026-09-08 原文 →
AI 资讯

Our site served every URL the same 3,780 bytes, and Google believed it

Checked with a Googlebot user agent one morning: every single URL on our site returned the same 3,780-byte shell. Same <title> , zero <h1> , zero body text. The homepage, a blog post and a product page were byte-identical before JavaScript ran. Search Console agreed with the crawler rather than with us. Of 741 URLs, 116 had earned a single impression in 28 days, and a landing page that had been live for five months was still reported as "URL is unknown to Google". Here is what I actually learned fixing it, including the two things that cost us the most time. Google does render JavaScript. That is not the point. The standard reply to this problem is "Googlebot executes JS now, you are fine." It does. Several of our pages were indexed, so rendering clearly happened. But rendering is a separate, budgeted queue . A domain with little authority does not get much of that budget. So the practical question is not "can Google render our page", it is "will Google spend its budget rendering this page, today, before it decides what the page is about". There is a second problem that has nothing to do with rendering: 741 URLs that are byte-identical before render look like duplicates. You are handing a duplicate-content signal to the crawler and hoping the render queue fixes your first impression. What we built, and what we deliberately did not We wrote a post-build script that injects a real <head> into each generated HTML file: title, description, canonical, robots, Open Graph, Twitter. Head only. The body stayed exactly as the SPA served it. That was deliberate: No hydration flash. No risk of a static copy drifting out of sync with what users see. Nothing that could be read as cloaking, because the static markup is a subset of the rendered markup, not a different page. Every value is read from the same source the React page reads. Where a title is a literal inside a component, the script extracts it from that component's source rather than having anyone retype it. A number ret

2026-09-08 原文 →
AI 资讯

AI React Native Form Builder: The Complete Data-Entry Stack in 2026

TL;DR Every mobile app is forms underneath: signup, checkout, onboarding, KYC. The UI is an afternoon; the invisible stack (keyboard geometry, validation, migrations, RLS, typed writes) is where weeks disappear. Most AI form builders generate a pretty <TextInput> and stop. The useful pattern is generating the whole pipeline from one prompt: SQL migration, RLS policies, regenerated types, controlled state, visible errors, and a real Supabase insert. Five silent-failure patterns ship broken forms constantly: Alert.alert on web, unchecked { error } , RLS with no policy, stale generated types, and guard clauses that swallow crashes. Iterate additively (point-and-edit, follow-up prompts) instead of regenerating. Full regenerations lose per-field polish. Why "just add a form" is never just a form Ask any React Native developer what's slow about mobile development and forms will be near the top of the list. Not for the reasons the UI suggests. The visible part (labels, inputs, a submit button) is an afternoon. The invisible part is where the calendar goes: Keyboard geometry. iOS pushes content up; Android resizes; the submit button ends up under the keyboard on one platform and floats wrong on the other. Every screen with a TextInput needs a KeyboardAvoidingView with the correct behavior prop and a ScrollView with keyboardShouldPersistTaps="handled" , or it ships broken. Controlled state. Every field wants a useState slice, an onChangeText handler, a value prop, and a clean way to reset. Formik and react-hook-form abstract this, but they add a dependency graph, and neither handles the mobile-specific ergonomics. Validation with visible errors. A validator that fails silently is worse than none. Errors have to render on the correct field, at the correct time. The database half. A form that doesn't persist is a demo. Persisting means a table, columns of the right type, RLS policies (or every query returns zero rows with no error), a typed client, and error handling on the mu

2026-09-07 原文 →
AI 资讯

Engineering a Digital Canon: Interactive Taxonomies for Over 40 Classical Zen Texts

Engineering a Digital Canon: Interactive Taxonomies for Over 40 Classical Zen Texts Preserving sacred literature and philosophical treatises online often suffers from poor structure, fragmented PDFs, and broken navigation. To solve this for classical Chan (Zen) Buddhism, we engineered chanzong.space (禅宗知识库) — a performant, open-access knowledge base built with Next.js 14, React 18, and D3.js. Whether you are studying the non-duality of the Platform Sutra or the intricate psychological analysis of Yogacara (唯识) mind theories, navigating multi-layered canonical texts requires modern web tooling. 🏛️ 1. Multi-Dimensional Canon Architecture Unlike a basic eBook reader, chanzong.space treats philosophical literature as a multi-relational graph: Foundational Classics (核心经典) : Platform Sutra (六祖坛经) : The fundamental teaching of direct seeing into one's true nature (自性顿悟). The Blue Cliff Record (碧岩录) : The pinnacle of Song Dynasty Koan commentary. Diamond Sutra (金刚般若波罗蜜经) : The ontological grounding of non-abiding mind (应无所住而生其心). Eight Verses on Eight Consciousnesses (八识规矩颂) : Master Xuanzang's indispensable guide to transforming consciousness into wisdom (转识成智). D3.js Dynamic Knowledge Graph : Spanning 500+ nodes (Patriarchs, Core Doctrines, Cultivation Methods, and Koans). Explore live in your browser: Global Zen Knowledge Topology . ⚡ 2. Technical Stack & Clean Typography To honor the contemplative nature of reading ancient texts, our frontend adheres to the rice-paper aesthetic ( bg-[#FAF9F6] ) paired with dark night sky navigation: Framework : Next.js 14 (App Router) + TypeScript + Tailwind CSS. Fast Search : Instant Ctrl+K global dialog searching across 40+ books, 160+ philosophical concepts, and 200+ koans. Vernacular Modern Commentary : Every chapter is paired with exclusive modern Chinese analysis and keyword glossaries, bridging ancient idioms into practical psychological insights. Offline Reliability : Full PWA Service Worker caching for distraction-free reading

2026-09-07 原文 →
AI 资讯

This is how I added an in-browser auto captions feature to my YouTube Shorts converter web application using Whisper AI and ffmpeg.wasm

A few weeks ago I launched Convert to Shorts — a free browser-based tool that converts horizontal videos to YouTube Shorts format (9:16) without uploading anything to a server. I wrote about the ffmpeg.wasm + Vite setup in a previous article. The most requested feature after launch was auto captions. Captions significantly boost Shorts engagement since most people watch without sound, and manually typing captions is tedious. The challenge: how do you add free auto captions to a privacy-first tool that never uploads your video to a server? The answer: run Whisper AI in the browser. The stack - Transformers.js ( @xenova/transformers ) — Hugging Face's JavaScript port of the Transformers library, runs ONNX models in the browser via WebAssembly Whisper tiny — OpenAI's speech recognition model, 75MB, surprisingly accurate for clear speech Web Audio API — for extracting and resampling audio from the video file ffmpeg.wasm — for burning captions into the video ASS subtitles — the subtitle format libass (inside ffmpeg.wasm) understands. Step 1: Audio extraction Whisper expects mono 16kHz audio as a Float32Array. The Web Audio API handles this cleanly: async function extractAudio ( file : File , trimStart : number , trimEnd : number ): Promise < Float32Array > { const arrayBuffer = await file . arrayBuffer (); const audioContext = new AudioContext ({ sampleRate : 16000 }); const audioBuffer = await audioContext . decodeAudioData ( arrayBuffer ); const sampleRate = audioContext . sampleRate ; const startSample = Math . floor ( trimStart * sampleRate ); const endSample = Math . floor ( trimEnd * sampleRate ); // Mix down to mono, slice to trim range const channelData = audioBuffer . getChannelData ( 0 ); const trimmed = channelData . slice ( startSample , endSample ); await audioContext . close (); return trimmed ; } Creating the AudioContext at 16kHz means the browser automatically resamples from whatever the source rate is (usually 44.1kHz or 48kHz). No manual resampling nee

2026-09-07 原文 →
AI 资讯

The app speaks 19 languages: tiered i18n and the AI translation pipeline

The codebase survey was blunt: zero i18n infrastructure , roughly 660 user-facing text nodes across 53 files, a dozen alert dialogs, forty toasts, screen titles scattered across layout files. English was load-bearing everywhere. The reason to fix it then , rather than "after launch", was the closed-test window : Google Play makes you sit in testing for fourteen days regardless, and fourteen days of real people using translated builds is worth more than fourteen days of them using English. So the app learned six languages in one pass, then thirteen more. TL;DR — i18next + react-i18next + a plural-rules polyfill (the JS engine ships a stub Intl on some platforms, and Arabic needs six plural categories), eight namespaces, static resources so the first frame already has copy. Language is per-user, not per-device — the currency pattern — cached for the first frame, mirrored on the profile so it roams, cleared and restored on account switch; the Cognito locale attribute is written at sign-up so emails can follow later. Arabic flips the shell RTL with a native flag and a one-shot restart prompt, logical direction classes, and a font trick: the Arabic face is registered under the Latin font's names , so every existing style re-faces with zero call-site changes. Two tiers — six human-reviewable launch languages, thirteen machine-translated — generated by a diff-only pipeline that forces structured output because free-form JSON kept breaking on quotes. (Part 33 of Building CannyCart , a voice-first shopping app I'm building in public. Self-contained — no earlier context needed.) Four pillars, all cloned from patterns the app already had The plan's insight was that the app already contained every pattern i18n needed — a per-user preference (currency), a device-detected onboarding step (country), a searchable picker (voice language). i18n was the fourth instance of each, not a new discipline. The library layer is i18next + react-i18next — pure JS, no dev-client rebuild — with t

2026-09-07 原文 →
开发者

React & Frontend Engineer Career Path — Beyond Knowing React (2026)

Knowing React Is Not the Same as Being a Frontend Engineer A huge number of self-taught developers can build a React component, wire up useState , and fetch data with useEffect . A much smaller number can build a frontend that stays fast as it grows, handles real error states gracefully, and doesn't quietly re-render half the page every time a user types a letter. That gap — between "I can use React" and "I can build a production frontend" — is where a lot of otherwise-promising candidates get stuck. It's not usually a knowledge problem about React's API. It's a gap in the surrounding skills: state architecture, performance, accessibility, and the unglamorous parts of frontend work that tutorials rarely cover in depth. This guide lays out a realistic path from "knows React" to genuinely job-ready frontend engineer, focused on the specific gaps that show up in real interviews and real codebases. This post originally appeared on the Ciphemic Academia blog . What "Frontend Engineer" Actually Requires Beyond React Basics The role is broader than component-building, and being explicit about what it covers helps target the right skills: State management at scale — not just useState in one component, but how state should flow through an application with many interconnecting pieces Performance — understanding re-renders, memoization, and why a frontend that works fine with test data can slow down badly with real data volume Accessibility and semantic HTML — building interfaces that actually work for everyone, not just visually API integration done properly — loading states, error states, race conditions, not just the happy-path fetch call Testing — component and integration tests that catch real regressions, not just tests that exist to say tests exist A typical React tutorial project touches the first item briefly and skips most of the rest. That's exactly why a portfolio built entirely from tutorial-style projects tends to fall short in real interviews. Step 1: Confirm Ja

2026-09-06 原文 →
AI 资讯

useEffect Fired Twice and It Found a Real Bug

useEffect fired twice, on mount, every single time, in development only. The API call inside it — a POST that created a resource — ran twice, and for about a day we had duplicate records showing up in a table that should have had exactly one insert per page load. The first reaction, and why it was wrong The instinct is to assume a bug — a rerender loop, a missing dependency, something actually broken. React 18's Strict Mode, in development, deliberately mounts, unmounts, and remounts every component once, specifically to surface effects that aren't properly cleaned up. It's not a bug in your code causing a double-fire; it's a bug in your code being caught by a feature built to catch exactly this. useEffect (() => { console . log ( ' mount ' ); // logs twice in dev, once in production const subscription = subscribeToUpdates (); // no cleanup — this is the actual problem Strict Mode is surfacing }, []); Production builds don't do this double-invocation — it's development-only, and specifically Strict-Mode-only, which is why the duplicate inserts we saw locally would eventually have shown up in production too, just less predictably, under a race condition instead of a guaranteed double-fire. Why this is a feature and not noise to suppress An effect that safely tolerates being mounted, torn down, and mounted again is an effect that correctly declares its dependencies and cleans up after itself — which is exactly the property you need for effects to behave correctly under React's concurrent features generally, not just under Strict Mode specifically. The double-invocation in development is a cheap, automatic test for that property, running on every single page load without you writing a test for it. The actual fix useEffect (() => { const subscription = subscribeToUpdates (); return () => subscription . unsubscribe (); // cleanup makes remounting safe }, []); For our specific case — a POST that shouldn't fire twice regardless of mount behavior — the deeper fix was recogn

2026-09-05 原文 →
AI 资讯

Advanced React Server Components Architecture in 2026 | Nainik Mehta

The Hidden Cost of React Server Components When React Server Components (RSC) were first introduced, they were hailed as the solution to the "bundle bloat" problem. By shifting rendering logic to the server, we promised users faster initial page loads and a cleaner separation of concerns. However, after deploying RSC at scale in production environments throughout 2026, many teams are discovering a harsh reality: RSC is not just a syntax update; it is a fundamental shift in architectural paradigm that punishes lazy design. If you aren't careful, your "performance-first" architecture can quickly become a massive bottleneck. Let’s dive into three critical lessons learned from the trenches of production RSC development. 1. The Sequential Waterfall Regression In the traditional client-side React world, we were accustomed to useEffect data fetching patterns. Moving to an async/await model in Server Components feels intuitive, but it introduces the risk of sequential waterfalls that block your entire render pipeline. The Anti-Pattern Consider a scenario where you need to fetch user profile data and their associated posts. A naive implementation might look like this: // ❌ The Waterfall: This will block the render until both finish async function Profile ({ id }) { const user = await getUser ( id ); const posts = await getPosts ( id ); return < ProfileView user = { user } posts = { posts } /> ; } In this example, the server must wait for getUser to resolve before even initiating the getPosts request. This doubles your latency. The Optimization: Parallelism and Streaming To fix this, you must leverage Promise.all to initiate requests concurrently. Even better, you should push these fetches into separate sibling components to allow React to stream the results as they arrive. // ✅ The Optimized Approach function Profile ({ id }) { return ( <> < Suspense fallback = { < UserSkeleton /> } > < UserComponent id = { id } / > < /Suspense > < Suspense fallback = { < PostsSkeleton /> }

2026-09-05 原文 →
开发者

I built a browser game that asks your microphone to imitate a robot

I wanted a microphone project with a very small brief: hear a sound, copy it, and see how close you got. That became Mimic Party Online , a browser game where each round gives you a short sound cue and one recording attempt. The cue might be a meme clip, an animal call, a machine noise, or something that is hard to describe without making the sound yourself. It looks like a toy, and it is. It also turned into a useful little audio problem. A score based only on volume would be boring, so the game needs to compare the shape of two sounds while staying fast enough to run in a browser. The round is intentionally simple The player does five things: Choose a sound pack. Listen to the reference. Record one take. Listen to the take. Read the score. The replay is important. People tend to remember the sound they meant to make. The recording tells them what actually came out. A convincing robot alarm can turn into a tired bicycle horn pretty quickly. Quick mode runs for four rounds. Survival mode gives the player three Mic lives and keeps the run going until those lives are gone. The game also has different routes, so a player can protect a streak or accept a shorter recording window for more points. The browser does the audio work The recording stays in the browser. The game uses the microphone stream, converts the take to mono PCM at 16 kHz, and extracts the values needed for scoring. The audio does not travel to a scoring server. For each take, the extractor looks at signals such as: pitch contour timing and active duration attack and energy rhythm and onset positions spectral shape The game does not use every signal for every sound. A pitched cue cares more about contour, while a machine noise depends more on its shape and attack. A rhythmic sound needs the hits to arrive at roughly the right moments. This is also why the score is more useful when it has labels. A result of 68 is not very instructive by itself. "Timing: 74" gives you something to work on in the next atte

2026-09-04 原文 →
AI 资讯

Migrating a Headless CMS? Your Frontend Shouldn't Know About It

A headless CMS migration often sounds simple: Contentful → Strapi Move the content, update the API calls, fix a few components, and you're done. Except... you're usually not. The hardest part of a headless CMS migration isn't moving the content. It's managing the contract between the CMS and the frontend . And if your React or Next.js application is tightly coupled to the CMS response structure, changing the CMS can turn into a much bigger project than expected. The problem Imagine your frontend directly consumes Contentful responses: const ProductCard = ({ product }) => { return ( < article > < h2 > { product . fields . title } < /h2 > < p > { product . fields . description } < /p > < img src = { product . fields . image . fields . file . url } / > < /article > ); }; It works. Until you migrate to Strapi. Now the response might look completely different: product . title product . description product . image . url Suddenly, the frontend needs to understand both CMS structures. And this problem isn't limited to simple fields. Things become much more complicated with: Rich text Media and assets References Nested relations Localization Draft/preview content SEO metadata Dynamic components Pagination GraphQL vs REST Different content modeling approaches The architecture I prefer Instead of allowing React components to consume the CMS directly, introduce a layer between the CMS and the application. ┌───────────────┐ │ Strapi │ └───────┬───────┘ │ ▼ ┌───────────────┐ │ CMS Adapter │ └───────┬───────┘ │ ▼ ┌───────────────┐ │ Domain Model │ └───────┬───────┘ │ ▼ ┌───────────────┐ │ React / Next │ └───────────────┘ The frontend doesn't need to know whether the data came from Strapi, Contentful, Shopify, WordPress, or something else. It just receives the data it needs. For example: type Product = { id : string ; title : string ; description : string ; image : { url : string ; alt : string ; }; }; The CMS adapter is responsible for transforming the CMS response into this model

2026-09-04 原文 →
AI 资讯

Why I Built Lexis - A Free, Local-First AI Productivity Suite

I've tried every productivity app out there. Notion, Obsidian, Todoist, Habitica, Day One - you name it. Every single one either wants my credit card, my email, or my data. Some want all three. So I built Lexis (lexisapp.xyz) - a free, local-first productivity suite that combines habits, notes, journal, tasks, documents, and an AI assistant into one app. No sign-up. No subscription. All data stays on your device. What is Lexis? Lexis is a web app (also available as a desktop Electron app) that bundles six productivity tools into one: Habits - Track daily habits with streaks, analytics, and a calendar view Notes - Rich text notes with full markdown support Journal - Daily journaling with mood tracking Tasks - Task management with priorities, due dates, and kanban-style organization Documents - Create and manage longer-form documents Noor - An AI assistant powered by three models (Ethos 4.7, Logos 4.5, Verse 4) that can chat, generate images, and help with your productivity data Everything runs in the browser. Your data is stored locally in IndexedDB. Nothing is sent to any server - not even us. Why Local-First? The local-first movement is about giving users ownership of their data. When your notes live in Notion's servers, you're at the mercy of their pricing, their uptime, and their privacy policies. With Lexis: Your data never leaves your device No account needed - just open the app and start using it Works offline - full functionality without internet (except AI features) GDPR compliant by design - we literally can't see your data because it never reaches our servers The AI Assistant (Noor) I wanted an AI that feels like it's yours, not a corporate chatbot. Noor is Lexis's built-in AI assistant with three models: Ethos 4.7 - the creative, conversational model Logos 4.5 - the analytical, precise model Verse 4 - the fast, efficient model Noor can chat with you about your tasks, habits, and notes. It can generate images. Voice dictation runs through your browser's bu

2026-09-04 原文 →
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 原文 →
AI 资讯

On-Device AI in React Native & Expo

In this Expo & React Native tutorial, you’ll learn how to run a large language model (LLM) directly on a user’s device: no server, no API key needed. We’ll start from scratch with a simple chat exchange, and progressively introduce more advanced features: multimodal input, speech-to-text, text-to-speech, voice activity detection, tool calling and RAG. Each concept is explained before the code, so you can follow along whether you're new to on-device AI. Why run AI On-Device? Most AI features rely on a cloud API: you send a request to a remote server, it runs the model, and sends a response back. That works well, but it comes with tradeoffs. Running the model directly on the device avoids all of them: Works offline — no internet connection required Privacy by design — user data never leaves the device Low latency — no network round-trip No cloud costs — inference is free The tradeoff is raw capability: on-device models are smaller and less powerful than frontier cloud models. But for many use cases like summarization, chatbots, or local search, they're more than good enough. About NobodyWho We'll use the NobodyWho library throughout this tutorial. It wraps llama.cpp in Rust and exposes a clean React Native API for running locally any model in .gguf format. Install it with npm install react-native-nobodywho or npx expo install react-native-nobodywho for Expo. Loading a Model NobodyWho can download a GGUF model for you directly from Hugging Face, cache it, and reuse it on every subsequent launch. That means you don't need to bundle anything into your app or manage downloads yourself: import { Chat } from " react-native-nobodywho " ; const chat = await Chat . fromPath ({ modelPath : " huggingface:NobodyWho/Qwen_Qwen3-0.6B-GGUF/Qwen_Qwen3-0.6B-Q4_K_M.gguf " , }); The first time this runs, the model is downloaded to the app’s cache directory. Every call after that loads the model directly. modelPath accepts a few different forms: Form Example Notes HuggingFace reference hf

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 资讯

Why My React App Still Runs on Singleton Classes

React spent the last decade training developers that a class is a code smell. Class components got deprecated, hooks won, and "just write a function" became the default advice for almost everything. That advice runs into a wall the moment a piece of code has to run outside a component: an HTTP interceptor, an event listener, a background task, a deep-link handler. None of those have a render tree to sit inside, which means none of them can call a hook. That's not a style opinion. It's a hard constraint. It's also the reason core pieces of infrastructure in most non-trivial React codebases — auth tokens, feature flags, routing rules, device identity, analytics — end up as classes, usually singletons, imported directly instead of consumed through a hook or a context provider. The render-tree boundary problem A hook only exists while its component exists. useState allocates memory tied to a place in React's tree; the moment that component unmounts, the state is gone, and before it mounts, the state isn't reachable at all. That's fine for almost everything a component owns. It stops being fine the moment something outside the tree needs the same piece of state. Authentication is the clearest version of this. A typical setup keeps the access token in a hook, refreshed on a timer, exposed to whatever component needs it: export const useSessionTokens = (): UseSessionTokens => { const [ tokens , setTokens ] = React . useState < AuthTokens | null > ( null ); const refreshAccessToken = async () => { if ( ! tokens ?. refreshToken ) return ; const newTokens = await refreshAndSetTokens ({ refreshToken : tokens . refreshToken }); setTokens ( newTokens ); return newTokens ; }; // ... return { tokens , refreshAccessToken , /* ... */ }; }; Perfectly normal hook. The problem shows up one layer down: an HTTP client's request interceptor is a plain function, registered once at app boot, running completely outside React's render tree. It can't call useSessionTokens() — it isn't a compon

2026-09-01 原文 →
AI 资讯

Upgrade .NET, React, and Next.js apps to latest versions with multiple AI Agents

Teaching an AI agent to upgrade .NET, React, and Next.js apps for real — not just talk about it Every engineering team has that repo. The one running a framework version from three or four years ago. Everyone knows it needs an upgrade. Nobody wants to be the one who breaks production doing it. That's the problem UpgradePilot — an open-source, multi-agent upgrade pipeline — is built to solve. And this week we shipped the piece that made it stack-agnostic: real, working upgrade automation for .NET, React, and Next.js, including repos that mix a .NET backend with a React or Next.js frontend in the same codebase. Here's what that actually means, because "AI upgrades your code" is a claim that's earned a lot of well-deserved skepticism. The design principle: shell out to the real tool, never fake it The easy version of this feature is an LLM that reads your package.json, guesses at new version numbers, and writes some plausible-looking code changes. That's not what we built. Every step in UpgradePilot's pipeline calls the actual toolchain: .NET — real dotnet restore, dotnet build, dotnet list package --outdated, dotnet ef migrations add. Package version bumps are verified by an actual restore, not assumed to work. React / Next.js — real npm install, npm run build, npm outdated. Codemods run through the actual react-codemod and @next /codemod CLIs — we pulled the real transform names directly from those projects' GitHub repos rather than guessing, because a fabricated transform name just fails at runtime. Target versions aren't invented. PackageTargetVersions come from dotnet list package --outdated and npm outdated — the same commands you'd run yourself. Codemod selection isn't invented either. UpgradePilot pulls React's and Next.js's own GitHub release notes, classifies breaking changes, and matches them against a verified catalog of real codemod transforms. If a step can't do something for real, it says so — with a confidence score and an explanation — instead of prete

2026-08-31 原文 →