Configuration
Every key of axiom.json: styling, icons, navigation, aliases and items.
Not published yet
npx axiom doesn’t work yet: the CLI isn’t on npm. This page is the
specification it is being built against, so keys and defaults may still
change.
axiom.json sits at the root of your project. It tells the CLI which styling variant to copy, where to put files, and which items the project contains.
init creates it. add updates it. fetch reads it. You can also edit it by hand, and you should commit it with the rest of your code.
{
"$schema": "https://axiom.dev/schema.json",
"styling": "unistyles",
"icons": "expo-symbols",
"navigation": "expo-router",
"aliases": {
"theme": "@/theme",
"core": "@/components/core",
"hooks": "@/hooks",
"components": "@/components/ui",
"blocks": "@/components/blocks"
},
"items": [
"bottom-sheet",
"button",
"overlay",
"portal",
"tappable",
"theme",
"tokens"
]
}| Key | Type | Required | Description |
|---|---|---|---|
$schema | string | no | JSON Schema used by your editor. |
styling | string | yes | The styling tool of your project. |
icons | string | no | Where the icons of your project come from. |
navigation | string | no | The navigation library of your project. |
aliases | object | no | Where each layer is copied and imported from. |
items | string[] | no | Every Axiom item copied into the project. |
$schema
"$schema": "https://axiom.dev/schema.json"Points to the JSON Schema of the file. Editors that support JSON Schema, like VS Code, use it to autocomplete keys and flag invalid values. The CLI ignores it.
styling
"styling": "unistyles"The styling tool your project uses. It decides which variant add and fetch copy.
| Value | Variant copied | Dependency installed by init |
|---|---|---|
stylesheet | stylesheet | none |
unistyles | unistyles | react-native-unistyles |
nativewind | tailwind | nativewind |
uniwind | tailwind | uniwind |
nativewind and uniwind copy the same component files. The value is still stored separately because init sets up each tool differently. See Styling.
Changing styling only affects items copied afterwards. Files already in your project stay as they are. To move a component to another variant, run add again and confirm the overwrite, or port it by hand.
icons
"icons": "expo-symbols"Where the icons of your project come from. The CLI asks the first time you add an item that needs icons, like icon or button, and saves the answer here.
| Value | Icon registry created by add icon |
|---|---|
expo-symbols | Filled with common icons from SF Symbols (iOS) and Material Symbols (Android). Expo projects only. |
custom | Empty. You fill it with any icon set or your own SVGs. |
The registry, icons.tsx, belongs to your project: changing icons doesn’t rewrite it. See Icon.
navigation
"navigation": "expo-router"The navigation library of your project. A few items behave differently with a navigator: use-overlay-back-handler, used by BottomSheet, Dialog and Menu, closes the overlay on the back gesture and the header back button instead of leaving the screen.
The CLI doesn’t ask. The first time you add an item that needs it, it reads your package.json and saves the result here. Pass --navigation <library> to set another value.
| Value | Detected when | What use-overlay-back-handler handles |
|---|---|---|
expo-router | expo-router is installed | Android back button, back gesture, header back button |
react-navigation | @react-navigation/native is installed, without Expo Router | Android back button, back gesture, header back button |
react-native | neither is installed | Android back button |
Changing navigation only affects items copied afterwards. Run add use-overlay-back-handler again to get the other version.
aliases
"aliases": {
"theme": "@/theme",
"core": "@/components/core",
"hooks": "@/hooks",
"components": "@/components/ui",
"blocks": "@/components/blocks"
}Each alias is used twice: the CLI copies a layer into the folder the alias points to, and copied files import that layer through the alias.
| Alias | Layers | Default |
|---|---|---|
theme | foundations | @/theme |
core | core | @/components/core |
hooks | hooks | @/hooks |
components | typography, atoms, molecules, organisms, templates | @/components/ui |
blocks | blocks | @/components/blocks |
Every key is optional. A missing key uses its default.
Where files go
Files are copied flat into the alias folder, without subfolders. Only the files of your styling variant are copied. add bottom-sheet gives:
components/
├── core/
│ ├── overlay.tsx
│ └── portal.tsx
└── ui/
├── bottom-sheet.tsx
└── use-bottom-sheet.tsA hook used by a single component, like use-bottom-sheet.ts, stays next to that component. Only items from the hooks layer, like use-refresh-control, go to aliases.hooks.
A few files don’t use aliases because their location is fixed, for example a config file that must sit at the project root.
Imports
The CLI rewrites imports in the files it copies:
- imports between files of the same item become relative (
./use-bottom-sheet); - imports of other items use your aliases.
With "core": "@/ui/core", a copied component imports @/ui/core/portal instead of @/components/core/portal.
Files already in your project are not rewritten when you change an alias. Update their imports yourself, or copy them again.
Resolving aliases
An alias only works if your project resolves it. The CLI turns @/ into a folder through the paths of your tsconfig.json: with "@/*": ["./src/*"], @/components/ui is written to src/components/ui.
{
"extends": "expo/tsconfig.base",
"compilerOptions": {
"paths": {
"@/*": ["./src/*"]
}
}
}Expo resolves tsconfig.json paths at runtime by default. A React Native project without Expo also needs the alias in its Babel config, for example with babel-plugin-module-resolver.
items
"items": ["bottom-sheet", "button", "overlay", "portal", "tappable", "theme", "tokens"]The Axiom items copied into the project, by name, sorted alphabetically.
initadds the foundations and core primitives it copies.addadds the component you asked for and every internal dependency it copied.add bottom-sheetalso addsportalandoverlay.fetchcopies every item in the list. Files already in your project are skipped. See fetch.
Internal dependencies are listed too, not only the components you asked for. The file shows at a glance what the project contains, and fetch restores the same set.
The list is not kept in sync with your files. Deleting a file doesn’t remove its item: remove it from items yourself, or the next fetch copies it back. Renaming a copied file has the same effect, since fetch looks for the original file name.
npm packages are not listed. They are already in package.json, and the CLI knows which ones each item needs.