JavaScript Integration
Integrate Tokencraft design tokens into your JavaScript or TypeScript applications.Quick Start
1. Install Dependencies
Copy
npm install node-fetch
# or
npm install axios
2. Fetch Tokens
Copy
const TOKENCRAFT_TOKEN = process.env.TOKENCRAFT_TOKEN;
const API_BASE = 'https://app.tokencraft.dev/api/v1';
async function fetchTokens(tokensetId, modeId, format = 'json') {
const response = await fetch(
`${API_BASE}/tokensets/${tokensetId}/modes/${modeId}/export?format=${format}`,
{
headers: {
'Authorization': `Bearer ${TOKENCRAFT_TOKEN}`
}
}
);
if (!response.ok) {
throw new Error(`Failed to fetch tokens: ${response.statusText}`);
}
return format === 'json' ? await response.json() : await response.text();
}
// Usage
const tokens = await fetchTokens('tokenset-123', 'mode-light', 'json');
Build-Time Integration
Next.js
Fetch tokens at build time:Copy
// scripts/fetch-tokens.js
const fs = require('fs');
const path = require('path');
async function fetchTokens() {
const response = await fetch(
`${process.env.TOKENCRAFT_API_BASE}/tokensets/${process.env.TOKENSET_ID}/modes/light/export?format=json`,
{
headers: {
'Authorization': `Bearer ${process.env.TOKENCRAFT_TOKEN}`
}
}
);
const tokens = await response.json();
// Save to file
fs.writeFileSync(
path.join(__dirname, '../src/tokens.json'),
JSON.stringify(tokens, null, 2)
);
console.log('✓ Tokens fetched successfully');
}
fetchTokens().catch(console.error);
Copy
// package.json
{
"scripts": {
"fetch-tokens": "node scripts/fetch-tokens.js",
"prebuild": "npm run fetch-tokens",
"build": "next build"
}
}
Copy
// src/tokens.ts
import tokens from './tokens.json';
export const colors = tokens.colors;
export const spacing = tokens.spacing;
// Type-safe access
export function getColor(path: string): string {
const keys = path.split('.');
let value: any = tokens;
for (const key of keys) {
value = value[key];
if (!value) throw new Error(`Token not found: ${path}`);
}
return value.value;
}
React
Use tokens in React components:Copy
import { colors } from '@/tokens';
export function Button({ variant = 'primary' }) {
const bg = variant === 'primary'
? colors.primary['500'].value
: colors.secondary['500'].value;
return (
<button style={{ backgroundColor: bg }}>
Click me
</button>
);
}
Vue
Copy
<script setup>
import tokens from '@/tokens.json';
const primaryColor = tokens.colors.primary['500'].value;
</script>
<template>
<button :style="{ backgroundColor: primaryColor }">
Click me
</button>
</template>
Runtime Integration
Fetch on App Load
Copy
// src/lib/tokens.ts
class TokenService {
private tokens: any = null;
async load() {
if (this.tokens) return this.tokens;
const response = await fetch('/api/tokens');
this.tokens = await response.json();
return this.tokens;
}
get(path: string): any {
if (!this.tokens) {
throw new Error('Tokens not loaded. Call load() first.');
}
const keys = path.split('.');
let value = this.tokens;
for (const key of keys) {
value = value[key];
if (!value) throw new Error(`Token not found: ${path}`);
}
return value.value;
}
}
export const tokenService = new TokenService();
Copy
// app/layout.tsx
import { tokenService } from '@/lib/tokens';
export default async function RootLayout({ children }) {
await tokenService.load();
return (
<html>
<body>{children}</body>
</html>
);
}
CSS Variables
Generate CSS
Copy
// scripts/generate-css.js
const fs = require('fs');
function tokensToCss(tokens, prefix = '--') {
let css = ':root {\n';
function traverse(obj, path = []) {
for (const [key, value] of Object.entries(obj)) {
if (value.value !== undefined) {
const varName = prefix + [...path, key].join('-');
css += ` ${varName}: ${value.value};\n`;
} else {
traverse(value, [...path, key]);
}
}
}
traverse(tokens);
css += '}\n';
return css;
}
async function generateCss() {
const tokens = await fetchTokens('tokenset-123', 'mode-light', 'json');
const css = tokensToCss(tokens);
fs.writeFileSync('src/styles/tokens.css', css);
console.log('✓ CSS generated');
}
generateCss();
Use in Styles
Copy
/* src/styles/globals.css */
@import './tokens.css';
.button {
background-color: var(--colors-primary-500);
padding: var(--spacing-base);
border-radius: var(--radii-md);
}
TypeScript Types
Generate Types
Copy
// scripts/generate-types.ts
import fs from 'fs';
function generateTypes(tokens: any): string {
let types = 'export interface DesignTokens {\n';
function traverse(obj: any, indent = 1) {
let result = '';
const spaces = ' '.repeat(indent);
for (const [key, value] of Object.entries(obj)) {
if (value.value !== undefined) {
result += `${spaces}${key}: {\n`;
result += `${spaces} value: string;\n`;
result += `${spaces} type: string;\n`;
result += `${spaces}};\n`;
} else {
result += `${spaces}${key}: {\n`;
result += traverse(value, indent + 1);
result += `${spaces}};\n`;
}
}
return result;
}
types += traverse(tokens);
types += '}\n';
return types;
}
// Generate and save
const types = generateTypes(tokens);
fs.writeFileSync('src/tokens.d.ts', types);
Use Types
Copy
import tokens from './tokens.json';
import type { DesignTokens } from './tokens';
const typedTokens: DesignTokens = tokens;
// Type-safe access
const primary = typedTokens.colors.primary['500'].value; // ✓
const invalid = typedTokens.colors.invalid['500'].value; // ✗ Type error
API Client
Full-Featured Client
Copy
// src/lib/tokencraft.ts
export class TokencraftClient {
constructor(
private token: string,
private baseUrl = 'https://app.tokencraft.dev/api/v1'
) {}
private async request(endpoint: string) {
const response = await fetch(`${this.baseUrl}${endpoint}`, {
headers: {
'Authorization': `Bearer ${this.token}`
}
});
if (!response.ok) {
throw new Error(`API error: ${response.statusText}`);
}
return response.json();
}
async getWorkspaces() {
return this.request('/workspaces');
}
async getTokenset(id: string) {
return this.request(`/tokensets/${id}`);
}
async exportTokens(tokensetId: string, modeId: string, format = 'json') {
const endpoint = `/tokensets/${tokensetId}/modes/${modeId}/export?format=${format}`;
const response = await fetch(`${this.baseUrl}${endpoint}`, {
headers: {
'Authorization': `Bearer ${this.token}`
}
});
if (!response.ok) {
throw new Error(`Export failed: ${response.statusText}`);
}
return format === 'json' ? response.json() : response.text();
}
}
// Usage
const client = new TokencraftClient(process.env.TOKENCRAFT_TOKEN!);
const workspaces = await client.getWorkspaces();
Caching
Copy
class TokenCache {
private cache = new Map<string, { data: any; timestamp: number }>();
private ttl = 5 * 60 * 1000; // 5 minutes
get(key: string): any | null {
const item = this.cache.get(key);
if (!item) return null;
if (Date.now() - item.timestamp > this.ttl) {
this.cache.delete(key);
return null;
}
return item.data;
}
set(key: string, data: any): void {
this.cache.set(key, {
data,
timestamp: Date.now()
});
}
}
const cache = new TokenCache();
async function getCachedTokens(tokensetId: string, modeId: string) {
const cacheKey = `${tokensetId}-${modeId}`;
let tokens = cache.get(cacheKey);
if (tokens) return tokens;
tokens = await fetchTokens(tokensetId, modeId);
cache.set(cacheKey, tokens);
return tokens;
}