Develop a Spin application

This article briefly describes how to create a new Spin application. For a more thorough guide to developing Spin applications, take a look here.

Prerequisites - Install the Spin CLI

Before developing a Spin application, you need to have the Spin CLI installed locally. Here’s a way to install the Spin CLI:

Install Spin

Download the spin binary using the install.sh script hosted on this site:

$ curl -fsSL https://developer.fermyon.com/downloads/install.sh | bash

Then move the spin binary somewhere in your path, so you can run it from anywhere. For example:

$ sudo mv ./spin /usr/local/bin/spin

Download the spin binary using the install.sh script hosted on this site:

$ curl -fsSL https://developer.fermyon.com/downloads/install.sh | bash

Then move the spin binary somewhere in your path, so you can run it from anywhere. For example:

$ sudo mv ./spin /usr/local/bin/spin

Download the Windows binary release of Spin from GitHub.

Unzip the binary release and place the spin.exe in your system path.

Install the Prerequisites

Install a Template

The quickest and most convenient way to start a new application is to use a Spin template. Let’s install the templates for your preferred language.

$ spin templates install --git https://github.com/fermyon/spin --update
Copying remote template source
Installing template redis-rust...
Installing template http-rust...
... other templates omitted ...
+------------------------------------------------------------------------+
| Name                Description                                        |
+========================================================================+
| ... other templates omitted ...                                        |
| http-rust           HTTP request handler using Rust                    |
| redis-rust          Redis message handler using Rust                   |
| ... other templates omitted ...                                        |
+------------------------------------------------------------------------+

Note: The Rust templates are in a repo that contains several other languages; they will all be installed together.

$ spin templates install --git https://github.com/fermyon/spin-js-sdk --update
Copying remote template source
Installing template http-js...
Installing template http-ts...
+------------------------------------------------------------------------+
| Name                Description                                        |
+========================================================================+
| http-js             HTTP request handler using Javascript              |
| http-ts             HTTP request handler using Typescript              |
+------------------------------------------------------------------------+

Ensure that you have Python 3.10 or later installed on your system. You can check your Python version by running:

python3 --version

If you do not have Python 3.10 or later, you can install it by following the instructions here.

$ spin templates install --git https://github.com/fermyon/spin-python-sdk --update
Copying remote template source
Installing template http-py...
+---------------------------------------------+
| Name      Description                       |
+=============================================+
| http-py   HTTP request handler using Python |
+---------------------------------------------+
$ spin templates install --git https://github.com/fermyon/spin --update
Copying remote template source
Installing template redis-go...
Installing template http-go...
+------------------------------------------------------------------------+
| Name                Description                                        |
+========================================================================+
| ... other templates omitted ...                                        |
| http-go             HTTP request handler using (Tiny)Go                |
| redis-go            Redis message handler using (Tiny)Go               |
| ... other templates omitted ...                                        |
+------------------------------------------------------------------------+

Note: The Go templates are in a repo that contains several other languages; they will all be installed together.

Additional info

If you already have templates installed, you can update them by running spin templates install --git https://github.com/fermyon/spin --update.

Install the Tools

Some languages require additional tool support for Wasm.

You’ll need the wasm32-wasi target for Rust:

$ rustup target add wasm32-wasi

Learn more in the language guide.

You’ll need the Spin js2wasm plugin:

$ spin plugins update
$ spin plugins install js2wasm --yes

Learn more in the language guide.

Historic: You may have seen a py2wasm plugin in your travels. Please note, py2wasm has since been replaced by componentize-py.

The process of getting your system ready to write Wasm-powered Python applications, using componentize-py is as follows:

# As shown above, we install the Python SDK (which provides us with Spin's http-py template)
$ spin templates install --git https://github.com/fermyon/spin-python-sdk --update

Once we have the Spin template(s) from the spin-python-sdk repository we can scaffold out a new app. For this example, we will be using the http-py template. The scaffolded app, that the http-py template creates, has a requirements.txt file that facilitates the installation of spin-sdk and componentize-py. While you could manually install these using Pip, the requirements.txt file has the appropriate version numbers set making the process quicker and also more robust. Let’s create a new Spin app and install the contents of requirements.txt:

# We then create our app using http-py
$ spin new -t http-py hello-python --accept-defaults

Once the component is created, we can change into the hello-python directory, create and activate a virtual environment and then install the component’s requirements:

# Change into the app directory
$ cd hello-python

Create a virtual environment directory (we are still inside the Spin app directory):

# python<version> -m venv <virtual-environment-name>
$ python3 -m venv venv-dir

Activate the virtual environment (this command depends on which operating system you are using):

# macOS & Linux command to activate
$ source venv-dir/bin/activate

If you are using Windows, use the following commands:

C:\Work> python3 -m venv venv
C:\Work> venv\Scripts\activate

The (venv-dir) will prefix your terminal prompt now:

(venv-dir) user@123-456-7-8 hello-python %

The requirements.txt, by default, contains the references to the spin-sdk and componentize-py packages. These can be installed in your virtual environment using the following command:

# Now we can install Componentize-Py and the Spin SDK via the requirements file
$ pip3 install -r requirements.txt 

From here the app is ready to build and run:

$ spin build --up

Learn more in the language guide.

You’ll need the TinyGo compiler, as the standard Go compiler does not yet support the WASI standard. See the TinyGo installation guide.

Learn more in the language guide.

Create a New Spin Application From a Template

Now you can create your very own application based on one of the templates you just installed. For this example, we’ll show how to create a HTTP application.

Use the spin new command and the http-rust template to scaffold a new Spin application:

$ spin new
Pick a template to start your application with:
  http-c (HTTP request handler using C and the Zig toolchain)
  http-csharp (HTTP request handler using C# (EXPERIMENTAL))
  http-go (HTTP request handler using (Tiny)Go)
  http-grain (HTTP request handler using Grain)
> http-rust (HTTP request handler using Rust)
  http-swift (HTTP request handler using SwiftWasm)
  http-zig (HTTP request handler using Zig)
  redis-go (Redis message handler using (Tiny)Go)
  redis-rust (Redis message handler using Rust)

Enter a name for your new application: hello_rust
Description: My first Rust Spin application
HTTP path: /...

This command created a directory with the necessary files needed to build and run a Rust Spin application. Here’s the spin.toml file, the manifest for a Spin application:

spin_manifest_version = 2

[application]
name = "hello_rust"
version = "0.1.0"
authors = ["Your Name <your-name@example.com>"]
description = "My first Rust Spin application"

[[trigger.http]]
route = "/..."
component = "hello-rust"

[component.hello-rust]
source = "target/wasm32-wasi/release/hello_rust.wasm"
allow_outbound_hosts = []
[component.hello-rust.build]
command = "cargo build --target wasm32-wasi --release"
watch = ["src/**/*.rs", "Cargo.toml"]

Use the spin new command and the http-ts template to scaffold a new Spin application. (If you prefer JavaScript to TypeScript, the http-js template is very similar.)

$ spin new
Pick a template to start your application with:
  http-js (HTTP request handler using Javascript)
> http-ts (HTTP request handler using Typescript)
Enter a name for your new application: hello_typescript
Description: My first TypeScript Spin application
HTTP path: /...

This command created a directory with the necessary files needed to build and run a TypeScript Spin application. Here’s the spin.toml file, the manifest for a Spin application:

spin_manifest_version = 2

[application]
authors = ["Your Name <your-name@example.com>"]
description = "My first TypeScript Spin application"
name = "hello_typescript"
version = "0.1.0"

[[trigger.http]]
route = "/..."
component = "hello-typescript"

[component.hello-typescript]
source = "target/hello-typescript.wasm"
exclude_files = ["**/node_modules"]
[component.hello-typescript.build]
command = "npm run build"

Use the spin new command and the http-py template to scaffold a new Spin application:

$ spin new
Pick a template to start your application with:
> http-py (HTTP request handler using Python)
Enter a name for your new application: hello-python
Description: My first Python Spin application
HTTP path: /...

This command created a directory with the necessary files needed to build and run a Python Spin application. Here’s the spin.toml file, the manifest for a Spin application:

spin_manifest_version = 2

[application]
authors = ["Your Name <your-name@example.com>"]
description = "My first Python Spin application"
name = "hello-python"
version = "0.1.0"

[[trigger.http]]
route = "/..."
component = "hello-python"

[component.hello-python]
source = "app.wasm"
[component.hello-python.build]
command = "componentize-py -w spin-http componentize app -o app.wasm"
watch = ["*.py", "requirements.txt"]

Use the spin new command and the http-go template to scaffold a new Spin application:

$ spin new
Pick a template to start your application with:
  http-c (HTTP request handler using C and the Zig toolchain)
  http-empty (HTTP application with no components)
> http-go (HTTP request handler using (Tiny)Go)
  http-grain (HTTP request handler using Grain)
  http-php (HTTP request handler using PHP)
  http-rust (HTTP request handler using Rust)
Enter a name for your new application: hello_go
Description: My first Go Spin application
HTTP path: /...

This command created a directory with the necessary files needed to build and run a Go Spin application using the TinyGo compiler. Here’s the spin.toml file, the manifest for a Spin application:

spin_manifest_version = 2

[application]
name = "hello_go"
version = "0.1.0"
authors = ["Your Name <your-name@example.com>"]
description = "My first Go Spin application"

[[trigger.http]]
route = "/..."
component = "hello-go"

[component.hello-go]
source = "main.wasm"
allow_outbound_hosts = []
[component.hello-go.build]
command = "tinygo build -target=wasi -gc=leaking -no-debug -o main.wasm main.go"
watch = ["**/*.go", "go.mod"]

Next, let’s build the app:

$ spin build
Building component hello-rust with `cargo build --target wasm32-wasi --release`
    Updating crates.io index
    Updating git repository `https://github.com/fermyon/spin`
   # ...
    Finished release [optimized] target(s) in 27.81s
Finished building all Spin components

If the build fails, check:

  • Are you in the hello_rust directory?
  • Did you successfully install the wasm32-wasi target?
  • Is your version of Rust up to date (cargo --version)? The Spin SDK needs Rust 1.64 or above.

As normal for NPM projects, before you build for the first time, you must run npm install:

$ npm install

added 141 packages, and audited 142 packages in 10s

20 packages are looking for funding
  run `npm fund` for details

found 0 vulnerabilities

Then run spin build:

$ spin build
Building component hello-typescript with `npm run build`

> hello-typescript@1.0.0 build
> npx webpack --mode=production && mkdir -p target && spin js2wasm -o target/hello-typescript.wasm dist/spin.js
  # ...
Starting to build Spin compatible module
Preinitiating using Wizer
Optimizing wasm binary using wasm-opt
Spin compatible module built successfully
Finished building all Spin components

If the build fails, check:

  • Are you in the hello_typescript directory?
  • Did you run npm install before building`?
  • Did you install the js2wasm plugin?
$ spin build
Building component hello-python with `componentize-py -w spin-http componentize app -o app.wasm`
Component built successfully
Finished building all Spin components

If the build fails, check:

  • Are you in the hello-python directory?
  • Did you install the requirements?
  • Is your virtual environment still activated?
$ spin build 
Building component hello-go with `tinygo build -target=wasi -gc=leaking -no-debug -o main.wasm main.go`
Finished building all Spin components

If the build fails, check:

  • Are you in the hello_go directory?
  • Did you successfully install TinyGo?
  • Are your versions of Go and TinyGo up to date? The Spin SDK needs TinyGo 0.27 or above.

Run the Application

Now it’s time to spin up the application:

$ spin up
Logging component stdio to ".spin/logs/"

Serving http://127.0.0.1:3000
Available Routes:
  hello-rust: http://127.0.0.1:3000 (wildcard)
Additional info

Spin prints application output, and any Spin errors, to the console. To see additional diagnostic information, set the RUST_LOG environment variable for detailed logs, before running spin up, e.g., RUST_LOG=spin=debug spin up.

Spin will instantiate all components from the application manifest, and will create the router configuration for the HTTP trigger accordingly. The component can now be invoked by making requests to http://localhost:3000:

$ curl -i localhost:3000
HTTP/1.1 200 OK
content-type: text/plain
transfer-encoding: chunked
date: Thu, 02 Nov 2023 02:08:31 GMT

Hello, Fermyon

Next Steps