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

标签:#ev

找到 5180 篇相关文章

AI 资讯

I Kept Hearing "Didn't We Already Send That?" So I Built a Tool to Fix It

I'm a self-taught developer. No CS degree, no funding, no team. Just me, a laptop, and a problem I kept watching people struggle with. The Problem Every freelancer and small agency I know deals with the same mess: client details scattered across WhatsApp chats, email threads, Google Drive folders, and random Notion pages. Nothing lives in one place. When a client asks "wait, didn't we already send you the logo files?" you're digging through three different apps trying to remember. I didn't just hear about this problem — I lived it. So four months ago, I started building Kray. What Kray Actually Does Kray gives freelancers and agencies one organized workspace per client — projects, links, and notes, all in a single place instead of scattered across five different tools. The part I'm most proud of: when you share a project with a client, they can open the link and see everything instantly — no sign-up, no account creation, no friction. Just a clean, simple view of what they need to see. The Stack Since I was building this entirely solo with zero budget, I leaned on tools that let me move fast without infrastructure headaches: React 19 + Vite + TypeScript (strict mode — no shortcuts) Tailwind v4 for styling Supabase for auth, database, and storage Deployed on Vercel No backend servers to manage. No DevOps to worry about. Just me shipping features. What I Learned Building Solo You will hit bugs that eat entire days. I spent hours debugging a sitemap indexing issue that turned out to be one missing header. That's the job — most of building isn't writing new features, it's fixing the thing that should've worked but didn't. Deploy discipline matters more than you think. I once tested a feature locally, assumed it was live, and spent 20 minutes confused about why production wasn't behaving — because I'd forgotten to push. Lesson learned: always verify what's actually deployed before debugging further. Marketing is its own skill, and it's humbling. I've spent the last severa

2026-08-08 原文 →
AI 资讯

Your firewall is your AI policy — I probed 18 major sites to read it

Everyone's arguing about AI search visibility. Almost nobody is measuring the boring part: whether AI crawlers can fetch your pages at all . So I built a small open-source tool — geo-crawl-audit — that probes any site with the user-agents of every AI crawler that matters (GPTBot, OAI-SearchBot, ClaudeBot, PerplexityBot, ChatGPT-User, and friends), measures how each is treated versus a normal browser, and checks the thing most people never think about: how many words exist in the raw HTML before any JavaScript runs . Because here's the detail the industry keeps missing — GPTBot, ClaudeBot, and PerplexityBot don't execute JavaScript. For most sites, Googlebot (feeding Gemini) and Applebot are the only AI-adjacent crawlers that render it. A site can rank #1 in Google and be a blank page to nearly everything else. I pointed it at 18 major sites on August 7. Five findings worth your time. 1. Access patterns line up with the business relationships The Guardian — which has a content deal with OpenAI — serves my simulated GPTBot, OAI-SearchBot, and ChatGPT-User a clean 200 . The same request wearing ClaudeBot, PerplexityBot, or CCBot : 403 , and those names are in its robots.txt disallow list too. Policy and enforcement agree. The New York Times — in litigation with OpenAI — 403s nearly everyone: GPTBot, OAI-SearchBot, ClaudeBot, PerplexityBot, Common Crawl, meta-externalagent. Two user-agents got through: bingbot and Amazonbot. I want to be careful about the claim here: a status code tells you who is blocked , not why . Any individual 403 has mundane explanations. But when the allow/deny matrix maps this cleanly onto public deals and public lawsuits, the firewall config has become a business document — and it's readable by anyone with a terminal. 2. robots.txt is a polite sign. Some doors are unlocked anyway. Reddit's robots.txt blocks every AI bot in my list — fourteen tokens, no exceptions. Enforcement tells a different story: my GPTBot UA got a 403 and ClaudeBot and CCB

2026-08-08 原文 →
AI 资讯

Docker for Beginners: Images, Containers, Ports, and Volumes Explained

Docker for Beginners: Images, Containers, Ports, and Volumes Explained If you've ever followed a programming tutorial and seen something like: docker run ... you've probably wondered: What exactly is Docker doing? I had the same question when I started learning Docker. At first, I thought Docker was simply a way to "run applications in containers." But there is much more to it. Once I understood four concepts — images, containers, ports, and volumes — Docker became much easier to understand. So let's break it down from the beginning. What Is Docker? Docker is a platform for building, packaging, and running applications in isolated environments called containers . The basic idea is simple: Package an application together with the things it needs to run, and make that package portable. For example, imagine you build a Python application. Your application might depend on: Python 3.12 FastAPI Uvicorn Several Python packages Environment variables Certain system libraries On your computer, everything works. Then someone else downloads your project. They install a different Python version. A package is missing. Something behaves differently. Now you have: "It works on my machine." Docker helps reduce this problem by allowing you to define the environment your application should run in. The Four Concepts You Need to Understand Before learning Docker commands, understand these four things: Docker Image ↓ Docker Container ↓ Ports ↓ Volumes Let's look at each one. 1. What Is a Docker Image? A Docker image is a packaged, read-only template used to create containers. Think of it like a blueprint. For example: Docker Image │ ├── Ubuntu ├── Python ├── Application code ├── Dependencies └── Configuration An image contains the instructions and filesystem needed to create a container. You can download images from container registries such as Docker Hub. For example: docker pull nginx This downloads the Nginx image. You can see your downloaded images with: docker images You might see s

2026-08-08 原文 →
AI 资讯

I Tried Building JavaScript Games Without a Game Engine. Here's What I Learned

I am a digital marketer, not a professional developer or game developer. Most of my career has been focused on SEO, growth marketing, paid acquisition, content, and digital strategy. When I started building GamesMom, however, I found myself learning much more about web development than I expected. GamesMom is a collection of free educational games and learning activities for kids that run directly in the browser. The site includes math games, word games, typing games, memory games, puzzle games, classroom games, quizzes, and other interactive activities. The idea was simple: make games that children can open and play without downloading an application or creating an account. I initially assumed that building browser games would require a dedicated game engine or a large JavaScript framework. After experimenting with different approaches, I found that many of the games I wanted to create could be built with ordinary HTML, CSS, and JavaScript. That was probably the most useful lesson I learned from the project. You don't always need a complicated technology stack to create an interactive web experience. I Started With the Simplest Approach When you're not a professional developer, it is tempting to look for the most sophisticated solution available. I did this too. I spent time looking at frameworks, game engines, libraries, and different ways of structuring interactive applications. Eventually I started asking a much simpler question: what does this particular game actually need? A basic educational game might need to display a question, accept an answer, update a score, show feedback, and move to the next question. Another might need a timer, a few buttons, and some randomization. Those requirements don't automatically justify a game engine. For simple browser games, the browser already provides a lot of what you need. HTML, CSS and JavaScript Can Go a Long Way The basic combination is surprisingly capable. HTML provides the structure of the page. CSS controls the v

2026-08-08 原文 →
AI 资讯

What Are Autonomous AI Agents? A Practical Guide for Developers

Most AI applications wait for a user to ask a question and then return an answer. Autonomous AI agents go further: they can interpret a goal , decide what steps are required, use external tools, evaluate the results, and continue working until the task is completed or human help is needed. For example, a chatbot can explain how to resolve a customer complaint. An AI agent can read the complaint, retrieve the customer's order, check company policy, prepare a response, update the support ticket, and request approval before issuing a refund. That ability to make decisions and take actions is what makes autonomous AI agents different from traditional chatbots and fixed automation. 1. What Is an Autonomous AI Agent? An autonomous AI agent is a software system that uses an AI model to pursue a goal with limited human intervention. It can understand instructions, create a plan, select tools, perform actions, observe the results, and adjust its approach when necessary. A typical agent can: Understand a high-level objective Break the objective into smaller tasks Choose which tools or APIs to use Retrieve relevant information Take actions in external systems Maintain context across multiple steps Evaluate whether each action succeeded Recover from some failures Stop, retry, or escalate to a human Autonomous does not mean completely independent or unrestricted. A well-designed agent operates inside defined permissions, policies, spending limits, approval rules, and stopping conditions. 2. How Autonomous AI Agents Work Most autonomous agents follow a continuous decision loop: Receive Goal ↓ Observe Context ↓ Create or Update Plan ↓ Choose a Tool ↓ Perform an Action ↓ Evaluate the Result ↓ Continue, Retry, Stop, or Escalate Suppose a user gives an agent this goal: Find three suitable meeting times with the product team next week and send invitations after I approve one. The agent may: Identify the required participants. Retrieve their calendar availability. Check working hours a

2026-08-08 原文 →
AI 资讯

Biryani CSS Art — India's Soul in Every Grain 🍛

This is a submission for Frontend Challenge - Comfort Food Edition, CSS Art . Inspiration I chose to build a classic Dum Biryani — the ultimate comfort food! 🍛 There is nothing quite like opening a steaming handi of biryani and seeing the rich, saffron-colored rice dotted with fried onions, mint, and spices. It's a dish that brings people together and feels like a warm hug, making it the perfect inspiration for the Comfort Food challenge. Demo Here is my CSS Art representation of a traditional Biryani Handi! I built this primarily using vanilla CSS to create the realistic clay texture of the pot, the individual grains of rice, the steam animations, and the garnishes. I added a tiny bit of JavaScript just for a subtle mouse-parallax tilt effect and a saffron sparkle when you click the pot. https://github.com/pandeynitish23/dev_css_chalange/ https://dev-css-chalange.nitishkumar-nk-np.workers.dev/ Journey Building this was a really fun exercise in CSS gradients and positioning! What I'm most proud of: The Clay Handi: I used layered radial and linear gradients along with inset box shadows to give the pot a realistic, 3D clay texture with lighting highlights. The Rice & Garnishes: Creating individual rice grains, mint leaves, and onion crisps using CSS border-radius and positioning was tedious but incredibly rewarding when it all came together. The Atmosphere: Adding animated steam and floating background spice particles helped bring the scene to life and make it feel hot and fresh. It was a great challenge keeping the JavaScript minimal and relying on pure CSS for the heavy lifting of the art itself!

2026-08-08 原文 →
AI 资讯

Your AI agent's UI is mediocre—and here's how to fix it

If you’ve been building with Claude or Cursor for the last year, you’ve noticed a pattern. The code comes out clean. The logic is sound. But the interfaces? They look like 2015-era Bootstrap clones. Everything has the same rounded corners, arbitrary shadows that don't communicate depth, and linear animations that feel robotic rather than organic. AI agents are incredible at generating functional HTML and CSS, but they lack a fundamental concept: design intent. They can write the code to make a button blue, but they struggle to understand why that button needs a specific spring-based scale effect when pressed, or how its elevation should change relative to the background surface. They produce 'zombie' interfaces—functional, but lifeless and fundamentally broken for high-end production use. This isn't just an aesthetic problem; it’s a technical one involving accessibility, usability, and user agency. I recently started using something called the UI/UX Excellence Prover via Vinkius to close this gap. It doesn't generate code—that's not its job. Instead, it acts as a design unit test for your agentic pipeline. You aren't asking it to 'make it look better'; you are asking it to validate that the generated component meets 2026-era standards across six specific pillars. The Death of Flat Decoration The first thing I noticed in most AI-generated layouts is what I call "flat decoration." Agents love using box-shadow as an ornament. They'll add a shadow to every card just because it looks 'modern.' But shadows aren't decorations; they are spatial communication tools. A properly engineered interface uses elevation (levels 0 through 5) to communicate hierarchy. Level 0 is your base surface. Level 3 might be a modal overlay that physically sits closer to the user in Z-space. If everything has a shadow, nothing has importance. When you run an agent's output through the Prover ( UI/UX Excellence Prover ), it flags these arbitrary shadows. It forces the agent to define elevation se

2026-08-08 原文 →
AI 资讯

Designing Clean Roblox GUIs: Grid, Contrast, and the 3-Click Rule

Designing Clean Roblox GUIs: Grid, Contrast, and the 3-Click Rule A Roblox game lives or dies by its UI. Players decide in seconds whether a game "feels" polished, and most of that feeling comes from the interface — health bars, inventory, shop buttons, loading screens. Yet a lot of Roblox GUIs are cluttered, low-contrast, and hard to tap on mobile. Here are the rules I keep coming back to. 1. Build on a grid, not by eye Roblox Studio's UIAspectRatioConstraint + UIGridLayout let you snap elements to a grid instead of dragging them freehand. Freehand layout looks fine on your monitor and breaks on every other screen. Pick a base cell size (e.g. 80×80) and make everything a multiple of it. A white health bar on a light background is invisible. Aim for at least 4.5:1 contrast on text and key elements. Dark UI over a dark game scene? Add a stroke — UIStroke is cheap and fixes readability instantly. 3. The 3-click rule A player should reach any core action (equip, buy, start) in 3 taps or fewer. If your shop is 4 menus deep, players leave before they spend Robux. Flatten it: one main HUD, one overlay panel per feature. 4. Mobile-first sizing Most Roblox players are on phones. A button that's comfortable on desktop is often too small to tap reliably on a 6" screen — minimum touch target ~48×48 px. Size with Scale , not Offset , so the UI scales with the viewport. 5. Reuse components Don't rebuild a button 12 times. Make one button template (Frame + TextLabel + UIStroke + UICorner + LocalScript) and clone it. This is the single biggest time-saver in Roblox UI work. The fast path If you'd rather not hand-roll every panel, a Roblox GUI maker lets you assemble common components and drop them straight into Studio — handy for prototyping before you commit to a fully custom design.

2026-08-08 原文 →
AI 资讯

The Headless Workspace: How Antigravity CLI Lowers the Neovim Learning Curve

A GUI IDE is great for local development, but it quickly falls apart when you transition to headless servers, low-power client machines, or remote clouds. If you pair an AI agent like Antigravity CLI with a native-first Neovim configuration, you can bypass complex setups entirely. Since the AI assistant is the one doing the heavy writing, refactoring, and saving of files, you don't need to be a Vim keyboard wizard to use Neovim. The editor simply becomes a fast, native terminal pane for inspecting the code and reviewing git diffs. By pairing the two, you can build a modern, high-performance workspace built on native features that runs perfectly in any terminal. Here is the backstory of how we ended up with this setup, and why going native-first in Neovim became our preferred remote development tool. 💻 The Backstory: From a Broken Screen to Ephemeral Cloud VMs My 10-year-old MacBook Pro recently had its screen break. It still works fine, but it is now permanently anchored to my desk with an external monitor. Buying a new laptop is too expensive right now, but I have an iPad that I use when traveling. To work from the iPad, I use Google Cloud Shell via the web browser. This allows me to write and inspect code using the Cloud Shell Editor and run Antigravity CLI . However, Cloud Shell has strict storage, memory, and CPU limits. As an Application Modernization, DevOps, and SRE developer, my projects are resource-intensive. I need to run multi-container environments like the Google Cloud Microservices Demo . Plus, next week I’m attending the Gemma Day Event hosted by the Google DeepMind team. This will be my first hands-on contact with Gemma, and after the event, I plan to continue testing how the model interacts inside a Kubernetes cluster, establishing observability for LLM-native metrics (like token throughput and response latency). I don't want to buy an expensive machine with a GPU just to test these setups. Instead, I want to spin up a GPU-enabled VM in Compute Eng

2026-08-08 原文 →
AI 资讯

I Deployed My Backend to Render… and Then Everything Broke 💀

I Deployed My Django App to Render… and Then Everything Broke 💀 Deploying an application sounds simple. Push the code. Configure the service. Deploy it. Done. Yeah… not exactly. 💀 I recently deployed one of my Django applications to Render, and the deployment itself looked successful. The service was live. Gunicorn started. Render gave me a live URL. But when I actually opened the application and started making requests… 500 Internal Server Errors. And that's where the real debugging started. 🚀 Deploying the Application to Render My application had a frontend and a Django backend. The basic flow looked like this: User ↓ Frontend ↓ Django Backend ↓ Database Everything was working correctly on my local machine. So I connected the repository to Render and configured the deployment. The build completed successfully, and the server started with Gunicorn. Render even showed the service as live. At this point, I thought: "Okay, we're done." I was very wrong. 😭 💥 The Actual Problem Started After Deployment Once the application was live, I started seeing requests returning: 500 Internal Server Error There were also other requests returning 400 errors. The important part was that the deployment itself wasn't necessarily failing. The application was running, but the application was failing when handling requests. That distinction was important. Instead of immediately changing random code, I went back to the Render logs. 🔍 The Render Logs Were the First Place I Looked The logs showed that Gunicorn was starting successfully: Gunicorn starting Listening for requests So the server process itself was alive. But then requests started showing errors like: GET ... 500 GET ... 500 GET ... 400 This made me realize something: A deployment being marked as "Live" doesn't mean every part of the application is working correctly. The next step was to find out why the requests were failing . 📁 Then I Found a Frontend Build Problem One of the warnings in the logs was: No directory at: /opt/rend

2026-08-08 原文 →
AI 资讯

Building an LLM Cost Dashboard

Cost dashboards usually fail in one of two directions: a single total that nobody can act on, or forty panels that nobody reads. Five charts, each answering a question somebody actually asks out loud, is about the right size — and each of them is a query you can run today. Three audiences ask genuinely different questions of the same data, and a dashboard that ignores the split ends up serving none of them. Finance asks what this month will be and why it differs from last month. Engineering asks what a particular change did. Product asks whether a feature can be afforded at ten times the current user count. The five charts below cover all three, in roughly that order — which is also why the top of the dashboard is a trend line and not a breakdown: the first question anyone has is whether the number is moving, and only then which part of it moved. Everything runs against the llm_request table from the logging page and the daily rollup from per-customer tracking . One rule for all of them: where environment = 'prod' , always, because eval and staging spend contaminates every trend it touches. 1 · Spend and run rate Daily spend, with a month-to-date total and a straight-line projection to month end. The projection is the panel finance looks at; the daily series is what makes a step change obvious. with daily as ( select started_at :: date as day , sum ( cost_usd ) as spend from llm_request where environment = 'prod' and started_at >= date_trunc ( 'month' , now ()) - interval '2 months' group by 1 ), mtd as ( select sum ( spend ) as spend_mtd , count ( * ) as days_elapsed from daily where day >= date_trunc ( 'month' , now ()):: date ) select d . day , d . spend , avg ( d . spend ) over ( order by d . day rows between 6 preceding and current row ) as spend_7d_avg , ( select round ( spend_mtd , 2 ) from mtd ) as mtd , ( select round ( spend_mtd / nullif ( days_elapsed , 0 ) * extract ( day from date_trunc ( 'month' , now ()) + interval '1 month - 1 day' ), 2 ) from mtd )

2026-08-08 原文 →
AI 资讯

Alerting on LLM Metrics Without Alarm Fatigue

Most LLM alerting starts as a threshold on latency and a threshold on error rate, fires nine times in the first week, and is muted by the second. The fix is not better thresholds. It is a different trigger model and a much shorter list of things allowed to page. Level-triggered, not edge-triggered An edge-triggered alert fires on a transition: latency crossed 3 seconds, error rate spiked. It is easy to write and it is why your phone buzzed at 03:00 about a condition that resolved itself in forty seconds. A level-triggered alert asks a different question — is the system currently in a bad state, and has it been for long enough to matter? Concretely, the difference is that the alert condition is evaluated over a window and describes a sustained state, and it clears when the state clears rather than when someone acknowledges it. Every rule below is of that shape. Anything that fires on a single scrape does not belong in a paging policy; put it in a dashboard. Page on symptoms, ticket on causes The reliable partition, straight out of ordinary SRE practice and entirely applicable here: Page when users are being harmed now, and a human can do something about it in minutes. That is a small list: the feature is failing, the feature is unusably slow, or money is leaving the building at an unplanned rate. Ticket when something is degraded, trending wrong, or will bite in days. Rising retry rate. One provider slower than usual while failover is absorbing it. Attribution coverage slipping. Neither for everything else. If nobody would act on it, it is a chart. The distinction matters more for LLM features than for a normal service because so many of the interesting signals are causes : a provider 429 rate, a fallback rate, a cache-hit drop. If failover is working, none of those are user-visible and none of them should wake anyone. They are exactly what you want in the morning ticket queue. Burn-rate alerts, with the numbers The standard design — described in Google’s Site Reliab

2026-08-08 原文 →
AI 资讯

Four false positives in one evening: telling a broken web app from a broken measurement

I spent an evening opening other companies' product configurators — 3D and parametric tools on manufacturers' sites — looking for things that were genuinely broken. Twenty-seven of them. The findings were real. But the part worth writing down is that four separate times in one evening, my tooling told me an application was broken when it was fine. Every one of those four passed automated checks that looked rigorous. What caught them was a screenshot. If you write scripts that judge pages you don't own — uptime checks, competitor teardowns, scraping health, QA of an embedded widget — you will hit these. Here is the full list of signals that lied to me, and the one control that never has. The four false positives All four produced the same symptom: no <canvas> on the page, and an almost empty innerText . That looks damning when the page is literally titled "Configurator". It is also what three completely healthy situations look like: The tool starts on a click. An orange button launches it. My script measured an unopened door and reported an empty room. Four automated passes — raw HTTP with a browser UA, my own browser, two runs from a clean profile, a control on the same domain — all four confidently examined a page that hadn't started yet. The entire UI lives inside the canvas. One hall configurator draws its menus, its undo/redo and its PDF export in WebGL. Empty DOM text is correct there, not a defect. The tool is behind a login. I was measuring a sign-in page. Fifty-four characters of text and one button reading "Anmelden". The page is a landing page about the configurator, not the configurator. No network-level or DOM-level check distinguishes these from an actual failure. A screenshot distinguishes all four instantly. So the first rule I now follow, before any measurement at all: Take the screenshot first. Look at the picture. What you cannot see in the image, you do not measure. It costs one second and it is the highest-yield step in the whole process. The cor

2026-08-08 原文 →
AI 资讯

Error Messages When the Model Fails

“Something went wrong. Please try again.” is correct for about a third of AI failures and actively harmful for the rest, because for the rest, trying again cannot possibly help and you have just told the user to spend money finding that out. Everything that can go wrong Errors arrive from at least four layers, and the user-facing consequences differ enough that collapsing them into one message destroys the only information you had. Failure Description Transport Connection dropped, DNS, TLS, the stream died mid-token. Retryable, usually transient, and the user did nothing wrong. This is the only class where 'try again' is straightforwardly true. Rate limited (429) Yours or the provider's capacity, not the request. Retryable but only after a wait, and the wait is often stated in a header. Telling the user to retry immediately guarantees a second 429. Provider 5xx / overloaded Retryable with backoff, and the single best case for automatic failover to another provider rather than for any message at all. Timeout Ambiguous by construction: the request may have completed on the provider's side and been billed. Retrying may duplicate a side effect, which is why idempotency matters more here than anywhere. Context length exceeded Deterministic. Retrying the identical request fails identically. The only fix is fewer tokens, and the interface knows that — so the message should offer the fix, not the retry. Content filter The provider blocked the input or the output. Not retryable unchanged. Distinct from a model refusal, and users experience the two very differently. Truncated output The generation hit max_tokens. Not an error at the transport layer at all — status 200, a finish reason of 'length', and an answer that stops mid-sentence. Silently the most common broken experience. Malformed structured output Valid HTTP, invalid JSON or a schema violation. Retryable and often succeeds on a second sample, because it is a sampling accident rather than a capability failure. Empty o

2026-08-08 原文 →
AI 资讯

How I Built an AI Content Factory That Sounds Like Me

I used to spend hours rewriting AI-drafted video scripts that sounded nothing like me. At best, I might finish one or two that were just okay, but most of the work was still on my shoulders. Now, with my new system, I can get 15 scripts done in one session. They match my writing style, my voice, and my company's knowledge. Instead of full rewrites, each script just needs a quick review. I built the system in about a week, and the difference showed up before the week was out. The first project was an internal video series to teach people about the software factory and LaunchDarkly, and I barely had to edit those scripts. For the first time, the AI handles most of the work. My recent projects have mostly involved agentic software delivery. The software factory is where all of it was heading, and my company spent months preparing to help customers build their own. We had internal material, public documentation, and ongoing conversations I wanted to add clarity to. So my challenge wasn't just learning, it was learning while producing content at the same time. Essentially, devrel. By the end, I had built what I like to call my own personal content factory. At first, it was separate from the software factory it describes, but over time, the line between them blurred. My approach is to let AI handle the bulk of the work, while I step in for the important decisions. This is the only way I've found to make AI content sound like me. The AI creates the drafts, and I step in at three key points: checking the voice, the facts, and the overall feel. The quality ceiling is set before the first draft. I didn't just ask for a video script about a topic. Instead, I gave Claude access to every source I had—public docs, internal notes, and product requirements. It used research agents to read everything at once and came back with clear, organized notes I could use. I set two important rules for this step. First, every part of the research was labeled as either public-safe or internal-o

2026-08-08 原文 →
AI 资讯

The only instant cameras worth your money

There’s something magical about using instant cameras that smartphones can’t match. You can capture a moment, print it out, and then give the photo as a gift or hold onto it. Image quality won’t be all that good, but imperfections are part of the allure. We tested instant camera models from popular brands and landed […]

2026-08-08 原文 →
AI 资讯

The SVG Color Cascade Nobody Explains (fill, stroke, currentColor, and why img src breaks it)

Change an SVG's color by editing fill and stroke , either as attributes or through CSS. Simple in theory. In practice there are three places a color can be declared in the same file, they follow the normal CSS cascade, and if you don't know that, "I changed the fill and nothing happened" turns into a twenty-minute debugging session. Here's the part of SVG color handling that usually doesn't get spelled out. fill and stroke are separate properties Every shape has an inside ( fill ) and an outline ( stroke ), set independently: <circle cx= "50" cy= "50" r= "40" fill= "#3366ff" stroke= "#000" stroke-width= "2" /> Unset fill defaults to black. Unset stroke defaults to none. If an icon is pure fill with no stroke at all (most converted icon-font SVGs are), editing stroke-width is never going to do anything visible, and that's usually the first dead end people hit. The cascade is the actual bug source A color can come from three places, and they don't have equal priority: A presentation attribute: <path fill="red" /> An inline style attribute: <path style="fill: red;" /> A <style> block or external stylesheet: path { fill: red; } Normal CSS specificity applies: style attribute beats stylesheet, stylesheet beats presentation attribute. Edit the fill="red" attribute directly, and if a <style> block elsewhere in the same file also targets that path, your edit is overridden and nothing changes on screen. No error, no warning, it just loses. If a color edit isn't sticking, grep the file for <style before assuming your tool, or your edit, is broken. This one thing accounts for most "the SVG editor is buggy" reports that are actually the cascade working exactly as designed. currentColor: SVG's inheritance trick Set fill="currentColor" and the shape stops carrying its own color and instead inherits whatever color is set to on an ancestor element, the same mechanism that makes text inherit color: <path fill= "currentColor" d= "..." /> .icon { color : #ff0000 ; } <span class= "icon

2026-08-08 原文 →
AI 资讯

The SVG Path Data Format, Explained (M, L, C, Q, A, Z)

If you've opened a <path d="..."> string and had no idea what you were looking at, here's the short version: it's a tiny drawing language. A pen moves around a coordinate space, and each letter in the string is an instruction telling it what to do next. TL;DR M / m moves the pen, L / l draws a straight line, C / c and Q / q draw bezier curves, A / a draws an arc, Z / z closes the shape. Uppercase is absolute coordinates, lowercase is relative to the pen's current position. A visual path editor drags the exact same numbers you'd type by hand, it just shows you the curve instead of making you compute it. Reading a path string <path d="M10 10 L90 10 L90 90 Z" /> Broken down: move to (10, 10), draw a line to (90, 10), draw a line to (90, 90), close the path back to the start. That's a right triangle. Every path, no matter how complex, is this same pattern: a command letter followed by however many numbers that command needs, repeated. The command set Command Name What it takes M / m Move to x, y L / l Line to x, y C / c Cubic bezier control1 x/y, control2 x/y, end x/y Q / q Quadratic bezier control x/y, end x/y A / a Arc rx, ry, rotation, large-arc-flag, sweep-flag, end x/y Z / z Close path none C and Q are both bezier curves, the difference is one control point ( Q ) vs two ( C ). Two control points give you more independent influence over each end of the curve; one control point gives you a simpler, more symmetric curve. There are also shorthand continuations ( S / s , T / t ) for chaining smooth curves without repeating a control point, but the six above are what you'll hit constantly. A is the one people avoid writing by hand. Six parameters, two of which are flags (0 or 1) that determine which of four possible arcs you get for the same radii and endpoints. Flip one and you're not slightly off, you're on the opposite side of the ellipse. Absolute vs relative is the part that bites Every command above has an uppercase and lowercase form, and it's not cosmetic: <!-- a

2026-08-08 原文 →
AI 资讯

Multi-Repo to Monorepo: How I Automated 6 Go Microservice Releases and Then Made It 15x Faster

Last month I spent more than an hour cutting a release across six Go microservice repos. Tag log, wait for CI. Update sdk's go.mod to point at the new log SHA, push, wait for CI. Repeat for utils. Then do api, cli, and worker in parallel - except I forgot to bump cli's dependency and the build broke at 11pm. That was the last manual release I did. This is the story of automating that entire workflow with Jenkins + Python + GitLab, then realizing the multi-repo architecture was the real problem, and collapsing everything into a Go monorepo that's 15x faster at cutting releases. The full setup runs on my laptop. You can fork it and try it yourself. Table of Contents The Six Modules The Stack Phase 1: Multi-Repo Automation Phase 2: The Monorepo Pivot The Unified CI Pipeline Real Numbers Caveats and Gotchas Try It Yourself The Six Modules The project simulates a real production system with six Go modules that have strict dependency ordering: Module Role Tag Scheme Depends On log Logger (leaf, no deps) v0.x.0 - sdk API client v0.x.0 log utils Shared utilities v0.x.0 log, sdk api/backend Backend APP-x.y.z log, utils cli CLI cli-x.y.z log, sdk worker Background v0.x.0 log, utils The first three modules are sequential - sdk can't tag until log is tagged, utils can't tag until sdk is tagged. The last three are terminal - they can process in parallel once the sequential chain is done. Every module lives on three long-lived branches: develop → release → master . A release means moving code through all three, in all six repos, in the right order. That's the problem. Do it manually and you're juggling 6 repos × 3 branches × dependency ordering. One forgotten go mod tidy and you're debugging at midnight. The Stack Everything runs on a MacBook. No cloud CI, no SaaS - just local tools wired together. MacBook GitLab.com +-------------------+ ngrok tunnel +------------------------+ | Jenkins LTS | <===============> | Webhooks (push / MR) | | (brew service) | | Commit status API | | :

2026-08-08 原文 →