Manual installation
No CLI. You place the tokens, the utility, and one component by hand, so you can see exactly what lands.
Overview
There is nothing magic in the CLI. It fetches a JSON registry item, writes the
files it names into the directories your components.json aliases point at, and
installs any real dependencies. Doing it by hand is entirely reasonable. It is
the right choice in three situations: your platform forbids fetching code at
build time, you want to review every byte before it enters the repository, or
your directory layout is unusual enough that fighting the aliases costs more
than copying four files.
Shipped, and no published host yet
The sixty implemented components are real code, and a registry item that
is being served carries the whole of the source you would otherwise copy by
hand. What is missing is the host: opsinjs.pensievelabs.org does not resolve, so fetching
a /r/<name>.json from it fails, and there is no npm package to fall back to.
Point the URLs below at a host that is serving the items and the shape is the
same. Troubleshooting.
Put the four pieces in place
The token layer
One CSS file defining every opsinjs custom property: the two colour axes, the
material ladder, the motion springs, and the type, space and shape scales. Save it
as app/opsinjs.css or wherever else your stylesheet lives, and import it after
Tailwind and before your own overrides.
@import "tailwindcss";
@import "./opsinjs.css";
@source "./components/opsinjs/**/*.{ts,tsx}";This file is generated from the token source and should be replaced wholesale
rather than edited. Extensions go in your own @theme block afterwards; see
Adding your own tokens.
The cn utility
Copied components import a class-merging helper. If you already have shadcn/ui you
already have it at lib/utils.ts and nothing needs doing. If not, it is the
standard clsx plus tailwind-merge composition, and it must live at the path
your imports expect.
The component source
Fetch the registry item for the component you want and write out each file it names. A registry item is a JSON document listing files, their target paths, their type, and any real dependencies. Nothing is hidden in it, which is the point of publishing the format. registry-item.json annotates every field.
The dependencies
Install whatever the registry item's dependencies array names. For most opsinjs
components this is nothing beyond what you already have. Nothing is installed that
the component does not genuinely need at runtime.
Fix the import paths
This is the only part that is fiddly by hand. Copied source uses the alias
conventions from components.json, such as @/components/... and
@/lib/utils. If you are not using those aliases, rewrite the imports as you
paste.
Rewriting imports is preferable to inventing a matching alias you will not use elsewhere, and if you are doing this more than twice it is a strong sign that adopting the alias convention would be cheaper than the ongoing edit.
Verify it worked
- The component compiles and its imports resolve. Check
cnin particular. - It renders styled. Unstyled means Tailwind is not scanning the directory you pasted into.
- Its colours come from custom properties. Literals mean the token layer is missing or in the wrong position.
- Adding
darkto the root element inverts the theme with no JavaScript. - You have recorded what you copied and when, in your own commit message,
because the file will not record it for you. Commit the files
shadcn addwrites in their own commit, so a later--diffhas something to compare against.
Troubleshooting
Unstyled component. The @source line does not cover where you pasted it.
cn is not exported. The utility is missing or at a different path from the
import.
Wrong colours. Import position: the token layer must come after Tailwind.
You edited the token layer directly and now an update conflicts. Expected.
Treat that file as generated: replace it, and keep your changes in your own
@theme block afterwards.
You are doing this for every component. Reconsider the CLI. Manual placement is a reasonable answer for one or two components and an expensive habit for twenty.
Next
- registry-item.json covers the format you are reading by hand.
- Adding your own tokens covers extending the token layer without editing it.
- Upgrading shows how to take a change to code you own.