Quick Start

One page summary of how to start a new FTL project.

Requirements

Install the FTL CLI

Install the FTL CLI via Hermit, Homebrew, or manually.

Hermit (Mac or Linux)

FTL can be installed from the main Hermit package repository by simply:

hermit install ftl

Alternatively you can add hermit-ftl to your sources by adding the following to your Hermit environment's bin/hermit.hcl file:

sources = ["https://github.com/TBD54566975/hermit-ftl.git", "https://github.com/cashapp/hermit-packages.git"]

Homebrew (Mac or Linux)

brew tap TBD54566975/ftl && brew install ftl

Manually (Mac or Linux)

Download binaries from the latest release page and place them in your $PATH.

Install the VSCode extension

The FTL VSCode extension will run FTL within VSCode, and provide LSP support for FTL, displaying errors within the editor.

Development

Intitialize an FTL project

Once FTL is installed, initialize an FTL project:

mkdir myproject
cd myproject
ftl init myproject . --hermit

This will create an ftl-project.toml file, a git repository, and a bin/ directory with Hermit tooling.

Create a new module

Now that you have an FTL project, create a new module:

ftl new go . alice

This will place the code for the new module alice in myproject/alice/alice.go:

package alice

import (
	"context"
	"fmt"

	"github.com/TBD54566975/ftl/go-runtime/ftl" // Import the FTL SDK.
)

type EchoRequest struct {
	Name ftl.Option[string] `json:"name"`
}

type EchoResponse struct {
	Message string `json:"message"`
}

//ftl:verb
func Echo(ctx context.Context, req EchoRequest) (EchoResponse, error) {
	return EchoResponse{Message: fmt.Sprintf("Hello, %s!", req.Name.Default("anonymous"))}, nil
}

Each module is its own Go module.

ftl new kotlin . alice

This will create a new Maven pom.xml based project in the directory alice and create new example code in alice/src/main/kotlin/com/example/EchoVerb.kt:

package com.example

import xyz.block.ftl.Export
import xyz.block.ftl.Verb


@Export
@Verb
fun echo(req: String): String = "Hello, $req!"
ftl new java . alice

This will create a new Maven pom.xml based project in the directory alice and create new example code in alice/src/main/java/com/example/EchoVerb.java:

package com.example;

import xyz.block.ftl.Export;
import xyz.block.ftl.Verb;

public class EchoVerb {

    @Export
    @Verb
    public String echo(String request) {
        return "Hello, " + request + "!";
    }
}

Any number of modules can be added to your project, adjacent to each other.

Start the FTL cluster

VSCode

If using VSCode, opening the directory will prompt you to start FTL:

VSCode

Manually

Alternatively start the local FTL development cluster from the command-line:

ftl dev

This will build and deploy all local modules. Modifying the code will cause ftl dev to rebuild and redeploy the module.

Open the console

FTL has a console that allows interaction with the cluster topology, logs, traces, and more. Open a browser window at https://localhost:8892 to view it:

FTL Console

Call your verb

You can call verbs from the console:

console call

Or from a terminal use ftl call to call your verb:

ftl call

Create another module

Create another module and call alice.echo from it with by importing the alice module and adding the verb client, alice.EchoClient, to the signature of the calling verb. It can be invoked as a function:

//ftl:verb
import "ftl/alice"

//ftl:verb
func Other(ctx context.Context, in Request, ec alice.EchoClient) (Response, error) {
    out, err := ec(ctx, alice.EchoRequest{...})
	...
}
package com.example

import xyz.block.ftl.Export
import xyz.block.ftl.Verb
import ftl.alice.EchoClient


@Export
@Verb
fun other(req: String, echo: EchoClient): String = "Hello from Other , ${echo.call(req)}!"

Note that the EchoClient is generated by FTL and must be imported. Unfortunately at the moment JVM based languages have a bit of a chicken-and-egg problem with the generated clients. To force a dependency between the modules you need to add an import on a class that does not exist yet, and then FTL will generate the client for you. This will be fixed in the future.

package com.example.client;

import xyz.block.ftl.Export;
import xyz.block.ftl.Verb;
import ftl.alice.EchoClient;

public class OtherVerb {

    @Export
    @Verb
    public String other(String request, EchoClient echoClient) {
        return "Hello, " + echoClient.call(request) + "!";
    }
}

Note that the EchoClient is generated by FTL and must be imported. Unfortunately at the moment JVM based languages have a bit of a chicken-and-egg problem with the generated clients. To force a dependency between the modules you need to add an import on a class that does not exist yet, and then FTL will generate the client for you. This will be fixed in the future.

What next?

Explore the reference documentation.