Skip to main content

Platform Integrations

Chartly integrates seamlessly with popular platforms, frameworks, and services using simple HTTP requests. This guide covers platform-specific integration examples and best practices.

PlatformTypeUse Case
JavaScript/Node.jsHTTP ClientClient & server usage
PythonHTTP ClientFlask, Django, FastAPI
ReactFrontend FrameworkDynamic chart components
SlackBot IntegrationSlash commands & apps
EmailHTML/EmailReports & notifications
No-CodeAutomationZapier, Make.com

JavaScript & Node.js

Basic HTTP Request

async function generateChart(chartConfig) {
const response = await fetch('https://api.chartly.dev/v1/chart', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-Api-Key': process.env.CHARTLY_API_KEY
},
body: JSON.stringify({
chart: chartConfig,
width: 600,
height: 400,
format: 'png'
})
});

if (!response.ok) {
throw new Error(`Chart generation failed: ${response.statusText}`);
}

return await response.arrayBuffer();
}

// Usage
const chartBuffer = await generateChart({
type: 'bar',
data: {
labels: ['Q1', 'Q2', 'Q3', 'Q4'],
datasets: [{
label: 'Revenue',
data: [100, 120, 115, 134]
}]
},
options: { responsive: false }
});

// Save to file
require('fs').writeFileSync('chart.png', Buffer.from(chartBuffer));

Express.js Integration

const express = require('express');
const app = express();

app.use(express.json());

app.post('/generate-chart', async (req, res) => {
try {
const { chartConfig, width = 600, height = 400 } = req.body;

const response = await fetch('https://api.chartly.dev/v1/chart', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-Api-Key': process.env.CHARTLY_API_KEY
},
body: JSON.stringify({
chart: chartConfig,
width,
height,
format: 'png'
})
});

if (!response.ok) {
return res.status(500).json({ error: 'Chart generation failed' });
}

const chartBuffer = await response.arrayBuffer();

res.setHeader('Content-Type', 'image/png');
res.setHeader('Cache-Control', 'public, max-age=3600');
res.send(Buffer.from(chartBuffer));
} catch (error) {
console.error('Chart generation error:', error);
res.status(500).json({ error: error.message });
}
});

app.listen(3000);

Next.js API Route

// pages/api/chart.js or app/api/chart/route.js
export default async function handler(req, res) {
if (req.method !== 'POST') {
return res.status(405).json({ error: 'Method not allowed' });
}

try {
const { chart, width = 600, height = 400, format = 'png' } = req.body;

const response = await fetch('https://api.chartly.dev/v1/chart', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-Api-Key': process.env.CHARTLY_API_KEY
},
body: JSON.stringify({
chart,
width,
height,
format
})
});

if (!response.ok) {
throw new Error('Chart generation failed');
}

const chartBuffer = await response.arrayBuffer();

res.setHeader('Content-Type', `image/${format}`);
res.setHeader('Cache-Control', 'public, max-age=3600');
res.send(Buffer.from(chartBuffer));
} catch (error) {
res.status(500).json({ error: 'Chart generation failed' });
}
}

Creating Permanent Chart URLs

async function createPermanentChartUrl(chartConfig) {
const response = await fetch('https://api.chartly.dev/v1/chart/create', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-Api-Key': process.env.CHARTLY_API_KEY
},
body: JSON.stringify({
chart: chartConfig,
width: 600,
height: 400,
format: 'png'
})
});

const data = await response.json();
return data.url;
}

// Usage
const chartUrl = await createPermanentChartUrl({
type: 'line',
data: {
labels: ['Jan', 'Feb', 'Mar'],
datasets: [{ data: [10, 20, 15] }]
},
options: { responsive: false }
});

console.log(`Chart available at: ${chartUrl}`);

Python

Basic HTTP Request

import requests
import json

def generate_chart(chart_config, width=600, height=400, format='png'):
"""Generate a chart using Chartly API"""

response = requests.post(
'https://api.chartly.dev/v1/chart',
headers={
'Content-Type': 'application/json',
'X-Api-Key': os.environ['CHARTLY_API_KEY']
},
json={
'chart': chart_config,
'width': width,
'height': height,
'format': format
}
)

response.raise_for_status() # Raises an exception for bad status codes
return response.content

# Usage
chart_config = {
"type": "line",
"data": {
"labels": ["Jan", "Feb", "Mar", "Apr"],
"datasets": [{
"label": "Sales",
"data": [12, 19, 3, 5],
"borderColor": "rgb(75, 192, 192)",
"tension": 0.1
}]
},
"options": {"responsive": False}
}

chart_bytes = generate_chart(chart_config)

# Save to file
with open("chart.png", "wb") as f:
f.write(chart_bytes)

Flask Integration

from flask import Flask, request, jsonify, send_file
import requests
import io
import os

app = Flask(__name__)

@app.route('/chart', methods=['POST'])
def generate_chart():
"""Generate chart endpoint"""
try:
data = request.get_json()

response = requests.post(
'https://api.chartly.dev/v1/chart',
headers={
'Content-Type': 'application/json',
'X-Api-Key': os.environ['CHARTLY_API_KEY']
},
json={
'chart': data['chart'],
'width': data.get('width', 600),
'height': data.get('height', 400),
'format': data.get('format', 'png')
}
)

if response.status_code != 200:
return jsonify({'error': 'Chart generation failed'}), 500

return send_file(
io.BytesIO(response.content),
mimetype=f"image/{data.get('format', 'png')}",
as_attachment=False,
download_name='chart.png'
)
except Exception as e:
return jsonify({'error': str(e)}), 500

if __name__ == '__main__':
app.run(debug=True)

Django Integration

# views.py
from django.http import HttpResponse, JsonResponse
from django.views.decorators.csrf import csrf_exempt
from django.views.decorators.http import require_http_methods
import requests
import json
import os

@csrf_exempt
@require_http_methods(["POST"])
def generate_chart(request):
"""Django view for chart generation"""
try:
data = json.loads(request.body)

response = requests.post(
'https://api.chartly.dev/v1/chart',
headers={
'Content-Type': 'application/json',
'X-Api-Key': os.environ['CHARTLY_API_KEY']
},
json={
'chart': data['chart'],
'width': data.get('width', 600),
'height': data.get('height', 400),
'format': data.get('format', 'png')
}
)

if response.status_code != 200:
return JsonResponse({'error': 'Chart generation failed'}, status=500)

http_response = HttpResponse(
response.content,
content_type=f"image/{data.get('format', 'png')}"
)
http_response['Cache-Control'] = 'public, max-age=3600'
return http_response

except Exception as e:
return JsonResponse({'error': str(e)}, status=500)

# urls.py
from django.urls import path
from . import views

urlpatterns = [
path('chart/', views.generate_chart, name='generate_chart'),
]

FastAPI Integration

from fastapi import FastAPI, HTTPException
from fastapi.responses import Response
import requests
import os
from pydantic import BaseModel
from typing import Optional

app = FastAPI()

class ChartRequest(BaseModel):
chart: dict
width: Optional[int] = 600
height: Optional[int] = 400
format: Optional[str] = "png"

@app.post("/chart")
async def generate_chart(request: ChartRequest):
"""FastAPI endpoint for chart generation"""
try:
response = requests.post(
'https://api.chartly.dev/v1/chart',
headers={
'Content-Type': 'application/json',
'X-Api-Key': os.environ['CHARTLY_API_KEY']
},
json={
'chart': request.chart,
'width': request.width,
'height': request.height,
'format': request.format
}
)

if response.status_code != 200:
raise HTTPException(status_code=500, detail="Chart generation failed")

media_type = f"image/{request.format}"
return Response(
content=response.content,
media_type=media_type,
headers={"Cache-Control": "public, max-age=3600"}
)

except requests.RequestException as e:
raise HTTPException(status_code=500, detail=str(e))

# Usage
# uvicorn main:app --reload

React

Chart Component with HTTP Requests

import { useState, useEffect } from 'react';

function Chart({ config, width = 600, height = 400 }) {
const [chartUrl, setChartUrl] = useState(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);

useEffect(() => {
const generateChart = async () => {
try {
setLoading(true);
setError(null);

// Call your backend endpoint that proxies to Chartly
const response = await fetch('/api/generate-chart', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
chart: config,
width,
height,
format: 'png'
})
});

if (!response.ok) {
throw new Error('Chart generation failed');
}

const blob = await response.blob();
const url = URL.createObjectURL(blob);
setChartUrl(url);
} catch (err) {
setError(err.message);
} finally {
setLoading(false);
}
};

if (config) {
generateChart();
}

// Cleanup blob URL
return () => {
if (chartUrl) {
URL.revokeObjectURL(chartUrl);
}
};
}, [config, width, height]);

if (loading) return <div>Loading chart...</div>;
if (error) return <div>Error: {error}</div>;

return chartUrl ? (
<img
src={chartUrl}
alt="Generated Chart"
width={width}
height={height}
style={{ maxWidth: '100%', height: 'auto' }}
/>
) : null;
}

// Usage
function Dashboard() {
const chartConfig = {
type: 'bar',
data: {
labels: ['Product A', 'Product B', 'Product C'],
datasets: [{
label: 'Sales',
data: [100, 150, 120],
backgroundColor: 'rgba(54, 162, 235, 0.8)'
}]
},
options: { responsive: false }
};

return (
<div>
<h1>Sales Dashboard</h1>
<Chart config={chartConfig} width={600} height={400} />
</div>
);
}

Custom Hook for Chart Generation

import { useState, useEffect } from 'react';

function useChart(config, options = {}) {
const [chartUrl, setChartUrl] = useState(null);
const [loading, setLoading] = useState(false);
const [error, setError] = useState(null);

const { width = 600, height = 400, format = 'png' } = options;

useEffect(() => {
if (!config) return;

const generateChart = async () => {
try {
setLoading(true);
setError(null);

const response = await fetch('/api/generate-chart', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
chart: config,
width,
height,
format
})
});

if (!response.ok) {
throw new Error('Failed to generate chart');
}

const blob = await response.blob();
const url = URL.createObjectURL(blob);

// Clean up previous URL
if (chartUrl) {
URL.revokeObjectURL(chartUrl);
}

setChartUrl(url);
} catch (err) {
setError(err.message);
} finally {
setLoading(false);
}
};

generateChart();
}, [config, width, height, format]);

// Cleanup on unmount
useEffect(() => {
return () => {
if (chartUrl) {
URL.revokeObjectURL(chartUrl);
}
};
}, [chartUrl]);

return { chartUrl, loading, error };
}

// Usage
function ChartWidget({ data }) {
const chartConfig = {
type: 'line',
data: data,
options: { responsive: false }
};

const { chartUrl, loading, error } = useChart(chartConfig, {
width: 500,
height: 300
});

if (loading) return <div>Loading chart...</div>;
if (error) return <div>Error: {error}</div>;

return chartUrl ? (
<img src={chartUrl} alt="Chart" width={500} height={300} />
) : null;
}

Slack

Basic Slack Bot Integration

const { App } = require('@slack/bolt');

const app = new App({
token: process.env.SLACK_BOT_TOKEN,
signingSecret: process.env.SLACK_SIGNING_SECRET
});

// Slash command: /chart
app.command('/chart', async ({ command, ack, respond }) => {
await ack();

try {
// Parse command text for chart data
const chartData = parseChartCommand(command.text);

// Generate chart via Chartly API
const response = await fetch('https://api.chartly.dev/v1/chart', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-Api-Key': process.env.CHARTLY_API_KEY
},
body: JSON.stringify({
chart: chartData,
width: 600,
height: 400,
format: 'png'
})
});

if (!response.ok) {
throw new Error('Chart generation failed');
}

const chartBuffer = await response.arrayBuffer();

// Upload chart to Slack
await app.client.files.uploadV2({
token: process.env.SLACK_BOT_TOKEN,
channel_id: command.channel_id,
file: Buffer.from(chartBuffer),
filename: 'chart.png',
title: 'Generated Chart',
initial_comment: `Chart generated from: ${command.text}`
});

} catch (error) {
await respond(`Error generating chart: ${error.message}`);
}
});

function parseChartCommand(text) {
// Simple example - parse "bar 10 20 30" into chart config
const parts = text.split(' ');
const type = parts[0] || 'bar';
const data = parts.slice(1).map(Number).filter(n => !isNaN(n)) || [1, 2, 3];

return {
type,
data: {
labels: data.map((_, i) => `Item ${i + 1}`),
datasets: [{
label: 'Data',
data: data,
backgroundColor: 'rgba(54, 162, 235, 0.8)'
}]
},
options: { responsive: false }
};
}

(async () => {
await app.start(process.env.PORT || 3000);
console.log('⚡️ Slack bot is running!');
})();

Slack Block Kit Integration

app.command('/dashboard', async ({ command, ack, respond }) => {
await ack();

try {
// Generate multiple charts and get permanent URLs
const [salesChartUrl, trafficChartUrl] = await Promise.all([
createPermanentChart(salesChartConfig),
createPermanentChart(trafficChartConfig)
]);

await respond({
blocks: [
{
type: "header",
text: {
type: "plain_text",
text: "📊 Weekly Dashboard"
}
},
{
type: "section",
text: {
type: "mrkdwn",
text: "*Sales Performance*"
}
},
{
type: "image",
image_url: salesChartUrl,
alt_text: "Sales Chart"
},
{
type: "section",
text: {
type: "mrkdwn",
text: "*Website Traffic*"
}
},
{
type: "image",
image_url: trafficChartUrl,
alt_text: "Traffic Chart"
}
]
});
} catch (error) {
await respond(`Error generating dashboard: ${error.message}`);
}
});

async function createPermanentChart(chartConfig) {
const response = await fetch('https://api.chartly.dev/v1/chart/create', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-Api-Key': process.env.CHARTLY_API_KEY
},
body: JSON.stringify({
chart: chartConfig,
width: 600,
height: 400
})
});

const data = await response.json();
return data.url;
}

Email & HTML

HTML Email Templates

<!DOCTYPE html>
<html>
<head>
<title>Monthly Report</title>
<style>
.chart-container {
text-align: center;
margin: 20px 0;
}
.chart-image {
max-width: 100%;
height: auto;
border: 1px solid #e1e5e9;
border-radius: 8px;
}
</style>
</head>
<body>
<h1>Monthly Performance Report</h1>

<div class="chart-container">
<h2>Revenue Trends</h2>
<!-- Using permanent chart URL -->
<img src="https://api.chartly.dev/v1/chart/abc123def456"
alt="Monthly Revenue Chart"
class="chart-image"
width="600"
height="400">
</div>

<div class="chart-container">
<h2>Traffic Analysis</h2>
<!-- Using signed URL for time-limited access -->
<img src="https://api.chartly.dev/v1/chart?chart=...&exp=1642262400&sig=hmac_signature"
alt="Traffic Analysis Chart"
class="chart-image"
width="500"
height="300">
</div>
</body>
</html>

Email Service Integration

const nodemailer = require('nodemailer');

async function sendReportEmail(recipients, reportData) {
// Generate permanent chart URLs
const [salesChartUrl, trafficChartUrl] = await Promise.all([
createPermanentChart({
type: 'line',
data: reportData.sales,
options: { responsive: false }
}),
createPermanentChart({
type: 'bar',
data: reportData.traffic,
options: { responsive: false }
})
]);

// Configure email transporter
const transporter = nodemailer.createTransporter({
host: process.env.SMTP_HOST,
port: 587,
secure: false,
auth: {
user: process.env.SMTP_USER,
pass: process.env.SMTP_PASS
}
});

// Send email with embedded charts
await transporter.sendMail({
from: '"Reports Team" <reports@yourcompany.com>',
to: recipients.join(', '),
subject: `Monthly Report - ${new Date().toLocaleDateString()}`,
html: `
<h1>Monthly Performance Report</h1>

<h2>Sales Performance</h2>
<img src="${salesChartUrl}"
alt="Sales Chart"
width="600"
height="300"
style="max-width: 100%; height: auto;">

<h2>Website Traffic</h2>
<img src="${trafficChartUrl}"
alt="Traffic Chart"
width="600"
height="300"
style="max-width: 100%; height: auto;">

<p>Best regards,<br>The Analytics Team</p>
`
});
}

async function createPermanentChart(chartConfig) {
const response = await fetch('https://api.chartly.dev/v1/chart/create', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-Api-Key': process.env.CHARTLY_API_KEY
},
body: JSON.stringify({
chart: chartConfig,
width: 600,
height: 300
})
});

const data = await response.json();
return data.url;
}

No-Code Platforms

Zapier Integration

Chartly provides native Zapier integration for no-code automation workflows.

Setup Steps:

  1. Search for "Chartly" in Zapier
  2. Connect your account with your API key
  3. Choose from available triggers and actions

Available Actions:

  • Generate Chart from Data - Create charts from spreadsheet data
  • Create Permanent Chart URL - Generate shareable chart links
  • Get Chart Analytics - Retrieve usage metrics

Example Zap Workflow:

Trigger: New row in Google Sheets
Action: Generate chart from row data
Action: Post chart to Slack channel
Action: Send chart via email

Webhook Alternative: If using custom webhooks, send POST requests to:

https://api.chartly.dev/v1/chart/create

With payload:

{
"chart": {
"type": "{{chart_type}}",
"data": {
"labels": {{label_array}},
"datasets": [{
"data": {{data_array}},
"backgroundColor": "rgba(54, 162, 235, 0.8)"
}]
},
"options": {"responsive": false}
},
"width": 600,
"height": 400
}

Make.com (Integromat)

{
"scenario": {
"name": "Weekly Report Charts",
"modules": [
{
"type": "trigger",
"app": "schedule",
"config": {
"interval": "weekly",
"time": "09:00"
}
},
{
"type": "action",
"app": "airtable",
"action": "list_records",
"config": {
"table": "Sales Data"
}
},
{
"type": "http",
"method": "POST",
"url": "https://api.chartly.dev/v1/chart/create",
"headers": {
"Content-Type": "application/json",
"X-Api-Key": "{{your_api_key}}"
},
"body": {
"chart": {
"type": "line",
"data": {
"labels": "{{airtable.labels}}",
"datasets": [{
"data": "{{airtable.data}}"
}]
},
"options": {"responsive": false}
},
"width": 800,
"height": 400
}
},
{
"type": "action",
"app": "email",
"action": "send_email",
"config": {
"to": "team@company.com",
"subject": "Weekly Report",
"body": "<img src='{{http.url}}'>"
}
}
]
}
}

Bubble.io Integration

API Connector Setup:

  1. Go to Plugins → API Connector
  2. Add new API call:
    • Name: Chartly Generate Chart
    • Type: Action
    • Method: POST
    • URL: https://api.chartly.dev/v1/chart/create

Headers:

X-Api-Key: [Your API Key]
Content-Type: application/json

Body (JSON):

{
"chart": {
"type": "<chart_type>",
"data": {
"labels": <label_list>,
"datasets": [{
"data": <data_list>,
"backgroundColor": "rgba(54, 162, 235, 0.8)"
}]
},
"options": {"responsive": false}
},
"width": <width>,
"height": <height>
}

Usage in Workflows:

  • Trigger: Button clicked or data change
  • Action: Call Chartly Generate Chart API
  • Result: Use returned URL in Image element

Mobile Apps

React Native HTTP Integration

import React, { useState, useEffect } from 'react';
import { View, Image, ActivityIndicator, Text } from 'react-native';

const ChartComponent = ({ chartConfig, width = 350, height = 200 }) => {
const [chartUri, setChartUri] = useState(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);

useEffect(() => {
const generateChart = async () => {
try {
setLoading(true);
setError(null);

// Call your backend API that proxies to Chartly
const response = await fetch('https://your-backend.com/api/chart', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${userToken}`, // Your app's auth
},
body: JSON.stringify({
chart: chartConfig,
width,
height,
format: 'png'
})
});

if (!response.ok) {
throw new Error('Chart generation failed');
}

const blob = await response.blob();
const uri = URL.createObjectURL(blob);
setChartUri(uri);
} catch (err) {
setError(err.message);
} finally {
setLoading(false);
}
};

if (chartConfig) {
generateChart();
}
}, [chartConfig, width, height]);

if (loading) {
return (
<View style={{ justifyContent: 'center', alignItems: 'center', height }}>
<ActivityIndicator size="large" />
<Text>Generating chart...</Text>
</View>
);
}

if (error) {
return (
<View style={{ justifyContent: 'center', alignItems: 'center', height }}>
<Text>Error: {error}</Text>
</View>
);
}

return chartUri ? (
<Image
source={{ uri: chartUri }}
style={{ width, height }}
resizeMode="contain"
/>
) : null;
};

// Usage
export default function Dashboard() {
const chartConfig = {
type: 'bar',
data: {
labels: ['Jan', 'Feb', 'Mar'],
datasets: [{
label: 'Sales',
data: [100, 150, 120],
backgroundColor: 'rgba(54, 162, 235, 0.8)'
}]
},
options: { responsive: false }
};

return (
<View style={{ padding: 20 }}>
<Text style={{ fontSize: 18, fontWeight: 'bold', marginBottom: 10 }}>
Sales Chart
</Text>
<ChartComponent
chartConfig={chartConfig}
width={350}
height={200}
/>
</View>
);
}

Flutter HTTP Integration

import 'package:http/http.dart' as http;
import 'package:flutter/material.dart';
import 'dart:convert';
import 'dart:typed_data';

class ChartlyService {
final String apiKey;
final String baseUrl = 'https://api.chartly.dev';

ChartlyService({required this.apiKey});

Future<String> createChart(Map<String, dynamic> chartConfig, {
int width = 600,
int height = 400,
String format = 'png'
}) async {
final response = await http.post(
Uri.parse('$baseUrl/v1/chart/create'),
headers: {
'X-Api-Key': apiKey,
'Content-Type': 'application/json',
},
body: json.encode({
'chart': chartConfig,
'width': width,
'height': height,
'format': format,
}),
);

if (response.statusCode == 201) {
final data = json.decode(response.body);
return data['url'];
} else {
throw Exception('Failed to create chart: ${response.body}');
}
}

Future<Uint8List> generateChart(Map<String, dynamic> chartConfig, {
int width = 600,
int height = 400,
String format = 'png'
}) async {
final response = await http.post(
Uri.parse('$baseUrl/v1/chart'),
headers: {
'X-Api-Key': apiKey,
'Content-Type': 'application/json',
},
body: json.encode({
'chart': chartConfig,
'width': width,
'height': height,
'format': format,
}),
);

if (response.statusCode == 200) {
return response.bodyBytes;
} else {
throw Exception('Failed to generate chart: ${response.body}');
}
}
}

// Widget usage
class ChartWidget extends StatefulWidget {
final Map<String, dynamic> chartConfig;
final int width;
final int height;

const ChartWidget({
Key? key,
required this.chartConfig,
this.width = 400,
this.height = 300,
}) : super(key: key);

@override
_ChartWidgetState createState() => _ChartWidgetState();
}

class _ChartWidgetState extends State<ChartWidget> {
String? chartUrl;
bool loading = true;
String? error;

final chartly = ChartlyService(apiKey: 'your_api_key_here');

@override
void initState() {
super.initState();
generateChart();
}

void generateChart() async {
try {
setState(() {
loading = true;
error = null;
});

final url = await chartly.createChart(
widget.chartConfig,
width: widget.width,
height: widget.height,
);

setState(() {
chartUrl = url;
loading = false;
});
} catch (e) {
setState(() {
error = e.toString();
loading = false;
});
}
}

@override
Widget build(BuildContext context) {
if (loading) {
return const Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
CircularProgressIndicator(),
SizedBox(height: 10),
Text('Generating chart...'),
],
),
);
}

if (error != null) {
return Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Icon(Icons.error, color: Colors.red),
Text('Error: $error'),
ElevatedButton(
onPressed: generateChart,
child: const Text('Retry'),
),
],
),
);
}

return chartUrl != null
? Image.network(
chartUrl!,
width: widget.width.toDouble(),
height: widget.height.toDouble(),
fit: BoxFit.contain,
errorBuilder: (context, error, stackTrace) {
return const Center(
child: Text('Failed to load chart'),
);
},
)
: const Center(child: Text('No chart available'));
}
}

// Usage example
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
final chartConfig = {
'type': 'bar',
'data': {
'labels': ['A', 'B', 'C'],
'datasets': [
{
'data': [10, 20, 30],
'backgroundColor': 'rgba(54, 162, 235, 0.8)',
}
]
},
'options': {'responsive': false}
};

return MaterialApp(
home: Scaffold(
appBar: AppBar(title: const Text('Chart Example')),
body: Center(
child: ChartWidget(
chartConfig: chartConfig,
width: 400,
height: 300,
),
),
),
);
}
}

Next Steps: