Blockforge

Command Palette

Search for a command to run...

InstallationMenu

Installation

Make sure you've covered the requirements first. Then pick the way that fits: the CLI (recommended) or copy-paste.

Register the namespace

Tell the shadcn CLI where @blockforge lives. You do this once per project — no token needed for free blocks. The fastest way is one command:

npx shadcn@latest registry add @blockforge=https://blockforge.terravidhal.me/r/{name}.json

That writes the entry into your components.json for you. Prefer to do it by hand? Add it yourself — same result:

components.json (manual)
{
  "registries": {
    "@blockforge": "https://blockforge.terravidhal.me/r/{name}.json"
  }
}

Pro blocks use the same endpoint but need your token — see Pro access.

Add a block

Two ways — pick one. Dependencies and ui components resolve automatically either way.

With the namespace (after the step above)

The @blockforge/…form only works once the namespace is registered (the step just above). It's the way to go for regular use:

npx shadcn@latest add @blockforge/hero-centered
Seeing Unknown registry "@blockforge"? The namespace isn't registered yet — run the registry command above, or use the raw URL below (no setup).

With a raw URL (zero setup)

Skip the setup entirely and pass the full URL — handy for a one-off free block:

npx shadcn@latest add https://blockforge.terravidhal.me/r/hero-centered.json

Or copy-paste

Open any block in the catalog, switch to the Code tab, copy, paste. Free blocks are open; pro blocks unlock after signing in with your purchase email.

CSS utilities

Some blocks use Blockforge's signature utilities (blueprint grids, marquee, orbit, border beam…). Installing via the shadcn CLI injects the ones a block needs automatically. If you copy-paste instead, append what you need from the full set below to your global CSS:

blockforge-utilities.css
@utility bg-grid-lg {
  background-image: linear-gradient(to right, color-mix(in oklab, var(--foreground) 9%, transparent) 1px, transparent 1px), linear-gradient(to bottom, color-mix(in oklab, var(--foreground) 9%, transparent) 1px, transparent 1px);
  background-size: 96px 96px;
}
@utility bg-grid-sm {
  background-image: linear-gradient(to right, color-mix(in oklab, var(--foreground) 4%, transparent) 1px, transparent 1px), linear-gradient(to bottom, color-mix(in oklab, var(--foreground) 4%, transparent) 1px, transparent 1px);
  background-size: 24px 24px;
}
@utility bg-dots {
  background-image: radial-gradient(circle, color-mix(in oklab, var(--foreground) 16%, transparent) 1px, transparent 1px);
  background-size: 14px 14px;
}
@utility bg-stripes {
  background-image: repeating-linear-gradient(-45deg, color-mix(in oklab, var(--foreground) 5%, transparent) 0 1px, transparent 1px 7px);
}
@utility animate-marquee {
  animation: marquee 32s linear infinite;
  @media (prefers-reduced-motion: reduce) {
    animation: none;
  }
}
@utility animate-marquee-reverse {
  animation: marquee 32s linear infinite reverse;
  @media (prefers-reduced-motion: reduce) {
    animation: none;
  }
}
@utility animate-caret {
  animation: caret-blink 1.1s steps(1) infinite;
  @media (prefers-reduced-motion: reduce) {
    animation: none;
  }
}
@utility animate-status {
  animation: status-pulse 2.4s ease-out infinite;
  @media (prefers-reduced-motion: reduce) {
    animation: none;
  }
}
@utility animate-orbit {
  animation: orbit 40s linear infinite;
  @media (prefers-reduced-motion: reduce) {
    animation: none;
  }
}
@utility animate-orbit-reverse {
  animation: orbit 40s linear infinite reverse;
  @media (prefers-reduced-motion: reduce) {
    animation: none;
  }
}
@utility animate-word-cycle {
  animation: word-cycle var(--cycle-duration, 8s) infinite;
  animation-delay: var(--cycle-delay, 0s);
  animation-fill-mode: both;
  @media (prefers-reduced-motion: reduce) {
    animation: none;
    opacity: 0;
    &:first-child {
      opacity: 1;
      transform: none;
    }
  }
}
@utility border-beam {
  position: relative;
  &::after {
    content: "";
    position: absolute;
    inset: -1px;
    border-radius: inherit;
    padding: 1px;
    background: conic-gradient(from var(--beam-angle), transparent 0deg 300deg, color-mix(in oklab, var(--foreground) 90%, transparent) 350deg, transparent 360deg);
    mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
    mask-composite: exclude;
    animation: beam-rotate 3.2s linear infinite;
    pointer-events: none;
  }
  @media (prefers-reduced-motion: reduce) {
    &::after {
      display: none;
    }
  }
}
@utility beam-hover {
  &::after {
    opacity: 0;
    transition: opacity 0.25s ease-out;
    animation-play-state: paused;
  }
  &:hover::after, &:focus-within::after {
    opacity: 1;
    animation-play-state: running;
  }
}
@utility flux-x {
  position: absolute;
  height: 1px;
  width: 9rem;
  background: linear-gradient(90deg, transparent, color-mix(in oklab, var(--foreground) 65%, transparent), transparent);
  animation: flux-x var(--flux-duration, 8s) linear infinite;
  animation-delay: var(--flux-delay, 0s);
}
@utility flux-y {
  position: absolute;
  width: 1px;
  height: 9rem;
  background: linear-gradient(180deg, transparent, color-mix(in oklab, var(--foreground) 65%, transparent), transparent);
  animation: flux-y var(--flux-duration, 9s) linear infinite;
  animation-delay: var(--flux-delay, 0s);
}
@keyframes marquee {
  to {
    transform: translateX(-50%);
  }
}
@keyframes caret-blink {
  50% {
    opacity: 0;
  }
}
@keyframes status-pulse {
  0% {
    box-shadow: 0 0 0 0 color-mix(in oklab, currentColor 45%, transparent);
  }
  70%, 100% {
    box-shadow: 0 0 0 6px transparent;
  }
}
@keyframes orbit {
  to {
    transform: rotate(360deg);
  }
}
@keyframes word-cycle {
  0%, 3% {
    transform: translateY(110%);
    opacity: 0;
  }
  7%, 24% {
    transform: translateY(0);
    opacity: 1;
  }
  29%, 100% {
    transform: translateY(-110%);
    opacity: 0;
  }
}
@property --beam-angle {
  syntax: "<angle>";
  initial-value: 0deg;
  inherits: false;
}
@keyframes beam-rotate {
  to {
    --beam-angle: 360deg;
  }
}
@keyframes flux-x {
  from {
    transform: translateX(-10rem);
  }
  to {
    transform: translateX(82rem);
  }
}
@keyframes flux-y {
  from {
    transform: translateY(-10rem);
  }
  to {
    transform: translateY(56rem);
  }
}
Buying the pro blocks? Wire up your token next.Pro access