AI 资讯
PyTrees Are Not One Thing: JAX, PyTorch, and TensorFlow Compared
PyTrees look deceptively simple. You flatten a nested Python object into leaves, keep a structure descriptor, and later rebuild or map over the same shape. That abstraction is powerful enough to carry optimizer states, model parameters, batched inputs, gradients, and sharding annotations. It is also just ambiguous enough that three major frameworks implement three subtly different languages under the same idea. This note compares JAX jax.tree_util , PyTorch torch.utils._pytree , and TensorFlow tf.nest . I tested the behavior in two environments: an older stack with JAX 0.4.35, PyTorch 2.2.2, TensorFlow 2.20.0, and a newer stack with JAX 0.10.0, PyTorch 2.12.0, TensorFlow 2.21.0. Most flatten/unflatten semantics were stable across these versions. The main version-sensitive result is PyTorch: _pytree.tree_map in 2.2.2 accepts only one pytree, while 2.12.0 supports multiple pytrees and behaves much closer to JAX prefix-style mapping. The short version: JAX treats pytrees as a transformation language, PyTorch is converging toward that model in torch.func , and TensorFlow exposes a broader nested-structure utility through tf.nest . Those differences show up exactly where backend-agnostic libraries usually hurt: None , dictionary order, custom containers, tree_map , autodiff, and vectorization. The Shape Of The APIs The three APIs have the same surface story but not the same contract. from jax import tree_util as jtu from torch.utils import _pytree as tpu import tensorflow as tf leaves , treedef = jtu . tree_flatten ( tree ) tree = jtu . tree_unflatten ( treedef , leaves ) tree = jtu . tree_map ( f , * trees ) leaves , spec = tpu . tree_flatten ( tree ) tree = tpu . tree_unflatten ( leaves , spec ) tree = tpu . tree_map ( f , tree ) # PyTorch 2.2.2 tree = tpu . tree_map ( f , * trees ) # PyTorch 2.12.0 leaves = tf . nest . flatten ( tree ) tree = tf . nest . pack_sequence_as ( structure , leaves ) tree = tf . nest . map_structure ( f , * structures ) Flattening means "whi
AI 资讯
Give Your Scheduling Bot Its Own Calendar
A scheduling link makes the human do the work; a scheduling agent with its own calendar does the negotiating. Booking pages outsource the back-and-forth to a UI. The agent model keeps it where it already happens — in email — and answers from a real address with a real calendar behind it. The setup: meeting requests land at scheduling@agents.yourcompany.com , an LLM parses intent, the agent checks availability against its own free/busy, proposes slots, and creates events that show up as normal invitations in Google Calendar, Microsoft 365, and Apple Calendar. No human mailbox in the loop, no delegation permissions, no calendar borrowed from whoever set the bot up. This runs on a Nylas Agent Account — a hosted mailbox-plus-calendar you provision through the API. Agent Accounts are in beta, so expect some movement before GA. Provision the identity One CLI command or one API call: nylas agent account create scheduling@agents.yourcompany.com The primary calendar is provisioned automatically — no extra call before you can create events on it. The API equivalent is POST /v3/connect/custom with "provider": "nylas" and the email address in settings ; no OAuth refresh token involved. Save the grant ID, then subscribe a webhook to four triggers: message.created , event.created , event.updated , and event.deleted . When Nylas sends the challenge GET to your endpoint, respond with the challenge value within 10 seconds to activate it. The negotiation loop The full tutorial wires this end to end, but the shape is: Human emails the agent. message.created fires; the webhook only carries summary fields, so the handler fetches the full body. The LLM extracts duration, timezone, and urgency. The agent queries /calendars/free-busy against its own primary calendar and replies with 3 candidate slots. The human picks one; another message.created fires; the agent creates the event with notify_participants=true . The availability check is the part people overcomplicate. Free/busy returns bus
AI 资讯
Build an Email Support Triage Agent With Its Own Inbox
Every shared support inbox eventually becomes a triage problem: 80 unread messages, no agreement on what "urgent" means, and the one person who knows which customer is about to churn is on PTO. Teams keep solving this with labels and heroics. It's a better fit for an LLM — as long as the LLM has somewhere safe to live. That's the case for giving the triage agent its own mailbox. Nylas Agent Accounts (currently in beta) are hosted mailboxes you create entirely through the API. A support@yourcompany.com Agent Account receives every inbound support email, gets six system folders out of the box ( inbox , sent , drafts , trash , junk , archive ), and exposes the same grant_id -based endpoints as any connected Gmail or Outlook account. Creating one is a single request: curl --request POST \ --url "https://api.us.nylas.com/v3/connect/custom" \ --header "Authorization: Bearer $NYLAS_API_KEY " \ --header "Content-Type: application/json" \ --data '{ "provider": "nylas", "settings": { "email": "support@yourcompany.com" } }' Save the grant_id from the response — every other call hangs off it. Four buckets beat five The classification scheme from the email triage agent recipe sorts mail into exactly four categories: Bucket Meaning Action URGENT Production incident, executive ask Draft a reply within the hour ACTION Code review, meeting follow-up Draft a reply same-day FYI Status update Leave it alone NOISE Newsletter, automated alert Archive Four is deliberate. Three loses fidelity — everything collapses into "important." Five and the model starts confusing adjacent categories. The prompt runs with temperature=0 and max_tokens=10 , and the model only sees sender + subject + a 200-character snippet, not the full body. That's enough for over 90% accuracy. Here's the prompt verbatim from the recipe: You triage email into one of four categories: URGENT — production incidents, executive requests; reply within 1 hour ACTION — code reviews, meeting follow-ups; reply same day FYI — info
AI 资讯
🗺️ The Ultimate Cybersecurity Roadmap (Momentum-First Learning System)
Most cybersecurity roadmaps fail beginners. They give you a long list of topics like Linux, Networking, Python, and Security tools without any order or direction. This makes people confused, overwhelmed, and they usually quit early. This roadmap is different. It follows a momentum-first learning system, where every step builds on the previous one. You don’t just learn topics — you grow step by step like a system. The goal is simple: You always know what to learn next and why you are learning it. 🧠 How This Roadmap Works Instead of random learning, this roadmap is divided into phases. Each phase: builds real skills connects with the next phase moves from basic → advanced focuses on practical understanding By the end, you will understand how systems work, how they are built, how they are tested, and how they are secured. 🟢 PHASE 1: 🧠 The Signal Awakening Protocol (System Basics) Goal: Understand how computers and the internet actually work. Topics Google Dorking Using advanced search techniques to find specific information on the internet. You learn how search engines work beyond normal searches. OSINT (Open Source Intelligence) Collecting information from public sources like websites, social media, and forums. You learn how to gather data like a digital investigator. How Web Browsers Work Understanding how a browser sends requests and receives data from servers. This helps you understand what happens behind every website you open. Introduction to Computers & Operating Systems Basic understanding of CPU, RAM, storage, and how operating systems manage everything. This is the foundation of all cybersecurity. Virtualization (VirtualBox / VMware) Running a virtual computer inside your main computer. You use this to create a safe lab for practice. Linux Basics Learning how to use Linux systems. Most servers and cybersecurity tools run on Linux, so this is important. Bash Scripting Writing simple scripts to automate tasks in Linux. You move from manual work to automation. O
AI 资讯
Kubernetes kills your pod? Here's why
Your pods keep getting killed. Not crashing — killed. One moment they're running fine, the next they're gone and Kubernetes is spinning up replacements. You check the logs and there's nothing useful. The pod just… disappeared. Turns out Kubernetes killed it on purpose. And if you don't tell it how much memory your app actually needs, it'll keep doing it. Why Kubernetes evicts pods Kubernetes runs on nodes — physical or virtual machines that host your containers. Each node has a finite amount of CPU and memory. When a node runs low on resources, Kubernetes has to make a choice: which pods stay, and which ones get evicted to free up space. The decision comes down to QoS classes — Quality of Service tiers that Kubernetes assigns to every pod based on how you've configured resource requests and limits. There are three classes: BestEffort — no resource requests or limits defined. Kubernetes has no idea how much CPU or memory the pod needs. These get killed first. Burstable — requests and limits are defined, but they're different (e.g., requests: 256Mi , limits: 512Mi ). The pod is guaranteed the request amount, but can burst up to the limit. Killed second. Guaranteed — requests and limits are set to the same value. Kubernetes reserves exactly that amount of resources for the pod. Killed last. If your pods don't have resource configuration at all, they're running as BestEffort. And when the node hits memory pressure, BestEffort pods are the first to go — no questions asked. The Guaranteed class Setting your pod to the Guaranteed class is one line in your deployment config. Define requests and limits for both CPU and memory, and make them identical: resources : requests : memory : " 512Mi" cpu : " 500m" limits : memory : " 512Mi" cpu : " 500m" That's it. Kubernetes now knows this pod needs exactly 512 MiB of RAM and half a CPU core, and it reserves that capacity when scheduling the pod onto a node. If a node doesn't have 512 MiB available, the pod won't be placed there. An
AI 资讯
How to make AI answer questions about your documents, by building RAG from scratch
In the previous post , we talked about context windows. The model has a fixed-size desk and everything has to fit on it at once. When too much is on the desk, things in the middle get missed. I ended that post with a promise: what if there was a way to give the model just the right piece, at the right time, from a document you've never even pasted in? That's this post. We're giving the model a search system. The problem: your document is too long You have a 2000-page document. An employee handbook, a product manual, internal documentation. You need one specific answer from it. You can't paste the whole thing into the model's context window. And even if you found a model with a window big enough, we learned what happens: attention degrades, things in the middle get missed, and the model answers confidently from the wrong section. So you need something different. A step that happens before the model sees anything. Something that finds the 2-3 paragraphs that actually answer your question, and passes only those to the model. That's retrieval. The full technique is called RAG: Retrieval-Augmented Generation . Search first, then generate. Three words, one loop Let's break the name down. Each word is a step. Retrieval. Go find relevant information. Think of it like checking the index of a textbook before diving into a chapter. You don't re-read the whole book. You find the right page first. Augmented. Add that retrieved info to the prompt. You're supplementing the model's built-in knowledge with fresh, specific context. Like handing someone a cheat sheet right before they answer a question. Generation. The model writes its response, but with the retrieved context sitting right there in the conversation. It generates an answer grounded in your actual data, not just its training. "Grounded" means the model has real evidence to point to. It's not guessing from memory. It's answering from something you gave it. The whole loop in one sentence: find the right chunks of informat
AI 资讯
How to Turn Any App into an MCP Server with MCPify
The AI landscape is shifting fast. Every week, a new agent framework, a new protocol, a new way for AI to interact with the world. But one thing has become painfully clear: most of our existing software was never built for AI agents to use. You have a SaaS product, a REST API, a database, maybe a frontend with useful actions. An AI agent cannot touch any of it without brittle browser automation or hand-written boilerplate. That is where MCPify comes in. MCPify is an open-source AI enablement compiler that transforms existing applications into AI-native, agent-operable systems. Instead of manually writing MCP server code for every tool you want an agent to use, you point MCPify at your codebase and it does the heavy lifting automatically. In this tutorial, I will walk you through turning any app into an MCP server using MCPify --- no prior MCP experience required. What Is MCP (Model Context Protocol)? Before we dive in, a quick refresher. The Model Context Protocol (MCP) is an open standard that defines how AI applications connect to external tools and data sources. Think of it as USB-C for AI agents --- a universal interface that lets any MCP-compatible client (Claude Desktop, Cursor, VS Code extensions, custom agents) talk to your services. An MCP server exposes tools that an AI agent can discover, inspect, and invoke at runtime. Building these servers manually for each endpoint, database query, or business workflow is tedious and does not scale. Enter MCPify: The MCP Server Generator MCPify ( https://github.com/amarnath3003/MCPify ) is an AI enablement compiler that scans your application and automatically generates a complete MCP server. It works by performing static analysis on your codebase --- frontend components, backend routes, API definitions, event handlers, and workflow logic --- and compiling that into MCP-compatible tools. Why MCPify stands out: Zero manual tool writing --- it discovers tools from your code automatically Permission-aware --- generated t
科技前沿
F1 teams spend millions on their simulators—what makes them different?
Latency, bandwidth, and fidelity all matter when you're chasing milliseconds.
AI 资讯
Recovering data from a failed RAID array with ddrescue: a practical walkthrough
When a RAID array fails, the worst thing you can do is panic and start poking at it immediately. I've seen too many cases where an impatient rebuild attempt overwrote the only good copy of data. This walkthrough covers how to safely approach a degraded or failed RAID — with ddrescue as your best friend. Step 0: Stop. Don't touch the array yet. Before running mdadm --assemble , before doing anything, clone your physical disks . A RAID 5 with one failed drive can lose everything the moment a second drive throws a read error during rebuild. This isn't hypothetical — it's how most total RAID losses happen. The golden rule: image first, recover second . Step 1: Assess the damage # Check current RAID state cat /proc/mdstat # More detail mdadm --detail /dev/md0 Look for: [UUU_] — one drive failed (underscore = missing) [UU__] — two drives failed (catastrophic for RAID 5) State: degraded , recovering , or failed Do NOT run mdadm --manage /dev/md0 --add /dev/sdX yet. Stop the array instead: mdadm --stop /dev/md0 Step 2: Clone each disk with ddrescue ddrescue is the right tool because it handles read errors gracefully: it maps bad sectors, retries them, and lets you resume interrupted sessions. Never use dd for a failing disk. Install it: # Debian/Ubuntu sudo apt install gddrescue # RHEL/CentOS sudo dnf install ddrescue Clone each RAID member to a separate image file (you need enough storage — same total size as all disks combined): # First pass: copy everything readable, skip bad sectors fast sudo ddrescue -d -r0 /dev/sda /mnt/backup/sda.img /mnt/backup/sda.log # Second pass: retry bad sectors up to 3 times sudo ddrescue -d -r3 /dev/sda /mnt/backup/sda.img /mnt/backup/sda.log Key flags: -d — direct disk access (bypass kernel cache) -r0 / -r3 — retry bad sectors 0 or 3 times The .log mapfile is critical: it lets you resume if the clone is interrupted Repeat for every disk in the array ( sdb , sdc , etc.). Step 3: Work from the images Once you have image files, assemble a soft
开发者
Best Portable Monitors (2026): Add a Second Screen I've Tested
If you're someone who needs to (or likes to) take their work on the go, a portable monitor will make a huge difference. These are my favorite that I tested.
AI 资讯
Using PostAll's API to Automate Your Content Workflow: A Getting-Started Guide
I didn't set out to build a content API. I set out to stop copy-pasting. Every week, the same ritual: open a doc, stare at a blank page, write a headline, delete it, write it again. Multiply that by every client, every product page, every email drip campaign. I wasn't doing creative work — I was doing assembly-line work while pretending it was creative. PostAll started as a script I wrote to stop doing that. The API is what that script became after other developers asked if they could use it too. This guide walks you through integrating PostAll's API into your own workflow — authentication, the endpoints you'll actually use, real working code in both Python and Node.js, and the specific places things will break before they work. By the end, you'll have a functioning pipeline that generates formatted, CMS-ready content programmatically. What you'll build A script that takes a list of content briefs (keywords, tone, target length) and returns publish-ready content — with proper formatting, metadata, and error handling for the rate limits you'll hit in production. Here's the shape of what you're building: [ CSV of briefs ] → [ PostAll API ] → [ formatted content objects ] → [ your CMS / database ] The full working code for both languages is at the end of each section. I'll explain the interesting parts inline. Prerequisites A PostAll account with API access enabled (free tier works for this guide — rate limits noted below) Node.js 18+ or Python 3.10+ Basic familiarity with async/await in either language An HTTP client: axios or native fetch for Node, httpx for Python Step 1: Authentication PostAll uses API key authentication. Every request needs your key in the Authorization header. Get your key: Dashboard → Settings → API Keys → Generate New Key Store it as an environment variable. Never hardcode it. export PostAll_API_KEY = "postall_live_xxxxxxxxxxxxxxxxxxxx" Your key has two prefixes: postall_live_ for production, postall_test_ for the sandbox. The sandbox returns r
AI 资讯
Build Your RAG System Right the First Time: 6 Decisions That Make or Break It
After debugging 20+ broken RAG systems, I've identified the 6 decisions that determine whether yours works. Here's how to get each one right. The RAG Developer's Trap Every RAG developer falls into the same trap: you build the basic pipeline, it sort of works, and then you spend weeks tweaking prompt templates — while the real problem sits untouched in your indexing pipeline. The 80/20 rule: 80% of RAG problems come from indexing, not generation. But 80% of debugging effort goes into generation. Let's fix that. Decision 1: Embedding Model — The Single Biggest Lever The mistake: Using all-MiniLM-L6-v2 for Chinese documents because it's the default in every tutorial. Why it's wrong: It's English-trained. Drop it on Chinese text and it loses 30-50% of semantic fidelity. Language Use This Chinese BAAI/bge-large-zh-v1.5 (1024-dim) Chinese + English BAAI/bge-m3 (multilingual + sparse) English text-embedding-3-large Code jina-embeddings-v3 or voyage-code-3 Non-negotiable: Indexing model and query model must be byte-for-byte identical. Switch models = rebuild entire index. Impact: +15-40% Recall@10 for Chinese RAG. Decision 2: Chunk Size — Not a Magic Number Physics: Too small (< 100 tokens) = semantic fragmentation. Too large (> 1000 tokens) = noise injection. Document Type Sweet Spot Overlap FAQ / Short-form 128-256 20 Technical docs 512 50 Long-form articles 768-1024 100 Code Function boundaries 0 The method matters more than the size. Use recursive splitting, not fixed-length: from langchain.text_splitter import RecursiveCharacterTextSplitter splitter = RecursiveCharacterTextSplitter ( chunk_size = 512 , chunk_overlap = 50 , separators = [ " \n\n " , " \n " , " . " , " " , "" ] ) Impact: +5-15% Recall@10. Decision 3: Index Type — HNSW vs IVF Scale Use Why < 1M vectors HNSW Recall > 0.95 1-5M, RAM tight IVF + PQ 75% memory savings > 5M IVF + PQ + Sharding Horizontal scale Key nuance: HNSW has high insertion cost. Streaming docs → IVF may be better even at small scale. Im
AI 资讯
How to Use Primitive Types in TypeScript: string, number, and boolean
TLDR TypeScript has 7 primitive types: string , number , boolean , null , undefined , bigint , and symbol . You use them to tell TypeScript what kind of value a variable holds. You write them in lowercase. TypeScript can often figure out the type for you. But knowing how each one works is key to writing safe and clear code. What Are Primitive Types? Primitive types are the simplest building blocks in TypeScript. Every piece of data in your program starts with one. They hold a single value. They are not objects. You cannot add methods or properties to them directly. TypeScript has 7 primitive types in total: Type What It Holds string Text like names, messages, or IDs number Any number: integers, decimals, negatives boolean Only true or false null An intentional empty value undefined A value that was never assigned bigint Very large whole numbers symbol A unique identifier value This article covers all 7. You will use string , number , and boolean the most in everyday TypeScript code. How to Use the string Type A string holds text. Use it for names, messages, emails, URLs, and any other text data. Basic string annotation let firstName : string = " Alice " ; let greeting : string = " Hello, world! " ; let empty : string = "" ; Three ways to write strings TypeScript supports the same three string styles as JavaScript: let single : string = ' Single quotes work fine ' ; let double : string = " Double quotes work too " ; let template : string = `Template literals with ${ firstName } ` ; Template literals (backticks) let you insert values inside a string with ${} . TypeScript checks the types of those inserted values too. let age : number = 30 ; let message : string = `I am ${ age } years old` ; // TypeScript checks that 'age' is compatible here What TypeScript catches with strings let name : string = " Alice " ; name = 42 ; // Error: Type 'number' is not assignable to type 'string'. name = true ; // Error: Type 'boolean' is not assignable to type 'string'. Once a variable
AI 资讯
InfiniteWP's Strengths and Who It Fits — An Honest Review from a Competing Tool Builder
Among WordPress maintenance tools, InfiniteWP is one of the most established names. Released by Revmakx in 2011, the tool has been operated continuously for over a decade. It enjoys deep loyalty from agencies that have invested years building operational know-how around it . We at WP Maintenance Manager take a different approach, and our comparison pages outline where the two diverge. But before talking about differences, the strengths of InfiniteWP deserve to be stated honestly . Here are the five points where InfiniteWP fits an agency particularly well. 1. Over a decade of operational track record InfiniteWP's biggest structural advantage is trust built across more than a decade of continuous operation . Released in 2011 — one of the oldest tools in the space A large base of long-time English-speaking users with shared operational patterns Well-defined upgrade paths from older versions Backward compatibility with existing workflows and scripts has been maintained for years For agencies already invested in InfiniteWP, switching tools means more than "migration work" — it means rebuilding the operational know-how accumulated over years . Continuing to use a tool with proven track record is, in itself, a strength that long-running platforms have. The temporal depth that newer tools simply cannot replicate is a meaningful selection reason for conservative industries — those reluctant to substantially change established workflows. 2. Self-hosted — full control of the dashboard InfiniteWP is self-hosted by default , letting you place the dashboard on your own server (a cloud-hosted version is available separately). Host on infrastructure you own Complete data ownership No dependency on external SaaS Arbitrary customization possible When the constraint is "client data must not sit in a third-party SaaS" or "our security policy doesn't permit SaaS," InfiniteWP's self-hosted architecture is a direct answer. If your team has experience operating PHP / WordPress infrastructu
AI 资讯
Your vector memory database remembers everything. That’s exactly the issue.
There is a design assumption baked into almost every vector database and AI memory implementation that sounds reasonable until you watch it grow nodes in production: that remembering more is always better. Through testing and refining our AUDN code, that is not exactly correct. After running VEKTOR Slipstream against real development sessions for 99 days, the database held 1,413 stored memories across four namespaces. Looking at the importance score distribution, 83 percent of those memories sat below 0.25 out of 1.0, what the system considers the noise floor. The remaining 17 percent, just 60 memories out of 1,413, sat above 0.75 and dominated every recall result. This is exactly what a curation layer is supposed to produce. Those 1,154 low-scored memories are accurate. They are not deleted. They are retrievable by direct query. What they are not is important enough to compete with the 60 high-signal entries every time the agent needs context. AUDN penalised them gradually over hundreds of writes because similar, more specific, or more frequently reinforced memories covered the same ground better. The system created a hierarchy. Without curation, all 1,413 memories would compete equally for every recall slot — and the agent would consistently surface redundant, lower-value context alongside the things that actually matter. That is what standard vector memory looks like without a curation layer. A slow, invisible degradation that nobody notices until the agent starts confidently giving you answers that are three months out of date. Every memory node in Vektor carries an importance score between 0 & 1. When a memory is first stored, it receives a score based on the content’s estimated significance. That score is not fixed. Every time a new memory arrives that is semantically related but not directly contradictory, the compatible verdict for that existing memory takes a small redundancy penalty. The penalty is intentionally modest: a factor based on how similar the in
AI 资讯
Everyone wants a piece of Tesla’s battery business
Electricity demand from AI data centers is pushing everyone — including automakers like GM and Ford — into the energy storage business.
AI 资讯
The future of AI regulation is courting the strangest, most anxious bedfellows
Hello and welcome to Regulator, a newsletter for Verge subscribers about tech politics, tech influence, and tech shenanigans in Washington, DC. (If you're not a subscriber, you can get on board here.) We're back after a two-week hiatus, during most of which I was gallivanting in the Netherlands for a family wedding, and a trip […]
AI 资讯
Google won’t just admit it’s feeding YouTube creators to its music AI
If you've uploaded a song to YouTube, Google almost certainly considers your video fair game for training its Lyria music AI, it just won't admit it right now. A group of independent musicians is suing Google, claiming that it illegally used songs they uploaded to YouTube to train its Lyria 3 model. Google has filed […]
AI 资讯
A Day in the Life: Complete Claude Code Session Walkthrough
Part 7 of 7 · Series: Building Your AI Developer Handbook · GitHub The Scenario You're building a password reset feature. User enters email → gets a reset link → clicks link → enters new password. Standard flow. Medium complexity. Let's walk through every step using the full workflow — as if you're looking over the shoulder of someone who built this system. "Show me your workflow and I'll show you your output quality." Before You Even Type Claude loads automatically in the background: ✓ ~/.claude/CLAUDE.md loaded ← the global handbook ✓ .claude/CLAUDE.md loaded ← project rules (TypeScript, pnpm) ✓ memory/MEMORY.md scanned ← all lessons and preferences You haven't typed anything yet. Claude already knows: Feature-based folder structure State management ladder No mocking the database No AI attribution in commits No useCallback without profiler evidence "A doctor who reviews your file before you enter the room is more useful than one who asks 'so, remind me who you are?'" Step 1: /status — Confirm the Setup /status Model: claude-sonnet-4-6 Effort: normal Plugins: security-guidance ✓ Thirty seconds. Sometimes the wrong model loads due to overload fallback. Sometimes a plugin fails silently. This check costs 30 seconds and prevents a surprise 30 minutes later. "A pilot's first action after sitting in the cockpit isn't to take off. It's to check all instruments are reading correctly." Step 2: /cost — Baseline /cost → Tokens used: 2,847 | Estimated cost: $ 0.004 Note this number. You'll compare it later before the expensive code review step. A surprise spike means something went wrong. Step 3: /plan — Design Before Coding /plan Build a password reset feature: - User enters email on /forgot-password - System sends a reset link (token, expires in 1 hour) - User clicks link → /reset-password?token=xxx - User enters new password - Token validated, password updated, token invalidated Claude responds with a plan — no code yet : Proposed approach: 1. DB: Add password_reset_tokens
AI 资讯
# I Just Published My First npm Package — Here's Everything I Did
A complete walkthrough of publishing Cartlify — a React e-commerce UI kit — to npm for the first time. The Milestone Yesterday I published Cartlify to npm. npm install cartlify It sounds simple. But getting to that one line took more decisions, more configuration, and more trial and error than I expected. This article covers everything — from setting up the build config to the actual publish command — so you don't have to figure it out the hard way. What Is Cartlify? Cartlify is a production-ready React + TypeScript + Tailwind CSS component library focused on e-commerce UI. 4 components that every e-commerce project needs: ProductCard — 3 layout variants, image gallery, wishlist, sale badges, skeleton loading CartDrawer — animated slide-in, focus trap, ESC dismiss, quantity stepper CheckoutStepper — horizontal/vertical, animated connectors, keyboard navigation PageLoader — 4 animation styles, 3 position modes Plus 3 utility hooks, 11 tree-shakeable icons, 40+ CSS design tokens, full dark mode, and 141 Jest + React Testing Library tests. Built so freelance developers and indie makers can skip the painful e-commerce UI layer and ship faster. Why Publish to npm? Before npm, Cartlify was only available on Gumroad as a paid download. That's fine — but npm adds something Gumroad can't: Developer sees Cartlify → runs npm install cartlify → evaluates the compiled output → trusts the quality → buys the full source on Gumroad npm is a credibility and discovery channel — not just a distribution method. A package on npm signals that something is real, maintained, and production-ready. Also: npmjs.com gets millions of developer searches every month. That's free traffic you can't get from Gumroad alone. The Build Setup — tsup The most important decision before publishing is how you bundle your library. I chose tsup — a zero-config TypeScript bundler built on esbuild. Here's why: Tool Config needed Speed Output Rollup Lots Medium ESM + CJS Webpack Heavy Slow CJS only Vite lib mode