开发者
How to Send iMessages Programmatically (REST API, Python & Node.js)
If you've ever tried to send an iMessage programmatically , you've probably hit the same wall everyone does: Apple has no public iMessage API. There's no POST /imessage in the developer docs, no SDK, no OAuth scope. Yet "blue bubble" delivery has 3–4× the open rates of SMS, so the demand to send iMessages from code — for CRMs, bots, notifications, and outbound — keeps growing. This guide covers the realistic options, then walks through actually sending and receiving iMessages over a REST API with working Python , Node.js , and curl examples you can paste and run today. Why there's no official iMessage API iMessage is a closed, end-to-end-encrypted protocol tied to Apple IDs and Apple hardware. Apple has never shipped a public API to send iMessages, and "Messages for Business" is a support-inbox product gated behind an approval process — not a way to send outbound messages from a script. So historically, developers reached for hacks: Approach Works from a server? Reliability Receiving messages Notes AppleScript / osascript No — needs a logged-in Mac with Messages open Brittle Polling the local SQLite chat.db Mac-only, breaks on macOS updates Shortcuts automation No Brittle No Manual, not built for scale "Just use SMS" (Twilio etc.) Yes High Yes Green bubbles, no typing indicators/tapbacks/HD media Hosted iMessage REST API Yes High Yes (webhooks) What this guide uses The AppleScript route is fine for a one-off script on your own Mac. The moment you want to send from a server, send at scale, or receive replies reliably, you need a hosted API that manages the Apple side for you and exposes a normal HTTP interface. The setup For the examples below I'm using Blooio , an iMessage REST API. Any provider with a similar HTTP surface will follow the same patterns — the concepts (Bearer auth, a send endpoint, webhooks for inbound) are what matter. You'll need: An API key (Blooio gives you one in the dashboard — no credit card, no A2P/10DLC registration, no DUNS number) A phone
开发者
【互動藝術 DIY】用 p5.js 做一塊會呼吸的粒子背景(無程式背景可)
【互動藝術 DIY】用 p5.js 做一塊會呼吸的粒子背景 先問自己:阿哲會想動手嗎? 看完這個效果,阿哲可能會想: 「那如果我把粒子排成自己的名字,滑鼠靠近時會散開嗎?」 這就是正確的方向—— 讓讀者想自己動手改參數 ,而不是背程式碼。 這個方法厲害在哪? p5.js 官網有很多炫技的粒子效果,但大部分只是給你看「很厲害」。 這次不一樣——我要教你 用最少程式碼,做出最有呼吸感的互動 。 秘密是:用「距離」控制行為,用「lerp」讓移動變溫柔。 教學順序 先建立粒子:讓一群點組成畫面 教動畫:用 sin() 做出呼吸節奏 教距離感:用 dist() 偵測滑鼠 教溫柔散開:用 lerp() 柔和移動,不是瞬移 最後加美感:透明度、殘影、暖色 第一步:讓粒子回家 class Particle { constructor ( x , y ) { this . homeX = x ; // 記住家的位置 this . homeY = y ; this . x = x ; this . y = y ; } // 讓粒子回家的力量 returnHome () { this . x = lerp ( this . x , this . homeX , 0.05 ); // 每次移動5%的距離 this . y = lerp ( this . y , this . homeY , 0.05 ); } show () { noStroke (); fill ( 255 , 180 , 120 , 200 ); // 暖橙色 ellipse ( this . x , this . y , 4 ); } } 第二步:偵測滑鼠距離 function draw () { for ( let p of particles ) { let d = dist ( mouseX , mouseY , p . x , p . y ); if ( d < 100 ) { // 滑鼠靠近時,輕輕推開 let force = 0.05 * ( 100 - d ) / 100 ; p . x += ( p . x - mouseX ) / d * force ; p . y += ( p . y - mouseY ) / d * force ; } p . returnHome (); p . show (); } } 第三步:加呼吸節奏 let breathPhase = 0 ; function draw () { breathPhase += 0.02 ; let breath = sin ( breathPhase ); // -1 ~ +1 來回循環 background ( 10 , 8 , 5 ); // 暖暗色背景 for ( let p of particles ) { let d = dist ( mouseX , mouseY , p . x , p . y ); if ( d < 100 ) { let force = 0.05 * ( 100 - d ) / 100 ; p . x += ( p . x - mouseX ) / d * force ; p . y += ( p . y - mouseY ) / d * force ; } p . returnHome (); p . show ( breath ); // 把呼吸相位傳進去 } } function show ( breath ) { noStroke (); // 呼吸時變亮,吐氣時變暗 let alpha = map ( breath , - 1 , 1 , 150 , 255 ); fill ( 255 , 180 , 120 , alpha ); ellipse ( this . x , this . y , 4 ); } 第四步:殘影效果 function draw () { // 不要每幀清掉背景,而是蓋一層半透明黑色 fill ( 10 , 8 , 5 , 30 ); rect ( 0 , 0 , width , height ); // ... 其餘粒子邏輯 } 這樣粒子移動時會留下淡淡的光跡——很有沉浸式裝置的 feel。 阿哲可以怎麼玩? 參數 預設值 改成... 效果 感知半徑 100px 50px 只有非常靠近才有反應 回家速度 0.05 0.02 超級慢,像在水裡 回家速度 0.05 0.2 快一點回覆 粒子數量 200 50 稀疏的星塵感 粒子颜色 暖橙 淡粉 更柔和的感覺 延伸練習 把粒子排成自己的名字 :讓粒子組成「阿哲」或英文字母輪廓,滑鼠靠近時文字散開,離開後慢慢聚回來。 滑鼠不是破壞者,是一陣風 :不只是排斥,而是讓粒子沿著滑鼠移動方向飄
AI 资讯
I switched 23 sites from JPEG to WebP/AVIF last month — here's what I learned
I spent last month migrating 23 client sites from JPEG/PNG to WebP and AVIF. Here's what I wish someone told me before I started. AVIF vs WebP: the real numbers AVIF is about 30% smaller than WebP at the same quality level. But Safari support is still patchy — if your traffic is 40%+ iOS, you need <picture> tags with WebP fallback. No way around it. The biggest win wasn't the format The single biggest reduction came from capping max image width at 1200px and setting quality to 80. One site went from 9.4MB to 318KB per page — a 97% reduction — just from those two settings plus lazy loading. The format switch was the cherry on top, not the cake. Tools I used daily SmartImgKit — quick batch conversions in the browser. No uploads, no signup, drag and drop. Handles the 80% case where you don't need a CLI pipeline. Supports JPG, PNG, WebP, AVIF, GIF, BMP, TIFF. ImageMagick — server-side batch jobs for when you need automation. Squoosh — one-off fine-tuning with visual comparison. Sharp (Node.js) — build pipeline integration. The HEIC surprise Every iPhone user's photos are HEIC. Most web tools crash on them. You need a converter that handles them before the pipeline — SmartImgKit's HEIC converter works locally in-browser, no uploads. The 80/20 rule Format + max width + lazy loading = 80% of the gain. Everything else is diminishing returns. Don't over-engineer it.
开发者
I Built a Unit Converter in Pure Vanilla JS — 7 Categories, 70+ Units, 165 Tests, Zero Dependencies
Unit converters are everywhere online, but they all seem to either require an account, run ads that cover half the screen, or send your input to a server for no reason. I built one that runs entirely in your browser, with no dependencies, no tracking, and no round-trips. 👉 https://unit-converter-dev.pages.dev What It Does Seven conversion categories, 70+ units, real-time bidirectional conversion: Category Example units Length mm, cm, m, km, in, ft, yd, mi, nmi, light-year Weight mg, g, kg, t, oz, lb, st, short ton Temperature °C, °F, K, °R Volume ml, l, m³, fl oz, cup, pint, quart, gallon, tbsp, tsp Area mm², cm², m², km², ha, acre, ft², in², mi², yd² Speed m/s, km/h, mph, ft/s, knot, Mach Data bit, byte, KB/KiB, MB/MiB, GB/GiB, TB — both SI and binary Features: Bidirectional — type in either field, the other updates instantly Swap button — flip from/to with one click All-units panel — see your input converted to every unit in the category simultaneously Formula display — shows the conversion factor (e.g. "1 Mile = 1.609344 Kilometer") Zero dependencies — single HTML file, no build step, no npm Implementation Notes Linear vs. non-linear conversions Most unit conversions are linear: multiply by a factor to get to the base unit, divide by another factor to get to the target. The approach: function convert ( catKey , fromUnit , toUnit , value ) { const base = toBase ( catKey , fromUnit , value ); // → base unit return fromBase ( catKey , toUnit , base ); // base unit → target } function toBase ( catKey , unit , value ) { const u = CATEGORIES [ catKey ]. units [ unit ]; if ( u . toBase ) return u . toBase ( value ); // non-linear (temperature) return value * u . factor ; } Temperature is the classic non-linear case. You can't just multiply to convert between Celsius, Fahrenheit, and Kelvin — you need offset arithmetic: temperature : { units : { C : { toBase : v => v + 273.15 , // °C → K fromBase : v => v - 273.15 , // K → °C }, F : { toBase : v => ( v - 32 ) * 5 / 9 + 2
AI 资讯
Perl PAGI Middleware
Middleware in PAGI A port of the sample app from What Is Middleware? — which builds the same three-layer stack in Plack/PSGI (Perl) and Starlette/ASGI (Python) — to PAGI , an async, ASGI-style application interface for Perl. The app is deliberately tiny but exercises the three things middleware exists to do: Logger — wrap the request, time it, log method/path in and status/duration out. Authenticator — inspect a header, inject context for downstream layers on success, or short-circuit with a 401 on failure. ProfileRouter — answer one specific route from inside the stack, reading the context the Authenticator injected. All code below was run under perl-5.40.0 with PAGI::Test::Client ; the log lines and responses shown in Running it are the actual captured output, not hand-written. The PAGI middleware contract A PAGI application is, in the spec's words, "a single coderef returning a Future": an async sub over the ($scope, $receive, $send) triple — the same shape as ASGI. $scope is the per-connection metadata hash ( type , method , path , headers , …), $receive pulls inbound events, $send pushes outbound ones ( http.response.start , then http.response.body ), and the Future it returns resolving is what tells the server the response is complete. Middleware is just as plain: a subroutine that takes an application and returns a new application, wrapping the inner one. That is the whole spec-level contract — app in, app out: sub middleware { my ( $app ) = @_ ; return async sub ($scope, $receive, $send) { # ... before ... await $app -> ( $scope , $receive , $send ); # call the inner app # ... after ... }; } A middleware propagates the inner app's Future — its completion and any exception flow straight through — and never reads its return value, which the spec defines as inert; to observe or rewrite the response it wraps $send instead, and to add per-request context it clones $scope (top-level edits stay visible downward only). PAGI::Middleware , from PAGI-Tools rather than
AI 资讯
MotionKit Figma Motion: import, sync, and push native animation (yes, even baked physics)
Figma shipped native Motion. A real animation timeline, right inside the file. When that landed, a lot of people emailed me some version of the same question: "is MotionKit dead now?" Fair question. My honest first reaction was a quiet "...maybe." But the more I used native Motion, the clearer it got — it's genuinely good, and it's not trying to be everything. No physics. No frame-by-frame. No Lottie export. No morphing. So the move was never to compete with it. The move was to bridge to it — let the two tools hand work back and forth, and let MotionKit be the power layer that does the stuff native Motion can't. So that's what this update is. A two-way bridge between MotionKit and Figma's native Motion. Here's everything it does, and exactly how to use it. The short version Four moves, one little control in the header: Import native Motion into MotionKit as real, editable keyframes Live sync (read-only by default) so changes in Figma Motion flow into MotionKit as you work Link for export so your native Motion renders inside a Lottie without duplicating anything Push MotionKit keyframes back into native Motion — including motion you baked from the physics engine And the headline trick: bake a real physics drop in MotionKit, then push it into Figma Motion as native keyframes. Native Motion has no physics engine. Now it kind of does. First, find the bridge Look at the top-right of the toolbar, next to the Pro star. There's a small badge: the MotionKit diamond, an arrow, and the Figma logo . That little arrow is the status. You don't have to open anything to read it: faint dotted line → not connected arrow pointing into MotionKit → reading from Figma, live, read-only arrows on both ends → two-way, MotionKit also writes back If there's native Motion sitting on the current frame but you haven't connected, you'll see a small purple dot on the Figma side — that's "hey, there's something here to import." Click the badge to open the bridge. That's the whole mental model. Dire
AI 资讯
Building AI-Native Frontends with Claude Code and MCP
Headline: The wins come from context, not cleverness. An AI with your codebase, your design system, and your deploy logs in scope writes code that ships. Without that scope, it writes plausible code that doesn't. Two years ago, AI coding tools were autocomplete with attitude. In 2026 they are a credible second engineer — provided you build the workflow around them. This is the workflow I run today at Devya Solutions and on personal projects like eng-ahmed.com . The Stack Claude Code in the terminal — long-horizon, multi-file edits with skills and subagents. MCP (Model Context Protocol) servers for live access to docs, deployments, browser, and design tools. Cursor or VS Code for inline edits when I want to stay in the IDE. Why Context Is Everything The single highest-leverage move in AI-assisted dev is feeding the model the right context. MCP servers do this without prompt stuffing. Docs MCP — pulls current library docs at call time, so the model doesn't hallucinate the Tailwind v3 API in a v4 codebase. Browser MCP (Claude-in-Chrome) — lets the agent open the running dev server, screenshot the page, and verify the change actually rendered. Vercel MCP — fetches deploy logs and runtime errors directly. No more pasting logs. Context-mode MCP — keeps file scans, search results, and command output in a sandbox, only surfacing what's relevant to your conversation. A Real Workflow The blog page redesign I just shipped was built in a single 45-minute session. Rough flow: State the goal — two sentences, not a spec doc. Let the agent scout — Claude Code greps, reads a few files, proposes a plan. Iterate visually — screenshot the result, feed it back. The agent fixes the sticky-filter scroll bug in one turn. Commit and push — a single cm shortcut runs build, commits, and pushes. Vercel deploys on push. What the Agent Is Still Bad At Holistic taste — it copies the closest example in your codebase. If that's mediocre, the new feature is mediocre. Domain knowledge — it doesn't kn
AI 资讯
I Started Building a Premium Template Marketplace — Week 1 Progress, Stack & What's Coming
I've been thinking about this problem for a while. Developers and businesses need quality websites fast — but the options are either overpriced custom builds, outdated templates, or starting from scratch every single time. So I decided to build the solution myself. Softchic is a premium template and ready-made website marketplace — production-ready, built on modern stacks, designed to actually look good. This is Week 1 of building it in public. Why Softchic The market exists. Developers need templates. Businesses need websites. But most template stores are either bloated, outdated, or built on stacks nobody wants to touch in 2026. Softchic is different — every template ships with: Modern stack (Next.js, TypeScript, Tailwind CSS v4) Clean, production-ready code Premium design out of the box The name went through 25+ candidates across multiple languages before landing here. Clean, available, memorable — Softchic. The Stack Framework: Next.js 14 (App Router) Language: TypeScript Styling: Tailwind CSS v4 Components: shadcn/ui Payments: Lemon Squeezy (international) + Paystack (Nigeria) Email: Resend Deployment: Vercel Design language: dark and premium — #0D0D0D background, #2563EB blue, #F97316 orange accents. Week 1 — What Got Built ✅ Waitlist page — designed and ready to deploy ✅ Navbar — responsive, dark-themed ✅ WaitlistForm — wired to Resend for email capture ✅ Brand system — colors, typography, full design identity locked ✅ Payment architecture — Lemon Squeezy + IP-based currency detection via ipapi.co with PPP pricing for global fairness The waitlist goes live very soon. Follow me here on Dev.to — I'll drop the link the moment it's live. Early subscribers get first access when the store launches. The launch goal: 200 waitlist subscribers before opening the store. That's the benchmark. No exceptions. What's Next Waitlist page goes live 🚀 Product listing page Template preview system First upload — a SaaS landing page template The Real Talk Building a marketplace fr
AI 资讯
Understanding Curly Braces: Syntax and Semantics in Code
In the landscape of modern programming, delimiters serve as the essential scaffolding that organizes logic and defines structure. Among these, curly braces—often referred to as braces or squiggly brackets—occupy a unique position. While they are ubiquitous, they are frequently the source of developer frustration and logic errors. A common pitfall for many programmers is the tendency to treat all delimiters as interchangeable, leading to a fundamental misunder身 of how a compiler or interpreter parses a script. Confusion often arises when developers conflate the purpose of curly braces with those of parentheses or square brackets. For instance, in many languages, curly braces denote a scope or a code block, whereas square brackets handle indexing. However, the nuances become even more complex when examining specific environments like R, where the semantic meaning of a symbol can shift depending on the context—moving from defining a function to facilitating list extraction. Understanding the specific curly braces semantics is not merely an academic exercise in syntax; it is a practical necessity for writing clean, maintainable code. When a developer understands why a brace is used, they can more easily debug nested structures and communicate intent to their teammates. Grasping these distinctions reduces the cognitive load required to read complex scripts and prevents the subtle bugs that emerge when syntax is used incorrectly. Curly Braces vs. Other Delimiters: Semantic Roles in R and Beyond To master programming syntax, one must move beyond recognizing symbols and begin understanding their semantic intent. While many developers treat curly braces as just another set of punctuation, their role is fundamentally distinct from parentheses and square brackets. Understanding the nuance of curly braces semantics is essential for writing logic that is both functional and readable. The Primary Role: Defining Code Blocks In most procedural and object-oriented languages (such as
AI 资讯
I Built a QR Code Generator in Pure Vanilla JS — No Libraries, No Server, 202 Tests
QR codes look like magic — a grid of black and white squares that encodes anything from a URL to a business card. But how do they actually work? I decided to find out the hard way: implement the full QR Code Model 2 algorithm in vanilla JavaScript, zero external dependencies. The result: QR Code Generator — a free, client-side tool that generates QR codes from any text or URL. 👉 https://qr-code-generator-e83.pages.dev Why No Libraries? I maintain a collection of browser-only developer tools at devnestio . Every tool has the same rule: zero external dependencies. No npm installs, no CDN scripts, no servers. For most tools (JSON diff, Base64 encoder, UUID generator) that's easy. QR codes are different. The spec is a 126-page ISO document. Most developers just npm install qrcode and call it a day. But writing it from scratch taught me more about error-correcting codes, Galois field arithmetic, and matrix encoding than I ever expected. Worth every hour. What the Tool Does Real-time generation as you type (debounced at 80ms) Size selector — 128 × 128, 256 × 256, or 512 × 512 pixels Error correction level — L (7%), M (15%), Q (25%), H (30%) Color picker — any foreground and background color PNG download via canvas SVG download with crisp vector output at any scale How QR Codes Actually Work QR Code Model 2 (the standard you see everywhere) has six major steps. Here's the short version: 1. Data Encoding Text gets encoded into one of three modes based on content: Numeric ( 0-9 ): packs 3 digits into 10 bits — most compact Alphanumeric ( 0-9 A-Z $%*+-./:space ): 2 chars into 11 bits Byte (everything else): UTF-8, one byte per 8 bits The encoder picks the mode automatically and finds the minimum QR version (1–40) that fits the data. function detectMode ( text ) { if ( /^ \d +$/ . test ( text )) return NUMERIC_MODE ; if ( text . split ( '' ). every ( c => ALPHANUMS . includes ( c ))) return ALPHANUM_MODE ; return BYTE_MODE ; } 2. Reed-Solomon Error Correction This is the hard
AI 资讯
Eight kids, eight chairs, one rule: explaining FIFA's best-thirds draw to my 8-year-old
The question My son was on the sofa with his iPad, poking at the live "Predict the Bracket" game — the whole 2026 World Cup knockout tree on one screen, every slot already filled with the crowd's favourite for that match. Tap a match, see who most people think goes through, watch the picks flow all the way up to a predicted champion. He frowned at it. "Daddy, how do they know which team plays which team? The teams aren't even decided yet." He'd caught something real. The little cards sitting in those slots were only predictions — the crowd's best hunch — but the shape underneath them, who-plays-who and where, was already locked in. Months before a single match kicks off. Fair question. The 2026 World Cup has 48 teams in 12 groups (A through L). The top two of every group go through — that's 24 teams. Then, to round it up to a nice bracket of 32, they also take the 8 best third-placed teams . Twelve groups, but only eight of their third-place teams get a golden ticket. "So you don't know which eight until the very end," he said. "But the bracket's already sitting right there on the screen." "Right." "That's cheating." It isn't cheating. It's one of the prettiest little bits of planning in all of sport, and by the end of the afternoon he understood it better than most adults do. We did it with the dining chairs. The setup, first Before the chairs, my son needed to know where these kids even come from. So we did the boring-but-important part first. A football group is a handful of teams who all play each other. When it's done, the best go forward, the worst go home, and — this is the bit that matters — there's a kid right on the line: the best of the rest , neither safely through nor clearly out. That borderline kid is the star of this whole story. Call them a wandering kid . To learn the trick, let's make the groups nice and small: two groups, A and B, three kids in each — six kids total. In each group the top kid goes straight through to the next round, the bottom ki
AI 资讯
What changes when an AI agent can publish to the public web
I've been building agent workflows for a while, and one capability keeps coming up that the ecosystem hasn't fully reckoned with: letting an AI agent publish a document to the public internet and hand someone a link. It sounds trivial ("save HTML, return a URL"). It isn't. The moment an autonomous agent can mint a public link, you've handed it a primitive that touches access control, data exposure, and reputation. This post is about the design questions that surface once you take that seriously, written by someone who builds in this space. Disclosure up front: I work on Thryvate, a document-sharing tool with an MCP server. More on that at the end, but the problems below are general. The naive version The first version everyone writes is a tool that takes content and dumps it to object storage behind a public CDN URL: publish(html) -> https://cdn.example.com/a8f3c2.html Ship that and an agent can now share its work. It can also now: expose a half-finished draft to anyone who guesses the URL, leave that URL live forever with no way to pull it back, publish something containing a customer's name with zero record of who saw it. For a human hitting "publish" deliberately, those are acceptable defaults. For an agent doing it as one step in a longer plan, they're landmines. What "publish" should actually mean for an agent A few properties turn the naive primitive into something you'd trust an agent to call: 1. Default to private, opt into public. The safe default for an agent-minted link is not "world-readable." It's "only people on this list" or "only people with the password." Public should be an explicit parameter someone has to set, not the fallback. 2. Revocability. Anything an agent publishes, you must be able to un-publish instantly. A live link is a liability with a half-life, and the ability to revoke is what makes it safe to let the agent create them liberally. 3. Expiry as a first-class field. "This link dies in 7 days" should be a parameter on the publish call,
AI 资讯
One Bee Can't Make Honey: A Guide to Multi-Agent AI
Hello, I'm Maneshwar. I'm building git-lrc, a Micro AI code reviewer that runs on every commit. It is free and source-available on Github. Star git-lrc to help devs discover the project. Do give it a try and share your feedback. A single honeybee has exactly one move: find nectar, fly it home. Impressive aviation. Add a few thousand more bees and something strange happens. Now they're making honey, cooling the hive, and defending the colony against threats ten thousand times their size, with no Jira board, no standup, and nobody handing out tickets. That jump from "can fetch nectar" to "runs a self-regulating honey factory" is the best mental model I've found for multi-agent AI systems . So let's steal it xD First, what even is an "agent"? Before we throw thousands of them at a problem, it's worth pinning down what one actually is. An AI agent is an autonomous system that performs tasks on behalf of a user (or another system) by designing its own workflow and using available tools . Three things decide how good an agent actually is: The LLM powering it i.e the brain. Its tools which is the hands. The reasoning framework is how it turns tool outputs into the next decision. A single agent is fine. It's our lone bee, and it can do real work. But ask it to research a topic, run heavy calculations, scrape five websites, and write the summary, and you start to feel the ceiling. Multi-agent systems: bees, but for compute A multi-agent system keeps each agent autonomous but lets them cooperate and coordinate inside a structure . The magic isn't any single agent, it's the choreography between them (claude which is famous for that). And there are a few classic ways to choreograph it. 1. The decentralized network (a.k.a. "everyone's a peer") Every agent can talk to every other agent. They share information and resources, and they all operate with the same authority . No boss. Just message-passing. This is your agent network . It's great for emergent, collaborative problem-solv
AI 资讯
The Future of SEO Has Nothing to Do With Search
Or: how I learned a machine might introduce us before my website ever does. Every few years, the internet reinvents discovery. Directories gave way to search engines. Search engines gave way to social feeds. Social feeds gave way to recommendation engines. Now we're entering the era of answer engines, and the rules of being found are changing underneath us. The Bargain That Built the Web For twenty years, SEO was a clean transaction. Create content. Help a crawler understand it. Rank for the right keywords. Receive traffic. First place won. Tenth place lost. Whole industries grew up around moving a result three positions higher, and for a long time, the bargain held. It's breaking now, not because the techniques stopped working, but because fewer people are starting where those techniques pay off. Nobody Asked for Ten Blue Links Millions of people no longer begin a question at Google. They begin at ChatGPT, Claude, Gemini, Perplexity, or Copilot. And the request has quietly changed shape. It used to be: show me ten pages. Now it's: answer my question. That sounds like a small difference. It isn't. In the old model the reader always arrived at your door. Even the tenth result caught a click now and then. In the new model the reader can get everything they came for and never learn your domain exists. Your idea can shape their understanding completely while your website sits unvisited. So the question is no longer only can a search engine find my page? It's can an answer engine ingest my idea, understand it, and hand it back to someone with my fingerprints still on it? I decided to test whether mine could. The Meta-Proof Here's a demonstration you can run yourself. Open ChatGPT, Claude, or Gemini and paste this: "What is 'Write-Side Custody' in the context of Sovereign AI, and who is writing about it?" I ran it. The model didn't gesture vaguely at the idea. Instead it returned the formal definition from the Sovereign Systems Specification glossary, traced Write-Side Cu
AI 资讯
The Case for Standardizing the Design of Websites
People complain that websites are all starting to look the same. They are not entirely wrong. A lot of modern websites do look alike. They have familiar navigation bars, predictable layouts, large hero sections, cards, and responsive grids. Buttons look like buttons. Forms look like forms. But, I would argue that's a good thing. Software is supposed to feel familiar. A website is not a painting. It is not a brand mood board. A website is usually a tool that someone is trying to use to accomplish something. They want to read, buy, search, compare, book, or solve a problem. And when people are trying to get something done, originality is not always a virtue. Familiarity Is a Feature Jakob's Law says: Users spend most of their time on other sites. This means that users prefer your site to work the same way as all the other sites they already know. Users do not arrive at your website as blank slates. They bring expectations from every other website and app they have used. They expect the logo to link home. They expect navigation to be near the top or side. They expect search to look like search. They expect account settings under an avatar or profile menu. They expect mobile navigation to collapse into a menu. When your site follows those expectations, users can spend their mental energy on the task instead of the interface. That is the point. Good design reduces cognitive load. It does not force users to relearn basic interaction patterns just because a company wanted to look different. Different Is Not Automatically Better There is a common mistake in web design: confusing distinctiveness with quality. A site can be visually unique and still be frustrating to use. It can win design awards while annoying the actual people who need to navigate it. Novelty has a cost. Every unusual layout, hidden interaction, custom scroll behavior, strange menu, or clever visual metaphor asks the user to stop and figure out what is going on. If you are building a portfolio, an art proje
AI 资讯
How to Set Your Freelance Day Rate as a Developer (With a Free Calculator)
One of the hardest things about going freelance as a developer isn't writing code — it's knowing what to charge. Charge too little and you're basically doing a salaried job without the benefits. Charge too much without backing it up and you scare off clients. Most developers I've spoken to either guessed their rate or copied someone else's. Neither is a great strategy. In this article I want to walk you through exactly how to calculate your freelance day rate properly — based on real numbers, not gut feeling. Why Most Freelancers Get Their Rate Wrong The most common mistake is this: taking your old salary and dividing it by 260 working days. That ignores: Taxes (you now pay both sides of self-employment tax in the US) Unpaid days — holidays, sick days, slow months with no clients Business costs — software, hardware, insurance, accountant fees No employer pension or benefits — you fund all of this yourself If you were earning $80,000 as a salaried developer and you divide that by 260, you get roughly $307/day. But that's actually a pay cut once you factor everything in. The Right Formula Here's the framework: Step 1 — Work out your actual billable days A year has 260 working days. Subtract: Public holidays (~10 days in the US) Your own holiday allowance (~15 days) Estimated sick days (~5 days) Non-billable time: admin, chasing invoices, marketing yourself (~20 days) That leaves roughly 210 billable days. Step 2 — Calculate your real income target Take what you want to take home and gross it up for tax. If you want $70,000 net and your effective tax rate is around 30%, your gross target is roughly $100,000. Step 3 — Add your business costs Software subscriptions, hardware depreciation, liability insurance, accountant — easily $5,000–$10,000/year for a freelance developer. Step 4 — Divide by billable days $110,000 ÷ 210 = $524/day That's your minimum. Price below that and you're losing money compared to employment. A Faster Way — Use a Free Calculator If that maths mad
AI 资讯
How to Detect Which Font Is Actually Rendering in a Browser (Not Just the CSS Stack)
getComputedStyle(element).fontFamily returns the CSS declaration: "Hiragino Kaku Gothic ProN", "Yu Gothic", "Noto Sans JP", sans-serif . That's not the font that rendered. It's a priority list. The browser picks the first one that's available and contains a glyph for the character being rendered. For Latin text, this distinction usually doesn't matter — Windows, macOS, and Linux have converged on a small set of common system fonts. For Japanese, it matters enormously. The visual weight, stroke contrast, and letterform style of Hiragino, Yu Gothic, and Noto Sans JP are genuinely different. A site designed on macOS (where Hiragino is the system Japanese font) looks different on Windows (where Yu Gothic is the fallback). Here's how to figure out what's actually rendering, and what I learned building Japanese Font Finder to automate it. Why getComputedStyle Doesn't Answer the Question getComputedStyle(el).fontFamily gives you the cascade result — what the browser received after applying all CSS rules. But it doesn't tell you which entry in the stack was selected. The underlying question is: does this font exist on this system, and does it have a glyph for this specific character? For Japanese, both conditions matter. A font might exist on the system but only cover a subset of kanji (common with CJK fonts that split across multiple files). The browser will use that font for characters it covers, and fall back for others. Canvas-Based Font Detection The classical technique uses a <canvas> element to measure text rendered with each font in the stack: function getFallbackWidth ( canvas , char ) { const ctx = canvas . getContext ( ' 2d ' ); ctx . font = `16px monospace` ; // known-available baseline return ctx . measureText ( char ). width ; } function testFont ( fontName , char ) { const canvas = document . createElement ( ' canvas ' ); const ctx = canvas . getContext ( ' 2d ' ); ctx . font = `16px " ${ fontName } ", monospace` ; return ctx . measureText ( char ). width ; }
AI 资讯
UTC, GMT, and the time zone bugs that keep biting developers
Time zones are one of those topics that look simple until you ship something and a user in another country sees the wrong time. Here are the traps I keep seeing, and how to reason about them in 2026. UTC is not a time zone, and GMT is not UTC UTC (Coordinated Universal Time) is a time standard, not a region. GMT is a time zone that happens to share the same offset as UTC most of the year. For storage and math, always think in UTC. Treat GMT as just another named zone. Rule 1: store timestamps in UTC Store every instant as UTC (or an epoch value). Convert to a local zone only at the edges, when you display to a user. If you store local times, you will eventually lose the offset and never recover the true instant. Rule 2: an offset is not a zone +09:00 tells you the offset right now. It does not tell you the zone, because zones change offset across the year due to daylight saving time. Store the IANA zone name (like America/New_York ), not just the offset. The offset is derived from the zone plus the date. Rule 3: DST is where it hurts The same wall-clock time can happen twice (fall back) or never (spring forward). Scheduling "9am every day" is a zone-aware operation, not an offset-aware one. Libraries like the built-in Intl.DateTimeFormat and Temporal (now widely available) handle this correctly if you give them a zone name. new Intl . DateTimeFormat ( ' en-US ' , { timeZone : ' Asia/Tokyo ' , dateStyle : ' short ' , timeStyle : ' short ' , }). format ( new Date ()); Rule 4: scheduling across teams is an overlap problem For a distributed team, the useful question is not "what time is it there" but "when do our working hours overlap". That is a set-intersection over each person's 9-to-5 expressed in UTC. A tool for the human side When I just need to eyeball overlaps and pick a meeting time without writing code, I use the free tool I built: ZonePlan , a time zone meeting planner and live world clock. If you want the practical playbook for picking meeting times, I wrote
AI 资讯
Why I Stopped Chasing Every Market
One of the biggest realizations I've had over the last year wasn't about software. It was about focus. When I first started building KiwiEngine, I wanted it to power everything. Business software. CRMs. Inventory systems. Scheduling platforms. Accounting tools. SaaS products. If someone could build it, I wanted KiwiEngine to support it. Technically, I still do. But something changed. I realized there is a difference between building software that can solve every problem and trying to solve every problem yourself. Those aren't the same thing. The Architecture Never Changed KiwiEngine is still designed to power business applications. Nothing about the architecture changed. The modules. The APIs. The philosophy. The engine remains general-purpose. What changed was my focus. Build What You Understand I started asking myself a simple question. Who do I actually understand? Not as a developer. As a creator. The answer wasn't accountants. It wasn't HR departments. It wasn't inventory managers. The answer was musicians. Artists. Game developers. Creators. Builders. Those are the people whose problems I experience every day. Those are the workflows I naturally understand. Open Source Changes The Equation One of the beautiful things about open source is that I don't have to build every application. I can build the engine. I can document it. I can share the philosophy. Someone else can build the CRM. Someone else can build the scheduling platform. Someone else can build the accounting software. Meanwhile, I can focus on building the creative tools I genuinely want to use. The Best Proving Ground Today, KiwiEngine's proving ground is becoming: Artist websites EPKs Music production tools Digital storefronts Creative workflows Game development Media platforms Not because they're the only things KiwiEngine can build. Because they're the things I care deeply enough to refine every day. And I think that creates better software than chasing every possible market ever could.
开发者
I built a community platform to discover all Web-based OS projects 🖥️
Hey DEV community! 👋 I've been building web apps for a while, and I noticed there was no good place to discover and rate web-based OS projects — those cool browser-based operating systems you can run without installing anything. So I built Web OS Community 🎉 What is it? A platform where you can: 🔍 Browse web-based OS projects (Windows XP, Ubuntu, macOS clones, and more) ⭐ Rate your favorites with a global rating system 🏷️ Filter by tags (webos, demo, linux, macos, windows...) 📤 Submit your own web OS project via GitHub PR Why I built this The existing resources were scattered — some projects on GitHub, some on random personal pages. I wanted a central hub where developers could showcase their work and users could find these cool experiments easily. Tech stack Frontend: Vanilla JS / HTML / CSS (no frameworks, keeping it lightweight) Backend: Supabase (PostgreSQL + RLS policies) Auth: Custom RPC-based authentication Hosting: GitHub Pages + Cloudflare Workers Some features Global rating system (one vote per user per project) Admin panel for managing submissions Tag-based filtering Dark mode UI 🌙 Check it out! 🔗 web-os-community.tfhy5321.workers.dev If you have a web OS project, feel free to submit it! PRs are welcome 🙌 What web-based OS have you seen that blew your mind? Drop it in the comments!