kyzz-canvas
v2.0.0
Published
High-performance, lightweight custom canvas rendering engine for Node.js, Bun, Bots, and Web
Maintainers
Readme
Creator: Kyuu
Channel: https://whatsapp.com/channel/0029VbDO8tI2phHLTSN2ed0U
Contact: https://wa.me/6283150850721
📑 Daftar Isi
- Mengapa Kyzz Canvas?
- Instalasi
- Quick Start
- 🌐 HTML + CSS Rendering Engine
- Arsitektur Rendering (Tanpa Browser / Chromium)
- Quick Example: HTML + CSS → Image
- Integrasi Bot (WhatsApp, Telegram, Discord)
- Feature Matrix: Status Fitur Realistis
- HTML Tags & Custom Elements
- CSS Selector, Cascade & Specificity
- Flexbox & CSS Grid Layout
- CSS Variables, calc() & Sizing Units
- Gradients, Shadows, Backgrounds & Borders
- Transforms, Filters & Pseudo Elements
- Typography, Font Fallback & @font-face
- Auto Height, Device Scale Factor & Measurement
- Template Variables & Custom Components
- Keamanan & Proteksi SSRF
- Debug Mode
- Arsitektur & Konsep Engine
- Universal Asset Loader
- Sistem Font & Google Fonts
- Manipulasi Gambar
- Engine SVG Kelas Satu
- Daftar Lengkap Method Canvas
- Format Output & File Export
- Contoh Implementasi Bot
- Contoh Web Framework & Server
- Virtual Component / JSX Adapter
- HTML5 Canvas 2D Compatibility Adapter
- Tabel Benchmark Resmi
- Daftar Subpath Modules
- Prompt AI / System Instructions for LLMs
- Lisensi
⚡ Mengapa Kyzz Canvas?
| Parameter | Kyzz Canvas | node-canvas | @napi-rs/canvas |
|---|---|---|---|
| Paradigma API | Fluent Modern Custom API | Legacy ctx imperative | Legacy ctx imperative |
| Boilerplate ctx | Nol (Tidak perlu ctx) | Wajib const ctx = ... | Wajib const ctx = ... |
| Bundled Font Bawaan | Ya (DejaVu Sans bawaan) | Tidak (bergantung font OS) | Tidak (bergantung font OS) |
| Google Fonts Otomatis | Ya (fonts.google('Inter')) | Tidak (harus unduh manual) | Tidak (harus unduh manual) |
| Remote SVG / CDN | Ya (Auto-fetch + SSRF Guard) | Tidak | Terbatas |
| Dukungan Bun | 100% Native & Cepat | Sering gagal build/segfault | Perlu build flag khusus |
| Ketergantungan Wrapper | Engine independen | C++ Cairo / Pango wrapper | Skia wrapper |
📦 Instalasi
Install melalui package manager favorit Anda:
# npm
npm install kyzz-canvas
# Bun
bun add kyzz-canvas
# pnpm
pnpm add kyzz-canvas
# Yarn
yarn add kyzz-canvas🚀 Quick Start
Hanya butuh 4 baris untuk merender kartu selamat datang berkualitas tinggi:
import { Canvas, fonts } from 'kyzz-canvas';
await fonts.google('Poppins');
const canvas = new Canvas(800, 400);
canvas.bg({
type: 'linear',
x1: 0,
y1: 0,
x2: 800,
y2: 400,
stops: [
{ offset: 0, color: '#0f172a' },
{ offset: 1, color: '#1e1b4b' }
]
});
canvas.box(40, 40, 720, 320, {
radius: 20,
fill: 'rgba(255, 255, 255, 0.05)',
stroke: 'rgba(255, 255, 255, 0.1)',
strokeWidth: 1
});
canvas.circle(120, 120, 40, { fill: '#6366f1' });
canvas.text('Selamat Datang!', {
x: 180,
y: 115,
size: 36,
font: 'Poppins',
weight: 700,
color: '#ffffff'
});
canvas.text('Rendering modern tanpa ctx yang membingungkan.', {
x: 180,
y: 155,
size: 18,
font: 'Poppins',
weight: 400,
color: '#94a3b8'
});
const pngBuffer = await canvas.render('png');
await canvas.save('./output.png');🌐 HTML + CSS Rendering Engine
Kyzz Canvas dilengkapi dengan HTML + CSS Rendering Engine bawaan yang dirancang khusus untuk menghasilkan gambar berkualitas tinggi dari sintaks HTML dan CSS modern, tanpa menggunakan browser.
[!IMPORTANT] 100% Bebas Browser (Zero Chromium / Headless Browser): Kyzz Canvas TIDAK membutuhkan Chromium, Puppeteer, Playwright, Chrome, atau Firefox. Engine memproses HTML dan CSS melalui layout & paint pipeline custom kami sendiri, menghasilkan gambar dalam milidetik dengan penggunaan RAM minimal (~30 MB).
Arsitektur Rendering (Tanpa Browser / Chromium)
Pipeline rendering Kyzz Canvas memisahkan setiap tahap pemrosesan dengan arsitektur modular:
HTML Input
│
▼
Custom HTML Parser ───► Tokenisasi Tag, Atribut, Void Elements, Entitas
│
▼
DOM-like Tree
│
├── CSS Parser ────► Aturan CSS, @font-face, @import, Inline Styles
│ │
│ ▼
│ Style Resolver ─► Cascading, Specificity, CSS Variables, Inheritance
│
▼
Layout Engine ─────────► Box Model, Block/Inline Flow, Flexbox, Grid, Table, Positioning
│
▼
Paint Engine ──────────► Stacking Context, Gradients, Shadows, Borders, Radii, Transforms
│
▼
Kyzz Native Renderer ──► Vector Rasterization (Resvg) + Text & OpenType Shaper
│
▼
Image Encoder ─────────► PNG / JPEG / WebP / SVG BufferQuick Example: HTML + CSS → Image
import { HTML } from 'kyzz-canvas';
const image = await HTML.render(`
<style>
.card {
width: 700px;
padding: 32px;
border-radius: 24px;
background: linear-gradient(135deg, #7c3aed, #ec4899);
box-shadow: 0 16px 32px rgba(124, 58, 237, 0.35);
color: white;
font-family: Inter, sans-serif;
}
.title {
font-size: 42px;
font-weight: 700;
margin-bottom: 8px;
}
.desc {
font-size: 18px;
opacity: 0.9;
}
</style>
<div class="card">
<div class="title">Kyzz Canvas</div>
<p class="desc">Pure HTML + CSS → Image Rendering Engine</p>
</div>
`, {
width: 700,
height: 'auto',
deviceScaleFactor: 2 // Output tajam 1400px (retina)
});
// Simpan ke file
await image.save('card.png');Atau gunakan method berantai langsung pada instance Canvas:
import { Canvas } from 'kyzz-canvas';
const canvas = new Canvas(800, 500);
await canvas.html(`
<div style="width: 700px; padding: 24px; background: #1e1b4b; border-radius: 16px; color: white;">
<h1>Kyzz Canvas</h1>
<p>Chained canvas.html()</p>
</div>
`, { x: 50, y: 50, width: 700 });
const buffer = await canvas.render('png');Integrasi Bot (WhatsApp, Telegram, Discord)
Hasil dari HTML.render() dapat langsung di-pass sebagai Buffer gambar ke berbagai library bot populer:
WhatsApp Bot (Baileys)
import { HTML } from 'kyzz-canvas';
const buffer = await HTML.render(welcomeTemplate, {
width: 800,
height: 'auto',
deviceScaleFactor: 2,
variables: {
username: 'Kyuu',
memberCount: 1500
}
});
await sock.sendMessage(remoteJid, {
image: buffer,
caption: 'Welcome to the server!'
});Telegram Bot (Telegraf / Grammy)
const photo = await HTML.render(rankCardTemplate, {
width: 720,
height: 'auto',
deviceScaleFactor: 2
});
await bot.sendPhoto(chatId, photo);Discord Bot (discord.js)
const attachment = await HTML.render(leaderboardTemplate, {
width: 800,
height: 'auto'
});
await channel.send({
files: [attachment]
});Feature Matrix: Status Fitur Realistis
| Kategori | Fitur | Status | Detail & Catatan |
|---|---|---|---|
| HTML | Parser HTML | Stable | Parser pure-JS mandiri, mendukung tag modern, nested, entitas & custom tag |
| HTML | Custom Elements | Stable | Mendukung tag custom seperti <profile-card>, <rank-badge> tanpa error |
| HTML | Keamanan Script | Safe / Disabled | Tag <script>, atribut on*, dan URL javascript: diabaikan/dibersihkan |
| CSS | CSS Parser | Stable | Mendukung <style>, inline style="", @font-face, @import, shorthand |
| CSS | Selector & Specificity | Stable | *, tag, .class, #id, A B, A > B, A + B, A ~ B, [attr], :nth-child |
| CSS | CSS Variables | Stable | Mendukung :root { --var: ... } dan var(--var, fallback) dengan inheritance |
| CSS | CSS Calc | Stable | Evaluasi matematis calc() dengan operator +, -, *, / |
| Layout | Box Model | Stable | content-box, border-box, margin (termasuk auto), padding, border |
| Layout | Flexbox | Stable | direction, wrap, justify-content, align-items, gap, grow, shrink, order |
| Layout | CSS Grid | Stable | grid-template-columns: repeat(...), fr, px, %, gap, auto-placement |
| Layout | Positioning | Stable | static, relative, absolute, fixed, top/right/bottom/left, inset, z-index |
| Layout | Auto Height | Stable | height: 'auto' otomatis menghitung tinggi total layout konten secara presisi |
| Layout | Tables & Lists | Stable | <table>, <tr>, <th>, <td>, border-collapse, <ul>, <ol>, <li> |
| Desain | Gradients | Stable | linear-gradient(), radial-gradient() dengan sudut dan multi-stop |
| Desain | Box Shadow | Stable | Drop shadow blur, spread, offset-x/y, multiple shadow layers |
| Desain | Borders & Radius | Stable | Sudut membulat individual (border-top-left-radius, dll.), gaya solid/dashed/dotted |
| Efek | Transforms | Stable | rotate(), scale(), translate(), skew(), matrix(), transform-origin |
| Efek | Filters | Stable | blur(), brightness(), contrast(), grayscale(), saturate(), sepia() |
| Efek | Pseudo Elements | Stable | ::before dan ::after dengan content: "..." dan absolute positioning |
| Efek | Clipping & Overflow | Stable | overflow: hidden, clip-path: circle(), ellipse(), polygon() |
| Media | Gambar (<img>) | Stable | Local, remote, CDN, data URI, object-fit: cover / contain / fill, border-radius clip |
| Media | Inline SVG (<svg>) | Stable | Vektor SVG langsung di-render dalam layout dengan styling CSS |
| Font | Remote Web Fonts | Stable | Resolusi otomatis @font-face dengan URL, Google Fonts, dan font fallback |
| Security| SSRF Guard | Stable | Pemblokiran otomatis IP privat, metadata cloud, localhost, dan timeout limit |
| Kompabilitas| Browser DOM Penuh | Partial | Didesain khusus untuk layout & pembuatan gambar statis server-side |
| Kompabilitas| Eksekusi JavaScript | Not Supported | Engine ini adalah static image renderer, bukan browser runtime |
Flexbox & CSS Grid Layout
Flexbox
Mendukung penuh tata letak kartu yang fleksibel:
<div class="row">
<img class="avatar" src="avatar.png" />
<div class="content">
<h3>Username</h3>
<p>Online</p>
</div>
</div>
<style>
.row {
display: flex;
align-items: center;
gap: 16px;
padding: 20px;
background: #18181b;
}
.avatar {
width: 64px;
height: 64px;
border-radius: 50%;
object-fit: cover;
}
.content {
flex: 1;
}
</style>CSS Grid
Mendukung pembuatan leaderboard, dashboard stats, dan galeri:
<div class="stats-grid">
<div class="stat-box">Level: 45</div>
<div class="stat-box">Wins: 120</div>
<div class="stat-box">Rank: #3</div>
</div>
<style>
.stats-grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 12px;
width: 600px;
}
.stat-box {
background: #27272a;
padding: 16px;
border-radius: 12px;
text-align: center;
}
</style>Template Variables & Custom Components
Variabel Template (variables)
Sisipkan variabel dinamis tanpa library templating eksternal:
await HTML.render(`
<h1>Halo, {{user.name}}!</h1>
<p>Poin Anda: {{points}}</p>
`, {
variables: {
user: { name: 'Kyuu' },
points: 12500
}
});Custom Component
Daftarkan komponen reusable untuk kemudahan generator template:
HTML.component('rank-badge', ({ props }) => `
<span style="background: #f59e0b; color: #000; font-weight: bold; padding: 4px 10px; border-radius: 8px;">
RANK #${props.number || '1'}
</span>
`);
await HTML.render(`
<div class="card">
<rank-badge number="1" />
</div>
`);Auto Height, Device Scale Factor & Measurement
Auto Height (height: 'auto')
Sangat berguna untuk kartu teks dinamis seperti quote card, log chat, atau leaderboard yang panjangnya berubah-ubah:
const result = await HTML.render(html, {
width: 800,
height: 'auto' // Tinggi dihitung otomatis berdasarkan konten
});Measurement API (HTML.measure)
Menghitung dimensi tanpa merender atau mengkode gambar, menghemat CPU untuk layout planning:
const { width, height } = await HTML.measure(html, { width: 800 });
console.log(`Dimensi yang dibutuhkan: ${width}x${height}px`);Device Scale Factor (Retina / 2x / 3x)
Hasilkan gambar beresolusi tajam tanpa mengubah ukuran CSS:
const retinaImage = await HTML.render(html, {
width: 600,
height: 400,
deviceScaleFactor: 2 // Menghasilkan gambar 1200x800px super tajam
});Debug Mode
Ingin melihat bagaimana parser memproses dokumen dan layout tree? Aktifkan debug: true:
const result = await HTML.render(html, {
width: 800,
debug: true
});
console.log(result.debugInfo.dom); // Struktur pohon DOM
console.log(result.debugInfo.layout); // Koordinat setiap layout box
console.log(result.debugInfo.styles); // Computed CSS style setiap element🏛️ Arsitektur & Konsep Engine
Kyzz Canvas dirancang dari awal dengan pemisahan komponen yang bersih:
Kyzz Canvas
├── Canvas High-level fluent builder & orchestration
├── Scene Graph Hierarchical vector tree & transformation stack
├── Font Manager Multi-source loader, shaper & fallback resolver
├── Universal Asset Loader HTTP/HTTPS, GitHub, CDN, Cloudflare, Buffer, Data URL
├── Security Guard SSRF protector, private IP blocker & SVG sanitizer
├── Image Engine Sharp-accelerated resizing, rounded avatar, blur
├── SVG Engine Vector parser, path normalizer & viewBox scaler
└── Encoders libvips-powered PNG, JPEG, WebP, GIF generator🌐 Universal Asset Loader
Kyzz Canvas memiliki sistem pemuatan aset universal terpadu dengan perlindungan keamanan bawaan:
Sumber Aset yang Didukung
- Local Filesystem: Path relatif (
./assets/logo.png) dan absolut (/var/data/avatar.jpg). - HTTP / HTTPS URL: Mengunduh aset jarak jauh secara otomatis.
- GitHub URL: Otomatis mengubah URL
github.com/.../blob/...menjadi URL raw tanpa error 404 HTML. - Google Fonts: Resolusi stylesheet dan unduhan binary font otomatis.
- CDN: jsDelivr, unpkg, cdnjs, Cloudflare R2, Cloudflare Pages.
- Data URL: Skema
data:image/png;base64,...ataudata:font/ttf;base64,.... - Binary Objek:
Buffer,Uint8Array,ArrayBuffer. - Web API Objek: Web API
ResponsedanBlob.
Proteksi Keamanan SSRF Bawaan
Engine otomatis memvalidasi setiap URL eksternal:
- Memblokir private network & localhost (
127.0.0.1,localhost,10.0.0.0/8,192.168.0.0/16,172.16.0.0/12). - Memblokir cloud metadata endpoints (
169.254.169.254). - Memblokir protokol non-HTTP seperti
file://,ftp://,gopher://. - Mencegah serangan SVG XXE dan injeksi tag
<script>/ handleronload.
Konfigurasi Cache & Timeout
import { assets } from 'kyzz-canvas/assets';
assets.config({
cache: true,
maxItems: 200,
maxSize: '150MB',
timeout: 10000,
diskCache: true,
cacheDir: './.kyzz-cache'
});🔤 Sistem Font & Google Fonts
1. Zero-Config Bundled Font
Setiap instalasi kyzz-canvas menyertakan font DejaVu Sans. Teks langsung dirender tanpa konfigurasi tambahan pada Docker container atau Linux serverless.
2. Mengambil Google Fonts
import { fonts } from 'kyzz-canvas/fonts';
await fonts.google('Inter');
await fonts.google('Fira Code', {
weight: [400, 600, 700],
style: 'normal'
});3. Font dari GitHub & Remote CDN
await fonts.add('https://github.com/google/fonts/blob/main/ofl/roboto/Roboto-Bold.ttf', {
family: 'Roboto',
weight: 700
});
await fonts.add('https://cdn.jsdelivr.net/npm/@fontsource/inter/files/inter-latin-400-normal.woff');4. Font dari Local File & Buffer
fonts.add('./fonts/CustomFont.ttf', { family: 'CustomFont' });
fonts.add(fontBuffer, { family: 'DynamicFont', weight: 600 });5. Multi-Font Fallback Otomatis
fonts.fallback([
'Inter',
'Noto Sans Arabic',
'Noto Sans JP',
'Noto Color Emoji',
'DejaVu Sans',
'sans-serif'
]);Jika font utama tidak memiliki glyph tertentu (misal: tulisan Arab, Kanji, atau Emoji), engine secara otomatis mencari glyph ke font fallback dalam urutan rantai yang ditentukan.
🖼️ Manipulasi Gambar & Foto Profil (PP)
Kyzz Canvas dirancang khusus untuk memproses foto profil bot WhatsApp, Discord, dan Telegram tanpa repot:
import { Canvas, Image, KyzzImage, createImage } from 'kyzz-canvas';
const img = await Image.from('https://example.com/avatar.jpg');
const roundAvatar = await img
.resize(200, 200)
.circle()
.toBuffer();
const cardBanner = await Image.from('./assets/banner.png')
.resize(800, 300)
.roundCorners(24)
.blur(2)
.toBuffer('webp');Menempelkan Foto Profil (PP) dengan Fallback Otomatis
Jika URL foto profil kosong (null, undefined, atau privacy WhatsApp diset ke private) atau gagal dimuat dari WhatsApp CDN, gunakan fitur fallback:
await canvas.image(ppUrl, {
x: 40,
y: 40,
width: 120,
height: 120,
radius: 60,
fit: 'cover',
fallback: true // otomatis menampilkan avatar kontak bawaan jika link kosong atau gagal!
});Anda juga dapat menyediakan file fallback kustom:
await canvas.image(ppUrl, {
x: 40,
y: 40,
width: 120,
height: 120,
radius: 60,
fallback: './assets/avatar_contact.png'
});Validasi Gambar (validateImage & isValidImage)
Sebelum memproses gambar dari user atau URL eksternal, Anda dapat memvalidasinya secara instan:
import { validateImage, isValidImage } from 'kyzz-canvas';
const check = await validateImage(avatarUrlOrBuffer);
if (check.valid) {
console.log('Format:', check.format, 'Ukuran:', check.width, 'x', check.height);
} else {
console.log('Bukan gambar valid:', check.error);
}
if (await isValidImage(input)) {
await canvas.image(input, { x: 50, y: 50, width: 100, height: 100 });
}📐 Engine SVG Kelas Satu
Kyzz Canvas mendukung parsing dan rendering SVG secara native, baik string SVG maupun URL eksternal:
await canvas.svg('<svg viewBox="0 0 100 100"><circle cx="50" cy="50" r="40" fill="#38bdf8"/></svg>', {
x: 50,
y: 50,
width: 80,
height: 80
});
await canvas.svg('https://cdn.example.com/icons/shield.svg', {
x: 150,
y: 50,
width: 80,
height: 80
});Standalone SVG Rendering:
import { renderSvgToBuffer } from 'kyzz-canvas/svg';
const buffer = await renderSvgToBuffer('<svg>...</svg>', {
width: 1024,
height: 1024,
format: 'png'
});🛠️ Daftar Lengkap Method Canvas
Inisialisasi
const canvas = new Canvas(width, height);Background
canvas.bg('#111827');
canvas.background('rgb(17, 24, 39)');
canvas.bg({
type: 'linear',
x1: 0,
y1: 0,
x2: 600,
y2: 0,
stops: [
{ offset: 0, color: '#3b82f6' },
{ offset: 1, color: '#8b5cf6' }
]
});Kotak & Persegi Panjang (box / rect)
canvas.box(x, y, width, height, {
radius: 16,
fill: '#1e293b',
stroke: '#38bdf8',
strokeWidth: 2,
shadow: {
color: 'rgba(0, 0, 0, 0.4)',
blur: 10,
offsetX: 0,
offsetY: 4
}
});Lingkaran & Elips (circle / ellipse)
canvas.circle(cx, cy, radius, {
fill: '#10b981',
stroke: '#ffffff',
strokeWidth: 2
});
canvas.ellipse(cx, cy, rx, ry, {
fill: '#ec4899'
});Garis & Poligon (line / polygon / path)
canvas.line(x1, y1, x2, y2, {
stroke: '#f59e0b',
strokeWidth: 3,
dash: [8, 4]
});
canvas.polygon([
{ x: 100, y: 50 },
{ x: 150, y: 150 },
{ x: 50, y: 150 }
], {
fill: '#8b5cf6'
});
canvas.path('M 10 80 Q 95 10 180 80 T 350 80', {
stroke: '#06b6d4',
strokeWidth: 4,
fill: 'none'
});Tipografi & Teks (text)
canvas.text('Hello World', {
x: 50,
y: 100,
size: 32,
font: 'Poppins',
weight: 600,
color: '#ffffff',
align: 'left',
baseline: 'alphabetic',
letterSpacing: 1.5,
maxWidth: 400
});Transformasi & State
canvas.save();
canvas.translate(100, 50);
canvas.rotate(45, cx, cy);
canvas.scale(1.5, 1.5);
canvas.restore();Resource Management
canvas.dispose();💾 Format Output & File Export
const pngBuf = await canvas.render('png');
const jpgBuf = await canvas.render('jpeg', { quality: 85 });
const webpBuf = await canvas.render('webp', { quality: 90, lossless: false });
const gifBuf = await canvas.render('gif');
await canvas.save('./card.png');
await canvas.save('./card.webp', { quality: 85 });🤖 Contoh Implementasi Bot
WhatsApp Bot (Baileys)
import makeWASocket from '@whiskeysockets/baileys';
import { Canvas } from 'kyzz-canvas';
async function sendWelcome(sock, jid, pushName) {
const canvas = new Canvas(800, 350);
canvas.bg('#111827');
canvas.box(30, 30, 740, 290, { radius: 16, fill: '#1f2937' });
canvas.circle(120, 175, 50, { fill: '#25d366' });
canvas.text(pushName, { x: 200, y: 160, size: 36, color: '#ffffff' });
canvas.text('Selamat bergabung di grup!', { x: 200, y: 200, size: 20, color: '#9ca3af' });
const buffer = await canvas.render('jpeg', { quality: 85 });
await sock.sendMessage(jid, {
image: buffer,
caption: `Halo @${jid.split('@')[0]}! Selamat datang!`,
mentions: [jid]
});
}Telegram Bot (Telegraf)
import { Telegraf } from 'telegraf';
import { Canvas } from 'kyzz-canvas';
const bot = new Telegraf(process.env.BOT_TOKEN);
bot.command('profile', async (ctx) => {
const canvas = new Canvas(600, 300);
canvas.bg('#0f172a');
canvas.box(20, 20, 560, 260, { radius: 16, fill: '#1e293b' });
canvas.text(ctx.from.first_name, { x: 50, y: 100, size: 32, color: '#38bdf8' });
canvas.text(`ID: ${ctx.from.id}`, { x: 50, y: 140, size: 18, color: '#94a3b8' });
const buffer = await canvas.render('png');
await ctx.replyWithPhoto({ source: buffer });
});
bot.launch();Discord Bot (discord.js)
import { Client, GatewayIntentBits, AttachmentBuilder } from 'discord.js';
import { Canvas } from 'kyzz-canvas';
const client = new Client({ intents: [GatewayIntentBits.Guilds, GatewayIntentBits.GuildMembers] });
client.on('guildMemberAdd', async (member) => {
const channel = member.guild.systemChannel;
if (!channel) return;
const canvas = new Canvas(800, 300);
canvas.bg('#18191c');
canvas.box(20, 20, 760, 260, { radius: 20, fill: '#2f3136' });
const avatarUrl = member.user.displayAvatarURL({ extension: 'png', size: 256 });
await canvas.image(avatarUrl, { x: 50, y: 60, width: 140, height: 140, radius: 70 });
canvas.text(member.user.tag, { x: 220, y: 130, size: 36, color: '#ffffff' });
canvas.text(`Member #${member.guild.memberCount}`, { x: 220, y: 175, size: 20, color: '#5865f2' });
const buffer = await canvas.render('png');
const attachment = new AttachmentBuilder(buffer, { name: 'welcome.png' });
await channel.send({ content: `Selamat datang, ${member}!`, files: [attachment] });
});
client.login(process.env.DISCORD_TOKEN);🌐 Contoh Web Framework & Server
Express.js
import express from 'express';
import { Canvas } from 'kyzz-canvas';
const app = express();
app.get('/api/card', async (req, res) => {
const title = req.query.title || 'Dynamic Card';
const canvas = new Canvas(600, 300);
canvas.bg('#0f172a');
canvas.text(String(title), { x: 50, y: 150, size: 32, color: '#ffffff' });
const image = await canvas.render('webp', { quality: 80 });
res.setHeader('Content-Type', 'image/webp');
res.setHeader('Cache-Control', 'public, max-age=3600');
res.send(image);
});
app.listen(3000);Hono
import { Hono } from 'hono';
import { Canvas } from 'kyzz-canvas';
const app = new Hono();
app.get('/og-image', async (c) => {
const canvas = new Canvas(1200, 630);
canvas.bg('#09090b');
canvas.text('Hono + Kyzz Canvas', { x: 80, y: 320, size: 56, color: '#fafafa' });
const buffer = await canvas.render('png');
return c.body(buffer, 200, {
'Content-Type': 'image/png',
'Cache-Control': 'public, max-age=86400'
});
});
export default app;Fastify
import Fastify from 'fastify';
import { Canvas } from 'kyzz-canvas';
const fastify = Fastify();
fastify.get('/badge', async (request, reply) => {
const canvas = new Canvas(300, 100);
canvas.bg('#10b981');
canvas.text('Status: Active', { x: 30, y: 60, size: 24, color: '#ffffff' });
const buffer = await canvas.render('png');
reply.type('image/png').send(buffer);
});
fastify.listen({ port: 3000 });Bun Native HTTP
import { Canvas } from 'kyzz-canvas';
Bun.serve({
port: 3000,
async fetch(req) {
const canvas = new Canvas(500, 200);
canvas.bg('#0284c7');
canvas.text('Powered by Bun & Kyzz', { x: 40, y: 110, size: 28, color: '#ffffff' });
const buffer = await canvas.render('png');
return new Response(buffer, {
headers: { 'Content-Type': 'image/png' }
});
}
});⚛️ Virtual Component / JSX Adapter
Anda dapat menggunakan objek bergaya JSX atau deklaratif untuk mendeskripsikan elemen:
import { renderElement } from 'kyzz-canvas/react';
const buffer = await renderElement({
type: 'box',
props: {
width: 600,
height: 300,
bg: '#0f172a',
children: [
{
type: 'text',
props: {
x: 40,
y: 80,
text: 'Declarative Canvas',
size: 32,
color: '#38bdf8'
}
}
]
}
}, { format: 'png' });🎨 HTML5 Canvas 2D Compatibility Adapter
Jika Anda memiliki kode lama yang menggunakan pola ctx.fillRect() atau ctx.fillText(), Anda dapat menggunakan adapter WebCanvas:
import { WebCanvas } from 'kyzz-canvas/web';
const webCanvas = new WebCanvas(500, 300);
const ctx = webCanvas.getContext('2d');
ctx.fillStyle = '#1e1b4b';
ctx.fillRect(0, 0, 500, 300);
ctx.fillStyle = '#a855f7';
ctx.font = '24px sans-serif';
ctx.fillText('HTML5 Canvas 2D Compatibility', 30, 80);
const buffer = await webCanvas.toBuffer('png');📊 Tabel Benchmark Resmi
Pengujian dilakukan pada Node.js v22 & Bun v1.4 (AMD64 Linux):
| Kategori Pengujian | Latensi Rata-Rata | Throughput Render | |---|---|---| | Shapes & Vector Rendering | 42.35 ms | 1,417 /menit | | Typography & Text Metrics | 46.06 ms | 1,303 /menit | | Standalone SVG Rendering | 31.97 ms | 1,877 /menit | | 800x400 PNG Encoding | 0.96 ms | 62,271 /menit | | 800x400 JPEG Encoding | 1.81 ms | 33,138 /menit | | 800x400 WebP Encoding | 1.86 ms | 32,178 /menit | | Peak Heap Memory Usage | ~32.9 MB | Sangat hemat memori |
📦 Daftar Subpath Modules
Package diekspor secara modular untuk efisiensi treeshaking:
| Subpath Import | Isi & Fungsi |
|---|---|
| kyzz-canvas | Canvas, fonts, assets, KyzzImage, singleton utama |
| kyzz-canvas/fonts | FontManager, fonts, Google Fonts resolver, OpenType shaper |
| kyzz-canvas/svg | renderSvgToBuffer, parseSvgViewBox, engine SVG |
| kyzz-canvas/image | KyzzImage, resize, crop, avatar circle, filter blur |
| kyzz-canvas/assets | UniversalAssetLoader, assets, disk cache, SSRF validator |
| kyzz-canvas/web | WebCanvas, CanvasRenderingContext2D adapter |
| kyzz-canvas/react | renderElement, declarative virtual JSX adapter |
| kyzz-canvas/html | HTML, HTMLEngine, parseHTML, parseStylesheet, full HTML+CSS renderer |
| kyzz-canvas/errors | Kelas error terstruktur (HTMLRenderError, FontNotFoundError, KyzzCanvasError, dll.) |
🤖 Prompt AI / System Instructions for LLMs
Salin dan gunakan instruksi di bawah ini saat meminta bantuan AI (seperti ChatGPT, Claude, Gemini, Cursor, Copilot, atau Antigravity) untuk membuat kode menggunakan Kyzz Canvas:
Anda adalah asisten coding ahli dalam menggunakan library rendering gambar Node.js/Bun bernama "Kyzz Canvas" (package npm: "kyzz-canvas").
ATURAN PALING KRUSIAL:
1. JANGAN PERNAH menyarankan atau menggunakan "@napi-rs/canvas" atau "node-canvas".
2. JANGAN PERNAH menulis pola legacy "ctx" (seperti `canvas.getContext('2d')`, `ctx.fillText`, `ctx.fillRect`, `ctx.beginPath()`) kecuali user secara eksplisit meminta adapter "kyzz-canvas/web".
3. Kyzz Canvas memiliki API custom sendiri yang berorientasi objek, berantai (fluent), dan intuitif:
- Membuat canvas: `const canvas = new Canvas(width, height)`
- Background: `canvas.bg('#111')` atau `canvas.background({ type: 'linear', ... })`
- Teks: `canvas.text('Hello', { x: 40, y: 80, size: 32, font: 'Inter', color: '#fff' })`
- Kotak / Rect: `canvas.box(x, y, w, h, { radius: 16, fill: '#5865f2' })` atau `canvas.rect(...)`
- Lingkaran: `canvas.circle(cx, cy, radius, { fill: '#10b981' })`
- Elips: `canvas.ellipse(cx, cy, rx, ry, { fill: '#ec4899' })`
- Garis: `canvas.line(x1, y1, x2, y2, { stroke: '#fff', strokeWidth: 2 })`
- Poligon: `canvas.polygon([{x, y}, ...], { fill: '#fff' })`
- Path SVG: `canvas.path('M ... Z', { fill: '#fff' })`
- Gambar: `await canvas.image(urlOrBuffer, { x, y, width, height, radius })`
- SVG: `await canvas.svg(svgStringOrUrl, { x, y, width, height })`
- Render output: `const buffer = await canvas.render('png')` (bisa juga 'jpeg', 'webp', 'gif')
- Simpan ke file: `await canvas.save('./output.png')`
- Free memory: `canvas.dispose()`
PENGELOLAAN FONT:
- Library sudah memiliki font bawaan "DejaVu Sans" yang langsung aktif tanpa konfigurasi.
- Mengambil font Google secara langsung:
`import { fonts } from 'kyzz-canvas/fonts';`
`await fonts.google('Poppins', { weight: [400, 700] });`
- Font dari URL / GitHub / CDN:
`await fonts.add('https://example.com/font.ttf', { family: 'MyFont' });`
- Rantai fallback otomatis:
`fonts.fallback(['Poppins', 'DejaVu Sans', 'sans-serif']);`
MANIPULASI GAMBAR & AVATAR:
- `import { Image, KyzzImage } from 'kyzz-canvas';`
- `const avatar = await Image.from(urlOrBuffer).resize(200, 200).circle().toBuffer();`
- Menempel PP ke Canvas: `await canvas.image(ppUrl, { x: 40, y: 40, width: 120, height: 120, radius: 60, fallback: true });`
- Fallback otomatis menangani PP WhatsApp yang null/private atau koneksi lambat.
MODUL EKSPOR LANGSUNG DARI ROOT (PROFESSIONAL):
- Semua fitur dapat diimpor langsung dari root package:
`import { Canvas, fonts, assets, Image, KyzzImage, WebCanvas, createCanvas, createImage, renderSvg } from 'kyzz-canvas';`
- Subpath ekspor opsional tetap tersedia (`kyzz-canvas/fonts`, `kyzz-canvas/image`, dll.).
KARAKTERISTIK TEKNIS:
- Multi-runtime: Kompatibel 100% dengan Node.js (CommonJS & ESM) dan Bun.
- Otomatis mendeteksi format gambar (JPEG, PNG, WebP) via magic bytes sehingga foto profil WhatsApp JPEG dirender sempurna tanpa blank.
- Selalu gunakan async/await saat memanggil `canvas.render()`, `canvas.save()`, `canvas.image()`, `canvas.svg()`, dan `fonts.add()`.📄 Lisensi
Didistribusikan di bawah lisensi MIT. Bebas digunakan untuk keperluan komersial, open source, bot WhatsApp, Telegram, Discord, maupun project pribadi.
Dibuat dengan ❤️ oleh Kyzz Canvas Team & kyzzknz.
