Instalação

Como consumir @bacdmy/ui em apps Next.js.

1. Autenticação no GitHub Packages

  1. Crie um Personal Access Token (classic) no GitHub com o escopo read:packages. Se o pacote for privado, inclua também repo.
  2. No app consumidor, o .npmrc commitado deve ter o registry do escopo:
@bacdmy:registry=https://npm.pkg.github.com

Não coloque _authToken no .npmrc do repositório. Uma linha com ${NODE_AUTH_TOKEN} vazio sobrescreve o PAT do ~/.npmrc e causa E401.

Local

Coloque o PAT no ~/.npmrc do usuário:

//npm.pkg.github.com/:_authToken=ghp_…

Vercel / CI

Defina a env NODE_AUTH_TOKEN (PAT com read:packages) e injete o token no Install Command (ou num preinstall), por exemplo:

echo "//npm.pkg.github.com/:_authToken=${NODE_AUTH_TOKEN}" >> .npmrc && pnpm install

2. Instalar

pnpm add @bacdmy/ui@0.0.1

Ícones: Tabler (não Lucide)

Este design system usa @tabler/icons-react (Tabler Icons), não Lucide. Os primitivos do pacote já importam ícones Tabler; nos apps consumidores, use o mesmo pacote para manter consistência visual e de API.

  • Importe como IconXyz (ex.: IconPlus, IconChevronDown).
  • Não instale lucide-react nem misture bibliotecas de ícones no mesmo app.
  • Se o app ainda não tiver a dependência: pnpm add @tabler/icons-react.
import { IconPlus, IconChevronDown } from '@tabler/icons-react'

<Button>
  <IconPlus data-icon="inline-start" />
  Novo
</Button>

3. next.config

O pacote exporta TypeScript fonte. Transpile no Next:

import type { NextConfig } from 'next'

const nextConfig: NextConfig = {
  transpilePackages: ['@bacdmy/ui']
}

export default nextConfig

4. Estilos

No CSS global do app (depois de configurar Tailwind v4):

@import '@bacdmy/ui/styles';
/* CSS específico do app (blog, marketing…) abaixo */

O CSS do pacote mapeia @theme assim: --font-sans, --font-heading e --font-mono ← --font-geist-mono. Sem as variáveis no <html>, as classes font-sans / font-heading / font-mono não resolvem.

5. Importar componentes

import { Button, Logo } from '@bacdmy/ui'
// ou por caminho:
import { Button } from '@bacdmy/ui/button'

6. Fontes

O design system não embute arquivos de fonte. Cada app carrega Inter, Inter Tight e Geist Mono com next/font/google e publica CSS variables no <html>.

O que cada variável alimenta

  • --font-sans → corpo / UI (font-sans, default do html)
  • --font-heading → títulos (font-heading, Logo labels, headings)
  • --font-geist-mono → código / mono (font-mono no tema aponta para essa variável)

Layout do app

import { Geist_Mono, Inter, Inter_Tight } from 'next/font/google'
import { cn } from '@bacdmy/ui' // ou '@/lib/utils'

const inter = Inter({ subsets: ['latin'], variable: '--font-sans' })
const interTight = Inter_Tight({
  subsets: ['latin'],
  variable: '--font-heading',
  weight: 'variable'
})
const geistMono = Geist_Mono({
  variable: '--font-geist-mono',
  subsets: ['latin']
})

export default function RootLayout({ children }) {
  return (
    <html
      lang="pt-BR"
      className={cn(
        'h-full antialiased',
        geistMono.variable,
        inter.variable,
        interTight.variable,
        'font-sans'
      )}
      suppressHydrationWarning
    >
      <body className="min-h-full flex flex-col">{children}</body>
    </html>
  )
}

As classes *.variable do next/font injetam --font-* no elemento. font-sans no html aplica a família de corpo como default. Não redefina essas variáveis no CSS do app — o pacote já as consome em @bacdmy/ui/styles.