Farcaster Editor
A fully featured, performant, and open source Cast creator for your React app.
Why should you use this and not build your own cast creator?
- We've spent over 100 hours on this open source library to get it just right for your Farcaster app.
- It supports: @ mentions, channels, link highlighting & automatic embeds, image, url and video embeds, max lengths in bytes, open graph previews, textcuts
- You can easily use Mods that allow users to add Rich Embeds like image uploads, video uploads or choosing a GIF.
- It's open source (opens in a new tab), MIT licensed and designed to put you in full control - you choose which if any Mods you want to use with it.
- You can and are free to use this even if you aren't integrating Mod - it doesn't depend on any of Mod's core SDKs.
- It's lightweight, treeshakeable and performant, built on tiptap and prosemirror. It's extendable with your own Mods or tiptap plugins if you'd like.
- It's unopinionated about UI and works with your UI library
Usage
import { useEditor, EditorContent } from "@mod-protocol/react-editor";
import { EmbedsEditor } from "@mod-protocol/react-ui-shadcn/dist/lib/embeds";
import { Embed, ModManifest, fetchUrlMetadata, handleAddEmbed, handleOpenFile, handleSetInput } from "@mod-protocol/core";
import { Channel, getFarcasterChannels, getFarcasterMentions } from "@mod-protocol/farcaster";
import { MentionList } from "@mod-protocol/react-ui-shadcn/dist/components/mention-list";
import { ChannelList } from "@mod-protocol/react-ui-shadcn/dist/components/channel-list";
// use our API_URL, self host our API, or use your own API.
const getUrlMetadata = fetchUrlMetadata(API_URL);
const getResults = getFarcasterMentions(API_URL);
const getChannels = getFarcasterChannels(API_URL);
// ...
const { editor, getEmbeds, setEmbeds, handleSubmit, getText, setChannel, getChannel } = useEditor({
fetchUrlMetadata: getUrlMetadata,
onError: (error) => console.error(error),
onSubmit: (cast) => console.log(cast), // submit to your hub
linkClassName: "text-blue-600",
renderChannelsSuggestionConfig: createRenderMentionsSuggestionConfig({
getResults: (query) => getChannels(query, true),
RenderList: ChannelList,
}),
renderMentionsSuggestionConfig: createRenderMentionsSuggestionConfig({
getResults: getResults,
RenderList: MentionList,
}),
});
return (
<>
<EditorContent
editor={editor}
autoFocus
className="w-full h-full min-h-[200px]"
/>
<EmbedsEditor embeds={getEmbeds()} setEmbeds={setEmbeds} />
<ChannelPicker
getChannels={getChannels}
onSelect={setChannel}
value={getChannel()}
/>
<CastLengthUIIndicator getText={getText} />
<Button type="submit">Cast</Button>
</>
);