Skip to content

Introduction

Jason Prasad edited this page Oct 6, 2025 · 82 revisions

Overview

⚠️ Bazaar is under active development and the exact details with respect to syntax or response format are subject to change. Additionally, the generated code may be subjected to change with custom compiler plugins.

Bazaar is a templating language and compiler pipeline to support server-driven UI (SDUI) applications. Just as a 'bazaar' from an urban or architectural view is a dynamic and mutable space occupied by various food vendors, craftspeople, etc., Bazaar attempts to unify the fragmented space of frontend and backend frameworks in serving dynamic content. It does so by the following:

  1. A declarative syntax to specify a schema of types
  2. An expressive templating syntax to capture the dynamic relationship between UI components and its data
  3. A compiler plugin pipeline that is extendible for code generation targeting multiple platforms and application's niche needs
  4. A standardized response format

An Example

πŸ“± Note: This table is best viewed on larger screens. On mobile, you may need to rotate your device.

hello_world.bzr iOS
package helloworld

component Button { label string onClick func()? = nil }
func ShowToast(message string, duration double)
data HelloWorldModel { message string duration double = 2 }
template HelloWorld(model HelloWorldModel) { Button("Hello, world!") { ShowToast(model.message, model.duration) } }

Let's say we have a simple hello_world.bzr like the above that describes the example iOS interface. To generate code targeting a Go backend we would run the following bazaarc command.

bazaarc --go_out=. --plugin=bazaarc-gen-go hello_world.bzr

This would produce the following Go code.

type HelloWorldModel struct {
    Message string
    Duration float64
}

func NewHelloWorldModel() HelloWorldModel {
    return HelloWorldModel{
        Duration: 2.0    
    }
}

func HelloWorld(model HelloWorldModel) bazaar.Component {
    // Generated code that produces a bazaar.Component...
}

This code may then be used later to render a response.

Handler Response
import "net/http"

func getHandler(w http.ResponseWriter, r *http.Request) { model := NewHelloWorldModel() model.Message = "πŸ‘‹πŸŒŽ" component := HelloWorld(model) component.Render(r.Context(), w) }
{
  "type": "helloworld.Button",
  "props": {
    "label": "Hello, World!",
    "on_click": {
      "type": "bazaar.closure",
      "block": [
        {
          "type": "helloworld.ShowToast",
          "args": {
            "message": "πŸ‘‹πŸŒŽ",
            "duration": 2.0
          }
        }
      ]
    }
  }
}

Further thought and careful consideration of the frontend framework will be needed; however, one could imagine running the following to generate the iOS framework code in Swift. Just as we used the generated Go code within a request handler, the generated iOS code would need further implementation by an iOS developer.

bazaarc --swift-ios_out=. --plugin=bazaarc-gen-swift-ios hello_world.bzr

Bazaar as... "1. A declarative syntax to specify a schema of types"

A challenge with SDUI is knowing and validating the exact schema of components and types available on the frontend. This problem is very similar to the frontend discovery of the full graph in a GraphQL API or even service-to-service discovery of RPC methods. Like GraphQL and protobuf, Bazaar is inspired to fulfill a similar need for SDUI. The type declarations in Bazaar's syntax form a schema of available types to the system (e.g. data, component, func, and etc.). It is an aspiration of Bazaar to serve as a schema that is enforceable and has many of the same methods of validation that are available to GraphQL or protobuf.

Bazaar as... "2. An expressive templating syntax to capture the dynamic relationship between UI components and its data"

template HomeRows(models [HomeRowModel]) {
    for model in models {
        Row {
            Text(model.label)
            
            if var imageRef = model.imageRef {
                Image(model.imageRef)
            }
        }
    }
}

UI is dynamic with respect to the data. The templating syntax of Bazaar will support a range of expressions. Another aspiration of Bazaar is to emulate the developer experience that a React, SwiftUI, or Compose developer would feel at home.

Bazaar as... "3. A compiler plugin pipeline that is extendible for code generation targeting multiple platforms and application's niche needs"

bazaarc --<go|kotlin-android|swift-ios|...>_out=<path> \
        --plugin=<bzrc-gen-go|bzrc-gen-kotlin-android|bzrc-gen-swift-ios|...>

The above command results in a process modeled by the following.

flowchart LR
    A@{shape: docs, label: "*.bzr"}
    A --> B["Bazaar Compiler"]
    B <--> |protobuf| C@{shape: processes, label: "Compiler Plugins"}
    C --> D@{shape: docs, label: "*.go, *.kt, *.swift,\n..."}
Loading

The Bazaar compiler frontend is responsible for the parsing, semantic analysis, and generating the intermediate representation for downstream code generation. The intermediate representation is then forwarded to a compiler plugin running as a separate process via RPC over stdin/stdout. This process will closely resemble how the protoc compiler works for protobuf (e.g. PluginProtos.CodeGeneratorRequest).

Bazaar as... "4. A standardized response format"

⚠️ The response format has received the least development attention and is subject to drastic change. The response format must have the ability to encode expressions that will be evaluated on the frontend. In a way, it will be sort of a restricted "byte code".

Although there is a great deal of flexibility present in the Bazaar syntax and compiler pipeline, the response format must be stricter and standardized for it to be useful and valid. For example, the same is true of the proto language and its binary format. Bazaar will strive to define a response format (e.g. JSON, protobuf, etc.) that can capture the expressivity of the templating syntax. For example, eventually Bazaar will support reactivity, annotations, and closures. These examples are present in the following and will be at the forefront of Bazaar's design iterations.

hello_world.bzr iOS
package counter

import helloworld
template Counter { @State var count = 0 Button("Increment count: ${count}") { count += 1 } }
{
  "type": "helloworld.Button",
  "context": [{
    "type": "bazaar.State",
    "name": "count",
    "value": {
      "int_value": 0
    }
  }], 
  "props": {
    "label": {
      "type": "bazaar.string_expression",
      "args": {
        "format": "Increment count: {count}"
        "variables": [
          "count"
        ]
      }    
    },
    "on_click": {
      "type": "bazaar.closure",
      "block": [
        {
          "type": "bazaar.increment_expression",
          "args": {
            "variable": "count",
            "value": 1
          }
        }
      ]
    }
  }
}

Related Links