Set up the anyTV Material 3 component library in this project, using the theme configured
below. Work from the project root and do these in order.
1. Create or edit `.npmrc`:
```ini
@anytv:registry=https://npm.pkg.github.com
//npm.pkg.github.com/:_authToken=${ANYTV_M3_TOKEN}
```
Commit `.npmrc` — it names the token, it does not carry it.
2. The token value lives in `.env.local`, which git ignores, under the name
`ANYTV_M3_TOKEN`. Ask me for the value rather than obtaining one, and keep it out of every
tracked file. Two tools need it: the shadcn-vue CLI reads `.env.local`, and pnpm reads the
same name from the shell environment.
3. Add this as a top-level key in `components.json`, beside `"aliases"`. Run
`pnpm dlx shadcn-vue@latest init` first if `components.json` is absent. `{name}` and
`${ANYTV_M3_TOKEN}` are placeholders the CLI expands, so keep both literal.
```json
"registries": {
"@m3": {
"url": "https://api.github.com/repos/anyTV/m3-ui/contents/r/{name}.json",
"params": { "ref": "components-v0.2.0" },
"headers": {
"Accept": "application/vnd.github.raw",
"Authorization": "Bearer ${ANYTV_M3_TOKEN}",
"X-GitHub-Api-Version": "2022-11-28"
}
}
}
```
4. Run `pnpm add @anytv/m3-tokens`.
5. In the Tailwind entry stylesheet, import the theme after Tailwind itself and set the
source colour configured below:
```css
@import 'tailwindcss';
@import '@anytv/m3-tokens/css/theme.css';
:root {
--m3-source-color: #6750A4;
}
```
6. In the same file, after those imports, paste this generated theme block exactly as it
stands. Every color role and the typeface in it are already resolved from the configuration
below, so nothing here is a placeholder to fill in:
```css
/* m3-ui theme — import after the base M3 tokens
* Source: #6750A4
* Scheme: tonalSpot
* Typeface: Roboto
* Generated typography and one declaration per color role via light-dark(); the mode is
* chosen by color-scheme, and the .light / .dark rules below let this block stand alone.
*/
:root {
--md-ref-typeface-brand: 'Roboto', system-ui, sans-serif;
--md-ref-typeface-plain: 'Roboto', system-ui, sans-serif;
--md-ref-typeface-weight-regular: 400;
--md-ref-typeface-weight-medium: 500;
--md-ref-typeface-weight-bold: 700;
font-optical-sizing: auto;
font-stretch: normal;
font-variation-settings: normal;
--m3-brand-font-optical-sizing: auto;
--m3-brand-font-stretch: normal;
--m3-brand-font-variation-settings: normal;
--m3-plain-font-optical-sizing: auto;
--m3-plain-font-stretch: normal;
--m3-plain-font-variation-settings: normal;
}
body {
font-family: var(--md-ref-typeface-plain);
}
code,
kbd,
pre,
samp {
font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono",
"Courier New", monospace;
font-optical-sizing: auto;
font-stretch: normal;
font-variation-settings: normal;
}
:root {
color-scheme: light dark;
--md-sys-color-background: light-dark(#fdf7ff, #141218);
--md-sys-color-on-background: light-dark(#1d1b20, #e6e0e9);
--md-sys-color-surface: light-dark(#fdf7ff, #141218);
--md-sys-color-surface-dim: light-dark(#ded8e0, #141218);
--md-sys-color-surface-bright: light-dark(#fdf7ff, #3b383e);
--md-sys-color-surface-container-lowest: light-dark(#ffffff, #0f0d13);
--md-sys-color-surface-container-low: light-dark(#f8f2fa, #1d1b20);
--md-sys-color-surface-container: light-dark(#f2ecf4, #211f24);
--md-sys-color-surface-container-high: light-dark(#ece6ee, #2b292f);
--md-sys-color-surface-container-highest: light-dark(#e6e0e9, #36343a);
--md-sys-color-on-surface: light-dark(#1d1b20, #e6e0e9);
--md-sys-color-surface-variant: light-dark(#e7e0eb, #49454e);
--md-sys-color-on-surface-variant: light-dark(#49454e, #cac4cf);
--md-sys-color-outline: light-dark(#7a757f, #948f99);
--md-sys-color-outline-variant: light-dark(#cac4cf, #49454e);
--md-sys-color-inverse-surface: light-dark(#322f35, #e6e0e9);
--md-sys-color-inverse-on-surface: light-dark(#f5eff7, #322f35);
--md-sys-color-shadow: #000000;
--md-sys-color-scrim: #000000;
--md-sys-color-surface-tint: light-dark(#65558f, #cfbdfe);
--md-sys-color-primary: light-dark(#65558f, #cfbdfe);
--md-sys-color-primary-dim: light-dark(#594982, #c7b4f5);
--md-sys-color-on-primary: light-dark(#ffffff, #36275d);
--md-sys-color-primary-container: light-dark(#e9ddff, #4d3d75);
--md-sys-color-on-primary-container: light-dark(#4d3d75, #e9ddff);
--md-sys-color-primary-fixed: #e9ddff;
--md-sys-color-primary-fixed-dim: #cfbdfe;
--md-sys-color-on-primary-fixed: #201047;
--md-sys-color-on-primary-fixed-variant: #4d3d75;
--md-sys-color-inverse-primary: light-dark(#cfbdfe, #65558f);
--md-sys-color-secondary: light-dark(#625b71, #cbc2db);
--md-sys-color-secondary-dim: light-dark(#564f64, #e8def8);
--md-sys-color-on-secondary: light-dark(#ffffff, #332d41);
--md-sys-color-secondary-container: light-dark(#e8def8, #4a4458);
--md-sys-color-on-secondary-container: light-dark(#4a4458, #e8def8);
--md-sys-color-secondary-fixed: #e8def8;
--md-sys-color-secondary-fixed-dim: #cbc2db;
--md-sys-color-on-secondary-fixed: #1e192b;
--md-sys-color-on-secondary-fixed-variant: #4a4458;
--md-sys-color-tertiary: light-dark(#7e5260, #efb8c8);
--md-sys-color-tertiary-dim: light-dark(#704654, #fec5d6);
--md-sys-color-on-tertiary: light-dark(#ffffff, #4a2532);
--md-sys-color-tertiary-container: light-dark(#ffd9e3, #633b48);
--md-sys-color-on-tertiary-container: light-dark(#633b48, #ffd9e3);
--md-sys-color-tertiary-fixed: #ffd9e3;
--md-sys-color-tertiary-fixed-dim: #efb8c8;
--md-sys-color-on-tertiary-fixed: #31101d;
--md-sys-color-on-tertiary-fixed-variant: #633b48;
--md-sys-color-error: light-dark(#ba1a1a, #ffb4ab);
--md-sys-color-error-dim: light-dark(#a80710, #ff554a);
--md-sys-color-on-error: light-dark(#ffffff, #690005);
--md-sys-color-error-container: light-dark(#ffdad6, #93000a);
--md-sys-color-on-error-container: light-dark(#93000a, #ffdad6);
}
.light {
color-scheme: light;
}
.dark {
color-scheme: dark;
}
```
7. Inside `<head>` in `index.html`, paste these font links exactly as they stand:
```html
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Roboto:wght@400;500;700&display=block">
```
8. Run `pnpm dlx shadcn-vue@latest add @m3/agent-rules`. It writes `.agents/m3-ui.md` and
`.agents/m3-ui-components.md` and prints one pointer line; put that line in this project’s
`AGENTS.md` or `CLAUDE.md` so every later session reaches them.
9. Read `.agents/m3-ui.md` and `.agents/m3-ui-components.md` in full, and follow them for
every component you add from here, one at a time:
`pnpm dlx shadcn-vue@latest add @m3/<name>`.
Done when `pnpm dlx shadcn-vue@latest search @m3` lists the registry’s items. A 404 from it
means the token value has not reached the CLI — an empty header is dropped rather than sent
blank. If an install fails with `ERR_PNPM_IGNORED_BUILDS`, allow `esbuild` and `vue-demi`
under `allowBuilds` in `pnpm-workspace.yaml`.
It writes the files, runs the installs, and asks you for the token value. The color and typeface you picked here are already in it.