# null
Source: https://canvacord.neplex.dev/builders/builtin-builders
# null
Source: https://canvacord.neplex.dev/builders/introduction-to-builders
Builders provide a way to create complex images using React-like components API. Canvacord under the hood abstracts over [satori](https://github.com/vercel/satori), an enlightened library to convert HTML and CSS to SVG by providing JSX interface as well as rendering the SVG to other numerous formats like PNG, JPEG, WEBP, etc. This makes it possible to create complex images with little to no configuration.
## Anatomy of a Builder
A builder is a class that extends the `Builder` class exported by Canvacord. This class contains all the complex logic behind rendering the jsx.
```tsx TypeScript
import { JSX, Builder } from "canvacord";
// Options for the builder
interface Props {
message: string;
}
class MyBuilder extends Builder {
public constructor() {
// The super constructor takes the width and height of the output image
super(500, 500);
}
public setMessage(value: string) {
// The set method is used to set the value of a property
this.options.set("message", value);
return this;
}
// The render method is where the JSX is rendered
public async render() {
const message = this.options.get("message");
// You can render any component you want
// this markup describes the shape/content of output image
return {message}
;
}
}
```
```jsx ES Modules
import { JSX, Builder } from "canvacord";
class MyBuilder extends Builder {
constructor() {
// The super constructor takes the width and height of the output image
super(500, 500);
}
setMessage(value) {
// The set method is used to set the value of a property
this.options.set("message", value);
return this;
}
// The render method is where the JSX is rendered
async render() {
const message = this.options.get("message");
// You can render any component you want
// this markup describes the shape/content of output image
return {message}
;
}
}
```
```jsx CommonJS
const { JSX, Builder } = require("canvacord");
class MyBuilder extends Builder {
constructor() {
// The super constructor takes the width and height of the output image
super(500, 500);
}
setMessage(value) {
// The set method is used to set the value of a property
this.options.set("message", value);
return this;
}
// The render method is where the JSX is rendered
async render() {
const message = this.options.get("message");
// You can render any component you want
// this markup describes the shape/content of output image
return {message}
;
}
}
```
**Good to know:** Rendering a text requires you to register at least one font.
## Usage
```tsx
// Create an instance of the builder
const builder = new MyBuilder()
// Set the message property
.setMessage("Hello, World!");
// Render the builder into image
const result = await builder.build();
// ^ result is by default a png buffer
```
# JSX Syntax
Source: https://canvacord.neplex.dev/builders/jsx-syntax
Learn how to use JSX syntax with Canvacord.
JSX is a syntax extension for JavaScript that looks similar to HTML. It allows you to write HTML-like code in your JavaScript files. If you're familiar with React, you'll feel right at home with JSX. A basic example of JSX syntax is shown below:
```jsx
const message =
Hello, world!
;
// ^^^^^^^^^^^^^^^^^^^^^^ JSX syntax
```
Notice how we are not using strings to define the HTML elements. Instead, we are using a syntax that looks like HTML.
## But this is not a valid JavaScript syntax!
You are right! JSX is not a valid JavaScript syntax. It needs to be transformed into a valid JavaScript syntax before it can be executed by the JavaScript engine. This is where the transpiler comes into play. The transpiler is a tool that converts magical stuff, including the JSX syntax into the equivalent JavaScript code. Some of the most popular transpilers for JSX are [Babel](https://babeljs.io/), [TypeScript](https://www.typescriptlang.org/), [SWC](https://swc.rs/), [esbuild](https://esbuild.github.io/), etc.
If you are TypeScript user, you dont even need to add anything else to your
project, just use the `@jsx` pragma and you are good to go.
## The JSX pragma
The JSX pragma is a comment that tells the transpiler how to transform JSX into the equivalent JavaScript code. The pragma is used to define the function that will be called when the JSX syntax is encountered. The pragma is defined at the top of the file and is usually in the form of a comment.
```js
/** @jsx JSX.createElement */
/** @jsxFrag JSX.Fragment */
```
The above pragma comment tells the transpiler to use the `JSX.createElement` function to transform the JSX syntax into the equivalent JavaScript code. The `JSX.Fragment` is used to wrap multiple elements in a single parent element. These functions are exported by `canvacord` as `JSX` namespace.
## TypeScript global JSX pragma
You can also set the pragma globally in your project by adding the following to your `tsconfig.json` file:
```json tsconfig.json
{
"compilerOptions": {
"jsx": "react", // Canvacord uses React-like JSX
"jsxFactory": "JSX.createElement", // works as @jsx
"jsxFragmentFactory": "JSX.Fragment" // works as @jsxFrag
}
}
```
## Don't want to/Can't use JSX?
If you don't want to use JSX or can't use JSX in your project, you can still use Canvacord. Canvacord provides a way to create images without using JSX. You can use the `Builder` class to create images without using JSX. The `Builder` class provides a way to create images using a more traditional approach.
### Element object
You can return element object from the render method as an alternative approach to JSX.
```js
async render() {
return {
type: 'h1',
props: {
children: 'hello, world',
},
};
}
```
### Calling JSX function
You can also call the JSX function directly to create elements.
```js
async render() {
return JSX.createElement('h1', {}, 'hello, world');
}
```
## Using JSX with Canvacord
```tsx TypeScript
/** @jsx JSX.createElement */
/** @jsxFrag JSX.Fragment */
import { JSX } from "canvacord";
const message = Hello, world!
;
```
```jsx ES Modules
/** @jsx JSX.createElement */
/** @jsxFrag JSX.Fragment */
import { JSX } from "canvacord";
const message = Hello, world!
;
```
```jsx CommonJS
/** @jsx JSX.createElement */
/** @jsxFrag JSX.Fragment */
const { JSX } = require("canvacord");
const message = Hello, world!
;
```
```tsx TypeScript
/** @jsx JSX.createElement */
/** @jsxFrag JSX.Fragment */
import { JSX } from "canvacord";
const message = Hello, world!
;
```
```jsx ES Modules
/** @jsx JSX.createElement */
/** @jsxFrag JSX.Fragment */
import { JSX } from "canvacord";
const message = Hello, world!
;
```
```jsx CommonJS
/** @jsx JSX.createElement */
/** @jsxFrag JSX.Fragment */
const { JSX } = require("canvacord");
const message = Hello, world!
;
```
# Leaderboard Builder
Source: https://canvacord.neplex.dev/builders/leaderboardbuilder
A builtin builder to create leaderboard images.
This page is a work in progress.
Leaderboard builder is another builtin builder provided by Canvacord to create leaderboard images. It is useful for creating leaderboards for games, servers, or any other application where you need to display a list of players with their ranks, levels, and experience points.
## API Documentation
Refer to [https://canvacord.js.org](https://canvacord.js.org/docs/canvacord/class/LeaderboardBuilder) for the complete API documentation. In the following sections, we will only cover the most common use cases.
## Let's get started
### Leaderboard image generation
```js ES Modules
import { Font, LeaderboardBuilder } from "canvacord";
// load font
Font.loadDefault();
// generate image
const lb = new LeaderboardBuilder()
// set title, image and subtitle
.setHeader({
title: "NeplexLabs",
image: "https://github.com/neplextech.png",
subtitle: "3258 members",
})
// set players, usually you would get this from a database but for this example we will hardcode it
.setPlayers([
{
avatar: "https://github.com/twlite.png",
username: "twlite",
displayName: "Archaeopteryx",
level: 32,
xp: 2420,
rank: 1,
},
{
avatar: "https://github.com/notunderctrl.png",
username: "avrajs",
displayName: "Avraj",
level: 30,
xp: 2390,
rank: 2,
},
{
avatar: "https://github.com/insypher.png",
username: "insypher01",
displayName: "insypher",
level: 29,
xp: 2280,
rank: 3,
},
{
avatar: "https://github.com/insypher.png",
username: "com6235",
displayName: "CatGPT",
level: 24,
xp: 2280,
rank: 5,
},
// ...
])
.setBackground("./my-background-image.jpg");
// changing variant
lb.setVariant("horizontal");
// or
lb.setVariant("default");
const image = await lb.build({ format: "png" });
```
```js CommonJS
const { Font, LeaderboardBuilder } = require("canvacord");
// load font
Font.loadDefault();
// generate image
const lb = new LeaderboardBuilder()
// set title, image and subtitle
.setHeader({
title: "NeplexLabs",
image: "https://github.com/neplextech.png",
subtitle: "3258 members",
})
// set players, usually you would get this from a database but for this example we will hardcode it
.setPlayers([
{
avatar: "https://github.com/twlite.png",
username: "twlite",
displayName: "Archaeopteryx",
level: 32,
xp: 2420,
rank: 1,
},
{
avatar: "https://github.com/notunderctrl.png",
username: "avrajs",
displayName: "Avraj",
level: 30,
xp: 2390,
rank: 2,
},
{
avatar: "https://github.com/insypher.png",
username: "insypher01",
displayName: "insypher",
level: 29,
xp: 2280,
rank: 3,
},
{
avatar: "https://github.com/insypher.png",
username: "com6235",
displayName: "CatGPT",
level: 24,
xp: 2280,
rank: 5,
},
// ...
])
.setBackground("./my-background-image.jpg");
// changing variant
lb.setVariant("horizontal");
// or
lb.setVariant("default");
const image = await lb.build({ format: "png" });
```
Canvacord automatically adjusts the size of the output image based on the number of players. Maximum number of players is 10, but recommended size is 8 players or less.
# Output
### Default variant

### Horizontal variant

# Rank Card Builder
Source: https://canvacord.neplex.dev/builders/rankcardbuilder
A builtin builder to create rank cards.
This page is a work in progress.
Rank card creation has been the most common use case for Canvacord to this date. Canvacord provides a `RankCardBuilder` class to create rank cards with ease. The `RankCardBuilder` class offers a lot of helper methods to customize the rank card to your liking.
## API Documentation
Refer to [https://canvacord.js.org](https://canvacord.js.org/docs/canvacord/class/RankCardBuilder) for the complete API documentation. In the following sections, we will only cover the most common use cases.
## Let's get started
### Importing the Required Classes
First, we need to import the `Font` and `RankCardBuilder` classes from the canvacord module.
```js ES Modules
import { Font, RankCardBuilder } from "canvacord";
```
```js CommonJS
const { Font, RankCardBuilder } = require("canvacord");
```
### Loading fonts
Canvacord does not load fonts by default. If your use case does not involve writing texts, this step can be omitted. However, rank cards require texts to be written on them, so we need to load the font into canvacord's font registry.
Canvacord by default ships with a font called [`Geist`](https://vercel.com/font?utm_source=canvacord\&utm_campaign=rank-card) (by [Vercel](https://vercel.com/?utm_source=canvacord\&utm_campaign=rank-card)). This font can be loaded with the `Font.loadDefault()` method:
```js
Font.loadDefault();
```
If you want to use a custom font instead, you can skip `Font.loadDefault()` method and utilize `Font.fromFile` or `Font.fromBuffer` method to load the font from a file or buffer respectively.
```js Load font from file
// synchronous method
Font.fromFileSync("./my-font.ttf");
// asynchronous method
await Font.fromFile("./my-font.ttf");
```
```js Load font from buffer
Font.fromBuffer(buffer);
```
**Good to know:** Currently only `TTF`, `OTF` and `WOFF` font formats are
supported.
### Creating a rank card builder
Now that we have loaded the font, we can create a new `RankCardBuilder` instance. This is a builder class exported by canvacord to specifically create rank cards. It offers a lot of helper methods to customize the rank card to your liking.
The following is an example of a rank card builder with common properties set:
```js
const card = new RankCardBuilder()
.setDisplayName("Wumpus") // Big name
.setUsername("@wumpus") // small name, do not include it if you want to hide it
.setAvatar("https://cdn.discordapp.com/embed/avatars/0.png?size=256") // user avatar
.setCurrentXP(300) // current xp
.setRequiredXP(600) // required xp
.setLevel(2) // user level
.setRank(5) // user rank
.setOverlay(90) // overlay percentage. Overlay is a semi-transparent layer on top of the background
.setBackground("#23272a") // set background color or,
.setBackground("./path/to/image.png") // set background image
.setStatus("online"); // user status. Omit this if you want to hide it
```
### Generating the image
```ts
const image = await card.build({
format: "png",
});
// image is a buffer. It can be written to a file or sent as an attachment over internet
```
### Result

## Advanced Usage
### Overriding default texts
The `setTextStyles` method is used to customize the text styles for different elements in a rank card or leaderboard. This method allows for the modification of default labels for level, experience points (XP), and rank display.
```js
card.setTextStyles({
level: "NIVEAU :", // Custom text for the level
xp: "EXP :", // Custom text for the experience points
rank: "CLASSEMENT :", // Custom text for the rank
});
```
### Result

### Customizing the colors
The `setStyles` method can be used to customize the colors of different elements in a rank card or leaderboard. This method allows for the modification of the background, progress bar, and text colors, etc. The style object is a key-value pair of the style name and the value to be set.
The style behaves similar to css properties.
#### Syntax 1 (Style object)
```scss
// Group of elements
ElementGroup {
// Element name
ElementName {
// Style object
style {
attribute-name: value;
}
}
}
```
#### Syntax 2 (Tailwind classes)
```scss
// Group of elements
ElementGroup {
// Element name
ElementName {
// Style object
tw = "tailwind-classes"
}
}
```
#### Examples
```js
// changing progress bar thumb color
card.setStyles({
progressbar: {
thumb: {
style: {
backgroundColor: "red",
},
},
},
});
// alternative syntax
card.setStyles({
progressbar: {
thumb: {
tw: "bg-red-500",
},
},
});
```
### Modifying progress bar width
The internal progress calculator may not be suitable for all use cases. You can set a custom progress calculator using the `setProgressCalculator` method. The progress calculator is a function that returns a number between 0 and 100, representing the progress percentage.
```js
card.setProgressCalculator((currentXP, requiredXP) => {
// do some crazy math here
// The value returned must be in the range of 0 to 100. It represents the width of the progress bar
return Math.floor((currentXP / requiredXP) * 100);
});
```
### Overriding emoji providers
Canvacord uses the `twemoji` provider by default. You can override this by using the `setGraphemeProvider` method. The `setGraphemeProvider` method accepts a `GraphemeProvider` enum value.
```js
// Twemoji
card.setGraphemeProvider(BuiltInGraphemeProvider.Twemoji);
// FluentEmojiHighContrast
card.setGraphemeProvider(BuiltInGraphemeProvider.FluentEmojiHighContrast);
// FluentEmoji
card.setGraphemeProvider(BuiltInGraphemeProvider.FluentEmoji);
// FluentEmojiColor
card.setGraphemeProvider(BuiltInGraphemeProvider.FluentEmojiColor);
// FluentEmojiFlat
card.setGraphemeProvider(BuiltInGraphemeProvider.FluentEmojiFlat);
// Openmoji
card.setGraphemeProvider(BuiltInGraphemeProvider.Openmoji);
// Noto
card.setGraphemeProvider(BuiltInGraphemeProvider.Noto);
// Blobmoji
card.setGraphemeProvider(BuiltInGraphemeProvider.Blobmoji);
// None
card.setGraphemeProvider(BuiltInGraphemeProvider.None);
```
# Analog Clock
Source: https://canvacord.neplex.dev/examples/builders/analog-clock
Create an analog clock with Canvacord.
This page is still a work in progress.
## Code
```ts TypeScript
import {} from "canvacord";
```
```js ES Modules
import {} from "canvacord";
```
```js CommonJS
const {} = require("canvacord");
```
## Usage
```ts TypeScript
import {} from "canvacord";
```
```js ES Modules
import {} from "canvacord";
```
```js CommonJS
const {} = require("canvacord");
```
## Result
# Discord Embed
Source: https://canvacord.neplex.dev/examples/builders/discord-embed
Dynamic Discord embed builder.
This page is still a work in progress.
## Code
```ts TypeScript
import {} from "canvacord";
```
```js ES Modules
import {} from "canvacord";
```
```js CommonJS
const {} = require("canvacord");
```
## Usage
```ts TypeScript
import {} from "canvacord";
```
```js ES Modules
import {} from "canvacord";
```
```js CommonJS
const {} = require("canvacord");
```
## Result
# Discord Profile (Large)
Source: https://canvacord.neplex.dev/examples/builders/discord-profile-large
Large version of the Discord Profile card.
This page is still a work in progress.
## Code
```ts TypeScript
import {} from "canvacord";
```
```js ES Modules
import {} from "canvacord";
```
```js CommonJS
const {} = require("canvacord");
```
## Usage
```ts TypeScript
import {} from "canvacord";
```
```js ES Modules
import {} from "canvacord";
```
```js CommonJS
const {} = require("canvacord");
```
## Result
# Discord Profile (Small)
Source: https://canvacord.neplex.dev/examples/builders/discord-profile-small
Small version of the Discord Profile card.
This page is still a work in progress.
## Code
```ts TypeScript
import {} from "canvacord";
```
```js ES Modules
import {} from "canvacord";
```
```js CommonJS
const {} = require("canvacord");
```
## Usage
```ts TypeScript
import {} from "canvacord";
```
```js ES Modules
import {} from "canvacord";
```
```js CommonJS
const {} = require("canvacord");
```
## Result
# Greetings Card
Source: https://canvacord.neplex.dev/examples/builders/greetings-card
Welcomer/Leaver cards with a custom background and text.
## Code
```tsx TypeScript
/** @jsx JSX.createElement */
/** @jsxFrag JSX.Fragment */
import { JSX, Builder, loadImage } from "canvacord";
interface Props {
displayName: string;
type: "welcome" | "goodbye";
avatar: string;
message: string;
}
export class GreetingsCard extends Builder {
constructor() {
super(930, 280);
this.bootstrap({
displayName: "",
type: "welcome",
avatar: "",
message: "",
});
}
setDisplayName(value: string) {
this.options.set("displayName", value);
return this;
}
setType(value: Props["type"]) {
this.options.set("type", value);
return this;
}
setAvatar(value: string) {
this.options.set("avatar", value);
return this;
}
setMessage(value: string) {
this.options.set("message", value);
return this;
}
async render() {
const { type, displayName, avatar, message } = this.options.getOptions();
const image = await loadImage(avatar);
return (
{type === "welcome" ? "Welcome" : "Goodbye"},{" "}
{displayName}!
{message}
);
}
}
```
```js ES Modules
import { JSX, Builder, loadImage } from "canvacord";
export class GreetingsCard extends Builder {
constructor() {
super(930, 280);
this.bootstrap({
displayName: "",
type: "welcome",
avatar: "",
message: "",
});
}
setDisplayName(value) {
this.options.set("displayName", value);
return this;
}
setType(value) {
this.options.set("type", value);
return this;
}
setAvatar(value) {
this.options.set("avatar", value);
return this;
}
setMessage(value) {
this.options.set("message", value);
return this;
}
async render() {
const { type, displayName, avatar, message } = this.options.getOptions();
const image = await loadImage(avatar);
return JSX.createElement(
"div",
{
className:
"h-full w-full flex flex-col items-center justify-center bg-[#23272A] rounded-xl",
},
JSX.createElement(
"div",
{
className:
"px-6 bg-[#2B2F35AA] w-[96%] h-[84%] rounded-lg flex items-center",
},
JSX.createElement("img", {
src: image.toDataURL(),
className: "flex h-[40] w-[40] rounded-full",
}),
JSX.createElement(
"div",
{ className: "flex flex-col ml-6" },
JSX.createElement(
"h1",
{ className: "text-5xl text-white font-bold m-0" },
type === "welcome" ? "Welcome" : "Goodbye",
",",
" ",
JSX.createElement(
"span",
{ className: "text-blue-500" },
displayName,
"!"
)
),
JSX.createElement(
"p",
{ className: "text-gray-300 text-3xl m-0" },
message
)
)
)
);
}
}
```
```js CommonJS
const { JSX, Builder, loadImage } = require("canvacord");
class GreetingsCard extends Builder {
constructor() {
super(930, 280);
this.bootstrap({
displayName: "",
type: "welcome",
avatar: "",
message: "",
});
}
setDisplayName(value) {
this.options.set("displayName", value);
return this;
}
setType(value) {
this.options.set("type", value);
return this;
}
setAvatar(value) {
this.options.set("avatar", value);
return this;
}
setMessage(value) {
this.options.set("message", value);
return this;
}
async render() {
const { type, displayName, avatar, message } = this.options.getOptions();
const image = await loadImage(avatar);
return JSX.createElement(
"div",
{
className:
"h-full w-full flex flex-col items-center justify-center bg-[#23272A] rounded-xl",
},
JSX.createElement(
"div",
{
className:
"px-6 bg-[#2B2F35AA] w-[96%] h-[84%] rounded-lg flex items-center",
},
JSX.createElement("img", {
src: image.toDataURL(),
className: "flex h-[40] w-[40] rounded-full",
}),
JSX.createElement(
"div",
{ className: "flex flex-col ml-6" },
JSX.createElement(
"h1",
{ className: "text-5xl text-white font-bold m-0" },
type === "welcome" ? "Welcome" : "Goodbye",
",",
" ",
JSX.createElement(
"span",
{ className: "text-blue-500" },
displayName,
"!"
)
),
JSX.createElement(
"p",
{ className: "text-gray-300 text-3xl m-0" },
message
)
)
)
);
}
}
module.exports = { GreetingsCard };
```
## Usage
```ts TypeScript
import { Font } from "canvacord";
import { GreetingsCard } from "./GreetingsCard";
// load font, in this case we are loading the bundled font from canvacord
Font.loadDefault();
// create card
const card = new GreetingsCard()
.setAvatar("https://cdn.discordapp.com/embed/avatars/0.png")
.setDisplayName("Wumpus")
.setType("welcome")
.setMessage("Welcome to the server!");
const image = await card.build({ format: "png" });
// now do something with the image buffer
```
```js ES Modules
import { Font } from "canvacord";
import { GreetingsCard } from "./GreetingsCard.js";
// load font, in this case we are loading the bundled font from canvacord
Font.loadDefault();
// create card
const card = new GreetingsCard()
.setAvatar("https://cdn.discordapp.com/embed/avatars/0.png")
.setDisplayName("Wumpus")
.setType("welcome")
.setMessage("Welcome to the server!");
const image = await card.build({ format: "png" });
// now do something with the image buffer
```
```js CommonJS
const { Font } = require("canvacord");
const { GreetingsCard } = require("./GreetingsCard.js");
// load font, in this case we are loading the bundled font from canvacord
Font.loadDefault();
// create card
const card = new GreetingsCard()
.setAvatar("https://cdn.discordapp.com/embed/avatars/0.png")
.setDisplayName("Wumpus")
.setType("welcome")
.setMessage("Welcome to the server!");
async function main() {
const image = await card.build({ format: "png" });
// now do something with the image buffer
}
main();
```
## Result
# Instagram Post
Source: https://canvacord.neplex.dev/examples/builders/instagram-post
Create an Instagram post with Canvacord.
This page is still a work in progress.
## Code
```ts TypeScript
import {} from "canvacord";
```
```js ES Modules
import {} from "canvacord";
```
```js CommonJS
const {} = require("canvacord");
```
## Usage
```ts TypeScript
import {} from "canvacord";
```
```js ES Modules
import {} from "canvacord";
```
```js CommonJS
const {} = require("canvacord");
```
## Result
# Music Card
Source: https://canvacord.neplex.dev/examples/builders/music-card
Music player card with custom text and image.
## Code
```tsx TypeScript
/** @jsx JSX.createElement */
/** @jsxFrag JSX.Fragment */
import { JSX, Builder, loadImage } from "canvacord";
interface Props {
image: string;
title: string;
author: string;
currentTime: string;
totalTime: string;
progress: number;
}
export class MusicCard extends Builder {
constructor() {
super(377, 523);
this.bootstrap({
author: "",
currentTime: "00:00",
totalTime: "00:00",
progress: 0,
image: "",
title: "",
});
}
setImage(image: string) {
this.options.set("image", image);
return this;
}
setTitle(title: string) {
this.options.set("title", title);
return this;
}
setAuthor(author: string) {
this.options.set("author", author);
return this;
}
setCurrentTime(time: string) {
this.options.set("currentTime", time);
return this;
}
setTotalTime(time: string) {
this.options.set("totalTime", time);
return this;
}
setProgress(progress: number) {
this.options.set("progress", progress);
return this;
}
async render() {
const { author, currentTime, image, progress, title, totalTime } =
this.options.getOptions();
const art = await loadImage(image);
return (
{title}
{author}
{currentTime}
{totalTime}
);
}
}
```
```js ES Modules
import { JSX, Builder, loadImage } from "canvacord";
export class MusicCard extends Builder {
constructor() {
super(930, 280);
this.bootstrap({
author: "",
currentTime: "00:00",
totalTime: "00:00",
progress: 0,
image: "",
title: "",
});
}
setImage(image) {
this.options.set("image", image);
return this;
}
setTitle(title) {
this.options.set("title", title);
return this;
}
setAuthor(author) {
this.options.set("author", author);
return this;
}
setCurrentTime(time) {
this.options.set("currentTime", time);
return this;
}
setTotalTime(time) {
this.options.set("totalTime", time);
return this;
}
setProgress(progress) {
this.options.set("progress", progress);
return this;
}
async render() {
const { author, currentTime, image, progress, title, totalTime } =
this.options.getOptions();
const art = await loadImage(image);
return JSX.createElement(
"div",
{
style: {
background: "linear-gradient(to top, #120C17, #010424, #201C5B)",
display: "flex",
flexDirection: "column",
alignItems: "center",
justifyContent: "center",
gap: 8,
borderRadius: "0.5rem",
height: "100%",
width: "100%",
},
},
JSX.createElement("img", {
src: art.toDataURL(),
alt: "img",
style: {
borderRadius: "50%",
height: "12rem",
width: "12rem",
},
}),
JSX.createElement(
"div",
{
style: {
color: "white",
display: "flex",
flexDirection: "column",
alignItems: "center",
},
},
JSX.createElement(
"h1",
{
style: {
fontSize: "1.5rem",
lineHeight: 2,
marginBottom: 0,
marginTop: "0.75rem",
},
},
title
),
JSX.createElement(
"h4",
{
style: {
fontSize: "1.125rem",
lineHeight: 1,
marginTop: 0,
color: "#FFFFFFAA",
fontWeight: 500,
},
},
author
)
),
JSX.createElement(
"div",
{
style: {
display: "flex",
flexDirection: "column",
},
},
JSX.createElement(
"div",
{
style: {
position: "relative",
height: "0.5rem",
width: "20rem",
backgroundColor: "white",
display: "flex",
flexDirection: "column",
},
},
JSX.createElement("div", {
style: {
position: "absolute",
height: "0.5rem",
width: `${progress}%`,
maxWidth: "20rem",
backgroundColor: "#9333EA",
},
})
),
JSX.createElement(
"div",
{
style: {
marginTop: "3px",
display: "flex",
alignItems: "center",
justifyContent: "space-between",
fontSize: "14",
fontWeight: "500",
color: "#FFFFFFAA",
},
},
JSX.createElement("span", null, currentTime),
JSX.createElement("span", null, totalTime)
)
)
);
}
}
```
```js CommonJS
const { JSX, Builder, loadImage } = require("canvacord");
class MusicCard extends Builder {
constructor() {
super(930, 280);
this.bootstrap({
author: "",
currentTime: "00:00",
totalTime: "00:00",
progress: 0,
image: "",
title: "",
});
}
setImage(image) {
this.options.set("image", image);
return this;
}
setTitle(title) {
this.options.set("title", title);
return this;
}
setAuthor(author) {
this.options.set("author", author);
return this;
}
setCurrentTime(time) {
this.options.set("currentTime", time);
return this;
}
setTotalTime(time) {
this.options.set("totalTime", time);
return this;
}
setProgress(progress) {
this.options.set("progress", progress);
return this;
}
async render() {
const { author, currentTime, image, progress, title, totalTime } =
this.options.getOptions();
const art = await loadImage(image);
return JSX.createElement(
"div",
{
style: {
background: "linear-gradient(to top, #120C17, #010424, #201C5B)",
display: "flex",
flexDirection: "column",
alignItems: "center",
justifyContent: "center",
gap: 8,
borderRadius: "0.5rem",
height: "100%",
width: "100%",
},
},
JSX.createElement("img", {
src: art.toDataURL(),
alt: "img",
style: {
borderRadius: "50%",
height: "12rem",
width: "12rem",
},
}),
JSX.createElement(
"div",
{
style: {
color: "white",
display: "flex",
flexDirection: "column",
alignItems: "center",
},
},
JSX.createElement(
"h1",
{
style: {
fontSize: "1.5rem",
lineHeight: 2,
marginBottom: 0,
marginTop: "0.75rem",
},
},
title
),
JSX.createElement(
"h4",
{
style: {
fontSize: "1.125rem",
lineHeight: 1,
marginTop: 0,
color: "#FFFFFFAA",
fontWeight: 500,
},
},
author
)
),
JSX.createElement(
"div",
{
style: {
display: "flex",
flexDirection: "column",
},
},
JSX.createElement(
"div",
{
style: {
position: "relative",
height: "0.5rem",
width: "20rem",
backgroundColor: "white",
display: "flex",
flexDirection: "column",
},
},
JSX.createElement("div", {
style: {
position: "absolute",
height: "0.5rem",
width: `${progress}%`,
maxWidth: "20rem",
backgroundColor: "#9333EA",
},
})
),
JSX.createElement(
"div",
{
style: {
marginTop: "3px",
display: "flex",
alignItems: "center",
justifyContent: "space-between",
fontSize: "14",
fontWeight: "500",
color: "#FFFFFFAA",
},
},
JSX.createElement("span", null, currentTime),
JSX.createElement("span", null, totalTime)
)
)
);
}
}
module.exports = { MusicCard };
```
## Usage
```ts TypeScript
import { MusicCard } from "./MusicCard";
const card = new MusicCard()
.setAuthor("JVKE")
.setTitle("Golden Hour")
.setImage(
"https://lh3.googleusercontent.com/i1qCCS4BbP6z11E08FkQg6fN-83Uj4fQg4bmBsD2E6SvGQ3RW7nXxpQ3hmcSlI5Ipek10H7R4BjV5mAY=w544-h544-l90-rj"
)
.setProgress(39)
.setCurrentTime("01:58")
.setTotalTime("02:59");
const image = await card.build();
// now do something with the image buffer
```
```js ES Modules
import { MusicCard } from "./MusicCard.js";
const card = new MusicCard()
.setAuthor("JVKE")
.setTitle("Golden Hour")
.setImage(
"https://lh3.googleusercontent.com/i1qCCS4BbP6z11E08FkQg6fN-83Uj4fQg4bmBsD2E6SvGQ3RW7nXxpQ3hmcSlI5Ipek10H7R4BjV5mAY=w544-h544-l90-rj"
)
.setProgress(39)
.setCurrentTime("01:58")
.setTotalTime("02:59");
const image = await card.build();
// now do something with the image buffer
```
```js CommonJS
const { MusicCard } = require("./MusicCard.js");
const card = new MusicCard()
.setAuthor("JVKE")
.setTitle("Golden Hour")
.setImage(
"https://lh3.googleusercontent.com/i1qCCS4BbP6z11E08FkQg6fN-83Uj4fQg4bmBsD2E6SvGQ3RW7nXxpQ3hmcSlI5Ipek10H7R4BjV5mAY=w544-h544-l90-rj"
)
.setProgress(39)
.setCurrentTime("01:58")
.setTotalTime("02:59");
async function main() {
const image = await card.build();
// now do something with the image buffer
}
```
## Result
# Quote card
Source: https://canvacord.neplex.dev/examples/builders/quote
Create an quote card with Canvacord.
## Code
```js CommonJS
const { JSX, Builder, loadImage, Font, FontFactory } = require("canvacord");
class QuoteCard extends Builder {
constructor() {
super(1200, 630);
this.bootstrap({
text: "",
author: "",
tag: "",
bgcolor: true,
watermark: "",
backgroundImage: "",
});
if (!FontFactory.size) Font.loadDefault();
}
setText(value) {
this.options.set("text", value);
return this;
}
setAuthor(value) {
this.options.set("author", value);
return this;
}
setTag(value) {
this.options.set("tag", value);
return this;
}
setColor(value) {
this.options.set("bgcolor", value);
return this;
}
setWatermark(value) {
this.options.set("watermark", value);
return this;
}
setBackgroundImage(value) {
this.options.set("backgroundImage", value);
return this;
}
async render() {
const { text, author, tag, watermark, bgcolor, backgroundImage } =
this.options.getOptions();
const img = await loadImage(backgroundImage);
return JSX.createElement(
"div",
{
className: "w-full h-full flex relative",
style: {
backgroundColor: "#000000",
borderRadius: "0.5rem",
overflow: "hidden",
},
},
JSX.createElement(
"div",
{
className: "w-1/2 flex relative",
style: {
width: "50%",
height: "100%",
},
},
JSX.createElement("img", {
src: img.toDataURL(),
className: "h-full w-full",
style: {
objectFit: "cover",
objectPosition: "center",
width: "100%",
height: "100%",
filter: bgcolor
? "none"
: "grayscale(100%) brightness(0.9) contrast(1.2)",
},
}),
JSX.createElement("div", {
className: "absolute inset-0 flex",
style: {
position: "absolute",
top: 0,
left: 0,
right: 0,
bottom: 0,
background:
"linear-gradient(60deg, rgba(0,0,0,0) 0%, rgba(0,0,0,0) 25%, rgba(0,0,0,0.4) 45%, rgba(0,0,0,0.8) 65%, rgba(0,0,0,0.95) 85%, #000000 100%)",
},
}),
JSX.createElement("div", {
className: "absolute inset-0 flex",
style: {
position: "absolute",
top: 0,
left: 0,
right: 0,
bottom: 0,
background:
"linear-gradient(to right, rgba(0,0,0,0) 0%, rgba(0,0,0,0.2) 70%, rgba(0,0,0,0.9) 100%)",
},
})
),
JSX.createElement(
"div",
{
className:
"w-1/2 relative flex flex-col justify-center items-center text-center",
style: {
display: "flex",
position: "relative",
width: "50%",
height: "100%",
flexDirection: "column",
justifyContent: "center",
alignItems: "center",
textAlign: "center",
padding: "2rem",
},
},
JSX.createElement(
"div",
{
style: {
display: "flex",
position: "relative",
width: "100%",
height: "100%",
flexDirection: "column",
justifyContent: "center",
alignItems: "center",
},
},
JSX.createElement(
"h2",
{
className: "text-white flex font-bold",
style: {
fontSize: "3rem",
fontWeight: "bold",
color: "#ffffff",
marginBottom: "1rem",
lineHeight: "1.2",
},
},
text
),
author &&
JSX.createElement(
"p",
{
className: "text-white flex",
style: {
fontSize: "1.5rem",
color: "#ffffff",
marginBottom: "0.5rem",
},
},
`- ${author}`
),
tag &&
JSX.createElement(
"p",
{
className: "text-gray-400 flex",
style: {
fontSize: "1rem",
color: "#9ca3af",
marginBottom: "2rem",
},
},
tag
),
watermark &&
JSX.createElement(
"div",
{
style: {
position: "absolute",
display: "flex",
bottom: "1rem",
right: "1rem",
},
},
JSX.createElement(
"p",
{
className: "text-gray-500 flex",
style: {
fontSize: "0.875rem",
color: "#6b7280",
},
},
watermark
)
)
)
)
);
}
}
module.exports = { QuoteCard };
```
## Usage
```js CommonJS
const { QuoteCard } = require("./QuoteCard");
const card = new QuoteCard()
.setText("hello")
.setAuthor("Ziji")
.setTag("__ziji")
.setWatermark("Ziji#7063")
.setBackgroundImage(
"https://lh3.googleusercontent.com/pw/AP1GczN0ncQYhFuV0qUcW68KX4a5DCwXw7MlobnY0aGOLnpUeareeV1pNxZoF4PayOrcqgBapur4iM0MlxdiW6T9uhwMqmlLP1A1TBKUIPOt7E0-eH0EV2FddVDvyyXHnx7tyGCLwheiZjiaVA9xSQ4a8xTnDw=w780-h712-s-no-gm"
)
.setColor(true);
const result = await card.build({ format: "png" });
// now do something with the image buffer
```
## Result
# Tweet Card
Source: https://canvacord.neplex.dev/examples/builders/tweet-card
Tweet card built with Canvacord.
This page is still a work in progress.
## Code
```ts TypeScript
import {} from "canvacord";
```
```js ES Modules
import {} from "canvacord";
```
```js CommonJS
const {} = require("canvacord");
```
## Usage
```ts TypeScript
import {} from "canvacord";
```
```js ES Modules
import {} from "canvacord";
```
```js CommonJS
const {} = require("canvacord");
```
## Result
# Stewie Griffin
Source: https://canvacord.neplex.dev/examples/image-manipulation/stewie-griffin
Become Stewie Griffin from Family Guy using Canvacord.
## Code
```ts TypeScript
import { join } from "path";
import {
createTemplate,
createImageGenerator,
TemplateImage,
type ImageSource,
} from "canvacord";
const StewieGriffin = createTemplate((image: ImageSource) => {
return {
width: 1024,
height: 1024,
steps: [
{
image: [
{
source: new TemplateImage(image),
x: 180,
y: 0,
width: 680,
height: 680,
},
],
},
{
image: [
{
source: new TemplateImage(
join(import.meta.dirname, "stewie-griffin-source.png")
),
x: 0,
y: 0,
},
],
},
],
};
});
export async function stewieGriffin(image: ImageSource) {
const output = await createImageGenerator(StewieGriffin(image)).render();
const result = await output.encode("png");
return result;
}
```
```js ES Modules
import { join } from "path";
import { createTemplate, createImageGenerator, TemplateImage } from "canvacord";
const StewieGriffin = createTemplate((image) => {
return {
width: 1024,
height: 1024,
steps: [
{
image: [
{
source: new TemplateImage(image),
x: 180,
y: 0,
width: 680,
height: 680,
},
],
},
{
image: [
{
source: new TemplateImage(
join(import.meta.dirname, "stewie-griffin-source.png")
),
x: 0,
y: 0,
},
],
},
],
};
});
export async function stewieGriffin(image) {
const output = await createImageGenerator(StewieGriffin(image)).render();
const result = await output.encode("png");
return result;
}
```
```js CommonJS
const { join } = require("path");
const {
createTemplate,
createImageGenerator,
TemplateImage,
} = require("canvacord");
const StewieGriffin = createTemplate((image) => {
return {
width: 1024,
height: 1024,
steps: [
{
image: [
{
source: new TemplateImage(image),
x: 180,
y: 0,
width: 680,
height: 680,
},
],
},
{
image: [
{
source: new TemplateImage(
join(__dirname, "stewie-griffin-source.png")
),
x: 0,
y: 0,
},
],
},
],
};
});
module.exports.stewieGriffin = async function (image) {
const output = await createImageGenerator(StewieGriffin(image)).render();
const result = await output.encode("png");
return result;
};
```
## Usage
```ts TypeScript
import { writeFile } from "node:fs/promises";
import { stewieGriffin } from "./stewie-griffin";
const targetImage = "https://cdn.discordapp.com/embed/avatars/0.png";
const result = await stewieGriffin(targetImage);
await writeFile("./stewie-griffin-result.png", result);
```
```js ES Modules
import { writeFile } from "node:fs/promises";
import { stewieGriffin } from "./stewie-griffin.js";
const targetImage = "https://cdn.discordapp.com/embed/avatars/0.png";
const result = await stewieGriffin(targetImage);
await writeFile("./stewie-griffin-result.png", result);
```
```js CommonJS
const { writeFile } = require("node:fs/promises");
const { stewieGriffin } = require("./stewie-griffin.js");
async function main() {
const targetImage = "https://cdn.discordapp.com/embed/avatars/0.png";
const result = await stewieGriffin(targetImage);
await writeFile("./stewie-griffin-result.png", result);
}
main();
```
## Result
# Canvacord Examples
Source: https://canvacord.neplex.dev/examples/introduction
Various examples of Canvacord API usage that you can copy and paste into your project.
Got something cool to show? [Submit your own
example](https://github.com/neplextech/canvacord) by making a pull request.
## Builder Examples
Here are some examples of Canvacord's Builder API usage that you can copy and paste into your project.
Welcomer/Leaver card with a custom background and text.
A music player card with a custom background and text.
An Instagram post card.
A tweet card example.
An analog clock example.
A Discord embed example.
A large Discord profile card.
A smaller Discord profile card.
## Image Manipulation Examples
Here are some examples of Canvacord's Image Manipulation API usage that you can copy and paste into your project.
Become Stewie Griffin from Family Guy.
# Built-in Image Manipulation APIs
Source: https://canvacord.neplex.dev/image-manipulation/builtin-apis
Use Canvacord's built-in builders to generate commonly used memes, such as triggered gif, jail image, and more.
This page is still a work in progress.
## Usage
Canvacord's built-in image manipulation APIs can be used from `canvacord` object. You need to import the `canvacord` object from the package as shown below:
```ts TypeScript
import { canvacord } from "canvacord";
```
```js ES Modules
import { canvacord } from "canvacord";
```
```js CommonJS
const { canvacord } = require("canvacord");
```
## Image Manipulation (Filters)
The filters API can be used to apply filters to an image, such as hue rotation, saturation, brightness, contrast, and more.
```ts TypeScript
import { canvacord } from "canvacord";
const output = await canvacord(image).hueRotate(70).encode();
// or
const output = await canvacord
.filters(500, 500)
.drawImage(image)
.hueRotate(70)
.encode();
```
```js ES Modules
import { canvacord } from "canvacord";
const output = await canvacord(image).hueRotate(70).encode();
// or
const output = await canvacord
.filters(500, 500)
.drawImage(image)
.hueRotate(70)
.encode();
```
```js CommonJS
const { canvacord } = require("canvacord");
const output = await canvacord(image).hueRotate(70).encode();
// or
const output = await canvacord
.filters(500, 500)
.drawImage(image)
.hueRotate(70)
.encode();
```
## Image Manipulation (Image Generation)
The image generation API can be used to generate images, such as affected image, triggered gif, beautiful image, and more.
```ts TypeScript
import { canvacord } from "canvacord";
import { createWriteStream, promises as fs } from "fs";
const img = "image-1.png";
const img2 = "image-2.png";
const img3 = "image-3.png";
// template
const affected = await canvacord.affect(img);
fs.writeFile("./affected.png", affected);
// gif
const triggered = await canvacord.triggered(img);
triggered.pipe(createWriteStream("./triggered.gif"));
// fuse
const fused = await canvacord.fuse(img, img2);
fs.writeFile("./fused.png", fused);
// kiss
const kissed = await canvacord.kiss(img, img2);
fs.writeFile("./kissed.png", kissed);
// spank
const spanked = await canvacord.spank(img, img2);
fs.writeFile("./spanked.png", spanked);
// slap
const slapped = await canvacord.slap(img, img2);
fs.writeFile("./slapped.png", slapped);
// beautiful
const beautiful = await canvacord.beautiful(img);
fs.writeFile("./beautiful.png", beautiful);
// facepalm
const facepalm = await canvacord.facepalm(img);
fs.writeFile("./facepalm.png", facepalm);
// rainbow
const rainbow = await canvacord.rainbow(img);
fs.writeFile("./rainbow.png", rainbow);
// rip
const rip = await canvacord.rip(img);
fs.writeFile("./rip.png", rip);
// trash
const trash = await canvacord.trash(img);
fs.writeFile("./trash.png", trash);
// hitler
const hitler = await canvacord.hitler(img);
fs.writeFile("./hitler.png", hitler);
// distracted
const distracted = await canvacord.distracted(img, img2, img3);
fs.writeFile("./distracted.png", distracted);
```
```js ES Modules
import { canvacord } from "canvacord";
import { createWriteStream, promises as fs } from "fs";
const img = "image-1.png";
const img2 = "image-2.png";
const img3 = "image-3.png";
// template
const affected = await canvacord.affect(img);
fs.writeFile("./affected.png", affected);
// gif
const triggered = await canvacord.triggered(img);
triggered.pipe(createWriteStream("./triggered.gif"));
// fuse
const fused = await canvacord.fuse(img, img2);
fs.writeFile("./fused.png", fused);
// kiss
const kissed = await canvacord.kiss(img, img2);
fs.writeFile("./kissed.png", kissed);
// spank
const spanked = await canvacord.spank(img, img2);
fs.writeFile("./spanked.png", spanked);
// slap
const slapped = await canvacord.slap(img, img2);
fs.writeFile("./slapped.png", slapped);
// beautiful
const beautiful = await canvacord.beautiful(img);
fs.writeFile("./beautiful.png", beautiful);
// facepalm
const facepalm = await canvacord.facepalm(img);
fs.writeFile("./facepalm.png", facepalm);
// rainbow
const rainbow = await canvacord.rainbow(img);
fs.writeFile("./rainbow.png", rainbow);
// rip
const rip = await canvacord.rip(img);
fs.writeFile("./rip.png", rip);
// trash
const trash = await canvacord.trash(img);
fs.writeFile("./trash.png", trash);
// hitler
const hitler = await canvacord.hitler(img);
fs.writeFile("./hitler.png", hitler);
// distracted
const distracted = await canvacord.distracted(img, img2, img3);
fs.writeFile("./distracted.png", distracted);
```
```js CommonJS
const { canvacord } = require("canvacord");
const { createWriteStream, promises: fs } = require("fs");
const img = "image-1.png";
const img2 = "image-2.png";
const img3 = "image-3.png";
// template
const affected = await canvacord.affect(img);
fs.writeFile("./affected.png", affected);
// gif
const triggered = await canvacord.triggered(img);
triggered.pipe(createWriteStream("./triggered.gif"));
// fuse
const fused = await canvacord.fuse(img, img2);
fs.writeFile("./fused.png", fused);
// kiss
const kissed = await canvacord.kiss(img, img2);
fs.writeFile("./kissed.png", kissed);
// spank
const spanked = await canvacord.spank(img, img2);
fs.writeFile("./spanked.png", spanked);
// slap
const slapped = await canvacord.slap(img, img2);
fs.writeFile("./slapped.png", slapped);
// beautiful
const beautiful = await canvacord.beautiful(img);
fs.writeFile("./beautiful.png", beautiful);
// facepalm
const facepalm = await canvacord.facepalm(img);
fs.writeFile("./facepalm.png", facepalm);
// rainbow
const rainbow = await canvacord.rainbow(img);
fs.writeFile("./rainbow.png", rainbow);
// rip
const rip = await canvacord.rip(img);
fs.writeFile("./rip.png", rip);
// trash
const trash = await canvacord.trash(img);
fs.writeFile("./trash.png", trash);
// hitler
const hitler = await canvacord.hitler(img);
fs.writeFile("./hitler.png", hitler);
// distracted
const distracted = await canvacord.distracted(img, img2, img3);
fs.writeFile("./distracted.png", distracted);
```
# Image Manipulation API
Source: https://canvacord.neplex.dev/image-manipulation/image-manipulation-api
Learn how to manipulate images using Canvacord's image manipulation api.
This page is still a work in progress.
Canvacord's image manipulation API works by allowing you to define how image should be processed by using a schema object. The schema object is a JavaScript object that defines the image manipulation process. This schema can generate both static as well as animated images.
## Example
Check out [Stewie Griffin](/examples/image-manipulation/stewie-griffin) example to see how you can create your own image manipulation function.
### Usage
```ts TypeScript
import {
createTemplate,
ImageFactory,
TemplateImage,
createImageGenerator,
type ImageSource,
} from "canvacord";
const Manipulator = createTemplate((image: ImageSource) => {
return {
steps: [
// base image
{
// one step can take multiple images
image: [
{
source: new TemplateImage(ImageFactory.AFFECT), // source image
x: 0, // x position
y: 0, // y position
},
],
},
// target image
{
image: [
{
source: new TemplateImage(image), // target image
x: 180, // x position
y: 383, // y position
width: 200, // width
height: 157, // height
},
],
},
],
};
});
// get target photo to use on "affected" meme image
const photo = await getPhotoForMemeSomehow();
const generator = createImageGenerator(Manipulator(photo));
// render out the image
await generator.render();
// get the resulting image in png format
const affectedMeme = await generator.encode("png");
```
```js ES Modules
import {
createTemplate,
ImageFactory,
TemplateImage,
createImageGenerator,
} from "canvacord";
const Manipulator = createTemplate((image) => {
return {
steps: [
// base image
{
// one step can take multiple images
image: [
{
source: new TemplateImage(ImageFactory.AFFECT), // source image
x: 0, // x position
y: 0, // y position
},
],
},
// target image
{
image: [
{
source: new TemplateImage(image), // target image
x: 180, // x position
y: 383, // y position
width: 200, // width
height: 157, // height
},
],
},
],
};
});
// get target photo to use on "affected" meme image
const photo = await getPhotoForMemeSomehow();
const generator = createImageGenerator(Manipulator(photo));
// render out the image
await generator.render();
// get the resulting image in png format
const affectedMeme = await generator.encode("png");
```
```js CommonJS
const {
createTemplate,
ImageFactory,
TemplateImage,
createImageGenerator,
} = require("canvacord");
const Manipulator = createTemplate((image) => {
return {
steps: [
// base image
{
// one step can take multiple images
image: [
{
source: new TemplateImage(ImageFactory.AFFECT), // source image
x: 0, // x position
y: 0, // y position
},
],
},
// target image
{
image: [
{
source: new TemplateImage(image), // target image
x: 180, // x position
y: 383, // y position
width: 200, // width
height: 157, // height
},
],
},
],
};
});
// get target photo to use on "affected" meme image
const photo = await getPhotoForMemeSomehow();
const generator = createImageGenerator(Manipulator(photo));
// render out the image
await generator.render();
// get the resulting image in png format
const affectedMeme = await generator.encode("png");
```
### Structure
```ts
export interface ImageGenerationStep {
/**
* The image to render.
*/
image?: ImgenStep[];
/**
* The text to render.
*/
text?: TextGenerationStep[];
/**
* The custom steps to apply to the canvas.
*/
custom?: CustomGenerationStep[];
/**
* The function to call before processing this step.
*/
preprocess?: (
canvas: Canvas,
ctx: SKRSContext2D,
step: ImageGenerationStep
) => Awaited;
/**
* The function to call when processing this step.
*/
process?: (
canvas: Canvas,
ctx: SKRSContext2D,
step: ImageGenerationStep
) => Awaited;
/**
* The function to call after processing has finished.
*/
postprocess?: (
canvas: Canvas,
ctx: SKRSContext2D,
step: ImageGenerationStep
) => Awaited;
}
export interface CustomGenerationStep {
/**
* The function to call when processing this step.
*/
process: (
canvas: Canvas,
ctx: SKRSContext2D,
step: ImageGenerationStep
) => Awaited;
}
export interface ImgenStep {
/**
* The image to render.
*/
source: TemplateImage;
/**
* The x position of the image.
*/
x: number;
/**
* The y position of the image.
*/
y: number;
/**
* The width of the image.
*/
width?: number;
/**
* The height of the image.
*/
height?: number;
/**
* The function to call before processing this step.
*/
preprocess?: (
canvas: Canvas,
ctx: SKRSContext2D,
source: ImgenStep
) => Awaited;
/**
* The function to call when processing this step.
*/
process?: (
canvas: Canvas,
ctx: SKRSContext2D,
source: ImgenStep
) => Awaited;
/**
* The function to call after processing has finished.
*/
postprocess?: (
canvas: Canvas,
ctx: SKRSContext2D,
source: ImgenStep
) => Awaited;
}
export interface TextGenerationStep {
/**
* The text to render.
*/
value: string;
/**
* The font of the text.
*/
font: string;
/**
* The color of the text.
*/
color: string;
/**
* Whether to stroke the text.
*/
stroke?: boolean;
/**
* The x position of the text.
*/
x: number;
/**
* The y position of the text.
*/
y: number;
/**
* The maximum width of the text.
*/
maxWidth?: number;
/**
* The line height of the text.
*/
lineHeight?: number;
/**
* The line width of the text.
*/
lineWidth?: number;
/**
* The alignment of the text.
*/
align?: "left" | "center" | "right";
/**
* The baseline of the text.
*/
baseline?: "top" | "middle" | "bottom";
/**
* The directionality of the text.
*/
direction?: "inherit" | "ltr" | "rtl";
/**
* The function to call before processing this step.
*/
preprocess?: (
canvas: Canvas,
ctx: SKRSContext2D,
text: TextGenerationStep
) => Awaited;
/**
* The function to call when processing this step.
*/
process?: (
canvas: Canvas,
ctx: SKRSContext2D,
text: TextGenerationStep
) => Awaited;
/**
* The function to call after processing has finished.
*/
postprocess?: (
canvas: Canvas,
ctx: SKRSContext2D,
text: TextGenerationStep
) => Awaited;
}
/**
* The template to use for image generation.
*/
export interface IImageGenerationTemplate {
/**
* The width of the template.
*/
width?: number;
/**
* The height of the template.
*/
height?: number;
/**
* The steps to apply to the canvas.
*/
steps: ImageGenerationStep[];
/**
* The gif options.
*/
gif?: EncoderOptions;
}
```
# Introduction
Source: https://canvacord.neplex.dev/introduction
Welcome to the canvacord documentation!
***
## What is canvacord?
Canvacord is a powerful utility to generate beautiful images in JavaScript or TypeScript. You use React-like components to declare how you want your image to look, without ever having to calculate the position of elements or worry about the size of the canvas. Canvacord does all the heavy lifting for you, such as image rendering, formats conversion, and more.
Canvacord abstracts the complexity of image generation and provides a simple and intuitive API to create images. This allows you to focus on the design and content of your images, rather than the technical details that goes into rendering them as needed.
Whether you're a beginner or an expert, Canvacord is the perfect tool to create stunning images for your projects with little to no effort.
***
## Pre-requisites
We try our best to make Canvacord as easy to use as possible. However, there are a few things you need to know before you start using Canvacord. To get the most out of Canvacord, you should have a basic understanding of the following:
Since Canvacord is a JavaScript library, you should have a basic
understanding of JavaScript to use it effectively.
Since Canvacord relies heavily on HTML tags, you should have a basic
understanding of it.
Canvacord uses CSS to style the images, such as setting the font size,
color, width, etc. Therefore, having a basic understanding of CSS will help
you style your images effectively.
Canvacord uses React-like components to generate images. Therefore, having a
basic understanding of React and its terms will help you get started with
Canvacord.
## Make it yours
If you have the understanding of the above concepts, you're ready to start using Canvacord. You can start by installing Canvacord and creating your first image. If you're new to Canvacord, we recommend you start with the [Quick Start](/quickstart) guide to get a better understanding of how Canvacord works.
Get started with Canvacord by creating your first image using built-in
builders.
Build your own image components using Canvacord's custom builders.
Learn how to manipulate images using Canvacord's built-in image manipulation
tools.
Learn about Canvacord's API and how to use it effectively.
Join our Discord server to get help, share your projects, and more.
Contribute to Canvacord by submitting bug reports, feature requests, and
more.
# Quickstart
Source: https://canvacord.neplex.dev/quickstart
Get started with Canvacord
## Setup your development environment
To get started with Canvacord, you need to have a few things set up on your local machine.
* [Node.js](https://nodejs.org/en/download/): Canvacord is built on Node.js, so you need to have it installed on your machine.
* [NPM](https://www.npmjs.com/get-npm): NPM is the package manager for Node.js. You will need it to install Canvacord and its dependencies.
* Optionally [TypeScript](https://www.typescriptlang.org/download): To get the best out of Canvacord, we recommend you use TypeScript, but it's not required.
### Installation
```bash npm
npm i canvacord
```
```bash yarn
yarn add canvacord
```
```bash pnpm
pnpm add canvacord
```
```bash bun
bun add canvacord
```
### Use it in your project
You can use Canvacord with or without JSX. JSX is a syntax extension for JavaScript that looks similar to HTML. It allows you to write HTML-like code in your JavaScript files. If you're familiar with React, you'll feel right at home with JSX.
#### Using Canvacord with JSX
```jsx ES Modules
/** @jsx JSX.createElement */
/** @jsxFrag JSX.Fragment */
// The JSX pragma tells transpiler how to transform JSX into the equivalent JavaScript code
// import Canvacord
// Builder = The base class for creating custom builders
// JSX = The JSX pragma for creating elements
// Font = The Font class for loading custom fonts
// FontFactory = The FontFactory for managing fonts
import { Builder, JSX, Font, FontFactory } from "canvacord";
import { writeFile } from "node:fs/promises";
// define a builder
class Generator extends Builder {
constructor() {
// set the size of the image
super(300, 300);
// if no fonts are loaded, load the default font
if (!FontFactory.size) Font.loadDefault();
}
async render() {
// declare the shape of the image
return (
Hello, World!
);
}
}
// create an instance of the builder
const generator = new Generator();
// build the image and save it to a file
const image = await generator.build({ format: "png" });
await writeFile("image.png", image);
```
```jsx CommonJS
/** @jsx JSX.createElement */
/** @jsxFrag JSX.Fragment */
// The JSX pragma tells transpiler how to transform JSX into the equivalent JavaScript code
// import Canvacord
// Builder = The base class for creating custom builders
// JSX = The JSX pragma for creating elements
// Font = The Font class for loading custom fonts
// FontFactory = The FontFactory for managing fonts
const { Builder, JSX, Font, FontFactory } = require("canvacord");
const { writeFile } = require("node:fs/promises");
// define a builder
class Generator extends Builder {
constructor() {
// set the size of the image
super(300, 300);
// if no fonts are loaded, load the default font
if (!FontFactory.size) Font.loadDefault();
}
async render() {
// declare the shape of the image
return (
Hello, World!
);
}
}
async function main() {
// create an instance of the builder
const generator = new Generator();
// build the image and save it to a file
const image = await generator.build({ format: "png" });
await writeFile("image.png", image);
}
main();
```
#### Using Canvacord without JSX
```js ES Modules
// import Canvacord
// Builder = The base class for creating custom builders
// JSX = The JSX pragma for creating elements
// Font = The Font class for loading custom fonts
// FontFactory = The FontFactory for managing fonts
import { Builder, JSX, Font, FontFactory } from "canvacord";
import { writeFile } from "node:fs/promises";
// define a builder
class Generator extends Builder {
constructor() {
// set the size of the image
super(300, 300);
// if no fonts are loaded, load the default font
if (!FontFactory.size) Font.loadDefault();
}
async render() {
// declare the shape of the image
return JSX.createElement(
"div",
{
style: {
display: "flex",
alignItems: "center",
justifyContent: "center",
backgroundColor: "white",
width: "100%",
height: "100%",
},
},
JSX.createElement("h1", null, "Hello, World!")
);
}
}
// create an instance of the builder
const generator = new Generator();
// build the image and save it to a file
const image = await generator.build({ format: "png" });
await writeFile("image.png", image);
```
```js CommonJS
// import Canvacord
// Builder = The base class for creating custom builders
// JSX = The JSX pragma for creating elements
// Font = The Font class for loading custom fonts
// FontFactory = The FontFactory for managing fonts
const { Builder, JSX, Font, FontFactory } = require("canvacord");
const { writeFile } = require("node:fs/promises");
// define a builder
class Generator extends Builder {
constructor() {
// set the size of the image
super(300, 300);
// if no fonts are loaded, load the default font
if (!FontFactory.size) Font.loadDefault();
}
async render() {
// declare the shape of the image
return JSX.createElement(
"div",
{
style: {
display: "flex",
alignItems: "center",
justifyContent: "center",
backgroundColor: "white",
width: "100%",
height: "100%",
},
},
JSX.createElement("h1", null, "Hello, World!")
);
}
}
async function main() {
// create an instance of the builder
const generator = new Generator();
// build the image and save it to a file
const image = await generator.build({ format: "png" });
await writeFile("image.png", image);
}
main();
```
## Result of the above code
## Further reading
To learn more about Canvacord, check out the following resources:
Learn how to generate custom images using Canvacord's builder api.
Learn how to manipulate images using Canvacord's built-in image manipulation
utilities.
Use Canvacord's built-in builders to create commonly used images quickly, such
as rank cards, leaderboard images, and more.
Use Canvacord's built-in builders to generate commonly used memes, such as
triggered gif, jail image, and more.
Find a list of builder examples that you can copy and paste into your project.
Create an issue on GitHub if you have a suggestion or found a bug in
Canvacord.