This document provides a comprehensive overview of the CoralCSS framework architecture, including its core modules, data flow, and extension points.
- Overview
- Core Architecture
- Module Structure
- Data Flow
- Plugin System
- Component System
- Runtime System
- Build Tools
- Performance Optimizations
- Extension Points
CoralCSS is a modern, zero-dependency CSS framework featuring:
- Utility-First CSS: Atomic classes like
p-4,bg-red-500,hover:text-white - Headless Components: Accessible, unstyled UI components with full behavior
- Plugin Architecture: Extensible system for custom utilities, variants, and themes
- Modern CSS Support: Container queries, CSS layers, cascade layers, and more
- Build Tools: Vite plugin, PostCSS plugin, and CLI for production optimization
┌─────────────────────────────────────────────────────────────────────────────┐
│ CoralCSS Framework │
├─────────────────────────────────────────────────────────────────────────────┤
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ Kernel │ │ Themes │ │ Plugins │ │Components│ │ Build │ │
│ │ (Core) │ │ │ │ │ │ │ │ Tools │ │
│ └────┬─────┘ └────┬─────┘ └────┬─────┘ └────┬─────┘ └────┬─────┘ │
│ │ │ │ │ │ │
│ └─────────────┴──────┬──────┴─────────────┴─────────────┘ │
│ │ │
│ ┌──────┴──────┐ │
│ │ Runtime │ │
│ │ (Browser) │ │
│ └─────────────┘ │
└─────────────────────────────────────────────────────────────────────────────┘
The Kernel is the central engine of CoralCSS. It orchestrates:
- Configuration Resolution: Merges presets, plugins, and user options
- Plugin Management: Registers, loads, and manages plugin lifecycle
- CSS Generation: Coordinates the full CSS generation pipeline
- Event System: Emits events for cache hits/misses, plugin registration, etc.
const kernel = new Kernel({
presets: [coralPreset()],
theme: { colors: { brand: '#ff6b6b' } },
plugins: [customPlugin]
})
const css = kernel.generate(['p-4', 'bg-brand', 'hover:text-white'])┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ Input │───▶│ Parser │───▶│ Matcher │───▶│ Generator │
│ Classes │ │ │ │ │ │ │
└─────────────┘ └─────────────┘ └─────────────┘ └─────────────┘
│ │ │
▼ ▼ ▼
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ ParsedClass│ │ MatchResult │ │ GeneratedCSS│
│ - variants │ │ - rule │ │ - selector │
│ - utility │ │ - match │ │ - props │
│ - modifiers│ │ │ │ - layer │
└─────────────┘ └─────────────┘ └─────────────┘
│
▼
┌─────────────┐
│ CSS String │
└─────────────┘
src/
├── kernel.ts # Core engine
├── index.ts # Public API exports
├── types.ts # TypeScript definitions
├── errors.ts # Custom error classes
│
├── core/ # Core processing modules
│ ├── matcher.ts # Rule matching with prefix indexing
│ ├── generator.ts # CSS generation
│ ├── parser.ts # Class name parsing
│ ├── cache.ts # LRU cache with TTL
│ ├── hybrid-cache.ts # Memory + IndexedDB cache
│ ├── extractor.ts # Class extraction from content
│ ├── transformer.ts # CSS transformations
│ ├── worker.ts # Web Worker for parallel processing
│ ├── incremental.ts # Incremental build support
│ └── tree-shake.ts # Dead code elimination
│
├── theme/ # Theme system
│ ├── default.ts # Default theme values
│ ├── colors.ts # Color scales (tailwind-compatible)
│ ├── spacing.ts # Spacing scale
│ ├── typography.ts # Font families, sizes, weights
│ ├── dark.ts # Dark mode utilities
│ └── semantic.ts # Semantic color tokens
│
├── plugins/ # Plugin system
│ ├── core/ # Core plugins (always loaded)
│ │ ├── utilities/ # Utility plugins (spacing, colors, etc.)
│ │ └── variants/ # Variant plugins (hover, responsive, etc.)
│ └── optional/ # Optional plugins (forms, animations)
│
├── presets/ # Pre-configured plugin bundles
│ ├── coral.ts # Default CoralCSS preset
│ ├── wind.ts # Tailwind-compatible preset
│ ├── mini.ts # Minimal preset
│ └── full.ts # All plugins preset
│
├── components/ # Headless components
│ ├── base.ts # BaseComponent class
│ ├── dialog.ts # Modal dialog
│ ├── dropdown.ts # Dropdown menu
│ ├── tabs.ts # Tab navigation
│ └── ... # 50+ components
│
├── runtime/ # Browser runtime
│ ├── observer.ts # DOM mutation observer
│ ├── injector.ts # Style injection
│ └── cdn.ts # CDN/JIT mode
│
├── build/ # Build tools
│ ├── vite.ts # Vite plugin
│ ├── postcss.ts # PostCSS plugin
│ └── cli.ts # CLI commands
│
├── utils/ # Utility functions
│ ├── string.ts # String manipulation
│ ├── css.ts # CSS formatting
│ ├── color.ts # Color manipulation
│ ├── dom.ts # DOM utilities
│ └── regex.ts # Regex helpers
│
└── cva/ # Class Variance Authority
└── index.ts # Variant-based class composition
The parser breaks down class names into structured components:
"hover:dark:bg-red-500/50!"
│
▼
┌───────────────────────┐
│ ParsedClass │
├───────────────────────┤
│ original: "hover:..." │
│ variants: ["hover", │
│ "dark"] │
│ utility: "bg-red-500" │
│ opacity: "50" │
│ important: true │
│ negative: false │
└───────────────────────┘
The Matcher uses prefix indexing for O(1) rule lookup:
// Rule registration
matcher.addRule({
name: 'background-color',
pattern: /^bg-([a-z]+)-(\d+)$/,
generate: (match, theme) => ({
backgroundColor: theme.colors[match[1]][match[2]]
})
})
// Matching process
"bg-red-500" → prefix: "bg" → lookup indexed rules → match pattern → MatchResultThe Generator creates CSS from match results:
// Input
{ rule, match: ['bg-red-500', 'red', '500'] }
// Output
{
selector: '.bg-red-500',
properties: { backgroundColor: '#ef4444' },
layer: 'utilities',
priority: 0,
variants: []
}Variants modify selectors and wrap CSS:
// hover variant
{ handler: (selector) => `${selector}:hover` }
// responsive variant (md:)
{ wrapper: '@media (min-width: 768px)' }
// Result for "md:hover:bg-red-500"
@media (min-width: 768px) {
.md\:hover\:bg-red-500:hover {
background-color: #ef4444;
}
}interface Plugin {
name: string
version?: string
dependencies?: string[]
priority?: number
install(api: PluginAPI): void
onReady?(): void | Promise<void>
onDestroy?(): void | Promise<void>
onError?(error: Error): void
}Plugins receive an API object for registration:
const myPlugin: Plugin = {
name: 'my-plugin',
install(api) {
// Add utility rules
api.addRule({
pattern: /^my-util-(\d+)$/,
generate: (match, theme) => ({ myProperty: match[1] })
})
// Add variants
api.addVariant({
name: 'my-variant',
handler: (selector) => `.my-context ${selector}`
})
// Extend theme
api.extendTheme({
myColors: { primary: '#ff0000' }
})
// Access theme values
const primary = api.theme('colors.primary')
// Listen to events
api.on('css:generated', (data) => { /* ... */ })
}
}Utility Plugins (src/plugins/core/utilities/):
spacing.ts- Padding, margin, gapsizing.ts- Width, height, min/maxcolors.ts- Background, text, border colorstypography.ts- Font size, weight, line-heightlayout.ts- Display, position, z-indexflexbox.ts- Flex utilitiesgrid.ts- Grid utilitieseffects.ts- Shadows, opacitytransforms.ts- Scale, rotate, translatetransitions.ts- Transition properties
Variant Plugins (src/plugins/core/variants/):
pseudo.ts- :hover, :focus, :active, etc.responsive.ts- sm:, md:, lg:, xl:, 2xl:dark.ts- Dark mode variantsmodern.ts- Container queries, has:, group:, peer:
All components extend BaseComponent which provides:
abstract class BaseComponent {
readonly id: string
readonly element: HTMLElement
protected state: ComponentState
protected config: ComponentConfig
// Abstract methods (must implement)
protected abstract getDefaultConfig(): ComponentConfig
protected abstract getInitialState(): ComponentState
protected abstract setupAria(): void
protected abstract bindEvents(): void
// Lifecycle
protected init(): void
protected render(): void
destroy(): void
// State management
protected setState(updates: Partial<ComponentState>): void
subscribe(listener: StateListener): () => void
// Events
protected dispatch(eventName: string, detail?: unknown): boolean
protected addEventListener(target, event, handler): void
// DOM utilities
protected query<T>(selector: string): T | null
protected trapFocus(element?: HTMLElement): void
protected lockScroll(): void
}┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ Constructor │────▶│ init() │────▶│ setupAria()│
└─────────────┘ └─────────────┘ └─────────────┘
│
▼
┌─────────────┐ ┌─────────────┐
│ bindEvents()│────▶│ Ready │
└─────────────┘ └─────────────┘
│
┌───────────────────┼───────────────────┐
▼ ▼ ▼
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ setState() │ │ Event │ │ destroy() │
└─────────────┘ └─────────────┘ └─────────────┘
│
▼
┌─────────────┐
│ render() │
└─────────────┘
// Create dialog
const dialog = createDialog(element, {
modal: true,
closeOnOutsideClick: true,
hooks: {
onOpen: () => console.log('Dialog opened'),
onClose: () => console.log('Dialog closed')
}
})
// Control
dialog.open()
dialog.close()
// Subscribe to state changes
const unsubscribe = dialog.subscribe((state) => {
console.log('State changed:', state)
})
// Cleanup
dialog.destroy()Watches for DOM changes and generates CSS on-the-fly:
const observer = createObserver({
target: document.body,
subtree: true,
attributes: true,
attributeFilter: ['class']
})
observer.start()
// Automatically generates CSS when new classes are detectedInjects generated CSS into the document:
const injector = createInjector({
target: 'head', // or shadow root
id: 'coral-styles'
})
injector.inject('.p-4 { padding: 1rem; }')
injector.update('.p-4 { padding: 1rem; }\n.m-4 { margin: 1rem; }')For browser-based JIT compilation:
<script src="https://unpkg.com/@coral-css/core/cdn.js"></script>
<script>
CoralCSS.start({
presets: ['coral'],
theme: { colors: { brand: '#ff6b6b' } }
})
</script>// vite.config.ts
import coral from '@coral-css/core/vite'
export default {
plugins: [
coral({
content: ['./src/**/*.{html,js,ts,jsx,tsx}'],
presets: [coralPreset()],
minify: true
})
]
}// postcss.config.js
module.exports = {
plugins: [
require('@coral-css/core/postcss')({
content: ['./src/**/*.html'],
presets: [require('@coral-css/core').coralPreset()]
})
]
}# Initialize configuration
coral init
# Analyze bundle
coral analyze --input dist/styles.css
# Optimize CSS
coral optimize --input dist/styles.css --output dist/styles.min.cssLRU Cache (src/core/cache.ts):
- In-memory cache with configurable max size
- TTL support for entry expiration
- Hit/miss statistics for monitoring
Hybrid Cache (src/core/hybrid-cache.ts):
- Two-tier: Memory (fast) + IndexedDB (persistent)
- Survives page reloads
- Automatic synchronization
The Matcher uses prefix indexing for fast rule lookup:
Rules: bg-red-500, bg-blue-500, text-red-500, p-4, m-4
Index:
"bg" → [bg-red-*, bg-blue-*]
"text" → [text-red-*]
"p" → [p-*]
"m" → [m-*]
Lookup "bg-green-500":
1. Extract prefix "bg"
2. Get indexed rules for "bg"
3. Test only 2 rules instead of all 5
Parallel CSS generation using Web Workers:
const pool = createWorkerPool({
size: navigator.hardwareConcurrency,
taskTimeout: 5000
})
// Distribute work across workers
const results = await pool.generateBatch(classes)Only regenerates CSS for changed files:
const builder = createIncrementalBuilder({
cacheDir: '.coral-cache',
parallel: true
})
await builder.build(changedFiles)Removes unused CSS rules:
const shaker = createTreeShake({
content: ['./src/**/*.tsx'],
safelist: ['bg-red-*']
})
const optimizedCSS = shaker.shake(generatedCSS)api.addRule({
name: 'gradient-text',
pattern: /^gradient-text-(\w+)-(\w+)$/,
generate: ([, from, to], theme) => ({
backgroundImage: `linear-gradient(to right, ${theme.colors[from][500]}, ${theme.colors[to][500]})`,
backgroundClip: 'text',
color: 'transparent'
}),
layer: 'utilities',
priority: 10
})// Simple pseudo selector
api.addVariant({
name: 'hocus',
handler: (selector) => `${selector}:hover, ${selector}:focus`
})
// With at-rule wrapper
api.addVariant({
name: 'print',
wrapper: '@media print'
})
// Dynamic variant with pattern
api.addVariant({
name: 'data',
match: /^data-\[(.+)\]$/,
handler: (selector, matches) => `${selector}[data-${matches[1]}]`
})class MyComponent extends BaseComponent {
protected getDefaultConfig() {
return { option: 'default' }
}
protected getInitialState() {
return { active: false }
}
protected setupAria() {
this.element.setAttribute('role', 'widget')
}
protected bindEvents() {
this.addEventListener(this.element, 'click', () => {
this.setState({ active: !this.state.active })
})
}
protected render() {
this.element.dataset.active = String(this.state.active)
}
}
export const createMyComponent = createComponentFactory(MyComponent)api.extendTheme({
colors: {
brand: {
50: '#fef2f2',
100: '#fee2e2',
// ...
900: '#7f1d1d'
}
},
spacing: {
'128': '32rem',
'144': '36rem'
},
fontFamily: {
display: ['Playfair Display', 'serif']
}
})The Kernel emits events throughout the CSS generation lifecycle:
const unsubscribe = kernel.on('css:generated', ({ classes, css }) => {
console.log(`Generated ${css.length} bytes for ${classes.length} classes`)
})- Use presets instead of individual plugins for common setups
- Enable caching in production with appropriate TTL
- Use content paths to limit class extraction scope
- Configure safelist carefully to avoid bloat
- Prefer plugins over modifying core code
- Use theme extension for custom values instead of hardcoding
- Follow naming conventions for custom utilities (
prefix-value) - Set appropriate priorities for rule ordering
- Extend BaseComponent for consistent lifecycle handling
- Implement all abstract methods properly
- Use state management instead of direct DOM manipulation
- Clean up event listeners in
destroy()
For more information, see:
