Navigation

v0.0.4
Customizing

Owning the source

Choose package imports, tracked copies from the installed version, or registry files, and connect copied source to your project.

On this page

Keep components in the package when you want upgrades to update their implementation. Copy source when the project needs to edit it. You can combine both: import most of Master UI and maintain a few local components.

Imports and source ownership

The copying path determines how you track updates. An import reads the installed package. own and add copy that installed source into the project and save base files and ownership records for status and diff. A registry client copies hosted files into the project without those Master UI records, so you maintain their update history yourself.

Choose the copying tool by where the source should come from and how you will track later changes:

PathSourceHow updates reach the project
Import @master/uiThe installed packageUpgrade the dependency
master-ui own or master-ui addThe installed packageReview status and diff, then merge into the local copy
A registry clientThe files served at the registry URLReview and merge copied files with your own workflow

Use the first-party commands when a copy must match the installed version. The hosted registry follows the site's published source; it is not selected by your project's lockfile.

#The package is the default

A component from the package keeps following upstream: a fix to a focus ring, a forced-colors outline or a new platform feature reaches the project with an update. Most changes to how a component looks do not need its source. A utility, a token, a public custom property or a theme covers them, and customization lists the conditions under which owning a component is the right step.

#What you can copy

  • Blocks and pages provide page markup. Copy it from the Code view, the page's Markdown or its registry item, then adapt the content. Keep the component styles it uses installed; markup that uses a layout class, such as page, shell, auto-grid or form, also needs that layout's styles.
  • Behaviors can stay in the package. Import a reference script such as @master/ui/behaviors/combobox.js, or take the copy that comes with its component when keys, focus or selection should differ. A copied stylesheet alone does not redirect an existing behavior import. See behaviors.
  • Framework components are local source. add copies the React, Svelte or Vue component and its local helpers. Package updates may improve that source, but your copy changes only when you merge them. Its behavior imports normally keep using the package. See React, Svelte and Vue.

#The registry

The registry is a set of JSON files generated from the same source as the package.

URLHolds
https://ui.master.co/r/registry.jsonThe index: every item with its files' paths, without their content
https://ui.master.co/r/<name>.jsonOne item, with the content of each file

Each item follows the shadcn registry-item schema. Items use registry:item, and their files use registry:file with explicit targets. This lets the registry distribute CSS, HTML and framework source without requiring a Tailwind stylesheet. This is the button item's structure, with its file contents left out:

button.json
{  "$schema": "https://ui.shadcn.com/schema/registry-item.json",  "name": "button",  "type": "registry:item",  "title": "Button",  "description": "A raised control that lifts on hover and sinks when pressed.",  "dependencies": ["@master/css"],  "registryDependencies": [    "https://ui.master.co/r/theme.json",    "https://ui.master.co/r/icon.json",    "https://ui.master.co/r/spinner.json"  ],  "files": [    { "path": "ui/button.css", "type": "registry:file", "target": "~/ui/button.css", "content": "…" },    { "path": "ui/button.json", "type": "registry:file", "target": "~/ui/button.json", "content": "…" }  ],  "categories": ["Actions"],  "docs": "Import ui/button.css after ui/theme.css. Its contract is ui/button.json; markup: https://ui.master.co/components/button.md"}

registryDependencies names the theme and the contracts the component composes. A component's item also has a meta key with its tier, whether it needs a script, its classes, and the tokens and mixins its stylesheet reads.

#Items

ItemNameFiles
The themethemeui/theme.css
The Paper themetheme-paperui/themes/paper.css
A component or a layout classThe name of its contract: button, dialog, shellui/<name>.css and ui/<name>.json; with a behavior, ui/<behavior>.js and the helpers it imports, ui/internal.js
A framework component<framework>-<name>, such as react-combobox, svelte-dialog, vue-toastThe component, such as ui/combobox.tsx, ui/Dialog.svelte or ui/Toaster.vue, and the helper it imports from beside it
A blockblock-<slug>, such as block-heroui/blocks/<slug>.html
A pagepage-<slug>, such as page-dashboardui/pages/<slug>.html

A block's or a page's file is the markup of the first preview on its page. Its registryDependencies are the components that markup uses.

#Take a component with master-ui

The master-ui command in the package is the first-party path. It copies from the installed package, so the source matches the version the project already runs.

Start from a project with Master UI installed. Run these commands at its root:

npx master-ui init        # once: ui/index.css, one @import per stylesheetnpx master-ui own button  # ui/button.css and ui/button.json; the import now points at the copy

Use the generated ui/index.css in place of the full @master/ui import. Check that its button import points to ./button.css; otherwise the page is still drawing the package's button. Own a component shows the stylesheet setup.

The command records base copies in ui/.base/ and hashes in master-ui.json. Commit them with the owned source so another checkout can compare it with a later installed package. See reviewing upstream changes for the update workflow.

own takes what has a contract: components and the layout classes. Blocks and pages are copied from their pages or from the registry.

A framework component is taken with add. It is recorded the same way, so status, diff and accept cover it too.

npx master-ui add combobox --framework=react   # ui/combobox.tsx and ui/use-behavior.tsnpx master-ui add dialog                       # the framework is remembered

#Use the shadcn CLI

Use a registry client when you want an item from the hosted catalog, including the markup of a block or a page. For the shadcn CLI, add the namespace to components.json; merge this field into an existing configuration:

components.json
{  "registries": {    "@master": "https://ui.master.co/r/{name}.json"  }}

Then add an item by name:

npx shadcn@latest add @master/button

The files land at their targets, ui/button.css and ui/button.json. Import the stylesheet after the theme, as the item's docs says.

A framework component is added the same way, as @master/react-combobox, or by its address with no components.json at all:

npx shadcn@latest add https://ui.master.co/r/react-combobox.json

Universal items with explicit targets can use a configuration containing only registries; they do not need a Tailwind project. See the registry API documentation. The item's targets place these files under the project's ui/ directory.

Framework items declare @master/ui and the framework as dependencies; stylesheet items declare @master/css and their registry dependencies. Review the package manifest and lockfile after installation, then confirm that copied source and installed dependencies work together. Run the page and check the copied component's states and keyboard behavior.

A registry installation does not create Master UI's base copies and ownership records. master-ui status and master-ui diff therefore cannot track that installation. Choose own or add when you want their update workflow.

#What stays the same

Owning a component changes who maintains its stylesheet. It does not change its contract.

  • The copy arrives with its contract, ui/<name>.json. For this project it replaces the library's: master-ui check, master-ui contract and agents read the copy.
  • The classes, the element each goes on, the state attributes and the public custom properties are the same on the day the component is taken. Blocks, behaviors and the documentation fit it as before.
  • The copy still reads the theme's tokens and applies its mixins, so it follows the theme, including a theme of your own.

It stays that way as long as the contract is kept true: when the stylesheet gains, renames or loses a class, the contract changes with it. Contracts describes what a contract holds.