Skip to content

Create Open Source GUI for Golem in TypeScriptΒ #1189

@jdegoes

Description

@jdegoes

Golem only has two methods of interaction:

  • The REST API
  • The Command-Line Interface (golem-cli)

Both of these are useful for programmatic purposes, while the CLI is designed mostly for developers in mind. However, neither of these methods are discoverable or provide a high-level graphical user-interface with a wonderful developer experience. While Golem Cloud comes with Console, a high-level graphical user-interface, Console is deeply integrated into the Cloud offering and relies on APIs that don't even exist in OSS or make sense there.

In order to provide developers a new graphical way of interacting with Golem, we wish to sponsor a ticket that is primarily intended for TypeScript developers -- with a shout-out to developers familiar with Effect TS (though use of this library or any other is not required). The end result will be a GUI for Golem that ships with the single executable (even though you could use it elsewhere) and makes it easy for developers to do local development and testing.

In order to claim this bounty, you need two do two things:

  1. Build a TypeScript application that allows graphical management of Golem, supporting all the APIs that Golem supports. This requires knowledge of TypeScript, front-ends, cross-browser development, user-experience, user-interface design (including usability), and developer experience.
  2. Serve the application as part of the Single Executable build of Golem (which bundles everything together in a single executable). This may require a tiny amount of Rust knowledge, but you can probably get by with Google and Copilot.

In particular, the application must support:

  1. Component management. Developers can create, update, and delete components visually. All backend APIs should have a way to perform the function visually.
  2. Worker management. Developers can create, update, manage, and delete workers visually. All backend APIs should have a way to perform the function visually.
  3. API management. Developers can create, update, manage, and delete APIs visually. All backend APIs should have a way to perform the function visually.
  4. Plugin management. All backend APIs should have a way to perform the function visually (chiefly about installing / uninstalling plug-ins inside components and workers).

Although one can take inspiration from Console, this is not necessary, as Cloud is designed for use in a multi-tenant environment, which does not apply to Golem. However, the breadth of support for backend APIs, as well as the polish and attention to aesthetics, should be similar to Console. You are free to make your own decisions on design, user-interface, user-experience, etc. However, if you choose poorly, and your user-interface is ugly, difficult to use, inconsistent, incomplete, or buggy, then your PR won't be merged.

A winning pull-request will include screenshots of every major area of the user-interface and attach pre-compiled single-executable binaries for Linux / MacOS or both.

Getting Started

In order to test the functionality that you develop in the GUI, you must develop and deploy your own backend on Golem. In fact, this should be the FIRST thing you do in order to solve this ticket--because otherwise you will not understand how Golem works or what sort of experience is required in order to build and deploy for Golem.

The steps are as follows:

  1. Pick a programming language supported by Golem (basically, any language that can compile or be bundled to WASM Components); see https://learn.golem.cloud.
  2. Define a WIT interface for your component. I included a WIT interface for a simple TODO backend below.
  3. Implement code for your component, which satisfies the WIT-based interface. How you do this is language-specific and documented here, among other places.
  4. Deploy your component on Golem. You can use Golem single executable, Golem Cloud, or deploy Golem in the cloud.
  5. Build an API for your component. You should use one worker per user, and have APIs like the following:
    GET /{user-id}/todos/
    POST /{user-id}/todos/ 
    GET /{user-id}/todos/{todo-id}
    PUT /{user-id}/todos/{todo-id}
    DELETE /{user-id}/todos/{todo-id}
    
    Together with other APIs for user profile, getting uncompleted todos, etc.
  6. Once you test this REST API, which will be served by the Worker Gateway, you are ready to proceed to implementing the solution.

After you implement the solution, you will be able to visually complete all of the above steps, as well as diagnose and debug issues related to development, update your component, and do all other functions supported by the Golem APIs.

package todo:personal@0.1.0;

interface types {
    // Basic timestamp type (Unix timestamp in milliseconds)
    type timestamp = u64;

    // User profile information
    record profile {
        name: string,
        email: string,
        created-at: timestamp,
        updated-at: timestamp,
    }

    // Input for updating profile
    record update-profile-input {
        name: option<string>,
        email: option<string>,
    }

    // Represents a task
    record task {
        id: u64,
        title: string,
        description: string,
        completed: bool,
        due-date: option<timestamp>,
        created-at: timestamp,
        updated-at: timestamp,
    }

    // Input for creating a task
    record create-task-input {
        title: string,
        description: string,
        due-date: option<timestamp>,
    }

    // Input for updating a task
    record update-task-input {
        title: option<string>,
        description: option<string>,
        completed: option<bool>,
        due-date: option<timestamp>,
    }

    // Error types
    enum error {
        not-found,
        invalid-input,
        internal-error,
    }
}

// Profile management interface
interface profile {
    use types.{error, profile, update-profile-input};

    // Get the current user's profile
    get: func() -> result<profile, error>;

    // Update the current user's profile
    update: func(input: update-profile-input) -> result<profile, error>;
}

// Task management interface
interface tasks {
    use types.{error, task, create-task-input, update-task-input, timestamp};

    // Create a new task
    create: func(input: create-task-input) -> result<task, error>;

    // Get a specific task by ID
    get: func(id: u64) -> result<task, error>;

    // Update an existing task
    update: func(id: u64, input: update-task-input) -> result<task, error>;

    // Delete a task
    delete: func(id: u64) -> result<_, error>;

    // List all tasks
    list: func() -> result<list<task>, error>;

    // List tasks due before a specific timestamp
    list-due-before: func(before: timestamp) -> result<list<task>, error>;

    // List all completed tasks
    list-completed: func() -> result<list<task>, error>;

    // List all incomplete tasks
    list-incomplete: func() -> result<list<task>, error>;
}

// Main world definition
world todo-worker {
    import types;
    export profile;
    export tasks;
}

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions