๐ชฟ Register for November's HONCathon here - ship apps, win prizes - sponsored by Cloudflare, Drizzle, Fiberplane, and Neon
Recently we needed some example apps to showcase how to build a HONC app with Fiberplane Studio for our November Honcathon, so I decided to build Honcanator: The AI goose generator.
The example app is pretty simple and uses a standard HONC setup (Hono, Drizzle, Neon, and Cloudflare Workers).
To create and store images, we also needed to use two Cloudflare services:
- Cloudflare R2 as object storage (like AWS S3)
- Cloudflare AI to generate images
Let's take a quick look at how I've built this app.
Configuring the basics
In order to use Cloudflare services like R2 and AI, we have to configure some additional Cloudflare bindings in our Worker.
That is as simple as editing the wrangler.toml
:
name = "honc-neon-template"
compatibility_date = "2024-10-28"
compatibility_flags = [ "nodejs_compat" ]
[observability]
enabled = true
[[r2_buckets]]
binding = "R2_BUCKET"
bucket_name = "geese"
[ai]
binding = "AI"
Then we can add it to our bindings in Hono:
type Bindings = {
DATABASE_URL: string;
R2_BUCKET: R2Bucket;
AI: Ai;
};
The R2Bucket
and Ai
types are Cloudflare special types which will give you a typed interface for interacting with these services.
Routes
The majority of our routes were simple CRUD routes which simply query the database and return some stuff from it so I won't bore you with the boring part, lets get to the actual interesting route: The creation endpoint.
The first few lines of the POST /api/geese/:name
route are simply a check to see whenever a goose with that name already exists.
app.get("/api/geese/:name", async (c) => {
const { name } = c.req.param();
const sql = neon(c.env.DATABASE_URL);
const db = drizzle(sql);
const goose = await db.select().from(geese).where(eq(geese.name, name));
if (goose.length === 0) {
return c.json({ error: "doesnt_exist" }, 404);
}
//...
})
After those checks are done, we get to the really interesting part: Making geese!
Image generation
This is where Cloudflare really shines. Creating an image is as simple
as three lines of code:
const model = "@cf/black-forest-labs/flux-1-schnell" as BaseAiTextToImageModels;
const prompt = `Please generate a image of a goose. Its name is ${name}. Make it in the style of comic or anime please`;
const response = await c.env.AI.run(model, {
prompt,
});
The list of models available on Cloudflare AI can be found here. The list of image
generation models is pretty small at the moment, there is currently a few Stable Diffusion models and Flux-1-Schnell model, which we are using in this example.
The response from the AI call comes back as a base64 encoded string, so we'll use the built-in Node.js Buffer
to get something that we can work with:
const base64image = response.image;
const buffer = Buffer.from(base64image, "base64");
โ ๏ธ Note: Cloudflare Workers's types are a little funky at the moment for AI models, so the code above might show a red squiggly error line in your IDE. The issue is being tracked here.
Saving to object storage
With our generated image now available to us as a Buffer
, putting it into R2 is as simple as writing one line of code:
await c.env.R2_BUCKET.put(`${name}.png`, buffer);
This shows how powerful the Hono bindings for Cloudflare are, we have just generated an image and stored it in object storage with like 6 lines of code.
Retrieving it is as simple as:
const image = await c.env.R2_BUCKET.get(`${name}.png`);
which comes in handy for our GET /api/geese/:name
route.
Using Fiberplane Studio, we can inspect the generated image for any of our geese and see a trace of the request, with the Neon database call and the call to R2, in the timeline.
Parting words
In conclusion, making a small app which generates images and stores them in object storage and a database really is no big feat with the HONC stack, which means you'll be able to build powerful goose-themed apps in no time.
To wrap things up, the code for everything discussed in this blog post can be found on GitHub, available for you to adapt and build upon how you wish:
Top comments (1)
This sounds like such a fun project! The way you're using Cloudflare services like R2 and AI to generate and store images is clever. If you're exploring hosting options, Cloudways offers a solid managed service that works well with cloud platforms like Cloudflare. Vercel and DigitalOcean also provide great flexibility for building similar apps with quick deployments.