Why Naming Matters
Without Conventions
- Button.tsx
- loginBtn.tsx
- SubmitBTN.tsx
- cta-button.tsx
Nobody can find anything. Imports break. Autocomplete fails.
With Buoy
- Button.tsx
- LoginButton.tsx
- SubmitButton.tsx
- CtaButton.tsx
Predictable, searchable, and consistent everywhere.
See it in action
buoy-cli
$
âš“ Checking naming conventions...
âš Found 5 naming inconsistencies
Components:
⚠LoginBtn.tsx → Expected: LoginButton.tsx
⚠userCard.tsx → Expected: UserCard.tsx
Tokens:
⚠--primary-clr → Expected: --color-primary
⚠--txtColor → Expected: --color-text
Props:
âš isDisabled vs disabled (inconsistent across 12 components)
What We Check
Components
- • PascalCase file names (Button.tsx, not button.tsx)
- • Match file name to default export
- • Suffix patterns (Button, ButtonGroup, ButtonIcon)
Tokens
- • Consistent prefix (--color-*, --spacing-*, --font-*)
- • kebab-case naming
- • Semantic names (--color-primary, not --blue-500)
Props
- • Boolean props: is*, has*, should* prefix
- • Handler props: on* prefix
- • Consistent across similar components
Files & Folders
- • components/ for shared components
- • features/ for feature-specific code
- • Consistent index exports
Customize Your Conventions
.buoy.yaml
# .buoy.yaml
naming:
components:
# File naming
fileCase: PascalCase # PascalCase, camelCase, kebab-case
matchExport: true # File name must match default export
# Suffixes
requiredSuffixes:
Button:
- Button
- Btn # Allow both
Icon:
- Icon
tokens:
prefix: "--ds-" # Token prefix
categories:
- color
- spacing
- font
- radius
- shadow
casing: kebab-case
props:
booleans: "is*" # isDisabled, isLoading
handlers: "on*" # onClick, onChange
refs: "*Ref" # buttonRef, inputRef