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

标签:#tutorial

找到 693 篇相关文章

开发者

Download Multiple Files as a ZIP in React — Including Multi-GB Archives

A “Download all as ZIP” button in React starts simple. A production version also needs progress, cancellation, retry, useful errors, and a plan for archives that are too large for browser memory. In this tutorial, we’ll use Eazip , an open-source ZIP toolkit for JavaScript and React. Its React package gives you a hook for starting ZIP jobs and a ready-made tray for showing their status. Everyday files can be zipped entirely in the browser. When the same feature needs to handle multi-GB archives or thousands of remote URLs, it can move the job to Eazip Cloud without adding any backend code. Install the React package npm install @eazip/react @eazip/react requires React 18 or later. It includes the core ZIP engine, so you do not need to install another Eazip package. Build a working ZIP download component This component lets a user select several files and download them as one ZIP: import { useState } from ' react ' ; import { EazipTray , useEazip } from ' @eazip/react ' ; export function FileZipDownload () { const [ files , setFiles ] = useState < File [] > ([]); const zip = useEazip (); return ( < section > < label > Files to download < input type = "file" multiple onChange = { ( event ) => setFiles ( Array . from ( event . currentTarget . files ?? [])) } /> </ label > < button type = "button" disabled = { files . length === 0 || zip . isBusy } onClick = { () => zip . download ({ files , zipName : ' selected-files.zip ' , }) } > Download { files . length || '' } files as ZIP </ button > < EazipTray /> </ section > ); } There are three Eazip pieces in this example: useEazip() gives the component its download commands and current task. zip.download() starts the ZIP job and returns immediately. <EazipTray /> shows progress, cancel, retry, partial results, errors, and the completed download. No provider or CSS import is required. What happens to the selected files? Without a strategy option, Eazip uses its Local strategy. The selected File objects stay on the user’s devi

2026-08-11 原文 →
AI 资讯

8051 What does SDCC do part 1 ?

1. Introduction and Problem Statement A good way to learn what a compiler really does when transforming a C source code into a binary is to disassemble the binary and compare it with the C source code. It is especially true for 8 bits microcontrollers like the 8051. In order to test SDCC we are going to use the following C source code. /* ========================================================================== * * Universal Test Corpus - Heterogeneous Architecture Analysis * * ========================================================================== */ #include <stdint.h> // 1. Global variables (testing absolute/relative addressing modes) volatile uint32_t global_var_32 = 0xDEADBEEF ; volatile uint8_t global_var_8 = 0x42 ; const char string_const [] = "TARGET_STRING" ; // 2. Function with parameter passing and local variables (stack / Frame Pointer test) int32_t callee_function ( int16_t a , int16_t b ) { volatile int32_t local_result = 0 ; // Basic and mixed arithmetic operations (8, 16, 32 bits) local_result += ( int32_t )( a * b ); local_result -= ( int32_t )( a / ( b | 1 )); // Avoid division by zero // Shift tests and logical operations (highly variable depending on ISAs) local_result = ( local_result << 2 ) ^ 0x55AA55AA ; local_result = ( local_result >> 1 ) | ( int32_t ) global_var_8 ; return local_result ; } // 3. Main function grouping complex control flows int main ( void ) { volatile int32_t accumulator = 0 ; int16_t i ; // Loop test (Conditional jumps, decrement, comparison tests) for ( i = 0 ; i < 10 ; i ++ ) { if ( i == 5 ) { accumulator += 100 ; } else { accumulator += i ; } } // Multiple branching test (Switch / Jump Table or cascaded if-else) switch ( global_var_8 ) { case 0x10 : accumulator += 10 ; break ; case 0x20 : accumulator += 20 ; break ; default: accumulator -= 5 ; break ; } // Function call (Stack management, save registers Link Register/PC) accumulator += callee_function (( int16_t ) accumulator , 3 ); // Pointer and indirect memory ac

2026-08-11 原文 →
AI 资讯

How to Build a Tableau Dashboard and Story

By the end of this guide you will have a published Tableau dashboard and a three-point story, built on a real dataset. It lives on a public URL you can put in an application. You build four small sheets. Each one makes exactly one point. You arrange them on a single screen, then walk a reader through them in three steps that end with a recommendation. Every step says what to click and what you should see afterwards. Four small sheets, rather than a wall of charts, because a dashboard has to argue for something. A screen holding everything you could build leaves the reader to work out what matters. Most readers will not do that work. Dashboard vs Story, in one line. A dashboard puts several charts on one screen so someone can explore. A story is a sequence of views with captions, clicked through in order, so someone is walked to a conclusion. Build both: the dashboard is what a hiring manager glances at, the story is what proves you can think. The original carries a diagram here. In words: Four separate worksheets stack on the left: a big single number, a set of vertical bars, a set of horizontal bars, and a scatter of circles. An arrow points right to one dashboard panel that holds all four of them arranged on a single screen: the number across the top, the two bar charts side by side in the middle, the scatter along the bottom. A second arrow points right to three story cards numbered one, two and three, each showing one of those views with a caption line above it. The worked example. Every instruction below is written against a real, free dataset: the Telco Customer Churn file on Kaggle, 7,043 customers, one row each. A finished analysis of it, including the Python script that shapes the data, is public at telco-churn-analysis . Swap in your own dataset and the steps do not change, only the field names do. Step 1: Shape the data before you open Tableau Tableau is a display layer. Deriving something inside it takes longer than deriving it upstream in SQL, Python or

2026-08-10 原文 →
AI 资讯

Technical Tenacity: What to Do When the Tools Fight Back

This guide gives you a repeatable loop for the days when nothing works, and four true stories showing it used on real problems. Here is what a working day actually contains. A website's firewall blocks you for no reason. A table that visibly exists tells your script it does not. A query runs for thirty minutes with no end in sight. A fix you know is correct changes nothing at all. None of that means you are doing it wrong. That is the job. What separates people who ship analyses from people who stop is technical tenacity : staying methodical when the tools fight back. It is not a personality trait you either have or lack. It is a small procedure, and you can learn it in the next ten minutes. The diagnosis loop (tenacity is a method, not a mood) Think back to the last time a tool beat you for an hour. What was the first thing you did when it failed, and what did you do second? Most people can name the first move and not the second, and the second is where the method lives. Gritting your teeth and re-running the same thing harder is not tenacity; it's frustration with extra steps. What experienced people actually run is a loop: Step Move 1. Read the actual message Not "it's broken" — the words. Error messages name the symptom precisely, even when the cause is elsewhere. 2. Form ONE hypothesis "The table isn't in the file the script reads." Specific enough to be wrong. 3. Run the cheapest test of it Prefer checks that take seconds — list the tables, count the rows, print one value. 4. Verify from a second vantage point Don't ask the tool that's confusing you whether it's confused. Check the file from outside, the data from a different program, the value with a different query. 5. Change ONE thing, re-run Change three things and you'll never know which one mattered — or which one broke something new. 6. Timebox, then change strategy If the current approach has eaten 30 minutes with no progress, stopping is a decision, not a defeat. There's usually a second road. Four tr

2026-08-10 原文 →
AI 资讯

COUNT in SQL, Explained for Beginners

COUNT looks like the simplest function in SQL, and it is the one that quietly trips up the most people in interviews and on the job. The confusion is almost always the same: COUNT(*) , COUNT(column) , and COUNT(DISTINCT column) look nearly identical but count three different things. Once you can say out loud what each one counts, a lot opens up. You can verify a data migration, find duplicates, and measure how complete a column is, all with the same little function. This guide is that explanation, with lots of small examples you can copy. The one-sentence version. COUNT(*) counts rows . COUNT(column) counts rows where that column is not NULL . COUNT(DISTINCT column) counts how many different non-NULL values that column has. Everything below is just that sentence, slowed down. The three forms of COUNT and what each one counts Picture one small table, customers , with a region column where two rows were never filled in: id name region 1 Maya North 2 Jordan South 3 Alex North 4 Sam NULL 5 Taylor NULL Now run the three forms on it: SELECT COUNT(*) AS all_rows, COUNT(region) AS rows_with_region, COUNT(DISTINCT region) AS different_regions FROM customers; all_rows rows_with_region different_regions 5 3 2 COUNT(*) = 5. Every row, no exceptions. The * means "the row itself," so NULLs never matter. COUNT(region) = 3. Only the rows where region has a value. Sam and Taylor are skipped because their region is NULL. COUNT(DISTINCT region) = 2. The different values are just North and South . The two Norths collapse to one, and NULL is not counted. The NULL rule that makes them disagree Predict it first. A table has 100 rows. Twenty of them have no email address. What does counting the email column give you? Say the number before you read on. Here is the whole trick in one line: COUNT(*) counts rows. COUNT(something) counts non-NULL values of that something. So the moment a column has any NULLs, COUNT(column) comes back smaller than COUNT(*) . That gap is not a bug, it is informat

2026-08-10 原文 →
AI 资讯

Entity Resolution: One Real Thing, Many Messy Names

This guide walks through five steps for working out which records are the same real thing, and merging them without wrecking your data. It runs on real chart data, and it includes the two times the rules came out wrong. Here is the problem in one example. Count the distinct artists in Billboard's public chart history and the number is wrong. "Elvis Presley" and "Elvis Presley With The Jordanaires" are the same man, and so are five other credit strings. One real-world entity , seven database strings . Every dataset with human-entered names has this. Customers who signed up twice. "IBM" against "I.B.M." against "International Business Machines". The same supplier in two systems, spelled two ways. The work of fixing it is called entity resolution . Matching across two datasets is record linkage . Removing duplicates inside one is deduplication . They are the same skill pointed at different situations, and it is one of the most common tasks an analyst actually gets handed. The vocabulary map Term Meaning Entity The real-world thing: one artist, one customer, one company Entity resolution Figuring out which records refer to the same entity Record linkage The same problem across two datasets. "Is row 5 in file A the same person as row 90 in file B?" Formalized by Fellegi & Sunter (1969) Deduplication The same problem inside one dataset Normalization / standardization Transforming values toward a canonical form (lowercasing, trimming, cutting suffixes) so equal things become equal strings Match key The cleaned column(s) you actually join on Match rate The share of records that found their counterpart. This is the number that keeps the whole exercise honest Clerical review Human eyes on the records the rules could not decide. This is a formal stage of the classic framework, not an admission of failure Step 1: measure the fragmentation before fixing anything The worked example is Billboard Hot 100 history, 1958 to present. The goal is one clean row per artist. Before writing

2026-08-10 原文 →
AI 资讯

The Laravel 13 Features That Matter in Real Projects

The Laravel 13 Features That Matter in Real Projects Laravel 13 shipped on March 17, 2026, and the upgrade story is unusually simple: zero application-level breaking changes from Laravel 12, one hard requirement (PHP 8.3), and several features that are genuinely useful in production rather than just impressive in release notes. This post focuses on the features you will actually reach for on real client projects — not an exhaustive tour. For the full release overview, upgrade checklist, and breaking changes reference, see Laravel 13: Features, Upgrade Guide, and Breaking Changes . Prerequisites: PHP 8.3+, Laravel 13.x (latest stable: 13.14.0 as of June 2026), Composer 2.x. 1. PHP Attributes on Models and Controllers Laravel 13 adds PHP 8-style #[Attribute] support across 15+ framework locations. The old property-based syntax still works — this is purely additive. On Eloquent Models: use Illuminate\Database\Eloquent\Attributes\Table ; use Illuminate\Database\Eloquent\Attributes\Fillable ; use Illuminate\Database\Eloquent\Attributes\Hidden ; #[Table('posts', primaryKey: 'id', incrementing: true, timestamps: true)] #[Fillable('title', 'body', 'user_id')] #[Hidden('deleted_at')] class Post extends Model {} On Controllers: use Illuminate\Routing\Attributes\Controllers\Authorize ; use Illuminate\Routing\Attributes\Controllers\Middleware ; #[Middleware('auth')] class CommentController extends Controller { #[Middleware('subscribed')] #[Authorize('create', [Comment::class, 'post'])] public function store ( Post $post ) { } } When to actually use this: Attributes shine on large domain models where $fillable , $hidden , $casts , and relationship declarations are scattered across the class. Collocating table definition and mass assignment rules at the top of the file improves readability at a glance. On small CRUD models, the tradeoff is extra import lines for minimal gain. Common mistake: Mass-converting every existing model to attribute syntax in a single PR. It creates a lar

2026-08-10 原文 →
AI 资讯

Build a React client intake form with file uploads

Client intake often requires two types of information: searchable answers and files for review. This Vite and React example collects both in the same response. You can try the form without an account. Ask only what you need The example asks for: the client's name; a work email address; the result they need; an optional target date; up to five briefs or reference files. Each answer should help someone prepare for the first call. Leave detailed discovery questions for the call. Define the form The form schema lives in the React app: import { createClient , defineForm , FilloForm } from " @usefillo/react " ; const intake = defineForm ({ id : " vite-client-intake " , title : " Tell us about your project " , description : " Tell us what you need, when you need it and which files will help us prepare. " , pages : [ { id : " intake " , blocks : [ { id : " name " , kind : " short_text " , label : " Your name " , required : true }, { id : " email " , kind : " email " , label : " Work email " , required : true }, { id : " outcome " , kind : " long_text " , label : " What result do you need? " , required : true , }, { id : " target-date " , kind : " date " , label : " Target date " }, { id : " documents " , kind : " file_upload " , label : " Briefs or reference files (PDF, DOCX, PNG or JPG) " , accept : [ " .pdf " , " .doc " , " .docx " , " .png " , " .jpg " , " .jpeg " ], maxFiles : 5 , }, ], }, ], settings : { submitLabel : " Send project details " }, }); Keep the form and field IDs after you collect the first response. Fillo uses them as stored answer keys. You can change labels and help text without changing the IDs. The React app controls the route, layout, styles and what happens after submit. Fillo handles the schema, validation, uploads and responses. The SDK renders React controls in the page. It does not use an iframe. Send files straight to storage The browser sends each file to the storage connected to the Fillo workspace. The Vite app does not proxy the file throu

2026-08-10 原文 →
AI 资讯

Nodes and Networks: How Blockchains Actually Stay Decentralized

When someone says "Bitcoin has over 15,000 nodes worldwide," they mean 15,000+ independent computers are each running Bitcoin software and each maintaining their own full copy of the blockchain. No server owns the truth. Every node checks it for itself. That single fact — every node independently verifies every transaction and block against protocol rules — is the reason blockchains don't need a central authority. If one node tries to cheat, the rest simply ignore it. There's no admin account to compromise because there's no admin. Not All Nodes Do the Same Job Full Node Downloads and stores the entire blockchain, every block since genesis, and independently validates everything against consensus rules. Highest security ~500 GB for Bitcoin ~1 TB for Ethereum This is the backbone of network security. A full node doesn't trust anyone's summary of the chain; it recomputes validity itself. Light Node (SPV) Stores only block headers, not full transaction data. Uses Merkle proofs and relies on full nodes to verify transactions. Low storage, ~50 MB Trusts full nodes for verification What most mobile wallets run Mining/Validator Node A full node that also participates in block creation. Miners (Proof of Work) solve computational puzzles; validators (Proof of Stake) stake cryptocurrency as collateral. Both earn rewards for securing the network. Creates new blocks Earns rewards Requires specialized hardware (PoW) or capital at stake (PoS) Archive Node Everything a full node stores, plus historical state at every block height. Complete history ~15+ TB for Ethereum Used by explorers, analytics platforms, and enterprise tooling Why Peer-to-Peer Instead of Client-Server A traditional web service is client-server: your browser requests data from a company's servers. If those servers go down, the service is unavailable. That's a single point of failure by design. Blockchain networks use peer-to-peer (P2P) architecture instead. Every participant is simultaneously a client and a serv

2026-08-10 原文 →
开发者

Geo-Blocking: Block Malicious Traffic from Specific Countries (2-Minute Setup)

Why Geo-Block? Not every country needs to reach your server. If you run a local business in Brazil, you don't need traffic from North Korea. If you serve customers in the EU, you probably don't need visitors from 150 other countries hitting your login page. Geo-blocking at the WAF level stops unwanted traffic before it ever reaches your application. No CPU spent. No database queries wasted. No bandwidth consumed. The Numbers from My Server After 30 days of logging, I checked where attacks came from: Traffic Source % of Total Requests % of Attacks Target countries (where my customers are) 23% 8% Non-target countries 77% 92% 77% of my traffic came from countries I don't serve, and 92% of attacks originated from those countries. Geo-blocking the non-target regions would eliminate the vast majority of malicious traffic with zero impact on real users. Setting Up Geo-Blocking in SafeLine Step 1: Go to IP Groups -> Geo Blocking in the dashboard. Step 2: Choose your approach: Option A: Allow-list mode (strictest) Block everything, then whitelist specific countries. Block : ALL Allow : United States , Canada , United Kingdom , Germany , France , Netherlands Option B: Block-list mode (targeted) Allow everything, then block specific high-noise regions. Block : Russia , China , Vietnam , North Korea , Iran Step 3: Apply the rule. Done. What Happens to Blocked Visitors Blocked IPs see a 403 Forbidden page. They can't reach your application at all — the WAF drops the connection at the proxy layer. Your app server never sees these requests. SafeLine logs every geo-blocked request to Attack Logs. You'll see: Which country the IP was from What URL they tried to access The exact timestamp Which Countries to Block Based on my 30-day log analysis and common community reports: Almost always safe to block: North Korea — 0 legitimate traffic for 99.9% of sites Iran — heavy scanner activity, minimal legitimate traffic (for non-Iranian sites) High scanner volume, consider blocking if not yo

2026-08-10 原文 →
AI 资讯

How to Set Up Rate Limiting on Any Web App (Free, No Code Changes)

The Problem Your login page, search endpoint, or contact form is getting hammered. Rate limiting is the fix — but implementing it in application code means finding every endpoint, writing middleware, choosing a storage backend, and deploying changes. On a WAF, you set it once and it applies everywhere. Why WAF-Level Rate Limiting Is Better Approach Code-Level WAF-Level Setup time Hours to days 5 minutes Code changes Required None Applies to One endpoint at a time All routes with one rule Storage Redis/Memcached needed Built into WAF Performance impact Hits your app server Blocked at proxy Updates Deploy new code Change a rule in dashboard Step-by-Step: Rate Limit Setup 1. Log into SafeLine Dashboard Go to https://<your-ip>:9443 . Navigate to Rules -> Add Rule -> Rate Limiting. 2. Create Your First Rule — Login Protection Name: Login brute force protection Match: URL contains /login OR /wp-login.php OR /auth Limit: 5 requests per minute per IP Action: Block (return 429 Too Many Requests) Block duration: 15 minutes This stops credential stuffing cold. An attacker who tries 5 wrong passwords in 60 seconds gets blocked for 15 minutes. That's a maximum of 480 attempts per day — vs unlimited without rate limiting. 3. Search Endpoint Protection Name: Search rate limit Match: URL contains /search OR /query Limit: 30 requests per minute per IP Action: Challenge (JS captcha) Search endpoints are expensive. A single user running a script can do 1,000+ queries per minute and degrade performance for everyone. 30/min is generous for humans but stops scripts. 4. Global Baseline Name: Global request limit Match: /* Limit: 300 requests per minute per IP Action: Throttle Catches anything that slips through specific rules. 300/min = 5/sec, which is more than any human needs. What Happens When a Limit Is Hit SafeLine logs every rate limit trigger to the Attack Log. You'll see: Which IP triggered it Which endpoint they were hitting Time of the trigger Whether they got blocked, challenge

2026-08-10 原文 →
AI 资讯

How to stop a Claude Code agent writing outside a directory

When you're sitting in front of an agent, "don't touch anything outside src/ " is enforced by you noticing. Unattended, it has to be enforced by something that runs whether or not anyone is watching. Claude Code gives you two mechanisms for that, and they are not interchangeable. One is declarative and can't express what you probably want. The other can, but is structurally blind to a whole category of writes. Here's what each one actually does, and the code for the second. Why permissions.deny isn't enough Permission rules live in settings.json and take the form Tool(specifier) : { "permissions" : { "deny" : [ "Read(./.env)" , "Read(./.env.*)" , "Write(./.github/**)" , "Write(//etc/**)" ] } } Paths are gitignore-style. A leading // means absolute, ~ means home, and anything else is relative to the settings file. deny beats ask , which beats allow , and rules merge across scopes rather than override — so a deny in project settings still applies even when your personal ~/.claude/settings.json allows the same thing. That precedence is the useful part: a deny rule is hard to undo by accident. The problem is shape. What you want for an unattended agent is an allow-list — only these directories, nothing else. What deny gives you is a block-list, and you cannot build the first out of the second. The obvious trick of denying everything and allowing back the exceptions fails on exactly the precedence rule that makes deny valuable: Write(**) in deny outranks every allow you pair it with, so the agent can write nothing at all. Claude Code does have one allow-list-shaped boundary — the project root, plus whatever you list in additionalDirectories . That stops an agent wandering into /etc . It says nothing about which directories inside your project it may write, which is usually the interesting question. Nobody's real worry is that a scheduled agent edits /etc/hosts . It's that the agent tasked with writing articles decides to fix its own scheduling config. So for anything fin

2026-08-10 原文 →
AI 资讯

Topic selected: Option A – Purely Technical: "Building a Secure AI Proxy for Browser Tools

This is the strongest choice. It teaches a tangible, highly demanded skill (API key security) with actual code, making the backlink to AfriWidget feel like a natural, neutral citation rather than a sales pitch. Here is the article, rewritten to be strictly technical, objective, and genuinely useful for dev.to readers. Stop Exposing Your AI API Keys: Build a Secure Proxy with Cloudflare Workers We have all seen it. You open the browser's DevTools on a "cutting-edge" AI startup's landing page, check the Network tab, and find a direct POST request to api.openai.com containing a plaintext API key in the headers. It is one of the most common—and dangerous—mistakes in modern web development. Exposing your LLM API key client-side is an open invitation for abuse, leading to stolen credits, hefty bills, and potential account suspension. The standard solution is the Backend-for-Frontend (BFF) proxy pattern. But how do you implement it practically, cheaply, and securely without spinning up a heavy Express server? In this guide, I will walk you through building a lightweight, serverless AI proxy using Cloudflare Workers to securely call Groq (or OpenAI) APIs from your browser-based calculators and tools. The Architecture: How It Works Instead of your frontend talking directly to the AI provider, we introduce a stateless middleware layer: Browser App → Cloudflare Worker (Proxy) → Groq/OpenAI API ↑ ↑ (No API Key) (API Key stored securely in Worker env vars) The Worker's responsibilities: Receive the sanitized calculation context from the frontend (numbers, not PII). Attach the secret API key via environment variables. Forward the request to the LLM provider. Stream or return the generated insight back to the client. Step 1: Scaffolding the Cloudflare Worker We will use the new create-cloudflare CLI. Make sure you have Node.js installed. npm create cloudflare@latest ai-proxy Choose "Hello World" worker and TypeScript. Once inside the directory, install the Groq SDK: npm install gr

2026-08-10 原文 →
AI 资讯

Why a 24 GB GPU Does Not Give Your Local LLM 24 GB

I keep seeing the same local LLM sizing mistake: "The model file is smaller than my GPU, so it should fit." That is only the first check. A 24 GB GPU does not give your model a clean 24 GB memory budget. The display stack, runtime, temporary buffers, model weights, and KV cache all compete for the same space. Here is the worksheet I use before I download a model or rent a GPU. 1. Start with the weight floor The simplest weight estimate is: weight_memory_gib = parameters * bits_per_parameter / 8 / 1024^3 For a simple 4-bit estimate: Model size Weight floor 7B 3.3 GiB 13B 6.1 GiB 70B 32.6 GiB These are floors, not promises. Real quantized files can also contain scales, metadata, and layers stored at higher precision. If you know the exact checkpoint size, use that instead of the simple bits-per-parameter estimate. Also use total parameters for a sparse mixture-of-experts model unless your runtime really offloads inactive experts. Active parameters describe compute per token. They do not automatically describe how many weights must be stored. 2. Reduce the physical capacity to a usable budget I normally start with 90 percent usable VRAM for planning: usable_vram = physical_vram * usable_fraction For a 24 GB card: 24 * 0.90 = 21.6 GiB usable The exact reserve depends on the OS, display use, driver, runtime, graph capture, allocator behavior, and other processes. The important part is to stop treating the number on the box as fully available. 3. Add the KV cache The KV cache is where context length and concurrency become expensive. A useful planning formula is: kv_cache_bytes = 2 * layers * kv_heads * head_dimension * context_tokens * concurrent_sequences * bytes_per_kv_value The factor of two stores keys and values. Take a model with: 32 layers 8 KV heads 128 dimensions per head 8,192 cached tokens 1 concurrent sequence 16-bit KV values, which use 2 bytes The KV cache is about 1 GiB. Raise the context to 32,768 tokens and it becomes about 4 GiB. Keep that context and ru

2026-08-10 原文 →
AI 资讯

Surviving the AI Bubble With Two Pieces of Junk From Amazon

Everyone is building agents. You should build escape hatches. We are living through the most expensive group hallucination in tech history. Every SaaS now has a chatbot stapled to it. Every CEO is an "AI thought leader" on LinkedIn. Every startup pitch deck is just the words "autonomous," "agentic," and "10x" in different fonts. NVIDIA could buy a small country. OpenAI burns through more cash in a quarter than NASA did getting to the moon. And for what? So you can generate slightly worse emails, slightly faster? Look, I love AI. I actually build with it. But I have been around long enough to know what a bubble smells like. It smells like free credits, unearned confidence, and a thousand wrappers around the same API call. The bubble will pop. Not in a dramatic, newspapers falling from the sky way. It will pop quietly. Credits will dry up. Models will get paywalled behind enterprise tiers. The cloud bill you have been ignoring will finally show up. And all those beautiful, cloud-dependent workflows you built will start blinking red. So while everyone else is trying to figure out how to make their AI agent book a flight, I have been asking a different question. What do you build when you assume the internet will get worse, the cloud will get more expensive, and you will need actual skills that survive a downturn? The answer, annoyingly, is two pieces of junk from Amazon that cost less than your last Uber Eats order. Piece of Junk #1: The $25 Router That Sees Everything It is not sexy. It is called the GL.iNet GL-MT300N-V2. Everyone calls it the Mango. It looks like a little yellow box that should have come free with your ISP in 2014. You can buy it on Amazon for about twenty six dollars when it is on sale. Sometimes twenty. Inside it is a tiny Linux computer running OpenWrt. It has two ethernet ports, a USB port, and just enough RAM to be dangerous. Most people buy it to get free WiFi in hotels. I bought it to spy on my own network. Because here is the dirty secret of

2026-08-09 原文 →
AI 资讯

Local LLMs in 2026: What Actually Runs Well on a Laptop Now

Two years ago, "run a language model locally" meant a weekend of compiling, a graveyard of CUDA errors, and a model that answered like it had a concussion. In 2026, you can install one tool, type one command, and have a genuinely useful assistant running on a laptop with no internet connection. Here's an honest map of what works, what doesn't, and where the sharp edges still are. Why bother running locally at all Three reasons keep pulling developers back to local inference: Privacy. The prompt never leaves your machine. For code you can't paste into a cloud box, or personal data, that's non-negotiable. Cost and offline. No per-token bill, no rate limits, and it works on a plane. Latency and control. No network round-trip, and you pin the exact model version forever — no silent upgrades changing your outputs. The catch has always been quality-per-watt. That's the number that moved. The hardware tiers, honestly 8 GB RAM / integrated GPU: You can run 3–4B parameter models at 4-bit quantization. Good for autocomplete, summarizing, simple Q&A. Don't expect deep reasoning. 16 GB RAM: The sweet spot for most developers. 7–9B models run comfortably and are genuinely helpful for coding assistance and drafting. 32 GB+ or a discrete GPU with 16–24 GB VRAM: Now you're running 20–30B models, or bigger models at aggressive quantization, with real reasoning ability. Apple Silicon (unified memory): Punches above its weight. A machine with 32–64 GB of unified memory runs models that would need an expensive discrete GPU on other platforms, because the CPU and GPU share the same memory pool. Quantization: the trick that makes it possible The reason a 7B model fits in 16 GB is quantization — storing weights at 4 bits instead of 16. The common format you'll see is GGUF, and the common recipe is 4-bit (often labeled Q4). The quality loss from full precision to 4-bit is surprisingly small for most tasks, while the memory savings are 4x. Below 4-bit (2–3 bit) the model starts to degrade n

2026-08-09 原文 →
AI 资讯

Build map guidance that follows the user without blocking pinch-to-zoom

A navigation map should help the user move through the world, not fight every gesture they make. I recently hit a deceptively simple bug while building field guidance in a React Native / Expo app: the route rendered correctly and the camera followed the current position, but users could not meaningfully zoom or pan while walking. They could pinch the map, but the next location update snapped the camera back to a fixed zoom. The map looked active. The experience felt broken. The cause: two camera owners The implementation combined two useful features: followsUserLocation={true} on the native map. animateCamera(...) after every location update, using a fixed walking zoom and pitch. Each feature was reasonable on its own. Together, they gave the camera two automatic owners and the user none. A pinch gesture changed the zoom for a fraction of a second. Then a GPS update arrived and our effect applied the navigation camera again. On iOS, native user-follow behavior added another layer of camera control. A better model: follow mode and explore mode The fix was not to stop navigation. Route progress, distance, bearing, breadcrumb recording and off-route detection should all continue regardless of what the user does with the map. Only the camera behavior should change. We now keep a small piece of local UI state: const [ cameraFollowing , setCameraFollowing ] = useState ( navigationActive ); useEffect (() => { if ( ! navigationActive || ! cameraFollowing || bearing == null ) return ; mapRef . current ?. animateCamera ( walkingCamera ( currentCoordinate , bearing ), { duration : 480 }, ); }, [ currentCoordinate , bearing , navigationActive , cameraFollowing ]); The native follow prop uses the same state: < MapView showsUserLocation followsUserLocation = { navigationActive && cameraFollowing } onTouchStart = { () => { if ( navigationActive ) setCameraFollowing ( false ); } } /> As soon as the user touches the map, the camera enters explore mode. Pinch, pan and rotation work n

2026-08-09 原文 →
AI 资讯

Cuando tu clasificador parpadea: histéresis para señales que oscilan

Tienes una señal que a cada observación te dice en qué estado estás: un monitor de salud que dice OK o CAÍDO , un detector de conectividad, un clasificador de modo. Y cerca del umbral oscila : OK, CAÍDO, OK, CAÍDO, OK . Cada cambio dispara algo —una alerta, un failover, entrar o salir de una posición— y de repente tu sistema está temblando por ruido, no por una transición real. Es el mismo problema que resuelve el termostato de tu casa desde hace un siglo, y la solución tiene nombre: histéresis . No cambies de estado hasta que el nuevo se haya sostenido. La regla, en una frase Un estado nuevo solo se confirma tras repetirse N observaciones consecutivas. Si el candidato cambia o revierte antes de llegar a N , la cuenta se reinicia. El estado vigente se mantiene estable; los parpadeos se ignoran. Lo empaqueté como librería — hysteresis-state , Python puro, sin dependencias— porque lo reescribía una y otra vez: from hysteresis_state import HysteresisState estado = HysteresisState ( " OK " , confirmations = 3 ) for lectura in stream : # "OK" / "CAIDO" actual = estado . update ( lectura ) # solo cambia tras 3 lecturas seguidas if estado . changed : # ¿esta lectura provocó la transición? alertar ( actual ) Aliméntalo con OK, CAÍDO, OK, CAÍDO, OK y no pasa nada: ningún candidato se sostuvo. Hacen falta tres CAÍDO seguidos para que el cambio se confirme. El detalle que casi siempre falta: histéresis asimétrica Un umbral único tiene un problema sutil. Si exiges 3 confirmaciones para entrar en fallo, también tardas 3 en salir — y a veces quieres justo lo contrario: caer rápido a lo seguro, volver despacio a lo arriesgado . Es el comportamiento de un disyuntor eléctrico: salta a la primera, se rearma con cautela. Se resuelve dejando que el umbral dependa de la transición: # 1 confirmación para caer a "CAIDO", 5 para volver a "OK" conf = lambda desde , hacia : 1 if hacia == " CAIDO " else 5 estado = HysteresisState ( " OK " , confirmations = conf ) estado . update ( " CAIDO " )

2026-08-09 原文 →
AI 资讯

Zero Knowledge Proofs: How to Win Every "Trust Me Bro" Argument With Math

A tutorial where you prove things without revealing things, and yes, the math actually maths. Here's something the internet doesn't want you to know: you overshare every single time you prove something. Prove you're over 21 at a bar? You hand over a card with your name, your address, your height, and your terrible 2019 haircut. Prove your income to a landlord? Here's every transaction I've made since college, please don't judge the 3am food delivery. We built the entire digital world on a verification model that boils down to "here's everything, trust me bro." Not anymore. There's a branch of cryptography that lets you prove a statement is true while revealing nothing else . It sounds fake. It's called a zero knowledge proof , and by the end of this article you'll understand one well enough to check it with Python. Then we'll look at Midnight , a blockchain that turned this party trick into a developer platform. Let's go. 🚀 🪪 The Trust Me Bro Problem Every verification system you use today works by disclosure . You prove things by showing the underlying data: Prove your age ➡️ show your whole ID Prove you can pay ➡️ show your bank statements Prove you're a real user ➡️ solve a CAPTCHA and sacrifice your data to the algorithm gods The data doesn't just get seen . It gets stored , and eventually it gets breached , and then a guy named xX_darkweb_Xx is selling your identity for the price of a burrito. The verifier never needed the data. They needed one bit of information : true or false. Everything else was collateral damage. In short: we've been answering yes or no questions with our entire life story. 🕵️ The Party Trick That Started It All Zero knowledge proofs let a prover convince a verifier that a statement is true without revealing why it's true. The classic example is Where's Waldo. Say I claim I found Waldo on the page and you don't believe me (fair, you've seen my code reviews). I could point at him, but then I've revealed the answer and ruined the puzzle. Ins

2026-08-08 原文 →
AI 资讯

Avoiding the 5 Mistakes Most Tutorials Make When Creating a File Encryption Tool

Why “it encrypts” doesn't equate to “it’s secure” If you want to find a tutorial for encrypting files in code, your search results will provide dozens of tutorials. Most of these tutorials will produce code that, on the surface, performs encryption. Users can provide plaintext, receive ciphertext, and the code also performs decryption. Unfortunately, the phrase “the output looks scrambled” is an unsecure way to test a program for security. These tutorials fail to incorporate security practices, which will result in these tools being rejected in real life security assessments. By identifying these mistakes, we can reason about the validity of these encryption schemes. This article covers the correct way to build a file encryption tool and the mistakes that beginner encryption tools include. These mistakes will help you learn the correct way to build an encryption tool. SecureVault (Node.js, packaged with no dependencies) is a command-line tool that is referenced throughout to help provide context to the design decisions that were made for this tool. Prerequisite mindset: When designing secure systems, always assume that the attacker knows more than you. Do you really think that your adversary will only submit the inputs you assumed they would submit? They will submit corrupted inputs, they will submit old ciphertexts, and they will do anything you thought was impossible. You need to have a secure design. You must think "what malicious inputs can I handle here?" . The goal: three guarantees, not one Before you even think about writing code, you need to know exactly what you mean by that something is secure. A good file encryption tool must provide three guarantees. Most of the tutorials that I have seen think only about the first one. Confidentiality - the attacker that steals the file should not be able to read the file. Integrity - If the attacker alters the encrypted file, you will know. Authenticity - The file can only be generated by a user that knows the passwor

2026-08-08 原文 →