Skip to main content

2 posts tagged with "Playground"

View All Tags

GraphQL Server in the Browser using WebAssembly

· 5 min read
Shadaj Laddad
Co-founder @ Exograph

On the heels of our last feature release, we are excited to announce a new feature: Exograph Playground in the browser! Thanks to the magic of WebAssembly, you can now run Exograph servers entirely in your browser, so you can try Exograph without even installing it. That's right, we run a Tree Sitter parser, typechecker, GraphQL runtime, and Postgres all in your browser.

See it in action

Head over to the Exograph Playground to try it out. It shows a few pre-made models and populates data for you to explore. It also shows sample queries to help you get started.

A few models need authentication, so you can click on the "Key" icon in the middle center of the GraphiQL component to simulate the login action.

When you open the playground, the top-left portion shows the model. The top-right portion shows tabs to give insight into Exograph's inner workings. The bottom portion shows the GraphiQL interface to run queries and mutations.

You can also create your model by replacing the existing model in the playground. The playground supports sharing your playground project as a gist.

How it works

The Exograph Playground runs entirely in the browser. Besides the initial loading of static assets (like the WebAssembly binary and JavaScript code), you don't need to be connected to the internet. This is possible because we compiled Exograph, written in Rust, to WebAssembly.

Playground Architecture


The builder plays a role equivalent to the exo build command. It reads the source code, parses and typechecks it, and produces an intermediate representation (equivalent to the exo_ir file). The builder also includes elements equivalent to the exo schema command to compute the SQL schema and migrations.

On every change to the source code, the builder validates the model, reports any errors, and produces an updated intermediate representation. You can see the errors in the "Problems" tab.

The builder also produces the initial SQL schema and migrations for the model as you change it. The playground will automatically apply migrations as needed. You can see the schema in the "Schema" tab.


The runtime is equivalent to the exo-server command. It processes the intermediate representation the builder produced and serves the GraphQL API. When you run a query, it sends it to the runtime, which computes the SQL query, runs against the database, and returns the results.

The runtime also sends logs to the playground, which you can see in the "Traces" tab. This aids in understanding what Exograph is doing under the hood, including the SQL queries it executes.


The playground uses pglite, which is Postgres compiled to WebAssembly. Currently, we store Postgres data in memory, so you will lose the data when you refresh the page. We plan to add support for saving the data to local storage.


The GraphiQL is a standard GraphQL query interface. You can run queries and mutations against the Exograph server. The playground populates the initial query for you to get started.

Sharing Playground Project as a Gist

The playground supports sharing the content as a gist. You can load such a gist using the gist query parameter. For example, to load the gist with ID abcd, you can use the URL

You can create a gist to share your model, the seed data, and the initial query populated in GraphiQL. The files in gist follow the same layout as the project directory in Exograph, except you use :: as the directory separator.

  • src::index.exo: The model
  • tests::init.gql:The seed data. See Initializing seed data for more details.
  • playground::query.graphql: The initial query in GraphiQL
  • The README to show in the playground

We will keep improving the sharing experience in the future.

What's next

This is just the beginning to make Exograph easier to explore. Here are a few planned features to make the playground even better (your feedback is welcome!):

  • Support JavaScript Modules: In non-browser environments, Exograph supports Deno Modules. Deno cannot be compiled to WebAssembly, so we cannot run it in the browser. However, browsers already have a JavaScript runtime 🙂, which we will support in the playground.
  • Persistent Data: We plan to add support for saving the data to local storage so you can continue working on your data model across sessions.
  • Improved Sharing: We will add a simple way to create gists for your playground content and share it with others.

Try it out and let us know what you think. If you develop a cool model, publish it as a gist and share it with us on Twitter or Discord. We would appreciate a star on GitHub!


What's new in Exograph 0.4

· 5 min read
Ramnivas Laddad
Co-founder @ Exograph
Shadaj Laddad
Co-founder @ Exograph

We are excited to announce the release of Exograph 0.4! This release introduces several new features and enhancements, many in response to our users' feedback (thank you!). While we will explore some of these features in future blogs, here is a quick summary of what's new since the 0.3 version.

NPM modules support

Exograph offers a Deno integration to write custom business logic in TypeScript or JavaScript. Until now, you could only use Deno modules. While Deno modules ecosystem continues to expand, it is not as rich as the Node ecosystem. Recognizing this, Deno added support for NPM modules to tap into the vast range of NPM packages, and Exograph 0.4 extends this support through our integration. You can now harness NPM modules to checkout with Stripe, send messages with Slack, interact with AWS, and so on.

As an illustration, here is how you would send emails using Resend. First, you would define a mutation:

module Email {
mutation sendAnnouncement(): Boolean

And implement it using the resend NPM module:

import { Resend } from "npm:resend";

const resend = new Resend("re_...");

export async function sendAnnouncement(): Promise<boolean> {
await resend.emails.send({
from: "...",
to: "...",
subject: "Exograph 0.4 is out!",
html: "<p>Exograph <strong>0.4</strong> is out with support for npm modules, playground mode, and more!</p>",

return true;

Compared to the example shown on the Resend site, the difference is the npm: prefix in the import statement. This prefix tells Exograph to look for the module in the npm registry.

Railway integration

Exograph's deployment has always been easy since the server is just a simple binary with everything needed to run. However, we strive to make it easier for specific platforms. Exograph 0.4 now supports Railway as a deployment target! Here is a quick video where we create an Exograph project from scratch and deploy it to Railway in under three minutes.

To support this kind of integration, where the cloud platform can also run the build step, we now publish two Docker images: cli with the exo binary and server with the exo-server binary.

exo playground

A recommended practice for GraphQL deployments is to turn off introspection in production, which is the default in Exograph. However, exploring the GraphQL API with such a server becomes difficult without code completion and other goodies. Exograph 0.4 introduces a new exo playground command that uses the schema from the local server and executes GraphQL operations against the specified remote endpoint.

exo playground --endpoint https://<server-url>/graphql
Starting playground server connected to the endpoint at: https://<server-url>/graphql
- Playground hosted at:

You will see a UI element in the playground showing the specified endpoint. Besides this difference, the playground will behave identically to the local playground, including autocomplete, schema documentation, query history, and integrated authentication.


This doesn't bypass the recommended practice of turning off introspection in production. The exo playground is useful only if you have access to the server's source code, in which case, you would know the schema, anyway!

See the video with the Railway integration above for a quick demo of the exo playground command.

Access control improvements

Exograph offers to express access control rules precisely. In version 0.4, we enhanced this expressive power through higher-order functions. Consider a document management system where users can read documents if they have read permissions and mutate if they have written permissions. The following access control rules express this requirement.

context AuthContext {
@jwt("sub") id: Int

module DocsDatabase {
query = self.permissions.some(permission => == &&,
mutation = self.permissions.some(permission => == && permission.write)
type Document {
@pk id: Int = autoIncrement()
permissions: Set<Permission>

type Permission {
@pk id: Int = autoIncrement()
document: Document
user: User
read: Boolean
write: Boolean

type User {
@pk id: Int = autoIncrement()
permissions: Set<Permission>

With this setup, no user can read or write a document without the appropriate permission. The some function allows you to express this requirement in a single line. Internally, it lowers it down to an SQL predicate for efficient execution.

Currently, we support the some higher-order function, which matches the Array.prototype.some function in Javascript. This function takes a predicate function and returns true if the predicate function returns true for any element in the array.

Other improvements

Besides these major features, we continue to improve Exograph to fit more use cases and simplify the developer experience.

For the Postgres plugin, for example, you can now specify that the tables could be in a non-public schema and specify deeply nested creating and updates in a single mutation. It also allows clients to supply the primary key value for UUID fields when creating an entity.

In version 0.3, we introduced a friction-free integration with Clerk for authentication. Since then, we have extended this support to Auth0 as an authentication provider! While Exograph generically supports all compliant OIDC providers, the playground integration for Clerk and Auth0 makes it easy to try out APIs that require authentication. Along the way, we updated key rotation for the OIDC authentication mechanism.

Let us know what you think of these new features and what you would like to see in the future. You can reach us on Twitter or Discord.