产品设计
Patreon launches 30 new creator features, including short-form Clips and revamped discovery
Patreon is overhauling how creators get discovered, adding short-form Clips, topic-based communities, and a revamped recommendation system designed to give smaller creators more visibility.
AI 资讯
Debates over AI consciousness are a trap
“Runaway” AI, “rogue” agents, and “autonomous” actors—the current rhetoric would have you believe that AI agents are not only awake and aware, but angry at their creators. Prominent tech leaders such as Demis Hassabis, Dario Amodei, and Sam Altman push for regulation of these seemingly “superhuman” systems, while a separate faction, led by policy organizations…
AI 资讯
🎬 Reel Quick now has a live animated demo in the GitHub README
The demo gives a quick look at the workflow for creating short-form videos with trimming, stitching, text overlays, voice tools, themes, and transitions. Built with FastAPI, Next.js, Redis/ARQ, and FFmpeg. Repo: https://github.com/ronin1770/reel-quick OpenSource #Python #FastAPI #NextJS #FFmpeg #VideoAutomation #DeveloperTools #AI
AI 资讯
AI Reviewing AI Is Not Review
Originally published at tddbuddy.com . Related reading: Where the Review Point Moved is the direct predecessor; this post argues the industry's response to that shift is doubling down on the wrong surface at higher throughput. What "Senior" Means When Typing Is Free and The Test Pyramid Was an Economic Argument name where signal actually lives now. The review agent left fourteen comments on the pull request and none of them were the reason the PR should not have merged. That is the shape of the failure. The reviewer that shipped the review was a tool built to catch what a human reviewer no longer had time for. Three of the comments were genuine issues, unused imports, a typo in a log message, a dead branch. Eleven were style opinions, restatements of what the diff already made obvious, or false positives on patterns the codebase had chosen deliberately. The human on the PR spent more time filtering the review than reading the diff. The change that actually needed a second pair of eyes (a renamed field in a shared DTO that had already broken a downstream consumer twice this year) merged without a comment on it from either the human or the machine. The industry response to agent-generated pull-request volume has been to deploy more agents. The response is understandable. It is also empirically counterproductive. A 2026 study measured what happens when only a code-review agent reviews an agent-authored PR: 60.2% of closed pull requests sat in the 0 to 30 percent signal-ratio range, and twelve of the thirteen review agents evaluated averaged below a 60% signal ratio. Signal is what a human reviewer needs. The review agent produces less of it per unit of reviewer attention than the diff would have without a bot in the middle. The Volume Problem Is Real Four hundred thousand pull requests in two months from a single code-writing agent. One in five reviews on the largest hosting platform now involves an agent. Pickup time on agent-authored PRs is 5.3 times longer than on h
AI 资讯
Connect a Carrd Landing Page to Payhip Without Building a Backend
Affiliate disclosure: I’m an independent Payhip Partner. The optional signup link at the end is my partner link; I may receive a commission from Payhip if a referred seller generates eligible revenue. I am not a Payhip employee or official representative. A creator selling one template or downloadable guide does not need to write a payment backend. The safer architecture is usually: Carrd or static page ↓ Payhip product page or direct checkout ↓ Hosted payment and product delivery Your public page explains the offer. The hosted commerce platform owns the payment flow. No card data, secret keys, or payment logic belongs in Carrd. This tutorial shows two link-based integrations and one optional embed route. Before you start You need: A published product in Payhip Its public product URL A button on your Carrd or static page A clear product description, support contact, and terms In Payhip, the product URL is available from the product’s Share / Embed controls. A typical product URL has this shape: https://payhip.com/b/PRODUCT_KEY Use your real product key in every example below. Option 1: Send visitors to the product page This is the safest default when the buyer still needs details before purchasing. In Carrd: Select the call-to-action button. Set its URL to your full Payhip product URL. Use a descriptive label such as View template details or See what’s included . Preview the page on desktop and mobile. On a conventional static site, the equivalent HTML is just an anchor: <a class= "product-button" href= "https://payhip.com/b/PRODUCT_KEY" > View product details </a> No JavaScript is required. Use this route when the Payhip product page contains important previews, license terms, compatibility notes, or variations that do not fit on your landing page. Option 2: Link directly to checkout If your landing page already gives the buyer everything needed to decide, a direct checkout removes an intermediate page. Payhip documents this URL format: https://payhip.com/buy?link=
AI 资讯
InfoQ Opens Enrollment for New AI-Assisted Engineering Online Certification Program
InfoQ has opened enrollment for the InfoQ Certified AI-Assisted Engineering Program, a five-week online certification program for senior engineers and architects who already run a coding agent against production code daily, where the open questions have moved past prompting into what the agent is allowed to touch and what catches its mistakes before a human does. By Artenisa Chatziou
AI 资讯
How Code in the Age of Artificial Intelligence Becomes Write-Only and Disposable
Artificial intelligence (AI) makes all code write-only,. It’s too dense to read, and tests define the behaviour and become the documentation. Code is also disposable; it becomes easier to rewrite than to debug. Humans can't review AI-generated code at scale. Intent decouples from implementation; developers should focus on creativity. By Ben Linders
AI 资讯
Unlocking hidden revenue streams with market models
Each day, an airline transports tens of thousands of passengers on hundreds of flights. Often these are not straightforward point-to-point routes, with passengers requiring multiple connections. The airline can consider potentially hundreds of variables to price each of these journeys: demand, season, time of day, current events, global markets, and competitor airline activity to name…
AI 资讯
Calling a TypeScript Backend Without Integration Code - A Simple Task Tracker with Graftcode
Most developers building frontend applications spend a lot of time writing code that communicates with their backend due to the traditional approach (using APIs). This is not because the logic is hard to implement, but because the communication itself is complex. When using standard APIs, we build routes, define request and response models, generate clients, and keep multiple layers on track with application updates. Instead of exposing backend functionality through REST endpoints and consuming it through HTTP clients, Graftcode exposes backend methods directly and generates packages that applications can install and use as dependencies. The result is a communication model that is like you are calling a library rather than consuming an API with strongly typed clients. Working with Graftcode is very simple: install your library and call its functions. In this article, we'll be building a simple task tracker or to-do list application using React and a TypeScript backend to see what working with Graftcode looks like. In this blog post, we will learn the following: Why API layers require you to maintain APIs manually How Graftcode exposes backend functionality through Graftcode Gateway How Graftcode Vision helps discover backend capabilities Familiarity with APIs and fetch() requests How React applications can use TypeScript backend logic without building API routes Why strongly-typed backend packages can improve developer experience Prerequisites Let’s get our hands a bit dirty, but before we do, there are some need-to-haves to get you started. Let’s have a look at that in this section: Latest Node version installed on your machine Basic knowledge of React and TypeScript Familiarity with how APIs and fetch requests work (for understanding how easy Graftcode’s approach is) A Graftcode account Graftcode gateway installed on your local machine With these prerequisites, you’ll first understand why most to-do list applications rely heavily on APIs for their logic and what c
开发者
React useEventListener Hook: Type-Safe DOM Events (2026)
Here's a modal close-on-Escape that quietly does the wrong thing: function Modal ({ onClose }: { onClose : () => void }) { useEffect (() => { const onKey = ( e : KeyboardEvent ) => { if ( e . key === " Escape " ) onClose (); }; window . addEventListener ( " keydown " , onKey ); return () => window . removeEventListener ( " keydown " , onKey ); }, [ onClose ]); return < div role = "dialog" > … </ div >; } If the parent passes an inline onClose={() => setOpen(false)} — and it almost always does — onClose is a new function on every render, so this effect tears the listener down and adds a fresh one on every single render of the parent. Drop onClose from the deps to stop the churn and you get the other bug: the listener now holds the first render's onClose forever, and closing the modal calls a stale closure. You can't win this with a dependency array, because the two things you want are in direct conflict: subscribe once , but always run the newest handler . The fix is to separate them — register the listener on a stable identity, and call through a ref that's kept current. useEventListener from @reactuses/core is that split, packaged. This post covers what it actually does under the hood, the four ways to name a target, exactly what TypeScript infers for each one (this part surprises people), the options that don't retrigger, and the two gotchas worth knowing before you ship it. Quick Start npm install @reactuses/core import { useEventListener } from " @reactuses/core " ; function Modal ({ onClose }: { onClose : () => void }) { useEventListener ( " keydown " , ( e ) => { if ( e . key === " Escape " ) onClose (); }); return < div role = "dialog" > … </ div >; } That's the whole fix. No dependency array, no useCallback on the parent, no cleanup to remember. The listener is added to window once when the component mounts and removed when it unmounts; the arrow function you passed is re-created on every render and it doesn't matter, because the listener never re-registers
AI 资讯
1a vez trabalhando com git com time: tudo que você precisa saber
Faz mais de 5 anos que eu não abria um PR ou issue técnica no Github, mas essa semana tenho aprendido algumas boas práticas e termos que reuni neste artigo. Introdução Essa semana eu fiz uma coisa simples: atualizei o README de um projeto open source, o 4noobs , da comunidade He4rt. Troquei um badge, ajustei o contraste de um logo, organizei umas pastas e adicionei um índice pra facilitar a navegação. Nada muito complexo no fim das contas. Só que antes de chegar no "nada muito complexo", eu passei um tempo enrolada com uma pergunta boba: "E se eu mandar isso direto pra branch principal e bagunçar tudo?" Se tu já sentiu esse friozinho na barriga antes de mexer num repositório que não é só teu, esse artigo é pra ti. Não importa se tu é dev há anos ou se nunca abriu um terminal na vida... A lógica por trás de "como contribuir sem quebrar nada" é a mesma e bem mais simples do que parece. Definição de Git Colaborativo Quando eu aprendi git há uns anos, aprendi somente o versionamento e a enviar os arquivos pra dentro do Github, mas ele é bem mais que isso, né? É através dele que times enormes interagem a respeito de um mesmo projeto de forma organizada, comentando, gerenciando tarefas, sugerindo melhorias e conhecendo o que os outros envolvidos estão fazendo. Isso é a parte do Git Colaborativo . O Git resolve isso com um conceito central: branches (ou "ramificações"). Cada branch é tipo uma cópia paralela do projeto, onde tu pode mexer à vontade sem afetar a versão "oficial" (geralmente chamada de main ou master ). Quando tu termina sua parte, tu propõe que essas mudanças sejam incorporadas de volta pelo Pull Request (PR) . Ou seja, o fluxo básico é: Tu cria uma branch nova a partir do projeto principal Faz as alterações lá, no seu espaço isolado Envia ( push ) essa branch pro repositório remoto Abre um Pull Request pedindo pra essas mudanças serem revisadas e, se aprovadas, unidas ( merge ) à branch principal Ninguém mexe direto na versão "de produção" do projeto. Isso
AI 资讯
Vibe Coding vs Prompt-Driven: One Year Later, the Debate Is Already Outdated
A year ago, the debate between “vibe coding” and “prompt-driven development” felt like the right lens for using AI in software. Today it’s outdated. The real frontier is no longer how to phrase a request, but how to build an environment that lets an AI agent explore, modify, and verify code safely. The shift from conversational prompts to structured development harnesses changes what it means to ship reliable software. Below are four concrete ways this evolution is reshaping daily work. From Prompt to Harness A finely crafted prompt can still produce a working feature, but it won’t prevent an agent from inventing APIs, skipping tests, or misreading business rules. The new bottleneck is the harness: Git for traceability, tests for feedback, linting for style, and explicit rules for constraints. When these elements are in place, even a short instruction like “fix the bug” can trigger a reliable, auditable workflow. Code is Abundant; Good Software is Rare Generating hundreds of lines of code costs almost nothing, but verifying that those lines align with product history, security policies, and hidden constraints is still manual. The developer’s scarcest resource is now judgment: deciding what to automate, what to document, and when to override the agent’s plausible but wrong solution. Documentation is Now for Machines README files and ADRs used to serve only humans. Today they also feed the agent’s context. A well-maintained AGENTS.md , coherent tests, and executable examples let an AI act with minimal prompting while remaining aligned with the team’s conventions. The repository becomes a self-explaining environment. Supervision is the Next Skill Single-agent workflows are giving way to multi-agent orchestration. Frontend, API, test analysis, and incident triage agents must coordinate without stepping on each other. Observability, conflict detection, and rollback mechanisms replace prompt tuning as the critical layer of control. The center of gravity has moved from “ho
AI 资讯
How to Fix 'command not found' (Without Reinstalling Everything)
Adapted from the Command Line Essentials Companion Guide . You install something, open a fresh terminal, type the command, and get bash: python3: command not found — or on Windows, 'python3' is not recognized as an internal or external command . The installer said it finished successfully. You can probably even find the program in your applications folder. And yet the terminal insists it doesn't exist. The instinct at this point is usually to reinstall, or install a second copy from somewhere else, hoping one of them "takes." That almost never fixes it, because reinstalling doesn't address what's actually wrong. What the error is actually telling you When you type a command, the shell doesn't scan your whole computer looking for it. It checks a specific, ordered list of directories — stored in an environment variable called PATH — and stops at the first match it finds. command not found doesn't mean the program doesn't exist anywhere on your machine. It means none of the directories in that list happen to contain it. That distinction matters, because it splits into three genuinely different problems: A typo. gerp isn't a command; grep is. This is the most common cause by a wide margin, and the easiest to rule out first. It isn't installed at all. The program genuinely doesn't exist on this machine yet. It's installed, but not somewhere the shell is looking. This is the one that catches people off guard — the software is sitting on disk, correctly installed, just outside every directory PATH currently checks. Reinstalling only ever fixes cause 2. If your actual problem is 1 or 3, a second install just gives you a second copy of a program that was never the issue. The fix, step by step Check for a typo first. Read the command back character by character. It sounds too simple to be worth a step, but it resolves this error more often than everything else combined. Confirm whether it's installed at all , independent of whether the shell can currently find it: which pytho
AI 资讯
5 Common Subnetting Mistakes That Break Real Networks
Subnetting errors rarely announce themselves as "bad math." More often, two devices make different decisions about whether a destination is local, a route points at the wrong boundary, or a cloud/VPN design contains two networks that cannot be unambiguously routed. These five failure modes are worth recognizing in live configurations. 1. The two hosts use different masks Consider Host A at 192.168.10.10/24 and Host B at 192.168.11.10/16 . A calculates that B is outside 192.168.10.0/24 , so A sends the packet to its default gateway. B calculates that A is inside 192.168.0.0/16 , so B treats A as local and tries ARP directly. The result can be asymmetric: one direction follows a router, while the reply is sent directly or never reaches the expected gateway. Check the actual prefix on both interfaces, not just the dotted decimal mask shown in a diagram. ip -br addr ip route ping -c 3 192.168.11.10 Correct the prefix so both endpoints agree, or intentionally route between two correctly defined subnets. 2. Overlapping subnets are assigned to different networks Suppose a branch uses 10.20.0.0/16 , while a cloud VPC or VPN peer also uses 10.20.0.0/16 . The problem is not that either mask is mathematically invalid. The problem is that a router cannot distinguish "the branch's 10.20.5.0/24 " from "the cloud's 10.20.5.0/24 " if both are reachable through different paths. Symptoms include traffic taking the wrong tunnel, routes that cannot be installed, or a VPN that connects but cannot reach some subnets. Inventory both sides of a tunnel and compare the complete network/prefix pairs. A longer, more specific route may make one destination appear to work while hiding the underlying overlap. ip route ip route get 10.20.5.25 traceroute -n 10.20.5.25 The durable correction is renumbering or using an intentional translation/design boundary. Adding increasingly specific routes is usually a brittle workaround. This is also why I prefer teaching subnetting inside routing and troublesh
AI 资讯
The excluded-plugin setting that Playwright ignored — fixing browser-mode updates and false residual warnings
The symptom In browser-mode maintenance (Playwright, no SSH), plugins marked as "excluded from update checks" were still being updated. After the run, a "plugin updates remaining" WARNING email arrived every time. The excluded plugins were intentionally left behind, but the residual check treated them as unfinished updates and fired a warning — a two-part problem: wrong behavior and a misleading alert. SSH path vs. Playwright path On SSH-capable sites, WP-CLI's --skip-plugins flag carries the ignored_plugins list into the update command. That path already excluded them correctly. The Playwright path was different. browser_update_remaining_plugins() worked by clicking the "select all" checkbox on update-core.php and submitting the form — no filtering at all. # Before: select-all, ignored_plugins never consulted page . check ( ' input[name= " action " ][value= " update-selected-plugins " ] ' ) for cb in page . query_selector_all ( ' input[name= " checked[] " ] ' ): cb . check () This function is the chokepoint for two flows: pure browser-mode updates ( run_browser_update_flow ) and the browser residual pass that runs after SSH updates ( run_browser_residual_update , on by default). So even SSH sites could have excluded plugins updated by the residual pass. Browser-driven bulk updates are also outside the scope of pinpoint rollback, meaning there is no automatic recovery if a wrong update goes through. Fix 1 — _ignored_plugin_slugs() and _plugin_slug_from_checkbox_value() When excluded plugins are configured, the fix replaces the select-all approach with per-checkbox evaluation. def _ignored_plugin_slugs ( site : dict ) -> set [ str ]: raw = site . get ( " ignored_plugins " , "" ) return { s . strip (). lower () for s in raw . split ( " , " ) if s . strip ()} def _plugin_slug_from_checkbox_value ( value : str ) -> str : return value . split ( " / " )[ 0 ]. strip (). lower () if " / " in value else value . strip (). lower () Plugin checkboxes on update-core.php use a va
AI 资讯
Deploying Multiple Python Bots to a Single Railway Container
A tutorial for running two or more python bots on Railway inside one container and one service, with independent crash recovery for each. Deploying Multiple Python Bots to a Single Railway Container If you're running more than one Python bot — say, a Telegram ingestion bot and a Discord notification bot that share a database — deploying each as its own Railway service means double the hosting cost and double the configuration for something that's logically one unit. This tutorial covers deploying both bots inside a single Railway container, with each one still getting fully independent crash recovery. Table of Contents Why Two Services Is Usually Overkill The Naive Fix and Why It Falls Short Step 1: Install StayPresent Step 2: Structure Your Project Step 3: Configure Multiple Bots in One Entry Point Step 4: Read Railway's Assigned Port Step 5: Deploy as a Single Railway Service Verifying Both Bots Are Running FAQs Conclusion Why Two Services Is Usually Overkill Railway (like most PaaS platforms) charges per service, and each service needs its own configuration, environment variables, and deployment pipeline. If two bots are closely related — sharing a database, a queue, or just conceptually belonging to the same project — running them as two separate Railway services duplicates all of that for no real benefit. The Naive Fix and Why It Falls Short A common first instinct is a shell script: python telegram_bot.py & python discord_bot.py & wait This runs both, but there's no real process supervision here — if telegram_bot.py crashes, nothing restarts it, and you still haven't solved Railway's HTTP port requirement, since neither script opens one. Step 1: Install StayPresent pip install staypresent[prod] # requirements.txt staypresent[prod] Step 2: Structure Your Project project/ ├── main.py ├── telegram_bot.py ├── discord_bot.py ├── requirements.txt Both bot scripts stay exactly as they are — nothing about their internal logic needs to change. Step 3: Configure Multipl
AI 资讯
How to Stop Your Discord Bot From Sleeping on Render's Free Tier
A step-by-step tutorial to stop a discord bot from sleeping on Render's free tier — the real cause, the fix, and a working code example. How to Stop Your Discord Bot From Sleeping on Render's Free Tier You've deployed your Discord bot to Render's free tier, it worked for a bit, and now it's going offline — sometimes after a few minutes, sometimes randomly. This is one of the most common issues developers hit deploying a bot for the first time, and it has a specific, well-understood cause and a fix you can ship in under ten minutes. Table of Contents Why This Happens on Render Specifically Confirming This Is Your Actual Problem Step 1: Install StayPresent Step 2: Wrap Your Bot's Entry Point Step 3: Read Render's Assigned Port Step 4: Set Your Render Start Command Step 5 (Optional): Prevent Inactivity Sleep Specifically Verifying It Worked FAQs Conclusion Why This Happens on Render Specifically Render's free-tier web services are checked for health over HTTP, and free services also spin down after a period without incoming traffic. A discord.py bot connects outward to Discord's gateway — it never opens an HTTP port of its own, which is completely normal bot behavior. Render's health checker, seeing nothing respond on the expected port, has no way to know the bot is actually working fine internally. It just sees silence, and reacts accordingly. Confirming This Is Your Actual Problem If your bot's entry point goes straight into bot.run(TOKEN) with nothing else, and Render's dashboard shows the deployment as unhealthy or repeatedly restarting with no matching error in your bot's own logs, this is almost certainly it. Step 1: Install StayPresent pip install staypresent[prod] Add it to your requirements.txt as well: staypresent[prod] discord.py Step 2: Wrap Your Bot's Entry Point Keep your existing bot code in bot.py completely unchanged. Create a new main.py : import os import staypresent staypresent . web . json ({ " status " : " running " }) staypresent . run ( " bot.py
AI 资讯
Perry Mason in: The Case of the Drifting Timer
Perry Mason in: The Case of the Drifting Timer Opening Statement You need a reactive "current time" in your Vue 3 app. A schedule grid with a red line showing "now." A live clock. A dashboard that updates every minute. Every Vue developer reaches for setInterval first. It works. But "works" and "works well" are different things. This is the story of taking a naive timer from "it ticks" to production-grade — and the four iterations it took to get there. The prosecution calls four exhibits. Let's begin. Exhibit A: The Memory Leak const currentTime = ref ( new Date ()) onMounted (() => { setInterval (() => { currentTime . value = new Date () }, 60000 ) }) It works. Sort of. The defense rests — but the prosecution is just getting started. Exhibits of negligence: The interval is never cleared. When the component unmounts, the timer keeps firing every 60 seconds forever — updating a ref nothing reads anymore, and holding its closure (and everything the ref references) in memory for the lifetime of the page. Silent. Invisible. The kind of leak that shows up in production after a user navigates around your app for 20 minutes. Exhibit B: Component-Only Cleanup const currentTime = ref ( new Date ()) let timeInterval = null onMounted (() => { currentTime . value = new Date () timeInterval = setInterval (() => { currentTime . value = new Date () }, 60000 ) }) onUnmounted (() => { if ( timeInterval ) clearInterval ( timeInterval ) }) Now we clean up. The interval is stored in a variable, cleared on unmount. A step forward. But onUnmounted has a scope limitation worth understanding: The limitation: onUnmounted only works inside components. If someone calls this logic from a Pinia store or outside a component's setup() context, onUnmounted never fires. The timer leaks silently. (Composables called synchronously during setup() are fine — Vue's docs recommend exactly that. The problem is when there's no component instance at all.) The timer fires 60 seconds after load , not at the t
科技前沿
NASA calls off mission to rescue Swift gamma-ray observatory
Without a rescue, NASA's Swift Observatory is expected to reenter the atmosphere later this year.
开发者
Implementing IN statements using JooqTemplate
@Service public class SimpleUserService { @Autowired private JooqTemplate jt ; public List < user > selectUserInDept ( UserParam param ) { //If deptIDs==null or deptIDs. isEmpty automatically ignores this query condition // SELECT * FROM user_table WHERE name LIKE '%?%' AND dept_id IN (?,?...); return jt . queryv ( "user_table" , User . class , "name%" , param . getName (), "dept_id:in" , param . getDeptIds ()); } public List < user > selectUserNotInDept ( UserParam param ) { // SELECT * FROM user_table WHERE name LIKE '%?%' AND dept_id NOT IN (?,?...); return jt . queryv ( "user_table" , User . class , "name%" , param . getName (), "dept_id:notin" , param . getDeptIds ()); } }