Smart Media is represented in the eliza server as an object stored in redis & mongo, and is linked to a published Lens post. It essentially extends a post with dynamic logic and functionality.
export type SmartMediaBase = {
agentId: UUID; // uuid
creator: `0x${string}`; // lens account
template: TemplateName;
category: TemplateCategory;
createdAt: number; // unix ts
updatedAt: number; // unix ts
templateData?: unknown; // specific data needed per template
}
export type LaunchpadToken = {
chain: LaunchpadChain; // base | lens
address: `0x${string}`;
}
export type SmartMedia = SmartMediaBase & {
postId: string; // lens post id; will be null for previews
maxStaleTime: number; // seconds
uri: URI; // lens storage node uri
token?: LaunchpadToken; // optional associated token
versions?: [string]; // versions of uri; only present in the db
};
Each smart media is created from a template, which defines how it should update, evolve, and potentially respond to changes in its social graph. Templates are defined in src/templates/ and adhere to this interface:
/**
* Represents a Smart Media template
*/
export interface Template {
/** Handler function */
handler: TemplateHandler;
/** Client metadata */
clientMetadata: TemplateClientMetadata;
}
/**
* Handler function for generating new metadata for a Smart Media post
*/
export type TemplateHandler = (
runtime: IAgentRuntime,
media?: SmartMedia,
templateData?: unknown,
) => Promise<TemplateHandlerResponse | null>;
/**
* Handler response where one of preview or metadata must be present
*/
export interface TemplateHandlerResponse {
preview?: { // not necessary for all templates
text: string;
image?: string; // base64
video?: string,
};
metadata?: TextOnlyMetadata | ImageMetadata | VideoMetadata; // only undefined on failure or generating preview
updatedUri?: string, // in case the handler wants versioning on the media
updatedTemplateData?: unknown, // updated payload for the next generation
totalUsage?: TemplateUsage,
}
/**
* Client metadata to faciliate the creation and configuration
*/
export type TemplateClientMetadata = {
category: TemplateCategory;
name: TemplateName;
/** Display info */
displayName: string;
description: string;
image: string;
/** Form data */
options: {
allowPreview?: boolean;
allowPreviousToken?: boolean;
requireImage?: boolean;
requireContent?: boolean;
};
templateData: {
form: z.ZodObject<any>;
};
/** Developer fee recipient: https://docs.bonsai.meme/elizaos/client-bonsai/developer-fees */
protocolFeeRecipient: `0x${string}`;
};
HTML Canvas Templates
You can enable a post to have an embedded iframe for interactive content. The iframe will have minimum dimensions of 600px by 600px.
Set clientMetadata.options.isCanvas to true
In your handler set an HTML string as the canvas key on a piece of smart media and save it to redis/mongo
The Bonsai app will read the metadata options and set the canvas attribute as true on the post metadata and then when you go to the post page it will automatically fetch https://{your-server-url}/post/:postId/canvas as the iframe url.
Template Examples
We've built two examples of smart media templates that showcase how a post can evolve based on social graph interactions and onchain data.
Adventure Time
Choose your own adventure. Creator sets the context and inits the post with the first page. Weighted comments / upvotes decide the direction of the story.
Artist is Present
The artist is present in the evolving art. Creator sets the original image and style. The comment with the most votes dictates how the image evolves.