惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

www.infosecurity-magazine.com
www.infosecurity-magazine.com
Vercel News
Vercel News
G
Google Developers Blog
MyScale Blog
MyScale Blog
The Register - Security
The Register - Security
I
InfoQ
Blog — PlanetScale
Blog — PlanetScale
D
DataBreaches.Net
Microsoft Security Blog
Microsoft Security Blog
V
Visual Studio Blog
V2EX - 技术
V2EX - 技术
F
Fortinet All Blogs
博客园_首页
S
Secure Thoughts
GbyAI
GbyAI
S
Security Affairs
N
News | PayPal Newsroom
Forbes - Security
Forbes - Security
Recent Announcements
Recent Announcements
H
Hackread – Cybersecurity News, Data Breaches, AI and More
Security Archives - TechRepublic
Security Archives - TechRepublic
宝玉的分享
宝玉的分享
Hugging Face - Blog
Hugging Face - Blog
Hacker News - Newest:
Hacker News - Newest: "LLM"
H
Heimdal Security Blog
A
About on SuperTechFans
P
Proofpoint News Feed
H
Help Net Security
Application and Cybersecurity Blog
Application and Cybersecurity Blog
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
Y
Y Combinator Blog
L
LINUX DO - 最新话题
Apple Machine Learning Research
Apple Machine Learning Research
L
LangChain Blog
博客园 - 叶小钗
A
Arctic Wolf
Cisco Talos Blog
Cisco Talos Blog
T
The Exploit Database - CXSecurity.com
人人都是产品经理
人人都是产品经理
T
Threat Research - Cisco Blogs
N
News and Events Feed by Topic
Security Latest
Security Latest
The Hacker News
The Hacker News
T
Tor Project blog
O
OpenAI News
博客园 - 三生石上(FineUI控件)
PCI Perspectives
PCI Perspectives
量子位
大猫的无限游戏
大猫的无限游戏
Stack Overflow Blog
Stack Overflow Blog

DEV Community

Authentication Security Deep Dive: From Brute Force to Salted Hashing (With Java Examples) Why AI Systems Don’t Fail — They Drift Spilling beans for how i learn for exam😁"Reinforcement Learning Cheat Sheet" I Replaced Chrome with Safari for AI Browser Automation. Here's What Broke (and What Finally Worked) How Python Borrows Other People's Work The $40 Architecture: Processing 1 Billion API Requests with 99.99% Uptime Vibe Coding: A Workflow Guide (From Zero to SaaS) Most webhook security guides protect the wrong side. The scary part is delivery. Headless CMS for TanStack Start: Build a Blog with Cosmic EU Age Verification App "Hacked in 2 Minutes" — What Actually Happened Comfy Cloud’s delete function does not actually remove files Running AI Models on GPU Cloud Servers: A Beginner Guide Event-driven media intelligence with AWS Step Functions and Bedrock I scored 500 AI prompts across 8 quality dimensions — here's what broke How to Call Google Gemini API from Next.js (Free Tier, No Backend Needed) The Portal Protocol: Reclaiming Human Connection in the Age of AI How to Fix Your Team's Scattered Knowledge Problem With a Self-Hosted Forum Intro to tc Cloud Functors: A Graph-First Mental Model for the Modern Cloud Designing Multi-Tenant Backends With Both Ownership and Team Access I Built a Neumorphic CSS Library with 77+ Components — Here's What I Learned PostgreSQL Performance Optimization: Why Connection Pooling Is Critical at Scale Cómo construí un SaaS multi-rubro para gestionar expensas en Argentina con FastAPI + Vue 3 🚀 I Built an Ethical Hacking Scanner Tool – Open Source Project I Replaced /usage and /context in Claude Code With a Single Statusline A Pythonic Way to Handle Emails (IMAP/SMTP) with Auto-Discovery and AI-Ready Design I Collected 8.9 Million Polymarket Price Points — Here's What I Found About How Markets Really Move EcoTrack AI — Carbon Footprint Tracker & Dashboard Everyone's Using AI. No One Agrees How. 5 self-hosted ebook managers worth trying in 2026 Building Your First AI Agent with LangChain: From Chatbot to Autonomous Assistant Common SOC 2 Failures (Real World) Stop Vibe-Checking Your AI App: A Practical Guide to Evals How to Use SonarQube and SonarScanner Locally to Level Up Your Code Quality Your Next To-Do App Is Dead — I Replaced Mine with an OpenClaw AI Sign a Nostr event in 60 lines of Python using coincurve — no nostr-sdk, no nbxplorer, no rust toolchain ITGC Audit Explained Like You’re in Big 4 Patch Tuesday abril 2026: Microsoft parcha 163 vulnerabilidades y un zero-day en SharePoint Stop scraping everything: a better way to track competitor price changes Listing on MCPize + the Official MCP Registry while routing payments OUTSIDE the marketplace — how I kept 100% of my x402 revenue Building an AI-Powered Risk Intelligence System Using Serverless Architecture Why We Ripped Function Overloading Out of Our AI Toolchain Testing AI-Generated Code: How to Actually Know If It Works SaaS Churn Is Killing Your Business. Here Is What to Do About It (Without a Support Team) The Speed of AI Is No Longer Linear - And Self-Improving Models Are Why How to Implement RBAC for MCP Tools: A Practical Guide for Engineering Teams From Standard Quote to Persuasive Proposal: AI Automation for Arborists I built a CLI that scaffolds complete multi-tenant SaaS apps Axios CVE-2025–62718: The Silent SSRF Bug That Could Be Hiding in Your Node.js App Right Now The dashboard that ended our friendship Data Pipelines Explained Simply (and How to Build Them with Python) The Hidden Cost of AI Systems Nobody Talks About. undefined vs undeclared, and how typeof behaves Switching from file-based jobs to NATS/Kafka in Rust without changing code io_uring Adventures: Rust Servers That Love Syscalls Why Agentic AI is Killing the Traditional Database The POUR principles of web accessibility for developers and designers Quantum Neural Network 3D — A Deep Dive into Interactive WebGL Visualization How To Install Caveman In Codex On macOS And Windows Automation Pipeline Reliability: Why Your Workflow Breaks When Nobody Is Watching I Built an 'Open World' AI Coding Agent — It Works From ANY Folder From Freelancing to Product: A Tech Service Company's SaaS Transformation China's AI Giants: Adding Tencent Hunyuan & ByteDance Doubao to AI University (74 Providers) On the Vibe Coders and Their Lies clerk: Auto-Summarize Your Claude Code Sessions AI Weekly — 2026/04/10–04/17 | The Model Lockdown Is Here, but the Toolchain Is the Real Battleground AI 週報 — 2026/04/10–2026/04/17 模型封鎖潮來了,但工具鏈才是真戰場 Maybe this is how Open-Source apps are born... 🚀 Fine-Tune LLMs with LoRA and QLoRA: 2026 Guide tRPC v11 + Next.js App Router: End-to-End Type Safety Without the Boilerplate ShadCN UI in 2026: Why I Stopped Installing Component Libraries and Started Owning My Components SaaS Billing in React Server Components: Stripe + Supabase Without a Single `useEffect` Join our DEV Weekend Challenge — $1,000 in Prizes Across TEN winners! Submissions Due April 20 at 6:59 AM UTC. Implementing FSRS Spaced Repetition in Flutter + Supabase — Adding Memory Science to an AI Learning App "I Texted My Localhost From the Train — Claude Code Fixed the Bug Before I Got Home" I Built a Sales Prep AI and It Went Deeper Than Expected Design to Code #2: One JSON, Eleven Outputs Solving the 100M-Row Problem: A Summary Table Pattern for High-Volume Push Notification Logs Flutter Web With Wasm: What Actually Changes For Developers I Built 50 Royalty-Free Soundtracks for My Side Project in a Weekend Using AI Music Generation The Vibe Coding Security Checklist: 7 Things to Check Before You Ship Stop Letting Googlebot Guess Fix Your React App's SEO Right Desconstruindo o Streaming do LinkedIn: Como Criar um Engine de Extração de Vídeo de Alta Performance com HLS e FFmpeg (EDA Part-1) EDA (Exploratory Data Analysis) Explained With Real Life — Why Looking at Your Data Is the Most Important Step in Machine Learning Brand Relationship Management at Scale: Our 4-Touch Outreach System for 200+ Brands Why String.fromEnvironment() Might Return an Empty String in Dart JGuardrails 1.0.0 — Hardening Java LLM Apps Against Jailbreaks, Toxicity, and Prompt Injection Plan and Schedule a Full Week of Threads Content From One Claude Conversation Coding Cat Oran Ep3, Five Tables Changed Everything Updated: BFF Pattern I'm done watching freelancers get buried by 200 proposals. So I'm building the alternative. This is my first post BFS Algorithm in Java Step by Step Tutorial with Examples Tracking LLM Pricing Monthly: An Open Dataset for 22 AI Models How We Measure Content ROI on a Comparison Site: Revenue Attribution Without Perfect Data Introducing Nova AI Ops: The AI-Native Operating System for SRE Teams I built a free desktop video downloader for Windows — Grabbit How Talkie OCR Helps Vision-Impaired & Dyslexic Users Read the World Around Them VRCFaceTracking安装和iPhone面捕配置教程,有bug Even CrowdStrike Can't See Your Agents The Automation Gold Rush: What n8n Workflows and Claude Are Opening Up for Developers Right Now
Introducing CarverJS
Het Dave · 2026-04-27 · via DEV Community

Here is a complete 2D game written in React. Move with WASD. Renders in a browser. The whole thing is around 40 lines.

import { useRef, useEffect } from "react";
import { Game, World, Actor } from "@carverjs/core/components";
import { useGameLoop, useInput } from "@carverjs/core/hooks";
import { useGameStore } from "@carverjs/core/store";
import type { Group } from "@carverjs/core/types";

function Player() {
  const ref = useRef<Group>(null);
  const setPhase = useGameStore((s) => s.setPhase);
  const { getAxis } = useInput();

  useEffect(() => {
    setPhase("playing");
  }, [setPhase]);

  useGameLoop((dt) => {
    if (!ref.current) return;
    ref.current.position.x += getAxis("KeyA", "KeyD") * 5 * dt;
    ref.current.position.y += getAxis("KeyS", "KeyW") * 5 * dt;
  });

  return (
    <Actor
      ref={ref}
      type="primitive"
      shape="circle"
      color="royalblue"
      geometryArgs={[0.5, 24]}
    />
  );
}

export default function App() {
  return (
    <Game mode="2d">
      <World>
        <Player />
      </World>
    </Game>
  );
}

Enter fullscreen mode Exit fullscreen mode

That is CarverJS. It is a React game engine I just published to npm in early beta. Free, MIT, version 0.0.1 at the time of this post, with two packages: @carverjs/core and @carverjs/multiplayer. The API will move before it hits 1.0.

This post is the long version of why I built it, what it actually does, and what is still half-finished. If you have ever closed a game-dev tutorial because step one was "install Unity," this one is for you.

Why I built it

The honest answer: I needed it for my own product.

I run a small edtech company. We are building game-based learning for K-12 students. Two products: a B2B platform for schools (admin dashboards, teacher tooling, student experience) and a B2C marketplace. Every product surface eventually renders a game. The games are short, social, browser-based, often multiplayer.

I am a React developer. The rest of my team are React developers. Our admin portal, teacher app, marketing site, internal tools — every product surface is React, all the way down. The natural question was: can the games also be React?

The non-React paths I evaluated:

  • Unity WebGL. Exports run 10-50 MB on average, multi-second cold loads, doesn't compose with React UI. Great engine for the wrong runtime.
  • Phaser. Mature, deep 2D feature set, but you are back to imperative game loops. State lives outside React.
  • Godot HTML5. Smaller than Unity, same composition problem. GDScript or C#, neither of which is the language we ship in.
  • Raw Three.js / R3F. Excellent for 3D scenes. No game abstractions. You build your own input system, collision system, audio manager, scene manager, asset loader, and multiplayer layer.

Each option meant either learning a separate engine or rebuilding a stack of plumbing. I started writing the plumbing once, then twice, then realized I was writing a game engine. So I made it deliberate, pulled it out of the company monorepo, and open-sourced it.

That engine is CarverJS.

The mental model

CarverJS is built on top of React Three Fiber and Three.js, but in normal use you do not import from either. Every component, hook, type, and store you need ships from @carverjs/core and @carverjs/multiplayer. If you already know R3F, the API shape will feel familiar. If you do not, you can ship a game without ever learning what an <Object3D> is.

Components describe the world:

<Game mode="3d">
  <World physics={{ gravity: [0, -9.81, 0] }}>
    <Actor type="primitive" shape="box" position={[0, 0, 0]} />
    <Actor type="model" src="/hero.glb" animationName="run" position={[1, 0, 0]} />
    <Actor type="sprite" src="/coin.png" billboard position={[3, 0, 0]} />
  </World>
</Game>

Enter fullscreen mode Exit fullscreen mode

Hooks drive behavior:

import { useRef } from "react";
import { Actor } from "@carverjs/core/components";
import { useGameLoop, useInput, useAudio } from "@carverjs/core/hooks";
import type { Group } from "@carverjs/core/types";

function Player() {
  const ref = useRef<Group>(null);
  const { isPressed, getAxis } = useInput({
    actions: { jump: ["Space"], shoot: ["KeyJ"] },
  });
  const { play } = useAudio({
    sounds: {
      jump: { src: "/jump.wav", channel: "sfx" },
      hit:  { src: "/hit.wav",  channel: "sfx" },
    },
  });

  useGameLoop((dt) => {
    if (!ref.current) return;
    ref.current.position.x += getAxis("KeyA", "KeyD") * 5 * dt;
    if (isPressed("Space")) play("jump");
  });

  return <Actor ref={ref} type="primitive" shape="capsule" />;
}

Enter fullscreen mode Exit fullscreen mode

The components are not thin wrappers. <Game> mounts the entire game stack on the way in: WebGL renderer, lighting presets, audio system, input manager, collision manager, and a game loop with phase tracking (loading, playing, paused, gameover). <World> groups actors, sets up a default camera per mode, and optionally enables Rapier physics as a lazy-loaded peer dependency. <Actor> is a discriminated union over three rendering modes — 3D models (.glb/.gltf), sprites (with optional grid- or atlas-based animation), and code-generated primitives — sharing a common base of transform, event, and physics props.

Hooks then read from the singleton systems <Game> set up. useGameLoop is useFrame with phase awareness, fixed-timestep mode, four staged update slots (earlyUpdate, fixedUpdate, update, lateUpdate), and a max-delta cap so a backgrounded tab doesn't spiral the simulation. useInput reads from a centralized InputManager with action mapping. useCollision registers AABB / sphere / circle colliders without dragging in a physics engine. useAudio registers sounds, supports spatial audio, music crossfades, six volume channels, and audio sprites.

The thing I was hunting for, that no lower-level library gave me cleanly, was this: a place to write game logic that looks and feels like React component logic. No imperative boot file. No animation loop wired by hand. No scene-graph state living outside React. Mount a component, the game starts. Unmount it, it cleans itself up.

2D and 3D in the same engine

You change one prop:

<Game mode="2d">  // OrthographicCamera, no shadows, no environment, brighter ambient
<Game mode="3d">  // PerspectiveCamera, shadows, sky, environment, OrbitControls

Enter fullscreen mode Exit fullscreen mode

The same <Actor> components work in both. A sprite in 3D mode billboards at the camera by default; in 2D mode it sits flat. Primitives become <mesh>es with the appropriate material. Models work in either mode, though most 2D games will not need them. Physics is mode-aware: in 2D, Z translation and X/Y rotation are auto-locked per actor so things stay on the plane.

This matters because most game projects do not get to pick "2D or 3D" cleanly. You build a 2D game and then realize the menu wants a parallax background with depth. You build a 3D game and then realize the HUD needs 2D widgets in world space. CarverJS gives you both in the same scene, with a <Camera> component that can override the defaults if you want full control of FOV, near/far, follow targets, or controls (orbit, map, pointerlock, none).

Multiplayer without a game server

This was the part I expected to be the hardest, and it turned out to be the part I am most glad to have built.

Multiplayer in CarverJS is peer-to-peer. One player is the host, all others are clients, and game traffic flows over WebRTC data channels. There is no game server in the architectural sense. The host is the server.

import { MultiplayerProvider } from "@carverjs/multiplayer";

<MultiplayerProvider appId="my-game">
  <Game mode="2d">
    <World>
      <Actor type="primitive" shape="circle" networked />
    </World>
  </Game>
</MultiplayerProvider>

Enter fullscreen mode Exit fullscreen mode

That networked prop is the entire opt-in. The actor's transform now syncs to every connected peer at 20 Hz, with delta compression. Only changed properties go on the wire.

Peer discovery is serverless too. You bring your own signaling network:

  • MQTT — default, free, zero-config. Uses public MQTT brokers. Good enough for prototyping and small games.
  • Firebase RTDB — bring your own Firebase project for production. More reliable, more isolated, easy rules.
  • Cloudflare TURN (or any TURN provider) — optional, for NAT traversal when peers behind restrictive networks cannot connect directly.

After signaling, all data flows directly between peers. No room state lives on a server you have to operate.

Sync modes are layered. You pick the one that fits the actor:

Mode Latency Feel Bandwidth Best for
Events discrete very low turn-based games, chat, infrequent triggers
Snapshot (default) smoothed moderate RPGs, casual co-op, strategy
Prediction instant higher FPS, racing, fighting, fast platformers

Different actors in the same game can use different modes. The player character can use prediction; the chest they are walking towards can use events; the moving platform under their feet can use snapshots. You configure it inline:

<Actor
  type="model"
  src="/player.glb"
  networked={{ sync: "prediction", owner: myPeerId, priority: 2 }}
/>

Enter fullscreen mode Exit fullscreen mode

Host migration is handled. If the host disconnects, peers sort by ID and the lowest ID becomes the new host. State is preserved through the migration — clients hit a brief migrating connection state and resume.

There is a working multiplayer demo in the repo — examples/multiplayer-2d, a small game called Coin Chase. Two players on different machines, collecting coins in real time, using Firebase RTDB for signaling and Cloudflare TURN for NAT traversal. Clone the repo and run it locally with two browser windows pointed at it.

I want to be clear about scope: this is not trying to be Photon or Colyseus. It is a peer-to-peer layer that fits inside React, designed for small to medium multiplayer games — roughly 2 to 16 players, browser-based. The trade-off is that the host has to stay online for the game to continue smoothly. Migration helps but is not a replacement for an authoritative server when you actually need one.

For MoneyTales — small classroom games, friends playing quick rounds — this is exactly the right shape. For your shooter MMO, it is not.

What is in the box right now

@carverjs/core ships:

  • <Game>, <World>, <Actor>, <Camera>, <AudioListener>
  • <SceneManager> and <Scene> for stack-based scene navigation with fade and custom-shader transitions, lazy-loaded scenes via Suspense, and per-scene error boundaries
  • <AssetLoader> and <LoadingScreen> for declarative asset preloading with retry, priority, progress, and groups
  • <ParticleEmitter> with presets (fire, smoke, explosion, sparks, rain, snow, magic, confetti)
  • useGameLoop, useInput, useCamera, useAnimation, useScene, useAssets, useTween, useParticles
  • useCollision (AABB / sphere / circle, layer-based filtering, sensors, no physics engine required)
  • useGridCollision (tile-based, O(1) lookups — perfect for Snake, tile RPGs, puzzles)
  • usePhysics (Rapier, lazy-loaded peer dependency)
  • useAudio (Web Audio with HTML5 fallback, spatial 3D audio, six volume channels, music crossfade, audio sprites, automatic AudioContext unlock)

@carverjs/multiplayer ships:

  • <MultiplayerProvider>, <MultiplayerBridge> (the R3F context bridge, since <Canvas> runs its own reconciler)
  • useMultiplayer, useLobby, useRoom, usePlayers, useHost
  • WebRTC transport with reconnection, host migration, interest management, and network simulation tools (latency, jitter, drop) for testing

The whole thing is TypeScript-first. Every hook and component has full type definitions. The core bundle is under 200KB before your assets, which is the whole point — a Unity WebGL export of an equivalently small game starts in the tens of megabytes.

Three demo games are open-source in the repo:

  • basic-2d — a minimal 2D scene with input
  • basic-3d — a minimal 3D scene with a model and orbit controls
  • multiplayer-2d — Coin Chase, the multiplayer demo above

You can run any of them with pnpm install && pnpm --filter @carverjs/example-basic-2d dev.

What CarverJS is not

This is a beta. Things will move before 1.0, and I want to be specific about scope.

  • It is not Unity. Do not bring AAA pipelines, baked global illumination, complex animation graphs, or 50-MB asset budgets here. The engine is designed for browser-shaped games.
  • It is not Phaser. Phaser is older, more battle-tested, and has a deeper 2D feature set, particularly for tile-based platformers. If you want a pure 2D engine that does not care about React, use Phaser. CarverJS is for the case where the game lives in a React app.
  • It is not a managed multiplayer backend. No matchmaking service, no analytics, no auth, no "studio plan." Bring your own Firebase or any signaling network. Bring your own TURN if you need NAT traversal.
  • The API will break. Minor versions will break things until 1.0. Pin your version. Read the changelog.

What CarverJS actually competes with is the version of "I will write my own game stack on top of R3F" that lives in your head when you start a side project. If that was the alternative, CarverJS will save you a lot of glue code.

What is next

The 1.0 milestone is roughly six months out. Between now and then:

  • Stabilize the core hooks and prop shapes (no big API churn after 1.0)
  • More multiplayer transports and a proper interest-management profile
  • A managed signaling service for teams who do not want to operate their own — paid, optional, the engine itself stays free and MIT
  • An asset marketplace for sprites, models, and audio packs, with most of the revenue going to creators
  • More examples — a multiplayer platformer, a tile-based puzzle, a 3D space shooter

The signaling service and the marketplace are how the project funds itself. The engine is free and stays free.

Try it

pnpm add @carverjs/core
# or
npm install @carverjs/core

Enter fullscreen mode Exit fullscreen mode

Clone the repo and play with the demo games:

git clone https://github.com/moneytales/carverjs.git
cd carverjs
pnpm install
pnpm build
pnpm --filter @carverjs/example-basic-2d dev

Enter fullscreen mode Exit fullscreen mode

If you build something with it, send it to me — I want to see what you make. If something is broken, GitHub Issues is the right place. If something is rough, Discord is where the rough things get tracked.

Most game engines were built by C++ programmers for C++ programmers, with a web export bolted on later. CarverJS was built backwards: web first, React first, game logic written the way component logic is written. It is an opinion as much as a tool. If the opinion fits, you will like the tool.