• Anthropic acquires Bun as Claude Code reaches $1B milestone ↗

    Bun is used as the runtime for Claude Code. Today it was acquired by Anthropic.

    We’ve been a close partner of Bun for many months. Our collaboration has been central to the rapid execution of the Claude Code team, and it directly drove the recent launch of Claude Code’s native installer. We know the Bun team is building from the same vantage point that we do at Anthropic, with a focus on rethinking the developer experience and building innovative, useful products.

    Congratulations to Jarred Sumner and the Bun team. Here he describes how the acquisition happened:

    We’ve been prioritizing issues from the Claude Code team for several months now. I have so many ideas all the time and it’s really fun. Many of these ideas also help other AI coding products.

    A few weeks ago, I went on a four hour walk with Boris from the Claude Code team. We talked about Bun. We talked about where AI coding is going. We talked about what it would look like for Bun’s team to join Anthropic. Then we did that about 3 more times over the next few weeks. Then I did that with many of their competitors. I think Anthropic is going to win.

    I had the privilege to walk with Jarred a couple weeks ago during a rainy day at Apple Park. He’s very smart. I’m thrilled to hear he’s getting all the fuel needed to build great tools.

  • We need to demand better ↗

    Matt Mahan, the mayor of San Jose, California:

    Without a doubt, California is still the most innovative state. But we won’t stay that way unless we face facts. And they are grim. 

    We have the nation’s highest poverty rate and highest unemployment rate. Our energy costs are the highest in the continental United States. Nearly half of America’s unsheltered homeless people live in California. And all the while, Californians bear the nation’s second-highest state and local tax burden and must reckon with hundreds of billions’ worth of unfunded pension liabilities and deferred maintenance on public infrastructure in the years ahead.

    As a mayor, I have the responsibility of addressing these challenges. My constituents don’t accept excuses, nor should they. In San Jose, we have not waited for Sacramento and have invested in quick-build housing solutions and are reducing our unsheltered homeless population. We are using new technologies and old-fashioned, street-level policing to become the safest big city in America again. We have embraced the responsible use of AI to make government more effective, from spotting potholes before they form to helping buses run faster. 

    […]

    On a city-to-city level, we’ve seen the benefits of close collaboration. […] However, statewide, Sacramento and local governments are not collaborating in a way that yields the best results for the public. 

    The most pressing example is homelessness. Last year, when 68% of Californians voted yes on Proposition 36, they agreed that those suffering from severe addiction should be required to go to treatment if they steal to buy drugs. This policy would save thousands of lives, billions of dollars, and help people get the treatment they need to escape the streets. Where is it? Sacramento refuses to implement it.

    California has seen nearly as many people die on our streets in the last 12 years as the nation lost in the Vietnam War, with most being overdose victims. A commonsense bill allowing — not requiring — dedicated sober living spaces for the homeless was just passed by the Legislature. Where is it? The governor vetoed it.

    Caltrans takes 4-6 weeks to approve clean ups for freeway ramps and underpasses which leads to large buildups of trash and suffering. The state cannot maintain their land. San Jose is stepping up by making a deal with the governor to delegate authority to the City to bring help and accountability to neglected state land in San Jose.

    Energy costs are a serious problem. California energy costs have gone up 34% since 2019 while Nevada fell 8% and Arizona fell 3%.

  • Frontend Aesthetics: A Prompting Guide ↗

    Anthropic:

    Claude can generate high-quality frontends, but without guidance it tends toward generic, conservative designs. […] Claude has strong knowledge of design principles, typography, and color theory, but defaults to safe choices unless explicitly encouraged otherwise.

    Anthropic found three strategies to produce better results:

    1. Guide specific design dimensions
    2. Reference design inspirations
    3. Call out common defaults to avoid

    With an aesthetics prompt section, the task create a SaaS landing page for a project management tool improves a lot:

    This example prompt applies these strategies:

    <frontend_aesthetics>
    You tend to converge toward generic, “on distribution” outputs. In frontend design, this creates what users call the “AI slop” aesthetic. Avoid this: make creative, distinctive frontends that surprise and delight. Focus on:

    Typography: Choose fonts that are beautiful, unique, and interesting. Avoid generic fonts like Arial and Inter; opt instead for distinctive choices that elevate the frontend’s aesthetics.

    Color & Theme: Commit to a cohesive aesthetic. Use CSS variables for consistency. Dominant colors with sharp accents outperform timid, evenly-distributed palettes. Draw from IDE themes and cultural aesthetics for inspiration.

    Motion: Use animations for effects and micro-interactions. Prioritize CSS-only solutions for HTML. Use Motion library for React when available. Focus on high-impact moments: one well-orchestrated page load with staggered reveals (animation-delay) creates more delight than scattered micro-interactions.

    Backgrounds: Create atmosphere and depth rather than defaulting to solid colors. Layer CSS gradients, use geometric patterns, or add contextual effects that match the overall aesthetic.

    Avoid generic AI-generated aesthetics:

    • Overused font families (Inter, Roboto, Arial, system fonts)
    • Clichéd color schemes (particularly purple gradients on white backgrounds)
    • Predictable layouts and component patterns
    • Cookie-cutter design that lacks context-specific character

    Interpret creatively and make unexpected choices that feel genuinely designed for the context. Vary between light and dark themes, different fonts, different aesthetics. You still tend to converge on common choices (Space Grotesk, for example) across generations. Avoid this: it is critical that you think outside the box!
    </frontend_aesthetics>

  • React 19.2 ↗

    The React Team:

    React 19.2 is now available on npm!

    This is our third release in the last year, following React 19 in December and React 19.1 in June. In this post, we’ll give an overview of the new features in React 19.2, and highlight some notable changes.

    New features include <Activity /> and useEffectEvent which has been in development for a while now.

    Effect Events

    Event callbacks now can be split outside of effects. This means event callback dependencies do not need to be in effect dependencies.

    function ChatRoom({ roomId, theme }) {
      const onConnected = useEffectEvent(() => {
        showNotification('Connected!', theme); // theme is no longer an event dependency
    });
    
    useEffect(() => {
      const connection = createConnection(serverUrl, roomId);
      connection.on('connected', () => {
        onConnected();
      });
      connection.connect();
      return () => connection.disconnect();
    }, [roomId]); // ✅ All dependencies declared (Effect Events aren't dependencies)

    Now you can avoid re-running effects for changes to variables which only affect a callback.

    This requires upgrading to [email protected] to permit effect events to be excluded from effect dependencies.

    Batched Suspense Boundaries for SSR

    We fixed a behavioral bug where Suspense boundaries would reveal differently depending on if they were rendered on the client or when streaming from server-side rendering.

    Starting in 19.2, React will batch reveals of server-rendered Suspense boundaries for a short time, to allow more content to be revealed together and align with the client-rendered behavior.

    This fix also prepares apps for supporting <ViewTransition> for Suspense during SSR. By revealing more content together, animations can run in larger batches of content, and avoid chaining animations of content that stream in close together.

    If total page load time approaches 2.5 seconds, React stops batching and reveals content immediately to help fulfill good LCP core web vitals for SEO.

    SSR: Web Streams support for Node

    renderToReadableStream is now available for Node.js. While React does not recommend using it due to performance concerns, I’m interested to see the performance delta inside projects which already mostly use Web Streams like Hono.

  • Pino ↗

    Pino is a very low overhead JavaScript logger. Low overhead is important when you have a lot of logs.

    Node.js docs for process I/O:

    Warning: Synchronous writes block the event loop until the write has completed. This can be near instantaneous in the case of output to a file, but under high system load, pipes that are not being read at the receiving end, or with slow terminals or file systems, it’s possible for the event loop to be blocked often enough and long enough to have severe negative performance impacts. This may not be a problem when writing to an interactive terminal session, but consider this particularly careful when doing production logging to the process output streams.

    If you’re not careful, logs can consume the entire event loop utilization.

    Process i/o behavior differences between Terminals, Files, and Pipes

    On a related note: process.stdout.write is synchronous when writing to a file or terminal but asynchronous when writing to a pipe. Sim Lijin wrote about disappearing bytes in Node.js which is due to these behaviors. In particular, synchronous writes are used for terminals because process I/O may not complete if you call process.exit(). This causes what may be unexpected differences in behavior. For example, pipes are async:

    node -e "process.stdout.write('@'.repeat(128 * 1024));" | wc -c
      131072

    But if you call process.exit(0) while writing to an async pipe, the result is truncated because the async write is interrupted:

    node -e "process.stdout.write('@'.repeat(128 * 1024)); process.exit(0);" | wc -c
      65536

    If you write to a file, process I/O writes are synchronous, so the entire content is written:

    node -e "process.stdout.write('@'.repeat(128 * 1024)); process.exit(0);" >node-stdout-test.out && wc -c node-stdout-test.out
      131072 node-stdout-test.out

    The reason the async write is 65,536 bytes comes from the pipe capacity of 16 pages. According to man pipe(7):

    Before Linux 2.6.11, the capacity of a pipe was the same as the system page size (e.g., 4096 bytes on i386). Since Linux 2.6.11, the pipe capacity is 16 pages (i.e., 65,536 bytes in a system with a page size of 4096 bytes).

Follow

Featured Blog Post

  • Starting at Apple

    I will help small businesses succeed by building Apple Business Essentials — a product which brings together device management, 24/7 Apple support, and iCloud storage into flexible subscription plans. More →