Technical overview of the Level-Up Circle Generator.
The entire application is contained in levelup-circle-generator.html (~2,500 lines). This includes:
- HTML — UI structure, form controls, canvas element
- CSS — Styling, responsive layout, animations, themes
- JavaScript — State management, canvas rendering, sharing, persistence
This design eliminates build tools, bundlers, and module systems. The app works by opening the HTML file directly in a browser.
index.html serves as a redirect to levelup-circle-generator.html using both a <meta http-equiv="refresh"> tag and a JavaScript fallback.
Within levelup-circle-generator.html, the code is structured in this order:
- Open Graph and Twitter Card meta tags for social previews
- lz-string CDN script for URL compression
- Reset and base styles
- Grid layout (
.container: 400px sidebar | 1fr preview) - Form control styling (inputs, selects, sliders, checkboxes)
- Button grid with gradient hover effects
- Collapsible
<details>/<summary>sections - Toast notification system (slide-in from right)
- Floating share bar (positioned top-right of preview)
- Fullscreen mode overrides
- Responsive breakpoints at 900px and 600px
- Toast container (positioned fixed, top-right)
- Controls panel with collapsible sections
- Point list container with add button
- Canvas element with
role="img"andaria-label - Floating share bar with 5 buttons (Copy Link, Twitter, Facebook, ChatGPT, Fullscreen)
- Color generation algorithm (
generateBrightColors,hslToHex) - State initialization and default labels
- Smart label wrapping (
smartWrapLabel,wrapText) - Bounding box calculation for labels
- Point management (add, delete, update label/color)
- Canvas rendering (
drawCircle) - Export to PNG (
exportPNG) - State persistence (localStorage auto-save, manual save/clear)
- URL encoding/decoding for sharing (
encodeStateToURL,decodeStateFromCompressed) - Social sharing functions (clipboard, Twitter, Facebook, ChatGPT)
- Fullscreen toggle
- ResizeObserver for responsive redraw
- Event listeners and initialization
The canvas rendering flow in drawCircle(ctx, size, isExport):
- Clear canvas — Fill with theme-appropriate background color
- Draw connection lines — If enabled, draw lines between all point pairs with optional neon glow
- Draw outer circle — Ring around the center with optional neon glow
- Draw points — Colored dots at radial positions with optional neon glow
- Draw labels — Smart-wrapped text with leader lines, positioned radially outside the circle
- Draw title — Centered title text at top with optional neon glow
For export, an off-screen canvas is created at the target resolution (1080/2048/3840). All sizes, fonts, and effects scale proportionally using a scale factor derived from exportSize / previewSize.
The generateBrightColors(n, options) function:
- Operates in HSL color space for perceptual uniformity
- Supports two spacing modes:
- Equal:
360 / Ndegrees between hues - Golden:
137.507764degrees (golden angle) for optimal visual separation
- Equal:
- Uses high saturation (~0.85–0.90) and 50% lightness for vibrancy
- Supports seeded random start hue for reproducibility
- Prevents adjacent duplicate colors by nudging hue when collisions occur
- Returns both hex colors and HSL values
smartWrapLabel(text, ctx, maxWidth) uses a multi-strategy approach:
- Single line — If text fits within 80% of max width, keep it on one line
- Semantic split — Look for connecting words (
with,and,of,for, etc.) and split there - Two-word split — Always split two-word phrases between the words
- Three-word balanced split — Try both 1+2 and 2+1 splits, pick the most balanced
- Multi-word balanced split — Find the split point that minimizes line-length difference
- Fallback — Use standard width-based wrapping (
wrapText)
Labels are positioned radially with alignment based on quadrant:
- Right side (roughly 10 o'clock to 2 o'clock): left-aligned
- Left side (roughly 4 o'clock to 8 o'clock): right-aligned
- Top/bottom: center-aligned
The layout uses CSS Grid with two responsive breakpoints:
| Breakpoint | Layout |
|---|---|
| > 900px (desktop) | 400px | 1fr two-column grid |
| 600–900px (tablet) | Stacked, controls collapse to 40vh max-height |
| < 600px (mobile) | Compact padding, 2-column button grid, full-width toasts |
A ResizeObserver on the preview container triggers redraw() when the viewport changes. On mobile, a toggle button and scroll indicator help manage the controls panel.
| Dependency | Load Method | Purpose |
|---|---|---|
| lz-string v1.5.0 | CDN <script> tag |
Compress/decompress state for URL sharing |
No other external dependencies. All rendering uses native Canvas 2D API. All persistence uses native localStorage. All sharing uses native window.open and navigator.clipboard.
- Point labels are HTML-escaped before insertion into the DOM to prevent XSS
- Color values are validated against a hex regex (
/^#[0-9A-Fa-f]{6}$/) - URL state is parsed through
JSON.parseof decompressed lz-string data with error handling