# Hono on Cloudflare with SST

We are going to build an API with Hono, add an R2 bucket for file uploads, and deploy it using Cloudflare with SST.

Before you get started, [create your Cloudflare API token](https://sst.dev/docs/cloudflare/#credentials).

* * *

## 1. Create a project

Let’s start by creating our app.

```
mkdir my-hono-api && cd my-hono-api

npm init -y
```

* * *

#### Init SST

Now let’s initialize SST in our app.

```
npx sst@latest init

npm install
```

Select the defaults and pick **Cloudflare**. This’ll create a `sst.config.ts` file in your project root.

* * *

#### Set the Cloudflare credentials

Set the token and account ID in your shell or `.env` file.

```
export CLOUDFLARE_API_TOKEN=aaaaaaaa_aaaaaaaaaaaa_aaaaaaaa

export CLOUDFLARE_DEFAULT_ACCOUNT_ID=aaaaaaaa_aaaaaaaaaaaa_aaaaaaaa
```

* * *

## 2. Add a Worker

Let’s add a Worker. Update your `sst.config.ts`.

```
async run() {

const hono = new sst.cloudflare.Worker("Hono", {

url: true,

handler: "index.ts",

});

return {

api: hono.url,

};

}
```

We are enabling the Worker URL, so we can use it as our API.

* * *

## 3. Add an R2 Bucket

Let’s add an R2 bucket for file uploads. Update your `sst.config.ts`.

```
const bucket = new sst.cloudflare.Bucket("MyBucket");
```

Add this above the `Worker` component.

#### Link the bucket

Now, link the bucket to our Worker.

```
const hono = new sst.cloudflare.Worker("Hono", {

url: true,

link: [bucket],

handler: "index.ts",

});
```

* * *

## 4. Upload a file

We want the `/` route of our API to upload a file to the R2 bucket. Create an `index.ts` file and add the following.

```
const app = new Hono()

.put("/*", async (c) => {

const key = crypto.randomUUID();

await Resource.MyBucket.put(key, c.req.raw.body, {

httpMetadata: {

contentType: c.req.header("content-type"),

},

});

return c.text(`Object created with key: ${key}`);

});

export default app;
```

Add the imports.

```
import { Hono } from "hono";

import { Resource } from "sst";
```

And install the npm packages.

```
npm install hono
```

* * *

## 5. Download a file

We want to download the last uploaded file if you make a `GET` request to the API. Add this to your routes in `index.ts`.

```
const app = new Hono()

// ...

.get("/", async (c) => {

const first = await Resource.MyBucket.list().then(

(res) =>

res.objects.sort(

(a, b) => a.uploaded.getTime() - b.uploaded.getTime(),

)[0],

);

const result = await Resource.MyBucket.get(first.key);

c.header("content-type", result.httpMetadata.contentType);

return c.body(result.body);

});
```

We are getting a list of the files in the files in the bucket with `Resource.MyBucket.list()` and we are getting a file for the given key with `Resource.MyBucket.get()`.

* * *

#### Start dev mode

Start your app in dev mode.

```
npx sst dev
```

This will give you the URL of your API.

```
✓  Complete

Hono: https://my-hono-api-jayair-honoscript.sst-15d.workers.dev
```

* * *

#### Test your app

Let’s try uploading a file from your project root. Make sure to use your API URL.

```
curl -X PUT --upload-file package.json https://my-hono-api-jayair-honoscript.sst-15d.workers.dev
```

Now head over to `https://my-hono-api-jayair-honoscript.sst-15d.workers.dev` in your browser and it’ll load the file you just uploaded.

* * *

## 6. Deploy your app

Finally, let’s deploy your app!

```
npx sst deploy --stage production
```

You can use any stage name here but it’s good to create a new stage for production.
