OpenCode-style font package with text-to-SVG conversion and web fonts for pixel-art style text rendering.
📖 View Interactive Documentation
This package provides:
- Grid-based pixel art font (OpenCodeLogo) with 32 glyphs (A-Z + 6 symbols:
-|'"?!) - Web fonts in multiple formats (WOFF2, WOFF, TTF) optimized for modern browsers
- JavaScript API for programmatic SVG text generation (two approaches)
- Simple font-based SVG generation (
convertTextToSVG) - Advanced blocky pixel-art rendering (
blockyTextToSVG)
- Simple font-based SVG generation (
- CSS helper for easy font integration
npm install @pantheon-ai/opencode-fontGenerate pixel-perfect SVG with blocky rendering and theme support:
import { blockyTextToSVG } from '@pantheon-ai/opencode-font';
const svg = blockyTextToSVG('OPENCODE', {
theme: 'dark', // or 'light'
blockSize: 6,
charSpacing: 1,
optimize: true, // Reduces file size by 30-40%
});
// Inject into your page
document.getElementById('logo').innerHTML = svg;Generate SVG text using the OpenCodeLogo font:
import { convertTextToSVG } from '@pantheon-ai/opencode-font';
const svg = convertTextToSVG('OPENCODE', {
fontSize: 48,
color: '#00ff00',
});
// Inject into your page
document.getElementById('logo').innerHTML = svg;Use the font directly in your CSS:
<!-- In your HTML -->
<link rel="stylesheet" href="node_modules/@pantheon-ai/opencode-font/css/opencode-font.css" />
<style>
.pixel-text {
font-family: 'OpenCodeLogo', monospace;
font-size: 48px;
color: #00ff00;
}
</style>
<h1 class="pixel-text">OPENCODE</h1>For more control, define your own @font-face:
@font-face {
font-family: 'OpenCodeLogo';
src:
url('node_modules/@pantheon-ai/opencode-font/fonts/OpenCodeLogo.woff2') format('woff2'),
url('node_modules/@pantheon-ai/opencode-font/fonts/OpenCodeLogo.woff') format('woff');
font-weight: normal;
font-style: normal;
font-display: swap; /* Recommended for web performance */
}
.my-text {
font-family: 'OpenCodeLogo', monospace;
text-transform: uppercase; /* Font only includes uppercase */
}Converts text to blocky pixel-art SVG with optimized paths and theme support.
Parameters:
text(string) — Text to convert (A-Z,-|'"?!supported)options(object) — Configuration options:theme('light' | 'dark') — Color theme (default:'light')blockSize(number) — Size of each pixel block in pixels (default:6)charSpacing(number) — Space between characters in blocks (default:1)optimize(boolean) — Enable SVG path optimization (default:true)
Returns: SVG string with pixel-perfect rendering
Example:
const svg = blockyTextToSVG('HELLO', {
theme: 'dark',
blockSize: 6,
charSpacing: 1,
optimize: true,
});Features:
- Pixel-perfect rendering - No font rendering inconsistencies across browsers
- Theme support - Built-in light/dark modes using OpenCode.ai colors
- Variable-width characters - 1-5 columns depending on character
- SVG optimization - Merges adjacent blocks for 30-40% size reduction
- Consistent output - Identical across all browsers and platforms
When to use:
- Logos and headers
- Pixel-art style graphics
- When you need exact pixel control
- When consistency across browsers is critical
Converts text to an SVG string using the OpenCodeLogo font.
Parameters:
text(string) — Text to convert (A-Z,-|'"?!supported)options(object) — Configuration options:fontSize(number) — Font size in pixels (default:48)color(string) — Text color (default:#000)fontFamily(string) — Font family name (default:OpenCodeLogo)width(number) — SVG width (optional, auto-calculated)height(number) — SVG height (optional, auto-calculated)role(string) — ARIA role attribute (default:img)ariaLabel(string) — ARIA label for accessibility (default: text content)
Returns: SVG string
Example:
const svg = convertTextToSVG('HELLO', {
fontSize: 64,
color: '#ff0000',
role: 'img',
ariaLabel: 'Hello message in pixel art style',
});When to use:
- Text-heavy content where file size matters
- When you want browser-native font rendering
- Dynamic text that changes frequently
| Feature | convertTextToSVG() |
blockyTextToSVG() |
|---|---|---|
| Rendering | Font-based <text> |
Pixel-perfect paths |
| Browser consistency | Depends on font rendering | Identical everywhere |
| Theme support | No | Yes (light/dark) |
| Variable width | Font-dependent | Yes (1-5 columns) |
| Optimization | No | Yes (30-40% size reduction) |
| Customization | Limited | Full control (blocks, spacing) |
| Recommended for | Text-heavy content | Logos, headers, pixel-art |
For complete blocky text API documentation, see src/alphabet/README.md.
- Character Set: ASCII uppercase (A-Z) + 6 symbols (
-|'"?!) - Total Glyphs: 32
- Design: 7×4 grid-based pixel art
- File Sizes:
- WOFF2: ~1.3 KB (recommended)
- WOFF: ~1.8 KB
- TTF: ~6.4 KB
- Total Package Size: ~9.5 KB (all formats)
Modern browsers with WOFF2 support are recommended:
- Chrome/Edge 36+
- Firefox 39+
- Safari 10+
- Opera 23+
Fallback to WOFF for older browsers.
- Bun v1.3.2+ or Node.js 20+
# Install dependencies
bun install
# Generate fonts
bun run generate:fonts
# Validate generated fonts
bun run validate:fonts
# Run tests
bun test
# Type check
bun run typecheck
# Build
bun run buildFonts are automatically generated in CI pipelines and are not committed to version control. To generate fonts locally:
bun run generate:fontsThis creates:
fonts/OpenCodeLogo.woff2(1.3 KB)fonts/OpenCodeLogo.woff(1.8 KB)fonts/OpenCodeLogo.ttf(6.4 KB)
Generation time: ~0.15s
# Run all checks (format, lint, typecheck, tests)
bun run format:check
bun run lint
bun run typecheck
bun test
# Build to verify distribution
bun run buildOpen demo/index.html in a browser to see an interactive demo of the font and SVG generation API.
Issue: Text appears in a fallback font instead of OpenCodeLogo
Solutions:
- Ensure fonts are generated:
bun run generate:fonts - Check font file paths in your CSS
- Verify fonts are included in your build output
- Check browser console for font loading errors
- Use
font-display: swapto see fallback text while loading
Issue: No text visible when using the font
Possible causes:
- Font only supports uppercase A-Z and symbols
-|'"?! - Lowercase letters are not included
- Numbers are not included
Solution: Use text-transform: uppercase in CSS or convert text to uppercase in JavaScript:
const svg = convertTextToSVG(text.toUpperCase(), options);Issue: fonts/ directory is empty
Cause: Fonts are generated during the publish process and included in the npm package
Solution:
- If using from npm: Fonts should be present in
node_modules/@pantheon-ai/opencode-font/fonts/ - If using from source: Run
bun run generate:fontsto generate fonts locally
Issue: Font generation fails in CI
Debugging steps:
- Check Node.js/Bun version compatibility (requires Node 20+ or Bun 1.3+)
- Ensure all dependencies are installed
- Check logs for specific error messages
- Verify
scripts/generate-fonts.tsis present - Run
bun run validate:fontsto diagnose issues
Issue: Font loading impacts page performance
Solutions:
- Use WOFF2 format exclusively (smallest at 1.3 KB)
- Preload fonts for critical text:
<link rel="preload" href="fonts/OpenCodeLogo.woff2" as="font" type="font/woff2" crossorigin />
- Use
font-display: swapto avoid FOIT (Flash of Invisible Text) - Consider subsetting if you only need specific characters
Fonts are automatically generated in CI and should not be committed to version control.
Development workflow:
- Make changes to
scripts/generate-fonts.tsif modifying glyphs - Run
bun run generate:fontsto test locally - Run
bun run validate:fontsto verify output - Commit changes (excluding
fonts/*.ttf,fonts/*.woff,fonts/*.woff2) - CI will generate fonts during validation and publishing
Font generation details:
- Source: Grid-based glyph definitions in
scripts/generate-fonts.ts - Pipeline: SVG glyphs → SVG font → TTF → WOFF/WOFF2
- Tools:
svgicons2svgfont,svg2ttf,ttf2woff,ttf2woff2 - Time: ~0.15s locally, ~0.14s in CI
This repository uses a fully automated CI/CD pipeline for testing, versioning, and publishing:
-
Pull Request Validation (
.github/workflows/1-validate.yml)- Runs on every PR to
main - Generates fonts before validation
- Executes: linting, type checking, tests with coverage, and build
- Analyzes PR size and warns if too large
- Runs on every PR to
-
Version Bumping (
.github/workflows/2-version-update.yml)- Triggers after merge to
main - Analyzes commits using conventional commit patterns
- Automatically creates version bump PR based on changes:
feat:→ minor version bumpfix:→ patch version bumpBREAKING CHANGEor!:→ major version bump
- Triggers after merge to
-
Auto-Merge (
.github/workflows/3-auto-merge.yml)- Automatically merges version bump PRs once checks pass
- Validates PR format and author
- Retries if checks are still pending
-
Tag Creation (
.github/workflows/4-create-tag.yml)- Creates git tag after version bump is merged
- Tag format:
v{major}.{minor}.{patch} - Triggers publishing workflow
-
Publishing (
.github/workflows/5-publish.yml)- Generates fonts for distribution
- Publishes to npm with provenance (includes fonts in package)
- Deploys demo to GitHub Pages (includes fonts)
- Creates GitHub Release with changelog
Use conventional commit messages to control version bumping:
feat: add new feature # minor bump (0.1.0 → 0.2.0)
fix: resolve bug # patch bump (0.1.0 → 0.1.1)
feat!: breaking change # major bump (0.1.0 → 1.0.0)
docs: update documentation # patch bump (0.1.0 → 0.1.1)
chore: update dependencies # patch bump (0.1.0 → 0.1.1)Add these secrets to your GitHub repository settings:
NPM_TOKEN- npm authentication token for publishingWORKFLOW_PAT(optional) - Personal Access Token with repo and workflow permissions for auto-merge
To manually trigger a version bump:
- Go to Actions → "2. Version Update (Create PR)"
- Click "Run workflow"
- Select version type: auto, major, minor, or patch
MIT