Post an Image on Lens

This tutorial will show you how to post an image on Lens leveraging Lens Storage Nodes.


You MUST be authenticated as Account Owner or Account Manager to post content on Lens.

1

Create a Form

First, start by defining a form that allows users to upload an image file and a text.

index.html
<form id="post-form">  <label for="image">Image file:</label>  <input type="file" name="image" accept="image/png" multiple />
  <label for="content">Post content:</label>  <textarea name="content" row="3"></textarea>
  <button type="submit">Post</button></form>

With an event listener to handle the form submission.

index.ts
document.getElementById("post-form").addEventListener("submit", onSubmit);
async function onSubmit(event: SubmitEvent) {  // prevent the full page reload of a typical form submission  event.preventDefault();
  const input = event.currentTarget.elements["image"];  const textarea = event.currentTarget.elements["content"];
  // …}

2

Create and Upload the Post Metadata

Next, create an instance of the Lens StorageClient.

storage.ts
import { StorageClient, testnet } from "@lens-protocol/storage-node-client";
export const storageClient = StorageClient.create(testnet);

And upload the image and post content altogether as a single folder with the Post Metadata object as index file.

index.ts
import type { Resource } from "@lens-protocol/storage-node-client";import { image, MediaImageMimeType } from "@lens-protocol/metadata";import { storageClient } from "./storage";
// …
async function onSubmit(event: SubmitEvent) {  // …
  const { folder, files } = await storage.uploadFolder(input.files, {    index: (resources: Resource[]) =>      image({        content: textarea.value,        image: {          item: resources[0].uri,          type: MediaImageMimeType.PNG,        },      }),  });
  // …}

As we didn't provide an acl option to the uploadFolder method, the folder will be immutable. See the Uploading Content guide for more information on ACL templates.

3

Submit On-Chain

Import the post action from the @lens-protocol/client package:

import { post } from "@lens-protocol/client/actions";

and the adapter for the library of your choice:

import { handleWith } from "@lens-protocol/client/viem";

Then, using the the folder.uri from the previous step, submit the post on-chain.

const result = await post(sessionClient, { contentUri: "<folder.uri>"" })  .andThen(handleWith(wallet));

The Lens SDK example here leverages a functional approach to chaining operations using the Result<T, E> object. See the Error Handling guide for more information.

4

Wait for the Transaction to Complete

Then, handle the result as explained in the Transaction Lifecycle guide.

Use the sessionClient.waitForTransaction method to poll the transaction status until it is mined.

const result = await post(sessionClient, { contentUri: "<folder.uri>" })  .andThen(handleWith(wallet));  .andThen(sessionClient.waitForTransaction);

5

Fetch the Post

Finally, fetch the newly created post.

Use the fetchPost action to fetch the post by its transaction hash.

import { fetchPost } from "@lens-protocol/client/actions";
// …
const result = await post(sessionClient, { contentUri: "<folder.uri>" })  .andThen(handleWith(wallet));  .andThen(sessionClient.waitForTransaction)  .andThen((txHash) => fetchPost(sessionClient, { txHash }));
if (result.isOk()) {  console.log(result.value); // { id: "42", … }}

That's it! You have successfully posted an image on Lens.