|
| 1 | +# Agent Rules |
| 2 | + |
| 3 | +1. **Public Repository Warning**: This is a PUBLIC repository. Never include internal/sensitive information in the project. |
| 4 | + |
| 5 | +2. **File Operations**: |
| 6 | + |
| 7 | + - Always read files before editing them |
| 8 | + - Always prefer editing existing files instead of creating new ones |
| 9 | + - Always use specialized tools (read_files, edit, write) instead of bash commands where possible |
| 10 | + - Never create documentation files unless directed |
| 11 | + |
| 12 | +3. **Communication Style**: |
| 13 | + |
| 14 | + - Always be concise and technical |
| 15 | + - Always output text directly to user, NOT via bash echo or comments |
| 16 | + - Always request more information when necessary |
| 17 | + - Never use emoji |
| 18 | + |
| 19 | +4. **Code Quality**: |
| 20 | + |
| 21 | + - Always run relevant tests for the area of code being modified |
| 22 | + - Always improve the test suite when fixing issues instead of just reading the code or using CLI |
| 23 | + - Always format files after editing using the relevant tool |
| 24 | + - Never use placeholders in code, always use real values or ask for them |
| 25 | + |
| 26 | +5. **Git Safety**: |
| 27 | + |
| 28 | + - Never push or commit unless directed |
| 29 | + - Never update git config |
| 30 | + - Never force push to main/master |
| 31 | + - Never use interactive git commands (`-i` flag) |
| 32 | + - Never skip hooks (--no-verify, --no-gpg-sign) |
| 33 | + - Never run destructive git commands unless directed |
| 34 | + - Never create PRs unless directed |
| 35 | + |
| 36 | +6. **Task Management**: |
| 37 | + |
| 38 | + - Always use the todo/task tool |
| 39 | + - Always mark todos/tasks as complete immediately after finishing them |
| 40 | + - Never work on multiple todos/tasks simultaneously |
| 41 | + |
| 42 | +7. **When stuck**: |
| 43 | + - Check existing documentation |
| 44 | + - Ask the developer for clarification |
| 45 | + - Review recent commits for context |
| 46 | + |
| 47 | +# Project Overview |
| 48 | + |
| 49 | +Compiled is a **compile-time CSS-in-JS library** for React that transforms styled components into atomic CSS at build time via Babel AST transformations. Unlike runtime CSS-in-JS libraries, all styles are extracted and processed during compilation. |
| 50 | + |
| 51 | +**Core principle**: Zero runtime CSS generation. All styles are determined at build time through static analysis and AST manipulation. |
| 52 | + |
| 53 | +# Architecture |
| 54 | + |
| 55 | +## Monorepo Structure |
| 56 | + |
| 57 | +Yarn workspaces monorepo with three main workspace types: |
| 58 | + |
| 59 | +- `packages/*` - Core libraries published to npm |
| 60 | +- `examples/*` - Example integrations (webpack, parcel, ssr) |
| 61 | +- `fixtures/*` - Test fixtures and babel component examples |
| 62 | + |
| 63 | +**Critical packages**: |
| 64 | + |
| 65 | +- `packages/babel-plugin/` - Core Babel transformation engine (AST processing) |
| 66 | +- `packages/react/` - Runtime library with `ax`, `ix`, `CC`, `CS` utilities |
| 67 | +- `packages/css/` - CSS parsing, sorting, and atomic stylesheet generation |
| 68 | +- `packages/webpack-loader/`, `packages/parcel-transformer/` - Bundler integrations |
| 69 | +- `packages/babel-plugin-strip-runtime/` - Extracts styles to separate `.compiled.css` files |
| 70 | +- `packages/codemods/` - Migration tools (emotion→compiled, styled-components→compiled) |
| 71 | +- `packages/eslint-plugin/` - ESLint rules for enforcing Compiled best practices |
| 72 | +- `packages/jest/` - Jest testing utilities and matchers |
| 73 | +- `packages/utils/` - Shared utilities across packages |
| 74 | +- `packages/benchmark/` - Performance benchmarking tools |
| 75 | + |
| 76 | +## Build System |
| 77 | + |
| 78 | +Uses TypeScript with **ttsc** (TypeScript Transformer Compiler) instead of plain `tsc`: |
| 79 | + |
| 80 | +```bash |
| 81 | +# Build order matters - babel fixtures first, then browser/cjs/esm |
| 82 | +yarn build:babel-fixture # Compile test fixtures |
| 83 | +yarn build:cjs # CommonJS output (packages/tsconfig.json) |
| 84 | +yarn build:esm # ES modules (packages/tsconfig.esm.json) |
| 85 | +yarn build:browser # Browser bundles (packages/tsconfig.browser.json) |
| 86 | +``` |
| 87 | + |
| 88 | +Post-build: `scripts/postbuild.sh` removes `__tests__/` and `__perf__/` from dist. |
| 89 | + |
| 90 | +## Atomic CSS System |
| 91 | + |
| 92 | +**Key concept**: One CSS rule per declaration. Class names encode both the atomic group (property+selectors+media) and value. |
| 93 | + |
| 94 | +Format: `_{group}{value}` where group is 4 chars and value is 4+ chars (e.g., `_1wyb1fwx` for `font-size:12px`). The underscore + 4-char group makes `ATOMIC_GROUP_LENGTH = 5` in code. |
| 95 | + |
| 96 | +**Runtime utilities** (`packages/react/src/runtime/`): |
| 97 | + |
| 98 | +- `ax()` - Merges classnames, ensures last atomic group wins (handles composition) |
| 99 | +- `ac()` - Advanced merging with AtomicGroups (chainable, memoized) |
| 100 | +- `ix()` - Injects CSS variables for dynamic values |
| 101 | +- `CC`, `CS` - Components for style sheet injection |
| 102 | + |
| 103 | +**Auto-ordering**: Pseudo-classes sorted to prevent cascade issues (`:link` → `:visited` → `:focus-within` → `:focus` → `:hover` → `:active`) |
| 104 | + |
| 105 | +# User-Facing APIs |
| 106 | + |
| 107 | +Main exports from `@compiled/react`: |
| 108 | + |
| 109 | +- `styled` - Create styled components (e.g., `styled.div({ color: 'red' })`) |
| 110 | +- `css` - Define styles for css prop (e.g., `css({ color: 'red' })`) |
| 111 | +- `cssMap` - Create CSS maps for conditional styling |
| 112 | +- `ClassNames` - Render prop component for dynamic className generation |
| 113 | +- `keyframes` - Define CSS animations |
| 114 | +- `xcss` / `cx()` - Strict-typed CSS system (Atlassian design system integration) |
| 115 | +- `createStrictAPI()` - Create type-safe CSS APIs with restricted properties |
| 116 | + |
| 117 | +See `packages/react/src/index.ts` for all exports. |
| 118 | + |
| 119 | +# Critical Workflows |
| 120 | + |
| 121 | +## Development |
| 122 | + |
| 123 | +```bash |
| 124 | +yarn install # Install + postinstall.sh (sets up tooling) |
| 125 | +yarn start # Storybook on :6006 (watch babel-plugin changes) |
| 126 | +yarn test <filter> --watch # Run specific tests |
| 127 | +yarn test:cover # Coverage report |
| 128 | +yarn test:vr # Visual regression tests with Loki (requires Storybook running) |
| 129 | +yarn benchmark # Run performance benchmarks |
| 130 | +yarn lint # Run ESLint |
| 131 | +yarn prettier:check # Check code formatting |
| 132 | +``` |
| 133 | + |
| 134 | +## Testing Patterns |
| 135 | + |
| 136 | +**Unit tests**: |
| 137 | + |
| 138 | +- Test files: `packages/*/src/**/*.test.{ts,tsx}` |
| 139 | +- Perf tests: `__perf__/*.test.ts` |
| 140 | +- Use `transform()` helper from `test-utils.ts` for Babel plugin tests |
| 141 | +- Babel plugin tests check transformed output with `.toMatchInlineSnapshot()` |
| 142 | +- Use `toHaveCompiledCss()` matcher from `@compiled/jest` |
| 143 | + |
| 144 | +**Visual regression tests**: |
| 145 | + |
| 146 | +- Uses Loki with Storybook |
| 147 | +- Run `yarn test:vr` (requires `yarn start` running in another terminal) |
| 148 | +- Accept changes with `yarn test:vr approve` |
| 149 | + |
| 150 | +**Performance tests**: |
| 151 | + |
| 152 | +- Benchmark files in `__perf__/` directories |
| 153 | +- Run with `yarn benchmark` |
| 154 | + |
| 155 | +## Working with Babel Plugin |
| 156 | + |
| 157 | +**Essential tool**: [astexplorer.net](https://astexplorer.net) - Use Babel 7 parser to visualize AST |
| 158 | + |
| 159 | +**Key transformation flow**: |
| 160 | + |
| 161 | +1. Parse JSX/TSX with Babel (`@babel/parser`) |
| 162 | +2. Traverse AST to find Compiled imports (`styled`, `css`, `cssMap`, `ClassNames`, `keyframes`) |
| 163 | +3. `buildCss()` - Extract styles from expressions (objects/template literals) |
| 164 | +4. `transformCssItems()` - Convert to atomic CSS rules |
| 165 | +5. `buildStyledComponent()` / `buildCompiledComponent()` - Generate runtime code |
| 166 | +6. `appendRuntimeImports()` - Add necessary runtime imports (`ax`, `ix`, `CC`, `CS`) |
| 167 | + |
| 168 | +**Common utilities** (`packages/babel-plugin/src/utils/`): |
| 169 | + |
| 170 | +- `css-builders.ts` - `buildCss()` main entry point |
| 171 | +- `build-styled-component.ts` - Generates `forwardRef` components |
| 172 | +- `transform-css-items.ts` - Converts styles to sheet/classname pairs |
| 173 | +- `ast.ts` - AST manipulation helpers |
| 174 | + |
| 175 | +## CSS Extraction (Production) |
| 176 | + |
| 177 | +Two-phase transformation: |
| 178 | + |
| 179 | +1. `@compiled/babel-plugin` - Transform CSS-in-JS to runtime code |
| 180 | +2. `@compiled/babel-plugin-strip-runtime` - Extract styles to `.compiled.css` |
| 181 | + |
| 182 | +Configure in `.babelrc`: |
| 183 | + |
| 184 | +```json |
| 185 | +{ |
| 186 | + "plugins": [ |
| 187 | + ["@compiled/babel-plugin"], |
| 188 | + [ |
| 189 | + "@compiled/babel-plugin-strip-runtime", |
| 190 | + { |
| 191 | + "extractStylesToDirectory": { "source": "src", "dest": "dist" } |
| 192 | + } |
| 193 | + ] |
| 194 | + ] |
| 195 | +} |
| 196 | +``` |
| 197 | + |
| 198 | +**Important**: Add `"sideEffects": ["**/*.compiled.css"]` to package.json to prevent tree-shaking. |
| 199 | + |
| 200 | +## Changesets for Releases |
| 201 | + |
| 202 | +```bash |
| 203 | +yarn changeset # Create changeset (select minor/patch) |
| 204 | +yarn release # Build + publish (CI only) |
| 205 | +``` |
| 206 | + |
| 207 | +- `minor` for new features, `patch` for bug fixes |
| 208 | +- Changesets live in `.changeset/` directory |
| 209 | + |
| 210 | +# Project Conventions |
| 211 | + |
| 212 | +## Import Sources |
| 213 | + |
| 214 | +Default import sources: `@compiled/react` (configurable via `importSources` option) |
| 215 | + |
| 216 | +Supports custom import sources for Atlassian internal packages. |
| 217 | + |
| 218 | +## Module Resolution |
| 219 | + |
| 220 | +Babel plugin uses synchronous resolver (via `enhanced-resolve`) to statically evaluate imports. Custom resolvers configurable via plugin options. |
| 221 | + |
| 222 | +## Dynamic Styles via CSS Variables |
| 223 | + |
| 224 | +Dynamic values injected as CSS variables: |
| 225 | + |
| 226 | +```jsx |
| 227 | +// Input |
| 228 | +<div css={{ color: props.color }} /> |
| 229 | + |
| 230 | +// Output |
| 231 | +<div |
| 232 | + style={{ "--_xyz": props.color }} |
| 233 | + className="_abc123" |
| 234 | +/> |
| 235 | +// CSS: ._abc123 { color: var(--_xyz); } |
| 236 | +``` |
| 237 | + |
| 238 | +## File Naming |
| 239 | + |
| 240 | +- Test files: `*.test.ts` (not `*.spec.ts`) |
| 241 | +- Perf tests: `__perf__/*.test.ts` |
| 242 | +- Fixtures: `__fixtures__/` directories |
| 243 | +- Parcel-specific tests: `*.parceltest.ts` |
| 244 | + |
| 245 | +## Code Quality |
| 246 | + |
| 247 | +- ESLint: `@compiled/eslint-plugin` provides 12+ rules for best practices |
| 248 | + - Recommended config: `plugin:@compiled/recommended` |
| 249 | + - Key rules: `no-css-tagged-template-expression`, `no-js-xcss`, `shorthand-property-sorting` |
| 250 | +- Prettier: Enforced via `yarn prettier:check` / `yarn prettier:fix` |
| 251 | +- TypeScript: Strict mode enabled, uses `ttsc` for custom transformers |
| 252 | +- Pre-commit hooks: Auto-runs lint and prettier via Husky |
| 253 | + |
| 254 | +## Style Buckets |
| 255 | + |
| 256 | +Styles injected in ordered buckets for cascade control: |
| 257 | + |
| 258 | +1. Default rules |
| 259 | +2. Link pseudo-selectors (`:link`, `:visited`) |
| 260 | +3. Focus pseudo-selectors (`:focus-within`, `:focus`, `:focus-visible`) |
| 261 | +4. Interaction pseudo-selectors (`:hover`, `:active`) |
| 262 | +5. At-rules (media queries - sorted mobile-first) |
| 263 | + |
| 264 | +See `packages/react/src/runtime/style.tsx` for bucket implementation. |
| 265 | + |
| 266 | +# Common Pitfalls |
| 267 | + |
| 268 | +1. **Double transformation**: Don't use both webpack-loader AND babel-plugin in babel config |
| 269 | +2. **AST type confusion**: Use `t.isIdentifier()` etc. before accessing node properties |
| 270 | +3. **Test snapshots**: Update with `--updateSnapshot` flag, not manual edits |
| 271 | +4. **Babel config in tests**: Always set `babelrc: false, configFile: false` to prevent inheritance |
| 272 | +5. **Atomic class deduplication**: Remember `ax()` uses last-wins strategy for same atomic group |
| 273 | +6. **xcss without TypeScript**: The xcss prop requires TypeScript - use ESLint rule `@compiled/no-js-xcss` to enforce |
| 274 | +7. **CSS extraction side effects**: Must add `"sideEffects": ["**/*.compiled.css"]` to package.json |
| 275 | + |
| 276 | +# Testing Examples Integration |
| 277 | + |
| 278 | +Run specific example apps: |
| 279 | + |
| 280 | +```bash |
| 281 | +yarn start:webpack # Webpack dev server |
| 282 | +yarn start:parcel # Parcel dev server |
| 283 | +yarn start:ssr # SSR example |
| 284 | +yarn build:webpack:extract # Test CSS extraction |
| 285 | +``` |
| 286 | + |
| 287 | +# Reference Files |
| 288 | + |
| 289 | +- Core transformation: `packages/babel-plugin/src/babel-plugin.ts` |
| 290 | +- Runtime utilities: `packages/react/src/runtime/` |
| 291 | +- All exports: `packages/react/src/index.ts` |
| 292 | +- Atomic CSS sorting: `packages/css/src/plugins/sort-atomic-style-sheet.ts` |
| 293 | +- Test patterns: `packages/babel-plugin/src/__tests__/index.test.ts` |
| 294 | +- ESLint rules: `packages/eslint-plugin/src/rules/` |
| 295 | +- Contributing guide: `CONTRIBUTING.md` (includes AST resources) |
| 296 | +- Documentation website: `website/` directory |
| 297 | + |
| 298 | +# Additional Resources |
| 299 | + |
| 300 | +- [AST Explorer](https://astexplorer.net) - Visualize Babel AST (use Babel 7 parser) |
| 301 | +- [Babel Handbook](https://github.com/jamiebuilds/babel-handbook) - Learn Babel plugin development |
| 302 | +- [Documentation website](https://compiledcssinjs.com) - User-facing docs and guides |
| 303 | +- Storybook examples: `stories/` directory - Live examples of all features |
0 commit comments