今日精选
HOT最新资讯
共 32493 篇Ditch Electron: Spawning a Rust-Powered Python Sidecar from Bun
Part 1 of the ERTH Architecture Series: Launching local backends on Port 0, dynamic port negotiation, and establishing the dual-core desktop backbone. If you are building a modern desktop application, you are probably tired of the same old options. On one hand, you have Electron . It’s the industry standard, but it forces you to bundle a full Chromium browser and a Node.js runtime with every app. Even a simple "Hello World" takes up 200MB+ of disk space and eats hundreds of megabytes of RAM. For background utility utilities or AI assistants that need to be nimble, this is a massive tax. On the other hand, you have Tauri . It solves the bundle size issue by binding to OS-native WebViews and using Rust for the backend. But unless you are already a Rust expert, you will find yourself fighting the compiler's borrow checker and async lifecycles, slowing down your development velocity. But what if you want to use Python for its rich AI ecosystem (Ollama, SQLModel, PyTorch), but still keep the UI lightweight, fast-loading, and responsive? Welcome to the ERTH Stack ( E lectroBun + R obyn + T urso + H TMX). In this first post of our 5-part series, we will break down how to launch a high-performance Python sidecar backend directly from a Bun-based desktop shell, bypassing the bloated Electron environment entirely. The Concept: Heterogeneous Dual-Core In the ERTH architecture, the desktop app is split into two physical processes: The Main Process (Bun) : Responsible for native OS window management, IPC (Inter-Process Communication), and hosting the HTML/CSS view. We use ElectroBun —a next-generation, ultra-lightweight wrapper that binds directly to the OS-native WebKit engine (no Chromium bloat!). The Sidecar Process (Python/Robyn) : Responsible for heavy computations, database access, and local LLM orchestration. We use Robyn , an incredibly fast, Rust-based async Python web framework. Here is how the lifecycle and process boundaries interact: Step 1: Spawning the Robyn Sidec
Why I Abandoned Electron & SPAs to Build a 128MB Local-First Desktop AI Agent
How the ERTH Architecture (ElectroBun + Robyn + Turso + HTMX) breaks the obesity of modern desktop app development. If you’ve tried to build a cross-platform desktop application recently, you’ve likely faced the classic developer’s dilemma: Electron makes developer velocity fast, but at the cost of dragging a bloated Chromium kernel and Node.js runtime into every build. A simple "Hello World" easily eats up 200MB+ of disk space and hundreds of megabytes of RAM. Tauri solves the footprint issue by using OS-native WebViews and Rust, but forces you onto Rust’s steep learning curve, sacrificing the agility of rapid prototyping. The Python Distribution Hell : With the rise of local LLMs and Edge AI, Python is the de facto language for AI orchestration. Yet, packaging Python, its heavy dependencies, and databases into a double-click-to-run package for non-technical users remains a nightmare. Faced with these shackles, I decided to take a step back and rewrite the physical laws of desktop development. Today, I’m introducing the ERTH Stack ( E lectroBun + R obyn + T urso + H TMX)—a heterogeneous, local-first, zero-JS desktop application architecture designed for independent full-stack creators. And yes, the entire bundle—including a browser shell, a high-performance Python sidecar, a local database, and local AI agent execution—packages into a single 128MB standalone binary. Our open-source implementation is live on GitHub: 👉 GitHub Repository: bnpysse/erth_assistant The Core Pillars of the ERTH Architecture To achieve a minimalist footprint without sacrificing developer velocity, we structured the architecture into four core layers: ERTH ARCHITECTURE [E]lectroBun (UI Shell) ───[HTMX]───► [H]TMX (Zero-JS Frontend) │ ▲ (IPC) (HTTP) ▼ │ [R]obyn (Python Sidecar) ───────────► [T]urso / libSQL (Local-First DB) 1. [E]lectroBun: The Lightweight Shell Instead of Electron’s heavy Chromium, ElectroBun binds directly to the OS-native WebKit engine (Cocoa WebKit on macOS, WebView2 on W
Model Context Protocol (MCP): Giao Thức Tương Lai Cho AI
Model Context Protocol (MCP): Giao Thức Kết Nối Thế Giới Cho Trí Tuệ Nhân Tạo Trong thế giới AI đang phát triển với tốc độ chóng mặt, việc xây dựng các ứng dụng thông minh, có khả năng tương tác linh hoạt với dữ liệu và công cụ bên ngoài là một thách thức lớn. Các mô hình ngôn ngữ lớn (LLM) như GPT, Claude, hay Gemini dù mạnh mẽ nhưng thường hoạt động trong "vùng cô lập", thiếu khả năng truy cập trực tiếp vào các hệ thống bên ngoài theo thời gian thực. Đây chính là lúc Model Context Protocol (MCP) xuất hiện như một giải pháp cách mạng. MCP là một giao thức mở, được thiết kế để tiêu chuẩn hóa cách thức các ứng dụng cung cấp ngữ cảnh (context) cho LLM, giúp phá vỡ rào cản giữa trí tuệ nhân tạo và thế giới thực. Bài viết này sẽ đi sâu vào phân tích Model Context Protocol , từ định nghĩa, kiến trúc, đến các lợi ích và ứng dụng thực tế, giúp bạn hiểu tại sao nó được coi là "ngôn ngữ chung" của tương lai AI. Model Context Protocol (MCP) Là Gì? Model Context Protocol (MCP) là một giao thức mở, được phát triển để tạo ra một chuẩn giao tiếp thống nhất giữa các LLM và các nguồn dữ liệu, công cụ bên ngoài. Hãy tưởng tượng MCP như một "cổng USB" dành cho AI. Thay vì mỗi ứng dụng AI phải viết mã tích hợp riêng lẻ với từng loại cơ sở dữ liệu, API, hay hệ thống tệp tin (mỗi loại một kiểu "phích cắm" khác nhau), MCP cung cấp một giao diện chuẩn. Bất kỳ ứng dụng nào hỗ trợ MCP đều có thể kết nối với bất kỳ nguồn tài nguyên nào cũng hỗ trợ MCP một cách liền mạch. Mục Đích Cốt Lõi Của MCP Mục tiêu chính của Model Context Protocol là giải quyết vấn đề "fragmentation" (phân mảnh) trong hệ sinh thái AI. Trước MCP, việc tích hợp thường diễn ra rời rạc: Mỗi nhà phát triển ứng dụng phải tự xây dựng các "kết nối" tùy chỉnh. Mỗi lần cập nhật mô hình hoặc công cụ có thể làm hỏng các tích hợp cũ. Khó khăn trong việc chia sẻ và tái sử dụng các công cụ AI giữa các dự án. MCP giải quyết những vấn đề này bằng cách cung cấp một lớp trừu tượng chuẩn hóa. Kiến Trúc Và Cách Thức Hoạt Động Của MCP Kiến
Why modal.open() should return Promise , not Promise
How treating modals as typed async operations eliminates boolean state, callback chains, and runtime surprises in React apps. React applications often treat modals as UI details. A boolean flag. A conditional render. An onClose callback. That works fine for one dialog. But real products have modals that are actually business flows: confirm this destructive action rename this entity and return the new name pick a date range and apply it resolve a conflict before continuing complete a wizard step before the next one unlocks These flows need more than a boolean. They need typed input, typed output, and a way to await the result — just like any other async operation in your app. const result = await modal . open ( renameReportModal , { reportId : report . id , currentName : report . name , }); if ( result . status === " renamed " ) { await renameReport ({ id : report . id , name : result . name }); } That is the idea behind: npm install @okyrychenko-dev/react-modal-manager zustand A modal lifecycle manager. Not a component. Not a design system. A typed async contract between your app logic and your dialog UI. The problem with traditional modal state In most React apps, modal state starts locally: function ReportsPage () { const [ isRenameOpen , setIsRenameOpen ] = useState ( false ); return ( <> < button onClick = { () => setIsRenameOpen ( true ) } > Rename </ button > { isRenameOpen && ( < RenameModal onClose = { () => setIsRenameOpen ( false ) } /> ) } </> ); } And then real requirements arrive: const [ isRenameOpen , setIsRenameOpen ] = useState ( false ); const [ isDeleteOpen , setIsDeleteOpen ] = useState ( false ); const [ isShareOpen , setIsShareOpen ] = useState ( false ); const [ renameTarget , setRenameTarget ] = useState < Report | null > ( null ); const [ deleteTarget , setDeleteTarget ] = useState < Report | null > ( null ); const [ shareTarget , setShareTarget ] = useState < Report | null > ( null ); The UI is not the problem. The orchestration is: Where d
How I Cut SQL Query Time from 45 Seconds to 8 Seconds on 2.3 Million Rows
I inherited a SQL Server database with 2.3 million rows. Queries took 45 seconds. Users were frustrated. Dashboards timed out. Here is exactly what I did. Step 1: Find the slowest queries I used SQL Server's query store to identify the top 10 worst performing queries. Step 2: Check the execution plan Missing index warnings everywhere. Also saw table scans on a 2 million row table. Step 3: Add targeted indexes Created two non-clustered indexes on the most filtered columns. No over-indexing. Just what the queries actually needed. Step 4: Rewrite the worst join One query was joining 6 tables with a cross apply that made no sense. Restructured to inner joins with proper filter ordering. The result 45 seconds down to 8 seconds. An 82% improvement. Real-time dashboards started working again. Key lesson Check what is actually slow before changing anything. Most people skip this and waste time optimizing the wrong thing. What is your fastest query optimization win?
How I Cut SQL Query Time from 45 Seconds to 8 Seconds on 2.3 Million Rows
I inherited a SQL Server database with 2.3 million rows. Queries took 45 seconds. Users were frustrated. Dashboards timed out. Here is exactly what I did. Step 1: Find the slowest queries I used SQL Server's query store to identify the top 10 worst performing queries. Step 2: Check the execution plan Missing index warnings everywhere. Also saw table scans on a 2 million row table. Step 3: Add targeted indexes Created two non-clustered indexes on the most filtered columns. No over-indexing. Just what the queries actually needed. Step 4: Rewrite the worst join One query was joining 6 tables with a cross apply that made no sense. Restructured to inner joins with proper filter ordering. The result 45 seconds down to 8 seconds. An 82% improvement. Real-time dashboards started working again. Key lesson Check what is actually slow before changing anything. Most people skip this and waste time optimizing the wrong thing. What is your fastest query optimization win?
Indexes: Quickstart Using PostgreSQL (15 sec read)
Let's consider a table user . When we execute a query to find Emily , we are actually going through each record , looking whether the name column equals Emily . Indexes comes in when you want to speed this up. Let's create an Index with the name idx_users_name (the name can be anything, and it doesn't matter functionally): CREATE INDEX idx_users_name ON users ( name ); Now when you run SELECT * FROM users WHERE name = 'Emily' ; Postgres will use the index we just created (not by the name, the name is just for us) to execute that query, and the time complexity is reduced from O(n) to O(log n) .
The biggest race in the world? The 24 Hours of Le Mans is this weekend.
More than 350,000 spectators will watch 62 cars compete, day and night.
Show HN: StackScope – I crawled over 40k indie launches to see what they ship
Hey all, I built StackScope, a crawler/catalogue that looks at new product launches and shows what they were built with. It watches launches from Product Hunt, Show HN, and PeerPush, then crawls the public site behind each one. The goal is to show what people actually launched with: hosting, frameworks, analytics, DNS, security headers, legal pages, AI-builder signals, and other public clues. I started building it because most stack-detection sites look at the web as a whole. I was more interest
A Developer using AI. What Could Possibly Go Wrong?
I was lurking around dev.to because I was bored and I saw a post made by @sylwia-lask on the...
Show HN: Script to bulk delete Claude chats from the web UI
I haven't found a way to delete all chats in bulk like you can on Chatgpt. With Claude, you have to scroll to the bottom, select everything, and delete. The problem is, if you have a lot of chats, it becomes impossible. I created this script. It does it alone. I hope it helps someone. (conversations disappear from the UI slowly, over several minutes, and remember to keep the tab open until the console shows "Finished", refreshing away from the page can stop the deletion process.)