WebContainers are having a moment

Issue #329.October 6, 2024.2 Minute read.
Bytes

Today’s issue: Unleashing the JavaScript within, server tongue twisters, and why not to use htmx.

Welcome to #329.


Eyeballs logo

The Main Thing

Steve Harvey laughing then looking worried

This AI editor is amazing! It can do 90% of my job for me!

WebContainers are having a moment

Remember WebContainers?

It’s the WebAssembly-based “micro operating system” that can run Vite operations and the entire Node.js ecosystem in the browser. The StackBlitz team created WebContainers to power their in-browser IDE, but it often felt like the technology was still searching for a killer use case – until now.

That’s because StackBlitz just launched bolt.new, an AI-powered dev sandbox that Eric Simons described during ViteConf as “like Claude or ChatGPT had a baby with StackBlitz.”

I’ll try not to picture that too vividly, but based on the overwhelmingly positive reviews so far, I guess it’s working – with dozens of developers describing it as a combo of v0, Claude, Cursor, and Replit.

How Bolt is different: Existing AI code tools can often run some basic JavaScript/HTML/CSS in the browser, but for more complex projects, you need to copy and paste your code into a local environment.

But not Bolt. By utilizing WebContainers, it allows you to prompt, run, edit, and deploy full-stack web applications, all from the browser.

Here’s what that looks like:

  • You can prompt bolt.new to create a production-ready, multi-page app with a specific backend and DB, using whatever tech stack you want (ex: “Build me a personal blog using Astro, Tailwind, and shadcn”).

  • Unlike other tools, Bolt can install and run relevant npm packages and libraries, interact with third-party APIs, and run Node servers.

  • You can manually edit the code it generates via an in-browser editor, or have Bolt solve errors for you. This is unique to Bolt, because it integrates AI at every level of WebContainers (not just the CodeGen step).

  • You can deploy to prod from chat via Netlify, without needing to log in.

There’s a lot more we could unpack here, but Eric’s demo is pretty wild.

Bottom Line: From the outside, it wasn’t always clear if StackBlitz would ever see a meaningful ROI for the 5+ years they’ve spent building WebContainers. But all of a sudden, it looks like they could be uniquely positioned to help developers harness AI to build legit full-stack apps. Buckle up.

        

datadog logo

Our Friends
(With Benefits)

Steve Buscemi sad face on the hulk

My CFO looking at our logging bill every month

Learn how to manage extremely large volumes of logs for free

Your team knows logging is important, but it can be a huge pain to set up and maintain at scale – and also hugely expensive.

That’s why Datadog created this free guide to Log Management & Analytics at Enterprise Scale. It shows you how their Logging without Limits tool decouples log ingestion from retention, as well as storage from query compute – which enables you to:

  • Collect, process, enrich, live search, and extract metrics from your log stream

  • Seamlessly integrate with your app via the Datadog JavaScript integration to speed up troubleshooting

  • Save money by prioritizing log retention based on use cases and budget

Check out this free product brief to see how it all works under the hood.


Spot the Bug logo

Spot the Bug

Presented by Apryse

Their PDF measuring tool lets you easily add PDF and CAD measurement or dimensioning tools to your application.

const fetchPokemon = async (id) => {
  const response = await fetch(`https://pokeapi.co/api/v2/pokemon/${id}`);
  if (!response.ok) {
    throw new Error(`Network response was not ok: ${response.statusText}`);
  }
  const data = await response.json();
  return data;
};

const getStarterPokemon = () => {
  const ids = [1, 2, 3]
  const pokemon = [];

  ids.forEach(async (id) => {
    const result = await fetchPokemon(id);
    pokemon.push(result);
  });

  return pokemon
}

getStarterPokemon()

Cool Bits logo

Cool Bits

  1. One is a new React framework for web and native that’s built on Vite, created by the team behind Tamagui, and supposed to bring balance to the force, not destroy it.

  2. Jake Lazaroff wrote this Local-First Case Study.

  3. Neon offers a fully managed Postgres platform with features designed to help you ship faster like instant provisioning, autoscaling, and branching. [sponsored]

  4. The CEO of Gumroad wrote an article for the htmx blog about Why Gumroad didn’t choose htmx for a new project. (Not enough horse lasers, apparently.)

  5. If you’re still struggling wrapping your head around how useEffect works, we’ve got just the article for you.

  6. Liran Tal wrote an article called Do not use secrets in environment variables and here’s how to do it better. Nice and descriptive title, no notes.

  7. The React Router v7 pre-release is now available with a first glimpse at the new Vite plugin that will enable RR to be a full-stack framework. What does Remix do again?

  8. CarbonQA provides high-quality QA services that scale. Their US-based testers work directly with your tools and will break your app repeatedly by doing all the manual testing you hate doing yourself. [sponsored]

  9. React Server Actions were renamed to Server Functions, because Server Actions are now a subset of Server Functions which serve up the best action at the function if the servers could serve actions.

  10. Jan Hesters wrote an article called Unleash JavaScript’s potential with functional programming. I’m not sure if this approach requires you to walk across hot coals like people do at Tony Robbins seminars, but I’m willing to do anything to unleash the JavaScript within.


Spot the Bug logo

Spot the Bug: Solution

Sponsored by Apryse

await-ing inside of a forEach will only end in pain. There are a few different ways to fix this, but here’s one using a for of loop.

const fetchPokemon = async (id) => {
  const response = await fetch(`https://pokeapi.co/api/v2/pokemon/${id}`);
  if (!response.ok) {
    throw new Error(`Network response was not ok: ${response.statusText}`);
  }
  const data = await response.json();
  return data;
};

const getStarterPokemon = async () => {
  const ids = [1, 2, 3]
  const pokemon = [];

  for (const id of ids) {
    const result = await fetchPokemon(id);
    pokemon.push(result);
  }

  return pokemon
}

await getStarterPokemon()