AI 资讯
From Keypoints to Measurements: Why Landmarks Alone Are Useless
Every hand-tracking demo shows you 21 dots. The interesting part is what nobody shows: turning dots into numbers someone can act on. Dots are a capability, not a product Run any modern hand-tracking model and you get 21 beautifully stable landmarks per hand at 30 FPS. Impressive — and by itself, worthless. No client has ever paid for dots. They pay for measurements : is this clearance compliant, is this part aligned, did this patient's range of motion improve. I learned this on utility infrastructure work, where the deliverable was never "we detected the wire" — it was the attachment height of that wire, and whether it violates clearance rules . Keypoints were step one of three. The demo: live metrics, not just a skeleton My portfolio's keypoint demo derives three measurements per hand, every frame: const wrist = lm [ 0 ]; const palm = distance ( wrist , lm [ 9 ]); // scale reference const pinch = distance ( lm [ 4 ], lm [ 8 ]) / palm ; // thumb tip ↔ index tip The crucial line is the scale reference . Pixel distances are meaningless — they change as you move toward the camera. Dividing by palm length (wrist to middle knuckle) gives a relative measurement that's stable under distance, and multiplying by the average adult palm length (~8.5 cm) converts it into an approximate real-world gap — the demo shows "≈ 3.2 cm" floating on the pinch line. In infrastructure work the same role is played by a known object dimension — a standard crossarm, a pole class height. Every measurement-from-pixels system needs its ruler. Finger counting is a geometric test (is each fingertip farther from the wrist than its middle joint?), and "hand openness" averages fingertip extension — three lines of geometry each, but they convert a model output into a readout a human understands instantly. Honest layering The landmarks come from MediaPipe's pretrained pipeline (palm detector → landmark regressor → gesture classifier, float16, WASM + GPU delegate) — Google's models, credited on the page
AI 资讯
Mirror Therapy Without the Mirror Box: Treating Phantom Limbs in a Browser Tab
A 1990s Nobel-adjacent therapy, a webcam, and 21 hand keypoints — recreating the mirror-box illusion for phantom limb pain, no hardware required. A therapy built on an illusion In the 1990s, neuroscientist V.S. Ramachandran discovered something remarkable: amputees suffering phantom limb pain often felt relief just by seeing their missing limb move again. His apparatus was almost comically simple — a box with a mirror. Put your intact hand in, look at its reflection where the missing hand would be, and move. The brain, watching the "missing" hand obey commands again, often dials the pain down. The limitation was never the science. It was the box: a physical apparatus, used in clinics, hard to scale, impossible to measure. Replacing glass with keypoints A webcam plus real-time hand tracking can produce the same illusion with better properties: webcam frame → hand landmark model (21 keypoints, on-device) → reflect: phantom[i] = { x: 1 − x, y, z } → render real hand (solid) + phantom twin (ghost) on canvas The reflection is one line of math. Everything around it is what makes the illusion land: const phantom = real . map ( p => ({ x : 1 - p . x , y : p . y , z : p . z })); The visual treatment matters more than I expected. The phantom hand is rendered as a ghostly cyan skeleton with a translucent palm fill, a "breathing" glow that pulses on a ~3 second cycle, and a fading afterimage trail of its last few frames — it reads as present but ethereal , which is exactly the perceptual story mirror therapy needs to tell. A dashed mirror plane down the center of the frame makes the reflection relationship legible at a glance. The engineering details that matter Tracking : MediaPipe HandLandmarker (Google's pretrained model — credit where due), running via WebAssembly with GPU delegate. ~30 FPS on a laptop. Privacy by architecture : every frame is processed on-device. For a medical-adjacent application, "video never leaves your browser" isn't a feature, it's a requirement. Lazy
AI 资讯
I Thought Open Source Was About Code. I Was Wrong.
The biggest lessons I learned from open source contributions weren't found in the code itself. Communication, collaboration, and workflows matter more than I expected. For a long time, I hesitated to contribute to open source. Part of it was because I assumed that contributing meant writing code. As a self-taught developer, that felt intimidating. The other part was "Git anxiety." Forks, branches, pull requests, merge conflicts, and CI checks all seemed like a lot to understand before I could even make a contribution. Eventually, I started small. Instead of focusing on code, I looked for opportunities to improve documentation, README files, and learning materials. What surprised me was that writing the actual change was often the easy part. Most of my learning happened outside the code itself: understanding contribution guidelines, repository workflows, automation, and review expectations. Over time, I realized that modern open source contribution is about much more than just writing code. Contribution Model Has Changed When many people think about open source contributions, the mental model is still fairly simple: Find Bug ↓ Write Code ↓ Open PR In reality, I realized that most modern repos involve much more than that. Before making a change, contributors often need to understand project workflows, CI pipelines, automated checks, contribution guidelines, and review expectations. The code change itself might only take a few minutes, while understanding how the repo operates can take much longer. A modern contribution often looks more like this: Understand Repository ↓ Understand Workflow ↓ Understand Automation ↓ Make Change ↓ Open PR ↓ Respond to Review It looks intimidating, but I think this flow helps projects stay maintainable as communications grow. What I've learned from contributing to different projects is that open source is not just a coding skill. It's also a collaboration skill. The faster you can understand how a project works, the easier it becomes to
工具
Microsoft Open-Sources PostgreSQL Extension for In-Database Durable Execution
Recently open-sourced by Microsoft, pg_durable is a PostgreSQL extension that enables durable workflows to run natively inside the database, eliminating the need for external orchestration systems. By Sergio De Simone
AI 资讯
Debugging the Google Maps Duplicate Loading Bug in React
Originally published on clintech.me If you've integrated Google Maps into a React app and seen Autocomplete randomly stop working, Directions silently fail, or the API throw google is not defined on second render — you've hit the duplicate loading bug. Here's exactly what caused it in my case and how I fixed it. The setup that broke things While building delivery address flows at POLOM — a production e-commerce platform — I integrated Google Places Autocomplete across 20+ screens. I had the Maps JavaScript API loading in two places: A provider.tsx for global script loading across the app A useLoadGoogleMaps hook inside a shared component This caused race conditions. The Autocomplete and Directions APIs were initialising before the script fully resolved in some renders, silently failing in others. The failure wasn't consistent, which made it harder to catch. The fix Step 1 — Remove the global load Delete the script tag or next/script call in provider.tsx . There should be exactly one place the Maps API loads. Step 2 — Centralise in a hook Move all loading logic into a single useLoadGoogleMaps hook using dynamic loading. If you're on Next.js, next/script with strategy="afterInteractive" inside the hook is the right approach. Step 3 — Guard before initialising if ( ! window . google ?. maps ) return ; Check that the API is fully available before attempting to attach Autocomplete or Directions . Don't assume the script load event means every namespace is ready. Step 4 — Scope your ref correctly Bind the autocomplete instance to inputRef.current explicitly. If the component remounts, re-initialise the binding — don't assume the previous instance is still attached. The result One load, one source of truth, no race conditions. Autocomplete and Directions worked consistently across all 20+ screens without reinitialising on every render. Security — the step most developers skip Restrict your API key at the Google Cloud Console level: HTTP referrers: whitelist your domain onl
AI 资讯
How do you maintain project context when you hit limits and have to switch AI tools?
One of the most frustrating parts of using AI coding tools is what happens when you have to switch between them. Every time I move to a different tool, I end up re-explaining the project, architecture, requirements, previous decisions, and all the context I’ve already built up elsewhere. It feels inefficient having to repeatedly provide the same context every time I switch tools or start a new session. Is anyone else running into this? How are you handling it today? submitted by /u/Bar_David [link] [留言]
AI 资讯
Developer Tools That Actually Save You Time in 2026
As developers, we often lose hours to repetitive tasks - formatting data, debugging auth tokens, or wrestling with encoding issues. The right set of utility tools can cut that overhead significantly. Here is a curated breakdown of the categories and tools worth keeping in your daily workflow in 2026. JSON and Data Formatting Tools Working with raw, minified API responses is a real productivity killer. A browser-based JSON formatter with real-time validation and proper indentation helps you parse and debug responses in seconds - without sending your data to third-party servers. Similarly, XML is far from dead; SOAP APIs and enterprise integrations still rely on it, so a solid XML formatter with XPath support is worth having around. On the frontend, a CSS minifier that handles dead code removal and selector optimization can meaningfully reduce your page load times. Data Conversion Utilities Modern stacks often have to bridge the gap between formats. A JSON-to-XML converter is critical when integrating with legacy systems, but look for one that handles arrays and special characters correctly. CSV-to-JSON converters help structure flat export data from spreadsheets or databases into something your application can consume. And if your deployment pipeline involves YAML config files, a formatter that catches indentation errors before they break your CI/CD run is essential. Encoding and Security Helpers Base64 encoding comes up constantly - from embedding images in CSS to building HTTP Basic Auth headers. A reliable encoder/decoder handles all these cases without fuss. URL encoding matters too; unencoded special characters in query strings cause subtle API bugs that are surprisingly hard to track down. For authentication debugging, a JWT decoder lets you inspect token payloads without needing to verify the signature - ideal for local development and troubleshooting. Code Generation and Color Utilities Distributed systems need collision-resistant unique IDs - a UUID generato
AI 资讯
How to add a contact form to your static site — no backend, no monthly fee
I got tired of paying for form services or spinning up a backend just to handle contact form submissions. So I built RG Forms — a contact form endpoint backed entirely by a Google Sheet you own. No server, no monthly fee, no third-party storing your data. The idea Most form tools store your submissions on their servers. You pay monthly, you depend on their uptime, and your data lives in their database. RG Forms does the opposite: every submission goes straight into a Google Sheet in your own Google Drive, sent by an Apps Script that you own and control. RG Forms provisions that sheet and script for you in about 90 seconds. After that, your endpoint runs forever at no cost — completely independent of any RG Forms server. Built for static sites If you host on GitHub Pages, Netlify, Vercel, Cloudflare Pages, or just plain HTML on a CDN, you've hit this wall: there's no backend to receive a form POST. The usual workarounds are a paid form service, a serverless function you have to write and maintain, or standing up a whole backend just for a contact form. RG Forms is built exactly for this. Your endpoint is a plain HTTPS URL you POST to straight from client-side JavaScript — no build step, no serverless function, no server of any kind. Drop the fetch call into your page and you're done. It pairs naturally with any static-site generator (Hugo, Jekyll, Astro, Eleventy, Next export) and any no-code builder that lets you add a snippet of JS. Your static site stays static; the form just works. How it's built RG Forms is a fully static web app. There's no RG Forms server, no database, no backend. Every API call during setup goes directly from your browser to Google using your own OAuth token. Setup (one time, in your browser): Your Browser ├─── Google OAuth ──▶ Short-lived token (memory only) ├─── Google Drive API ──▶ Creates Sheet + Drive folder └─── Apps Script API ──▶ Creates & deploys form handler Live endpoint (after provisioning): Your Website / App └─── POST to script
AI 资讯
SAFEDEPLOY AI: DevOps Pipeline Intelligence System
Problem Statement: DevOps Pipeline Agent: Modern software delivery pipelines generate large amounts of operational data. Understanding the relationship between deployments, infrastructure changes, and failures is increasingly complex. Build an AI agent that remembers deployment history, infrastructure modifications, build failures, and incident outcomes. The agent should learn from previous events to predict risks and recommend preventive actions before issues reach production. The project should showcase memory-driven operational intelligence. Solution Approach To address these challenges, we developed SAFEDEPLOY AI, a memory-driven operational intelligence platform that acts as the collective memory of software systems. SAFEDEPLOY AI continuously records: Deployment histories Infrastructure modifications Build outcomes Incident reports Module-level changes Operational metrics Instead of treating these as isolated records, the platform transforms them into searchable organizational knowledge. The AI assistant can answer questions such as: Which deployment introduced a failure? Has this issue occurred before? Which service has the highest deployment risk? What preventive actions worked in previous incidents? Which infrastructure changes caused production instability? This enables teams to move from reactive troubleshooting to proactive decision-making. Architecture and Design SAFEDEPLOY AI follows a cloud-native, layered architecture designed to provide deployment intelligence, operational visibility, and AI-driven decision support. The platform workflow begins with project creation and module registration. As deployments and infrastructure changes occur, SafeDeploy AI continuously records operational events, incident reports, security findings, and compliance records. This information is stored as a centralized knowledge base, enabling the AI engine to perform risk analysis, generate recommendations, and support context-aware issue resolution. Workflow Create Proje
AI 资讯
Building a Multi-Agent AI Movie Production Team with Google ADK
🚀 What I Built I created a collaborative AI Multi-Agent system using Google's new Agent Development Kit (ADK). The system functions as an automated Hollywood Production Team designed to streamline creative brainstorming. The user submits a simple movie prompt (e.g., "A movie about a time-traveling chef"), and the specialized agents work sequentially to refine the idea into a viable film concept. 🧠 My Agent Architecture My multi-agent team uses a sequential workflow tracking architecture consisting of two specialized agents running on gemini-2.5-flash : movie_writer : Takes the raw user input concept and expands it into a high-stakes, descriptive three-sentence movie plot. movie_critic : Automatically intercepts the writer's completed story context to deliver constructive structural improvements. These agents are orchestrated via a SequentialAgent pipeline configuration that manages data handoffs automatically. 🛠️ Key Learnings & Challenges Framework Evolution: I learned how to structure project modules using ADK 2.0's directory scanning conventions ( __init__.py mapping definitions). Overcoming Roadblocks: I originally ran into layout separation issues on Windows where the backend command runner could not discover the python modules. Resolving this taught me how the google.adk.cli maps working directory environments ( ./app ). Handling API Constraints: Dealing with transient API capacity limits (like standard 503 backend service spikes) taught me how crucial error handling and session resets are when building live AI tools.
开发者
WebKit finally gets support for fully customizable select elements
As part of Apple's worldwide developers conference (WWDC) they announced some of the new stuff coming to WebKit and Safari 27. Among them is a feature that Google Chrome got in April of last year: fully customizable select elements. As an accessibility professional, I am absolutely thrilled. I am disappointed, though, that Firefox doesn't have it yet. You can find the session for what's new here: https://developer.apple.com/videos/play/wwdc2026/204 submitted by /u/ThatBlindSwiftDevGuy [link] [留言]
开发者
Is finding a team of friendly engineers rare?
I don’t want to stereotype all devs, but a lot of them seem to have difficult personalities. Things I’ve noticed are smugness/arrogance/elitism, gatekeeping/knowledge hoarding, favoritism/cliques, ostracism and mobbing. You have ppl who are just downright mean and carry bad attitudes who constantly need to remind you how smart they are. So they use every opportunity to show off and one up you in front to management. A lot of ppl don’t take this as a job, it’s like their entire personality. And then you have these lone wolf or extremely socially awkward types that you can barely talk to. I think it’s kinda rare to find just a normal group of chill friendly engineers to work with. Thoughts? submitted by /u/throwaway0134hdj [link] [留言]
AI 资讯
Architecting a Production-Ready Express + TypeScript Backend: Type Augmentation, Global Errors, and Middleware Factories
When building a personal finance tracker, data integrity and system reliability are non-negotiable. One missing try/catch block can crash your whole server, and weak types can let invalid financial payloads corrupt your database. While building the backend for my personal finance tracker, I decided to move past generic tutorials and build a bulletproof, production-grade API core using Express, TypeScript, and Zod. In this post, I’ll show you how I implemented a type-safe middleware ecosystem, leveraged TypeScript declaration merging to extend the native Request object, and eliminated repetitive try/catch boilerplate across the entire codebase. 1. The Weapon Against Boilerplate: The asyncHandler HOC Writing try/catch blocks in every single controller handler clutters code and introduces human error—it’s easy to forget to pass an error to next() . To solve this, I engineered a Higher-Order Function (HOC) factory that wraps asynchronous request handlers and automatically catches rejected promises, safely routing them into the global error handler. import { Request , Response , NextFunction , RequestHandler } from ' express ' ; export const asyncHandler = ( fn : RequestHandler ): RequestHandler => { return ( req : Request , res : Response , next : NextFunction ) => { Promise . resolve ( fn ( req , res , next )). catch ( next ); }; }; Why this matters: Reliability: Async errors always reach the centralized error middleware. Readability: Route controllers stay beautifully clean, focusing only on business logic rather than async control flow wiring. 2. TypeScript Magic: Declaration Merging & Type Augmentation When dealing with authentication tokens, request tracing ( requestId ), or custom validated payloads, developers frequently resort to casting the request as any (e.g., (req as any).userId ). This completely destroys Type Safety. Instead of fighting the compiler, I leveraged TypeScript Declaration Merging to reopen Express's internal Request interface and merge my cust
AI 资讯
You Don't Need Another Agent. You Need a Linter.
In my last post I complained — a lot — about product managers and how they made my life hell with vibe code. PS: apologies, manager, if you're reading this — but it's true. Now, I'm not here just to complain. There were a lot of learning opportunities too, like how to handle legacy / vibe code. Because at the end of the day, both are the same: no one knows how they work, but somehow they keep working. Touching them is like defusing a bomb — you never know how your change might cascade and break the core logic. The good news is that vibe code is much simpler than legacy. AI, in all its glory, tries to write perfect-looking code — proper function names, comments, the works — not like legacy code where a single function runs 500 lines, with spaghetti names all over that make no sense and comments that are out of date. And that makes it something I can actually handle. I still don't have a perfect, step-by-step playbook — but I've got pieces. The first one. The cheapest and the oldest one. The one the industry solved decades ago and the whole "AI built my app in a day" crowd somehow forgot exists. A linter. Yes, you heard me right. A linter. ESLint. Most people who've been in this industry already know it. It's the most boring, reliable tool in the box. But in an era where the answer to every problem is "add another AI," it's worth saying out loud why the boring tool still wins. What a linter actually is If you vibe-coded your way into this world, or you're new to web dev in general and have never heard the word "lint", here's the honest version. A linter is a set of rules you add to your repo. It reads your code without running it, checks it against those rules, and flags everything that's broken, sloppy, or about to bite you in production. The detail people get wrong: it's not a grep for bad words. A real linter parses your code into a syntax tree and actually reasons about its structure — what's imported, what's called, what's reachable, what types flow where. That's
AI 资讯
Proxy OpenAI Through Kong AI Gateway on Kubernetes
The Problem With Talking Directly to LLMs Most teams start by wiring their app straight to the OpenAI API. It works — until you need to add auth, rate limiting, observability, or swap out the model provider. Now you're rewriting application code instead of config. An AI Gateway solves this. One entry point, one place to govern traffic, providers become swappable. Kong Gateway is a mature choice here — it's been doing this for APIs for years, and the AI Proxy plugin extends that to LLMs. This post walks through the key ideas. For the full step-by-step guide, head over to the tutorial on Hashnode . What We're Building A Kong Gateway 3.14 data plane running on Kubernetes (kind locally), connected to a Kong Konnect control plane. The AI Proxy plugin sits on a route and handles forwarding to OpenAI — your app just talks to Kong. Your app → POST /ai/chat (Kong proxy) → AI Proxy plugin attaches API key → OpenAI API → response back to your app Your app never holds an OpenAI key. Kong does. You get rate limiting, logging, and model-swapping for free at the gateway layer. The Key Bit: decK Config as Code The most interesting part of this setup is using decK to define the service, route, and plugin as a YAML state file — then syncing it to Konnect, which pushes it down to the data plane automatically. # kong-ai.yaml _format_version : " 3.0" services : - name : openai-service url : https://api.openai.com routes : - name : openai-chat-route paths : - /ai/chat plugins : - name : ai-proxy config : route_type : llm/v1/chat auth : header_name : Authorization header_value : " Bearer $OPENAI_API_KEY" model : provider : openai name : gpt-4o options : max_tokens : 512 One sync command and Konnect pushes the config to every connected data plane: deck gateway sync kong-ai.yaml \ --konnect-token " $KONNECT_TOKEN " \ --konnect-control-plane-name "kong-ai-tutorial" Once it's live, a single HTTPie call confirms the whole chain is working: http POST localhost:8080/ai/chat \ Content-Type:applic
AI 资讯
Inngest + Next.js: The Complete Guide (2026)
Serverless functions have a time limit. Vercel gives you 60 seconds on Pro. None of that is enough to send a welcome email sequence, process an uploaded CSV, or run any workflow with multiple external API calls. Inngest solves this by turning your Next.js API routes into reliable, retryable, observable background jobs — without Redis, without a worker process, without any separate queue infrastructure. Read the full guide with all code examples at stacknotice.com How It Works You define functions that run in response to events . When an event fires, Inngest calls your function via HTTP. If the function fails, Inngest retries it. If the function has multiple steps, Inngest checkpoints each step so a failure halfway through doesn't restart from scratch. Setup npm install inngest // lib/inngest/client.ts import { Inngest } from ' inngest ' export const inngest = new Inngest ({ id : ' my-app ' }) // app/api/inngest/route.ts import { serve } from ' inngest/next ' import { inngest } from ' @/lib/inngest/client ' import { welcomeSequence } from ' @/lib/inngest/functions/welcome ' export const { GET , POST , PUT } = serve ({ client : inngest , functions : [ welcomeSequence ], }) Welcome Email Sequence export const welcomeSequence = inngest . createFunction ( { id : ' welcome-email-sequence ' , retries : 3 }, { event : ' user/signed-up ' }, async ({ event , step }) => { const { userId , email , name } = event . data // Each step is independently retried await step . run ( ' send-welcome-email ' , async () => { await resend . emails . send ({ from : ' hello@yourapp.com ' , to : email , subject : `Welcome, ${ name } !` , html : `<p>Thanks for signing up...</p>` , }) }) await step . sleep ( ' wait-2-days ' , ' 2 days ' ) await step . run ( ' send-tips-email ' , async () => { await resend . emails . send ({ from : ' hello@yourapp.com ' , to : email , subject : ' Top 5 tips to get the most out of the app ' , html : `<p>Here are the tips...</p>` , }) }) await step . sleep ( ' wait
AI 资讯
I am building a PDF API because every codebase I touch has a haunted PDF service
There is a file in almost every backend I have worked on. It generates PDFs. Invoices, mostly. Sometimes reports or certificates. It was written years ago by someone who left, it runs a headless browser nobody fully understands, and it falls over on the last day of the month when finance needs the invoices out. I have rebuilt this same haunted corner enough times that I decided to fix it once, properly, for everyone. It is called PDFPipe. The actual problem Generating a PDF from HTML sounds trivial until you run it in production at any scale. The usual path is a headless Chromium (Puppeteer, Playwright, wkhtmltopdf, or Gotenberg). Then you discover: Chromium wants 0.5 to 1 GB of RAM per instance and falls over under load. Cold starts add seconds to every request after a deploy. Custom fonts do not load, or load inconsistently. Tables split across page breaks in ugly ways. You now own a service that needs health checks, retries, and monitoring. None of this is your product. It is undifferentiated infrastructure that breaks at the worst possible time. What PDFPipe does One endpoint. You send HTML or a template plus JSON data, you get back a PDF. curl https://api.pdfpipe.xyz/v1/pdf \ -H "Authorization: Bearer pp_live_..." \ -d '{"html":"<h1>Invoice #4012</h1>","options":{"format":"A4"}}' \ --output invoice.pdf That is the whole integration. No browser in your infra, no queue to babysit. Three decisions I made on purpose Flat pricing. A lot of PDF APIs price in credits where one large document burns several. I find that hostile. A document is a document. A real free tier. The industry standard free tier is around 50 documents a month, which is not enough to ship anything. PDFPipe gives 500. Security as a feature, not an afterthought. HTML-to-PDF services are a textbook SSRF target. Rendered markup can embed an iframe pointing at file:///etc/passwd or the cloud metadata endpoint at 169.254.169.254 and leak credentials straight into the returned PDF. There are CVEs for ex
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
开发者
The unwritten laws of software engineering
submitted by /u/fagnerbrack [link] [留言]
AI 资讯
Is adidas.com not just the absolute garbage of a website?
Did the mistake of shopping at adidas website and now I regret it. I should have heeded the warning signs from the massive amount of page flickers, jitters, random scrolling, popups and the fact it just completely freezes a fairly new iphone. It is that heavy. Filtering and searching is just call to a random generator that spits out whatever you did not search for. The login forces passkey instead of simple password. Oh and it also doesnt work to login. Tracking your order is a mere mirage they put there in words but is yet to be vibe coded. Do you believe this type of website is developed in house or outsourced? submitted by /u/GrumpyBitFlipper [link] [留言]