Build Tool
The @airframeui/build package provides a PostCSS plugin and CLI for customizing breakpoints and typography, plus the af theme commands for generating theme CSS from design-token files.
Default responsive utilities already ship with @airframeui/core. Use this package when you need custom breakpoints, @af bp() / @af-apply in your CSS, generated typography overrides, or theme generation.
Quick Start
Section titled “Quick Start”Installation
Section titled “Installation”npm install -D @airframeui/buildCLI Usage
Section titled “CLI Usage”- Initialize config (optional):
npx af init- Build CSS:
npx af buildPostCSS Plugin
Section titled “PostCSS Plugin”The PostCSS plugin can read configuration from airframe.config.js or accept options directly.
Option 1: Using airframe.config.js (Recommended)
Create airframe.config.js:
module.exports = {
breakpoints: {
sm: '600px',
md: '900px',
lg: '1200px',
},
useDefaults: true,
outputDir: '.airframeui'
};Then in postcss.config.js:
const airframeConfig = require('./airframe.config.js');
module.exports = {
plugins: {
'@airframeui/build/postcss': airframeConfig,
},
};Option 2: Inline configuration
module.exports = {
plugins: {
'@airframeui/build/postcss': {
breakpoints: {
sm: '600px',
md: '900px',
lg: '1200px',
},
useDefaults: true,
},
},
};Using @af bp() Directive
Section titled “Using @af bp() Directive”Use the @af bp() directive in your CSS to apply styles at specific breakpoints:
.my-component {
padding: 1rem;
}
@af bp(md) {
.my-component {
padding: 2rem;
}
}
@af bp(lg) {
.my-component {
padding: 3rem;
}
}With the custom config above (md: 900px, lg: 1200px), this generates:
.my-component {
padding: 1rem;
}
@media (min-width: 900px) {
.my-component {
padding: 2rem;
}
}
@media (min-width: 1200px) {
.my-component {
padding: 3rem;
}
}Without a custom config, defaults are used (md → 768px, lg → 1024px).
Using @af-apply Directive
Section titled “Using @af-apply Directive”The @af-apply directive allows you to apply utility classes inline within your CSS, similar to Tailwind’s @apply. This is useful when you want to reuse utility classes in custom CSS without duplicating their declarations.
Basic Usage
Section titled “Basic Usage”Apply simple utility classes:
.my-component {
@af-apply af-flex;
@af-apply af-gap-md;
@af-apply af-p-lg;
}This inlines the declarations from those utility classes into .my-component.
Complex Utilities with Pseudo-elements
Section titled “Complex Utilities with Pseudo-elements”The @af-apply directive also handles complex utilities that include pseudo-elements, such as af-scrollbar:
.sidebar-pane {
@af-apply af-scrollbar;
}This automatically includes all related rules, including:
- Base scrollbar styles (Firefox
scrollbar-widthandscrollbar-color) - Webkit scrollbar pseudo-elements (
::-webkit-scrollbar,::-webkit-scrollbar-thumb, etc.) - Hover and active states
The plugin creates nested rules for pseudo-elements using the & selector, so the generated CSS looks like:
.sidebar-pane {
/* Base styles from af-scrollbar */
scrollbar-width: thin;
scrollbar-color: var(--af-color-border-strong) transparent;
}
.sidebar-pane::-webkit-scrollbar {
width: 10px;
height: 10px;
}
.sidebar-pane::-webkit-scrollbar-thumb {
background-color: var(--af-color-border);
border-radius: var(--af-radius-full);
border: 2px solid transparent;
background-clip: padding-box;
transition: background-color var(--af-duration-fast) var(--af-ease-standard);
}
.sidebar-pane::-webkit-scrollbar-thumb:hover {
background-color: var(--af-color-border-strong);
}
.sidebar-pane::-webkit-scrollbar-track {
background: transparent;
border-radius: var(--af-radius-full);
}How It Works
Section titled “How It Works”- Plugin scans CSS: The PostCSS plugin scans all CSS rules to build a map of utility class definitions
- Finds utility class: When it encounters
@af-apply utility-class-name, it looks up the utility class in the map - Inlines declarations: For simple utilities, it inlines the declarations directly into the parent rule
- Handles pseudo-elements: For complex utilities with pseudo-elements, it creates nested rules using
&::pseudo-elementsyntax
Requirements
Section titled “Requirements”- Utility classes must be defined: The utility class must be defined in your CSS before
@af-applycan use it. Make sure to import@airframeui/core/core.css(or the utilities layer) before using@af-apply - PostCSS plugin must be configured: The
@airframeui/build/postcssplugin must be included in your PostCSS configuration (see PostCSS Plugin section above)
Example: Custom Component with Utilities
Section titled “Example: Custom Component with Utilities”@import "@airframeui/core/core.css";
.custom-card {
@af-apply af-card;
@af-apply af-p-xl;
@af-apply af-shadow-lg;
/_ Additional custom styles _/
border: 2px solid var(--af-color-primary);
}
.scrollable-content {
@af-apply af-scrollbar;
max-height: 400px;
overflow-y: auto;
}Framework Integration
Section titled “Framework Integration”Next.js
Section titled “Next.js”- Install:
npm install -D @airframeui/build- Create
airframe.config.js(optional, for custom breakpoints):
module.exports = {
breakpoints: {
sm: '640px',
md: '768px',
lg: '1024px',
},
useDefaults: true,
};- Create
postcss.config.js:
const airframeConfig = require('./airframe.config.js');
module.exports = {
plugins: {
'@airframeui/build/postcss': airframeConfig,
},
};Or use defaults (no config file needed):
module.exports = {
plugins: {
'@airframeui/build/postcss': {},
},
};- Use in
app/globals.css:
@import "@airframeui/core/core.css";
@af bp(md) {
.container {
max-width: 1200px;
}
}React (Vite)
Section titled “React (Vite)”- Install:
npm install -D @airframeui/build- Create
airframe.config.js:
module.exports = {
breakpoints: {
sm: '600px',
md: '900px',
lg: '1200px',
},
useDefaults: true,
};- Create
postcss.config.js:
const airframeConfig = require('./airframe.config.js');
module.exports = {
plugins: {
'@airframeui/build/postcss': airframeConfig,
},
};- Use in CSS:
@import "@airframeui/core/core.css";
@af bp(md) {
.grid {
grid-template-columns: repeat(2, 1fr);
}
}Angular
Section titled “Angular”- Install:
npm install -D @airframeui/build- Create
airframe.config.js(optional):
module.exports = {
breakpoints: {
sm: '640px',
md: '768px',
lg: '1024px',
},
useDefaults: true,
};- Create
postcss.config.js:
const airframeConfig = require('./airframe.config.js');
module.exports = {
plugins: {
'@airframeui/build/postcss': airframeConfig,
},
};- Use in
styles.css:
@import "@airframeui/core/core.css";
@af bp(lg) {
.sidebar {
display: block;
}
}Vue (Vite)
Section titled “Vue (Vite)”- Install:
npm install -D @airframeui/build- Create
airframe.config.js:
export default {
breakpoints: {
sm: '640px',
md: '768px',
lg: '1024px',
},
useDefaults: true,
};- Create
postcss.config.js:
import airframeConfig from './airframe.config.js';
export default {
plugins: {
'@airframeui/build/postcss': airframeConfig,
},
};- Use in CSS:
@import "@airframeui/core/core.css";
@af bp(md) {
.component {
padding: 2rem;
}
}Configuration
Section titled “Configuration”Config File
Section titled “Config File”Create airframe.config.js:
module.exports = {
breakpoints: {
sm: "640px",
md: "768px",
lg: "1024px",
xl: "1280px",
"2xl": "1536px"
},
useDefaults: true,
outputDir: ".airframeui",
typography: {
fontSizes: {
sm: "0.875rem",
lg: "1.1875rem"
},
fonts: {
sans: "ui-sans-serif, system-ui, sans-serif"
}
}
};Options:
breakpoints- Custom breakpoint valuesuseDefaults- Merge with default breakpoints (default:false)outputDir- Directory for generated CSS files, resolved from the project root (default:.airframeui)typography- Custom typography configuration (see Typography Customization section)
Default Breakpoints
Section titled “Default Breakpoints”If no config is provided, these defaults are used:
xs: 360pxsm: 640pxmd: 768pxlg: 1024pxxl: 1280px2xl: 1536px
Generated Files
Section titled “Generated Files”The plugin writes generated CSS to the project-root outputDir (default: .airframeui/):
responsive.css- Responsive utility classes for your configured breakpoints (af-grid-2@md,af-gap-lg@lg, etc.)typography.css- Custom typography tokens (if typography config is provided)
@airframeui/core already includes default responsive utilities. Import the generated responsive.css only when you customize breakpoints and want utilities regenerated for those values. @af bp() rules are inlined by PostCSS and do not require an extra import.
@import "@airframeui/core/core.css";
@import ".airframeui/responsive.css"; /* Generated */
@import ".airframeui/typography.css"; /* Generated (if typography config exists) */You can add .airframeui/ to .gitignore if you prefer not to commit generated files.
CLI Commands
Section titled “CLI Commands”af build
Section titled “af build”Build CSS with custom breakpoints:
# Use default config
af build
# Custom config file
af build --config custom.config.json
# Custom input/output
af build --input src/app.css --output dist/app.cssaf init
Section titled “af init”Create default config file:
af initaf theme (Theme generation)
Section titled “af theme (Theme generation)”Generate, lint, and validate Airframe theme CSS from design-token files (Tokens Studio, DTCG, CSS vars, Figma Variables, Style Dictionary). Powered by @airframeui/theme.
# Generate theme.css from a token file or HTTPS JSON/CSS URL
npx af theme generate --from ./tokens.json -o theme.css
# Lint an existing theme.css (unknown tokens, missing dark, contrast)
npx af theme lint theme.css --strict
# Validate a token file without writing CSS
npx af theme validate ./tokens.json --format autoSupported --format values: auto, dtcg, tokens-studio, css, figma-variables, style-dictionary, airframe-spec.
For a browser UI with live preview, use Theme Studio. For AI agents, install @airframeui/mcp (generate_theme, lint_theme, validate_theme, map_tokens) and see @airframeui/theme/rules.
Also see Theming.
Advanced Usage
Section titled “Advanced Usage”Custom Breakpoints Only (Default Behavior)
Section titled “Custom Breakpoints Only (Default Behavior)”By default (useDefaults: false), only your custom breakpoints are used:
{
"breakpoints": {
"mobile": "480px",
"tablet": "768px",
"desktop": "1200px"
}
}Or explicitly:
{
"breakpoints": {
"mobile": "480px",
"tablet": "768px",
"desktop": "1200px"
},
"useDefaults": false
}Then use in CSS:
@af bp(tablet) {
.component {
/* styles */
}
}Typography Customization
Section titled “Typography Customization”Customize typography tokens by adding a typography section to your airframe.config.js:
module.exports = {
breakpoints: {
sm: '640px',
md: '768px',
},
typography: {
// Font sizes (override any or all)
fontSizes: {
xs: '0.75rem',
sm: '0.875rem',
md: '1rem',
lg: '1.1875rem',
xl: '1.5rem',
'2xl': '2rem',
'3xl': '2.5rem',
'4xl': '3.5rem',
'5xl': '4.5rem',
},
// Font weights
fontWeights: {
regular: '400',
medium: '500',
semibold: '600',
bold: '700',
extrabold: '800',
},
// Line heights
lineHeights: {
tight: '1.15',
normal: '1.55',
loose: '1.75',
},
// Font families
fonts: {
sans: 'ui-sans-serif, system-ui, sans-serif',
mono: 'ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace',
},
// Type roles (override specific heading/body styles)
typeRoles: {
h1: {
size: 'var(--af-text-3xl)',
weight: 'var(--af-weight-bold)',
leading: 'var(--af-leading-tight)',
tracking: '-0.02em',
},
body: {
size: 'var(--af-text-md)',
weight: 'var(--af-weight-regular)',
leading: 'var(--af-leading-normal)',
},
},
},
};The plugin generates .airframeui/typography.css with your custom typography tokens. Import it after your core CSS:
@import "@airframeui/core/core.css";
@import ".airframeui/typography.css"; /* Generated file */Available type roles:
h1,h2,h3,h4,h5,h6- Heading stylesbody- Body textcaption- Small textdisplay- Large display/hero text
Each type role can override:
size- Font size (e.g.,"2rem"or"var(--af-text-2xl)")weight- Font weight (e.g.,"600"or"var(--af-weight-semibold)")leading- Line height (e.g.,"1.5"or"var(--af-leading-normal)")tracking- Letter spacing (e.g.,"-0.01em")
Fallback to Defaults
Section titled “Fallback to Defaults”Default behavior (useDefaults: false):
- Uses only your custom breakpoints (or defaults if none provided)
- No merging with default breakpoints
- Explicit control over which breakpoints are available
With useDefaults: true:
- Merges your custom breakpoints with defaults
- Extends the default set rather than replacing it
- Useful when you want to add custom breakpoints while keeping defaults
Defaults:
- If no config file is provided, defaults are used automatically
- Sensible defaults apply without extra setup
Migration from Manual Script
Section titled “Migration from Manual Script”If you were using npx --package @airframeui/core airframe-generate-responsive:
Before:
npx --package @airframeui/core airframe-generate-responsiveAfter (Recommended):
# Install the build package
npm install -D @airframeui/build
# Create airframe.config.js with your breakpoints
npx af buildOr continue using core directly:
npx --package @airframeui/core airframe-generate-responsiveThe PostCSS plugin approach is more integrated and works seamlessly with your build process.
Troubleshooting
Section titled “Troubleshooting”@af bp() not working?
Section titled “@af bp() not working?”- Make sure PostCSS plugin is configured correctly (see PostCSS Plugin section)
- Check that breakpoint name exists in your config
- Verify PostCSS is running in your build process
@af-apply not working?
Section titled “@af-apply not working?”- Make sure the PostCSS plugin is configured correctly (see PostCSS Plugin section)
- Ensure utility classes are imported before using
@af-apply(import@airframeui/core/core.cssfirst) - Verify the utility class name is correct (e.g.,
af-scrollbar, notaf-scroll-bar) - Check that PostCSS is processing your CSS files during build
Utility class not found warning?
Section titled “Utility class not found warning?”- The utility class must be defined in your CSS before
@af-applycan reference it - Make sure you’ve imported the core CSS:
@import "@airframeui/core/core.css"; - Verify the class name matches exactly (case-sensitive, with correct hyphens)
Generated responsive.css not found?
Section titled “Generated responsive.css not found?”- Check
outputDirin config (default: project-root.airframeui) - Ensure the build process has write permissions for that directory
- Verify PostCSS/
af buildis processing your CSS files
Breakpoints not applying?
Section titled “Breakpoints not applying?”- Set
useDefaults: trueif you want to merge your breakpoints with defaults - If
useDefaults: false, only your custom breakpoints will be used (or defaults if none provided) - Verify breakpoint values are valid (e.g.,
"640px"not640) - Check that responsive.css is imported after core.css (if using generated utilities)
See Also
Section titled “See Also”- @airframeui/build on GitHub — full package documentation
- @airframeui/theme on GitHub — theme generation library
- Theming — Theme Studio, CSS overrides, and MCP
- Tokens — design tokens overview
- Layouts — layout recipes