List every place your product renders a component, by page and by line of code, in the terminal, in Storybook, or across several repositories.
This playbook works on all Infa plans (Free, Pro, and Enterprise). The terminal command needs no account at all; the Storybook steps need a free Infa account and a board.
"Where is our Button actually used?" is one of the first questions a design system team asks, and one of the hardest to answer by hand. We at Infa answer it from two places: your code, which the Infa CLI reads for you, and your product, where the Chrome extension captures what people see. This playbook starts with the code, because it needs no tagging and gives you every usage in one run.
Copy link
What you get
For each component, a list of every place your code renders it:
The file and line, linked to it on GitHub or GitLab.
The element as written, for example <Button variant="primary" type="submit">.
The component it sits in, for example CheckoutForm.
The page it is on, matched to a screen on your Infa board when the board has one.
How its props are used across all of those places, for example variant: primary ×12, danger ×3.
Nothing is tagged by hand, and nothing goes stale: the list is read from your code every time you run it.
Where you look
What it shows
What it takes
Terminal
Every place, grouped by page
npx infa usages Button
Storybook Usage tab
The same list under each story, grouped by board screen
The Usage addon and npx infa storybook sync
The product, in the browser
Screenshots of the component on each screen
The Chrome extension
Copy link
1. See it in your terminal
In your repository, run:
npx infa usages Button
You can name the component or point at its file, which helps when several files declare a component with the same name:
npx infa usages src/components/Button/Button.tsx
The result is grouped by the page each usage is on:
Also read these folders: the product repositories that install your design system
--export Name
The export to look for, when one file exports several components
--include-tests
Count tests, stories and preview files as usages too
--json
Print the result as JSON, for scripts and agents
Pages come from your router
The CLI reads routes from Next.js (app/ pages and layouts, and pages/) and from React Router (<Route path element> and route objects), and follows imports up from each usage to the pages that render it. A layout reaches every page under it, so it shows as /settings/*.
Copy link
2. Put it in Storybook
If you use the storybook-infa-usage addon, the same list appears in each story's Usage tab, in a section called In code.
Install the latest addon and CLI, and register the addon in .storybook/main.ts:
Sign in and pick your board once, then sync from the folder Storybook runs in:
npx infa auth
npx infa board
npx infa storybook sync
Restart Storybook and open a story's Usage tab. Under the usages captured in the browser, In code lists every place your code renders the story's component, grouped by board screen, then by pages your board has no screen for yet, then "Not on a route". Each line links to the code. The section ends with the command that refreshes it.
Full view
Each story finds its component on its own, from its component: import. You don't need to add ids to your stories. To keep the list current, add a script and run it before Storybook, or in CI:
package.json
Copy code
Copy code
"scripts": {
"usage:sync": "infa storybook sync"
}
In CI, set INFA_ACCESS_TOKEN and INFA_BOARD_ID as secrets instead of running infa auth.
Copy link
3. When your design system lives in its own repository
A design system published as a package is used in other repositories, so its own repository has few usages. Point the CLI at the product repositories too:
npx infa usages Button --in ../web-app,../admin
npx infa storybook sync --in ../web-app,../admin
In those repositories, an import of your package's name counts as a usage, for example import { Button } from "@acme/ui" or import Button from "@acme/ui/Button". Their files show with the folder name in front (web-app/src/…).
Copy link
4. Tie pages to your board's screens
The Storybook list groups usages by screen when your board has a screen for the page. For a Next.js app using the App Router, create one screen per route in one step:
npx infa screens routes --publish
Pages without a screen still show, under their route, marked "No screen on the board".
Copy link
5. Add what people see in the product
Your code tells you where a component is rendered. The Chrome extension adds what people actually see: pick the component on a page and save it as a view of the component, on that page's screen. Those views appear in the same Usage tab, with a screenshot and a Browser badge, next to the code usages.
Copy link
What counts as a usage
A component rendered directly: <Button />
A renamed import: import { Button as Btn } from "@/components"
An import through barrel files (index.ts re-exports)
A namespace: import * as UI from "@/ui", then <UI.Button />
A lazy import: lazy(() => import("./Button")) or Next.js dynamic()
A wrapper in the same file: const PrimaryButton = styled(Button), whose uses are marked "through PrimaryButton"
A component passed on, for example as={Button}, marked "Passed on"
Types, such as ComponentProps<typeof Button>
Tests, stories and .preview.tsx files, unless you add --include-tests
The component's own file
Templates in Vue, Svelte or Angular: only JSX and TSX are read
File-based routers other than Next.js: TanStack Router, React Router v7 / Remix app/routes, Expo Router, Gatsby and Astro. Their usages are still listed, under "Not on a route"
The uses of a wrapper exported to other files, such as an exported styled(Button)
Copy link
Troubleshooting
The data file was written by an older CLI, or by the token script infa-usage-fetch. The tab shows the command to run instead: update with npm install --save-dev infa@latest, run npx infa storybook sync, then restart Storybook.
Your components are probably used in other repositories. Add them with --in ../app (step 3).
Your board has no screen for those pages yet. Create them with npx infa screens routes --publish (step 4).
Nothing the CLI recognizes as a page imports that file. This is common for a dialog opened from a shared hook, a page your router builds at runtime, or a router the CLI does not read yet. The usage is still listed with its file, line and the component it sits in.
Copy link
Conclusion
We at Infa built this so that "where is it used?" takes one command instead of an afternoon of searching. Start in the terminal to see the answer, put it in Storybook so your whole team sees it next to the component, and add the product's screens when you want to see what people see. If something you rely on is not read yet, tell us: the list above is where we are going next.
Find every place a component is used
This playbook works on all Infa plans (Free, Pro, and Enterprise). The terminal command needs no account at all; the Storybook steps need a free Infa account and a board.
"Where is our Button actually used?" is one of the first questions a design system team asks, and one of the hardest to answer by hand. We at Infa answer it from two places: your code, which the Infa CLI reads for you, and your product, where the Chrome extension captures what people see. This playbook starts with the code, because it needs no tagging and gives you every usage in one run.
For each component, a list of every place your code renders it:
<Button variant="primary" type="submit">.CheckoutForm.variant: primary ×12, danger ×3.Nothing is tagged by hand, and nothing goes stale: the list is read from your code every time you run it.
npx infa usages Buttonnpx infa storybook syncIn your repository, run:
You can name the component or point at its file, which helps when several files declare a component with the same name:
The result is grouped by the page each usage is on:
--in ../app,../admin--export Name--include-tests--jsonThe CLI reads routes from Next.js (
app/pages and layouts, andpages/) and from React Router (<Route path element>and route objects), and follows imports up from each usage to the pages that render it. A layout reaches every page under it, so it shows as/settings/*.If you use the storybook-infa-usage addon, the same list appears in each story's Usage tab, in a section called In code.
Install the latest addon and CLI, and register the addon in
.storybook/main.ts:Sign in and pick your board once, then sync from the folder Storybook runs in:
Restart Storybook and open a story's Usage tab. Under the usages captured in the browser, In code lists every place your code renders the story's component, grouped by board screen, then by pages your board has no screen for yet, then "Not on a route". Each line links to the code. The section ends with the command that refreshes it.
Each story finds its component on its own, from its
component:import. You don't need to add ids to your stories. To keep the list current, add a script and run it before Storybook, or in CI:In CI, set
INFA_ACCESS_TOKENandINFA_BOARD_IDas secrets instead of runninginfa auth.A design system published as a package is used in other repositories, so its own repository has few usages. Point the CLI at the product repositories too:
In those repositories, an import of your package's name counts as a usage, for example
import { Button } from "@acme/ui"orimport Button from "@acme/ui/Button". Their files show with the folder name in front (web-app/src/…).The Storybook list groups usages by screen when your board has a screen for the page. For a Next.js app using the App Router, create one screen per route in one step:
Pages without a screen still show, under their route, marked "No screen on the board".
Your code tells you where a component is rendered. The Chrome extension adds what people actually see: pick the component on a page and save it as a view of the component, on that page's screen. Those views appear in the same Usage tab, with a screenshot and a Browser badge, next to the code usages.
<Button />import { Button as Btn } from "@/components"index.tsre-exports)import * as UI from "@/ui", then<UI.Button />lazy(() => import("./Button"))or Next.jsdynamic()const PrimaryButton = styled(Button), whose uses are marked "through PrimaryButton"as={Button}, marked "Passed on"ComponentProps<typeof Button>.preview.tsxfiles, unless you add--include-testsapp/routes, Expo Router, Gatsby and Astro. Their usages are still listed, under "Not on a route"styled(Button)The data file was written by an older CLI, or by the token script
infa-usage-fetch. The tab shows the command to run instead: update withnpm install --save-dev infa@latest, runnpx infa storybook sync, then restart Storybook.Your components are probably used in other repositories. Add them with
--in ../app(step 3).Your board has no screen for those pages yet. Create them with
npx infa screens routes --publish(step 4).Nothing the CLI recognizes as a page imports that file. This is common for a dialog opened from a shared hook, a page your router builds at runtime, or a router the CLI does not read yet. The usage is still listed with its file, line and the component it sits in.
We at Infa built this so that "where is it used?" takes one command instead of an afternoon of searching. Start in the terminal to see the answer, put it in Storybook so your whole team sees it next to the component, and add the product's screens when you want to see what people see. If something you rely on is not read yet, tell us: the list above is where we are going next.