GitHub Next Logo

Vitale

Live notebooks in VS Code for JavaScript/TypeScript, web development, and AI experimentation

What's it for?
Exploratory development with rapid feedback.
Stage
Research prototype
Who made it?
Share

As software developers we understand the importance of a tight feedback loop. When we can get instant syntax- and type-checking, rapid runs of the tests affected by a change, or live previews of the UI, then we can go fast with confidence, correcting little mistakes in logic or design before they become big ones.

This fast feedback is especially powerful when we're not sure what we're doing (I can't speak for you but for me this is most of the time). When working in this mode of uncertainty---learning an API, narrowing down a bug, iterating on a UI---often the best way to proceed is to explore and see where we get; try something and see what happens; futz around and find out.

Vitale is a tool for this kind of exploratory development. It's a system for writing notebooks---documents that mix text, code, and code output---in VS Code using TypeScript and React. (Notebooks were popularized by Jupyter; more below in Inspirations.) Vitale is built using VS Code's support for custom notebook backends and on Vite's support for hot reloading TypeScript code (using the new Runtime API).

Using Vitale you can write TypeScript in a notebook and see live results inline. In the video below we use this feedback loop to develop a regular expression against a set of examples:

Develop a regular expression with live examples

There are lots of ways to get fast feedback in a TypeScript / React project: hot-reloading your app using Vite; auto-running tests with Vitest; CodeSandbox and other web-based tools; the Node.js REPL, and many others. Vitale can be another tool in your toolbox, with some distinct advantages:

  • like the Node.js REPL, Vitale provides interactive execution; but with the editing experience of VS Code---syntax highlighting, typechecking, GitHub Copilot, and your key bindings and extensions.
  • like the Vite dev server, Vitale rebuilds and re-runs your code as you change it; but you can run individual functions and components, not just the whole app.
  • like CodeSandbox and other web-based tools, Vitale provides an environment for rapid iteration; but integrated into your project, using your existing (Vite) build setup, and stored in your project repo.

Use cases

Here are some ways we've found Vitale useful at Next:

Explore an API

Interactively explore the GitHub API

Web APIs (like the GitHub REST API) can be complex, with dozens of endpoints and complicated argument and response types. It's hard to understand these APIs from the documentation alone; and clumsy to explore them with tools like curl and jq.

Using Vitale you can explore an API interactively in TypeScript: construct and issue requests; filter and transform responses; and render results in an interactive JSON viewer, or by using VS Code's built-in renderers for HTML and other formats.

For APIs which have a wrapper library (like Octokit for GitHub), you can benefit from type hints and autocomplete in the editor. For APIs which have VS Code authentication providers (like GitHub), you can authenticate without leaving VS Code. And when you've figured out the incantation you need, you can save the notebook as part of your project.

Develop a React component

Render React components with fast refresh

Modern React development tools like Vite provide a nice experience for interactive development of applications, with hot module reloading and fast refresh for quick turnaround when you make changes. These tools typically build and serve your entire project, but sometimes you want to narrow your focus: develop a single component interactively, experiment with component properties, and see different component states side by side.

Vitale supports rendering React components in a notebook cell, with hot module reloading and fast refresh built on Vite. You can use it to experiment with a component library (like Primer React), or to iterate on your own components and layouts.

Visualize an algorithm

Visualize and debug a scheduling algorithm

Sometimes the easiest way to understand an algorithm is to visualize it in some way. But it can be a lot of work to set up a visualization, so it isn't often a tool we reach for. Vitale makes it easy: you can generate a quick-and-dirty rendering in a notebook, and see it update as you make changes to the code.

In the video above, we visualize a function for finding a free meeting time across several people's calendars, using an HTML grid. (We use React server-side rendering as a convenience so we can use JSX and define components.) We quickly see that the algorthm has some bugs: we've used some when we need every in the outer loop; and we've neglected to consider the length of the meeting. Visualizing the output makes it easy to see that things aren't working, and gives us clues about what's wrong.

Craft a prompt

Experiment with Azure AI models and prompts

Cloud-hosted language models typically come equipped with an online "playground", where you can experiment with prompts, parameters, and model variants. These playgrounds are great for feeling out the vibes of a model. But for serious work you need to be able to construct prompts from data; compare outputs generated with different prompts, parameters, and models; and post-process model outputs for the needs of your application.

Vitale provides a flexible environment where you can construct prompts, call models, and process outputs programmatically, with the same responsiveness and interactivity you enjoy in an online playground; and again the exploration can be checked into your project for future use.

In the video above, we call a GPT-4o instance from the GitHub Models marketplace using the Azure AI Inference API (using Vitale's auth support), display streaming output (using Vitale's support for async generators), post-process the output (rendering it as Markdown using VS Code's built-in renderer), compare three models from the Models marketplace side by side (using Vitale's support for showing cell output in a separate VS Code view), and finally edit the prompt and see all three model outputs update (using Vitale's support for reactive re-execution.)

GitHub Models is in limited public beta, and Vitale is a great way to experiment with the various models in the marketplace. Sign up for the beta if you'd like to try it out!

Inspirations

Notebook environments arose in the '80s in computer algebra systems like Mathematica; more recently they became popular in the realms of data science and machine learning with IPython / Jupyter.

There are some existing notebook systems for TypeScript / JavaScript that work in VS Code, like the Node.js Notebooks extension and the Deno Jupyter kernel (which works with the cross-language Jupyter extension).

There are also some web-based notebook systems that work with TypeScript / JavaScript, like Observable (which makes notebooks fully reactive) and TypeCell (which embeds code in rich-text documents).

Programming environments supporting interactive, exploratory development arose in the '70s and '80s, most prominently in the Lisp and Smalltalk worlds.

Modern Lisp-derived systems like Clojure support dynamic development---"where you interact with your program while you write it, growing and adding to it while it’s running". And Smalltalk-derived systems like Pharo / Glamorous Toolkit support moldable development---"a way of programming through custom tools built for each problem."

Try it out

You can give Vitale a try right now! Just create a Vitale Codespace and try the example notebooks once it starts up.

Or follow the instructions in the README to try it in your own project by installing the VS Code extension and the support library.

What's next?

Vitale is a prototype, with a lot of rough edges, but it's already a useful tool.

One interesting direction for the future is to view Vitale as a lightweight extension mechanism for VS Code: for ad-hoc or project-specific tasks, you could build a tool directly in your project environment, rather than as a separate extension. (This is the vision of "moldable development".)

Many of the pieces are in place already, but to realize this idea Vitale would need to support richer interaction with the VS Code API (so far it supports only authentication and notification), a way to communicate between React code (running within VS Code in a webview) and Node code (running within Vite), and a way to persist the state of lightweight extensions across VS Code sessions.

We hope you find Vitale useful, and we'd love to hear your feedback! Tell us your thoughts in the project discussions or file an issue.