React 19 Actions: I Explained 3 Hooks Without Ever Explaining What an Action Is
Three parts into this series, and if you'd asked me to define the word sitting underneath every...
找到 4749 篇相关文章
Three parts into this series, and if you'd asked me to define the word sitting underneath every...
Let me describe a moment you might recognize. You had an idea for an app. You didn't know how to...
Sooner or later you hit the same small problem: two services, on two machines, want to touch the same thing at the same moment — append to a shared file, update a row nobody is fencing, call an API that tolerates one caller at a time. One of them has to wait. The usual answers feel heavier than the problem. Put a service in front and serialize everything through it — now you are building a queue, and then a second queue to hand results back, because you no longer know the outcome at the moment you asked. Cache the resource in Redis and lock there — fine until the resource does not fit in memory, and you have inherited Redlock's ordering guarantees (there are none) and its debates. I wanted the lock as its own primitive: lock a key, do the work, unlock the key. Nothing else. That is Locking-Center — a single binary, one dependency, no config file, no consensus layer to operate. This post is about the three ideas that made it small enough to be worth trusting. 1. One channel per key — and the queue comes for free Every key gets a Go channel with a buffer of exactly one: type Channel struct { key string mutexChan chan bool // buffered, capacity 1 } func NewChannel ( key string ) * Channel { return & Channel { key : key , mutexChan : make ( chan bool , 1 )} } Sending into it acquires the lock. Receiving from it releases : c . mutexChan <- true // acquire — blocks if someone already holds the key // ... critical section ... <- c . mutexChan // release The buffer of one is the whole trick. The first send fills the buffer and returns immediately: that caller holds the key. The second send has nowhere to go, so it blocks — and so does the third, and the fourth. The blocked senders are the wait queue. When the holder releases (a receive frees the slot), the runtime wakes the next blocked sender. And it wakes them in order. The Go runtime keeps a FIFO wait queue behind every channel, so callers are served roughly in arrival order rather than whoever happens to reschedule firs
When you're building a multi-tenant app, there's one bug category that's worse than any other: a user seeing someone else's data. Not a crash, not a broken button — a genuine privacy failure. I recently built a Next.js + Supabase + Stripe starter kit, and before I'd call the database layer "done," I wanted to actually prove the security held, not just assume it did because the code looked right. The setup Supabase's Row Level Security (RLS) lets you write policies directly in Postgres that filter rows based on who's asking — the database itself becomes the security boundary, not just your application code. That's powerful, but it also means a single wrong policy (or a missing one) silently exposes everything. Here's the policy pattern I used for an owner-scoped table: create policy "projects: owner reads" on public . projects for select to authenticated using (( select auth . uid ()) = owner_id ); Simple enough. But "simple enough" is exactly the kind of thing worth verifying rather than trusting. The actual test Rather than just trusting the policy, I ran an impersonation test directly in the SQL editor: begin ; set local role authenticated ; set local request . jwt . claims = '{"sub":"<a-real-user-id>"}' ; select id , name from public . projects ; rollback ; This temporarily pretends to be a specific user (inside a transaction that touches nothing) and asks: what can this user actually see? Run it with the real owner's ID — you get their rows. Run it with a fake or different user's ID — you should get zero rows back, not an error. That's the key detail: RLS filters rows out silently rather than throwing a permission error, so "nothing happened" is actually the success signal, not a bug. I did the same check for writes — attempting to delete another user's row from a different account's session, confirming it returns 0 rows affected rather than either succeeding or throwing. Why this matters more than it seems It's easy to write an RLS policy that looks right and s
Most teams don't notice their CI/CD pipeline is broken — they just notice that deploys "feel slow" and shrug it off as normal. It isn't. A pipeline that takes 25 minutes to ship a one-line copy change isn't a fact of life, it's a symptom. Here are the mistakes we see most often when reviewing pipelines — roughly in order of how much time they silently burn. 1. Running the full test suite on every single change If a developer fixes a typo in a README and the pipeline still runs the entire integration suite, database migrations, and end-to-end tests, you're paying full price for a change that touched nothing critical. Fix: split your pipeline into stages based on what actually changed. Path-based triggers (only run frontend tests if frontend files changed) and a fast "smoke test" tier before the full suite can cut average pipeline time dramatically without sacrificing safety. 2. No caching between builds Reinstalling every dependency from scratch on every run is one of the most common — and most fixable — sources of wasted time. Package managers, build artifacts, and Docker layers are all cacheable, and most CI platforms support this natively. Fix: cache dependency directories keyed by lockfile hash, and structure Dockerfiles so rarely-changing layers (base image, dependencies) come before frequently-changing ones (application code). 3. Sequential steps that don't need to be sequential Linting, unit tests, and security scans are often run one after another when they have no dependency on each other. That's pure wasted wall-clock time. Fix: parallelize independent jobs. Most CI systems support fan-out/fan-in patterns — run lint, test, and scan simultaneously, then gate the deploy on all three passing. 4. Environments that drift from production A pipeline that passes in staging and fails in production usually means the environments aren't actually equivalent — different env vars, different resource limits, different service versions. Teams respond by adding more manual
If you ever needed a quick list of Docker commands, here you go.. 1. Check that Docker is installed docker --version Shows the installed Docker version. 2. Run your first container docker run hello-world Pulls the official test image (if needed) and runs it. You should see a “Hello from Docker!” message. 3. See running containers docker ps Lists containers that are currently running. Use docker ps -a to also show stopped ones. 4. See downloaded images docker images Shows every image on your machine (name, tag, size, ID). 5. Stop a running container docker stop CONTAINER_ID Gracefully stops a container. Get the ID from docker ps . 6. Remove a stopped container docker rm CONTAINER_ID Deletes a container that is already stopped. 7. Force stop and remove docker rm -f CONTAINER_ID Force-stops the container (if it’s still running) and removes it in one step.
In this post I'll show how to merge PDF files entirely in the browser using PDF.js and pdf-lib — no server, no file upload, no backend. Everything runs on the user's machine, which is great for privacy and for keeping hosting costs at zero (it's just a static site). Why process PDFs on the client? Most "free" PDF websites quietly upload your documents to their server, which: Exposes private/sensitive files to third parties Imposes size limits Often slaps a watermark on the output Requires you to trust their storage If you handle PDFs with client-side JavaScript (WebAssembly / WASM + PDF.js), none of that happens. The user's file never leaves their device, and you don't need a backend at all — so it's cheap and private. Caveats pdf-lib works well with standard PDFs; heavily encrypted or unusual documents may need extra handling. Very large PDFs are memory-hungry since everything is client-side, but for typical documents it's fast and free. Some complex PDFs with unusual fonts can lose fidelity — test on your own files first. Try it I packaged this approach (plus split, compress, rotate, unlock, image-to-PDF) into a free no-upload tool: https://yourutilityhub.com/pdf/merge-pdf The whole project is open source: https://github.com/Jalal-khn/utilityhub- If you have questions about the architecture or want a deeper dive on any part, ask away. The basic idea Read the input file with FileReader Parse it with pdf-lib (a pure-JS PDF library) Copy the source pages into a new document Save the merged PDF and trigger a download Here's the core function: js import { PDFDocument } from "pdf-lib"; async function mergePdfs(files) { const merged = await PDFDocument.create(); for (const file of files) { const bytes = await file.arrayBuffer(); const src = await PDFDocument.load(bytes, { ignoreEncryption: true }); const pages = await merged.copyPages(src, src.getPageIndices()); pages.forEach((page) => merged.addPage(page)); } const out = await merged.save(); return new Blob([out], { typ
In mission-critical infrastructure, latency isn't just a metric—it's the difference between a resolved incident and a catastrophic outage. Whether you are managing an SRE team handling cluster failures or a teleassistance platform routing domestic SOS alerts, the core engineering challenge remains identical: getting a human's attention in milliseconds without administrative friction. This technical breakdown explores how we architected a high-availability voice routing engine using Cloudflare Workers and Twilio, bridging the gap between hardware teleassistance and DevOps incident workflows. The Dual-Use Architecture: From Teleassistance to SRE Paging Our platform core serves two distinct but structurally identical needs: Senior Safe: A Chilean domestic teleassistance product where an SOS trigger must reach a family guardian instantly. DevOps On-Call: An infrastructure alert triggered via Grafana or UptimeRobot webhooks that must wake up an engineer at 3 a.m. The blast radius differs (a household vs. a production database), but the technical path is identical. To solve this at scale without charging steep "per-seat" licensing models that penalize growing squads, we built the entire pipeline on serverless isolates. Bypassing Cold Starts with Edge Ingest When an emergency happens, you cannot afford to wait for a virtual machine or container to boot. The public ingest pipeline lives directly on Cloudflare Workers ( api.wakeupdev.com ). Because V8 isolates are kept warm globally across the edge network, there is zero Lambda-style cold start penalty on the first page. The ingest contract is minimal: Authentication: Handled via an x-api-key header. Payload: Raw text or JSON (capped at 4,000 characters). Execution: Credits are consumed atomically in a global Postgres layer before the voice cascade is scheduled. An HTTP 202 Accepted status code guarantees that the credit is validated and the call flow is in flight. Solving the Voicemail Problem: True Human Acknowledgement A
We've all heard the modern blogging advice: "Keep it short, write for humans, don't write novels." While short-form content has its place, long-form technical guides—when executed correctly—are absolute powerhouses. Writing a comprehensive, 5,000-word deep dive isn't about padding your word count with fluff; it's about building an irresistible, authoritative resource that search engines and developers simply cannot ignore. If done right, a single 5,000-word post can push your brand-new domain to a Domain Rating (DR) of 20 , pull in 1,000+ daily organic views , and land your site directly inside Google's AI Overviews (Position 0) . Here is the exact framework to pull this off. 1. Why 5,000 Words Still Works (When Done Right) Long-form content isn't dead— shallow long-form content is . When you cover a complex technical topic thoroughly, three things happen: High Information Gain: You answer questions that 500-word summaries skip over. Natural Keyword Spreading: You rank for hundreds of long-tail queries without keyword stuffing. Passive Backlink Generation: Developers, bloggers, and tech curators link to comprehensive references instead of surface-level posts. 2. Targeting the Right Topic You can't write 5,000 words on "How to install Node.js." You'll run out of meaningful things to say by page two. To sustain this length and quality, choose topics that have depth, high friction points, and multiple moving parts . Ideal Candidates: The Ultimate Architectural Guide: e.g., "Building a Multi-Tenant Microservices Architecture with Go and PostgreSQL" End-to-End Production Blueprints: e.g., "From Zero to Production: Deploying Next.js, Redis, and Prisma on AWS EKS" Comprehensive Comparative Deep Dives: e.g., "State Management in 2026: An In-Depth Benchmark of Redux, Zustand, Jotai, and Signal" 3. How to Structure for Readability & Google AI (Position 0) Google’s AI Overviews look for clean, structured answers to extract directly into Position 0. If your post is an unorganiz
GitHub Classroom launched in July 2013. In August 2026, it was sunset — and a lot of instructors were left scrambling for an alternative. The official recommendations point to "yet-another-online-service" - and your school might not like you sending student information (names, emails, etc.) through unknown online solutions. That was one of my pain points (among others). So I built CodeHub Classroom . 🎉 I teach computer programming at the post-secondary level. My colleagues and I needed to adjust fast. You might be scrambling for alternatives. So I'm throwing my hat in the ring with CodeHub Classroom . What it is CodeHub Classroom is a free desktop app that follows a two step Provision and Release approach to setting up student assignments as GitHub repositories. I'm baking in a lot of the features I hoped GitHub Classroom would eventually build, but never did. The core workflow is simple and deliberately opinionated, based on over a decade of actually using GitHub Classroom day-to-day: Provision — generate each student's private repository from your assignment template. Nobody has access yet. Release — invite each student as a collaborator on their own repository, exactly when you're ready. Why it's different It's built around your whole school term , not one classroom at a time. GitHub Classroom made you manage a separate "classroom" per course section. If you taught three sections of the same course, that meant duplicate setup (and possible copy/paste errors) for shared assignments. CodeHub Classroom shows every course and section you're teaching this term in one dashboard . It runs on your computer — there's no backend. No GitHub App, no shared service account, nothing for GitHub to rate-limit. It just drives the git and GitHub CLI ( gh ) tools you probably already have installed. If you've got the GitHub CLI, you already had everything CodeHub needs. On privacy This one matters to me, so I'll say it plainly: I built CodeHub Classroom so that ALL your classroom d
In eleven days, on 11 September 2026, the reporting obligations of the EU Cyber Resilience Act start applying to anyone who puts a product with digital elements on the European market. Not the full regulation. Just the part where, if you find out an actively exploited vulnerability is in your product, you have 24 hours to tell ENISA about it. I have watched a lot of engineering teams meet this class of deadline for the first time. It usually goes the same way. Somebody in sales gets a security questionnaire. Somebody in engineering gets forwarded the questionnaire. Three weeks later there is a shared folder called evidence-final-v3 with 200 screenshots in it, and nobody can tell you which screenshot answers which question. I have spent the last several months building a tool whose entire job is that folder, so I read the instruments properly. This is what I found out. It is written for engineers, not for a compliance team, and I try to be specific about what the text says rather than what a vendor blog says it says. Where SOC 2 came from, and why that still shapes it SOC 2 exists because of a misuse. In 1992 the AICPA published SAS 70, an auditing standard for service organisations. Its purpose was narrow: if you outsourced your payroll, your auditor needed some assurance that your payroll provider's internal controls did not corrupt your financial statements. It was an accounting instrument, for accountants, about financial reporting. Then the industry outsourced everything else. By the mid-2000s companies were sending their customer data to service providers, and they wanted assurance about that , not about financial reporting. There was nothing designed for it, so they asked for the thing that existed. Vendors started waving SAS 70 reports around as proof they were secure. They were not proof of that. SAS 70 had no defined control set at all: the service organisation wrote its own control objectives, and the auditor tested against whatever had been written. Two S
This is the second article in a series on time to revoke, following our piece on The Hacker News . The first explains how to measure the amount of time an exposed credential remains usable. This article focuses on the operational changes security teams can make to shrink that exposure window. TL;DR: Reducing time to revoke means addressing the operational blockers that keep exposed credentials valid after detection. Security teams need to validate which credentials still work, route them to the right owners, make revocation safer, and remove avoidable manual delays. Provider-specific runbooks, risk-based remediation paths, short-lived credentials, automation, and closure verification can all reduce the amount of time exposed access remains usable. Why time to revoke matters for AI-era non-human identity risk Every security team can find an exposed secret, but most can't tell you how long it kept working after they found it. Over 28.6 million new hardcoded secrets hit public GitHub in 2025, up 34% year over year, with AI-service secrets up 81% ( State of Secrets Sprawl 2026 ). AI-assisted development and agentic tooling cut both ways. Defenders find and triage more, but creation is outpacing governance. So while detection keeps up, revocation is where teams fall behind. And that disconnect is what this article is about. If an exposed credential remains valid, an attacker doesn't need to breach the same system twice. They can use it directly against any service that trusts the identity behind it, like a cloud console or a production database. And these credentials stay valid far longer than teams expect: 64% of secrets confirmed valid in 2022 were still valid when we retested them four years later. That is especially dangerous for non-human identities (NHIs). Service accounts and OAuth apps often run on long-lived tokens and deploy keys that no one rotates for months, sometimes years. Their access is broad, their ownership unclear. And because these identities keep cr
Retour d’experience sur l’automatisation de déploiements avec un agent LLM et sur les gardes-fous qu’il a fallu inventer en cours de route L’idée est venue d’un frustration banale. Sur mon projet terraform , je passais beaucoup de temps à refaire la même chose : lire un plan qui échoue , comprendre pourquoi , corriger des lignes de configurations , toujours trop long. Un agent LLM sait faire ca , mais la question était se savoir s’il pouvait le faire sans supervision , dans un pipeline , sur une infrastructure qui coûte de l’argent réel. Trois mois plus tard , la réponse est oui , mais pas du tout dans le périmètre que j’imaginais au départ. Le Montage: Rien de complexe, un VPS à 12 euro par mois , la CLI de l’agent installée dessus , et un runner Gitlab qui l’invoque sur un déclencheur précis: quand un terraform plan échoue sur une MR. l’agent recoit trois choises: la sortie d’erreur , le diff de la MR, et un accès en lecture du dépôt.Il produit une proposition de correctif sous forme de patch, qu’il pousse sur une branche dédiée. Ce qui a bien marché: les erreurs de typage et de reference. Un var.instance_type mal orthographié, un output référencé qui n'existe plus après un refactor, un module dont la signature a changé. L'agent corrige ça avec un taux de réussite que j'estime autour de 85 %. Ce sont des erreurs mécaniques, à contexte local, exactement ce qu'un LLM traite bien. Les messages d’erreur opaques. C'est le gain que je n'avais pas anticipé. Certaines erreurs de provider AWS sont d'une inutilité remarquable , un InvalidRequestException sans description, par exemple. L'agent, lui, va lire le corps de la requête dans les logs de debug et repérer le paramètre malformé. Il ne « comprend » pas mieux que moi, mais il lit trois cents lignes de log en deux secondes sans se lasser. À 19h un vendredi , ma qualité de diagnostic s’effondre. Celle de l’agent, non. Ce qui a cassé Il a proposé de détruire une base de données. C'est l'incident qui a tout recadré. Un clus
How we eliminated subtle stylesheet caching glitches during deployments on DEV without a massive rewrite.
Long-lived GCP service account keys are secrets that must be managed forever, are hard to rotate, and are easy to leak. Scaling Workload Identity Federation to 120+ production projects shows why it changes how machine identity is approached entirely: keys are secrets to manage, federated identities are trust relationships configured once, gated by attribute conditions. By Shijin Nair
We use AI daily to scaffold code, write copy, and debug layouts, but when it comes to maintaining a strict design system, things get blurry. You can feed an LLM your component library rules, spacing scales, and color tokens, but it still loves to hallucinate random padding values or invent arbitrary classes if you aren't paying close attention. It's great for writing boilerplate, but bridging the gap between a strict visual token structure and AI-generated code often feels like managing a junior dev who ignores the style guide. How are you integrating AI into your workflow without letting it compromise your design tokens and codebase consistency? Do you use it mainly for initial scaffolding, or have you found a reliable way to keep it strictly aligned with your system? If you're into clean design systems, frontend code, and bridging the visual-to-code gap, check out my work at Joemetry.
Hello, I'm Maneshwar, and I'm building LiveReview — a blast-radius aware AI code review built for...
Every self-hosted project I run starts the same way: a brand new VPS and about twenty minutes of setup before I install a single application. That twenty minutes is what separates "my server" from "someone else's crypto miner." A fresh box with a public IP starts getting probed within minutes, and the default configuration on most images is built for convenience, not safety. This is the secure baseline I set up on every new server, before Docker, before n8n, before anything else. It is also the starting point our production n8n guide assumes you already have. Every command below was checked against current Ubuntu LTS documentation, and I flag the parts that genuinely need a real server to verify. Key takeaways Never do daily work as root. Create a sudo user and log in as that instead. Use an SSH key and turn password login off, but only after you confirm the key works. Deny everything at the firewall by default, then open only the ports you actually use. Turn on automatic security updates so patches land while you sleep. If you plan to run Docker, remember that published ports skip UFW. Bind them to 127.0.0.1 . Prerequisites A VPS running a current Ubuntu LTS. Both 24.04 "Noble Numbat" and 26.04 "Resolute Raccoon" work well. I run long-lived boxes on Hostinger VPS hosting , which is also what powers the n8n guide. An SSH key pair on your own machine. If you do not have one yet, Step 3 creates it. A terminal, and a note of your provider's recovery console. Most hosts, Hostinger included, give you a browser based console in their control panel. That is your way back in if you ever lock yourself out, so find it before you start. Disclosure: some links in this guide, including the Hostinger link above, are referral or affiliate links. If you sign up through them we may earn account credit or a commission, at no extra cost to you. We only point at tools we actually run. Step 1: Log in and update the system Right after the server boots, log in with the credentials your pr
Introduction: The Developer's Credential Dilemma As developers, we manage dozens—if not hundreds—of sensitive credentials daily. From database connection strings and SSH keys to API tokens and third-party service logins, keeping track of these secrets securely without destroying developer velocity is a constant challenge. Far too often, developers fall into bad habits: reusing simple passwords, storing raw API keys in unencrypted .env files committed to Git, or sharing production tokens over Slack. These practices are major security risks. While there are many password managers on the market, Bitwarden has rapidly become the preferred choice for software engineers and DevOps teams. In this article, we will explore why Bitwarden is uniquely suited for developers, examine its developer-centric feature set, and walk through practical CLI examples. 1. True Open-Source Transparency For security software, trust is paramount. Closed-source proprietary password managers force you to trust the vendor's claims without verification. Bitwarden flips this model on its head. The entire Bitwarden codebase—including web vaults, mobile applications, desktop clients, browser extensions, and backend infrastructure—is 100% open source under GPLv3 and AGPLv3 licenses. You can inspect the source code directly on GitHub. Why Open Source Matters for Security: Public Auditing: Security researchers and the global developer community continuously audit the code for vulnerabilities. No Hidden Backdoors: Transparency ensures there are no intentional backdoors or tracking mechanisms. Longevity: Even if the company behind Bitwarden were to disappear, the software and server implementations could be maintained by the community. 2. Developer-First Workflows: The Bitwarden CLI ( bw ) Most password managers focus exclusively on GUI interfaces designed for non-technical users. Bitwarden provides a full-featured Command Line Interface (CLI) that allows developers to interact with their vault directly f
With all of the primary mechanics sufficiently developed to allow playtesting, the next step in the project was to develop levels to teach players how to use them as well as a single level containing puzzles for players to solve using the knowledge provided in the tutorial levels. The Tutorial The game tutorial is split into five short levels. Each level imparts knowledge of one or more of the previously developed game mechanics. The number of tutorial levels was decided by listing out all the required mechanics and dividing them up across a number of levels that gave each mechanic the desired amount of attention. The goal of this was to ensure that the player was not overwhelmed with too much new information at any one time. Here is how the mechanics were divided across the five levels: Level 1: Player movement, looking around, jumping, and interacting with objects Level 2: Command generation system, Activate command, and signal blocking and range limitations Level 3: Controlling robot NPCs, target destinations, Follow command, Move To command, Cancel command, NPC-locked doors, and pressure plates Level 4: Using the Attack command against NPCs and destinations Level 5: Reflective and absorptive surfaces, signal reflection, low-frequency signals, signal penetration limits, and secret areas Tell and Show The tutorial levels all follow a pattern of tell then show. Every mechanic is explained via text on walls in the levels, and immediately followed by an opportunity or obligation to use that mechanic. For example, the first tutorial level starts with the player facing a wall displaying the controls to look around. In order to progress into the next area, the player must use those controls to turn around in order to see the way out of the starting room as well as the text explaining how to move. Similarly, at the beginning of the second tutorial level, the controls for generating an Activate command are displayed on the wall in front of the player with a door to their