# Rivr

> DeFi staking landing page for a fluid-asset protocol: a video hero on a rounded card with glass stat cards and a carved documentation corner, a metrics band, a bento feature grid, a video call to action and a light footer. Self-contained light palette, Helvetica system type, Framer Motion throughout.

A shadcn/ui block from the [@hirael](https://hirael.com) registry, listed on [shadcn.exchange](https://shadcn.exchange/r/hirael/rivr).

- Page, with a live preview: https://shadcn.exchange/r/hirael/rivr
- Screenshot: https://abzjhwgwpdpz7ua5.public.blob.vercel-storage.com/shots/hirael/rivr-light-cf596a246cd419f0.png
- Registry item: https://hirael.com/r/rivr.json
- Categories: templates
- Listed: 2026-10-13, source last changed 2026-10-13

## Install

```bash
npx shadcn@latest add https://hirael.com/r/rivr.json
```

Run it in a project that has shadcn/ui set up. It adds the files below and installs what they depend on.

## Dependencies

- npm packages: `lucide-react`, `motion`
- Registry items: `button`

## Files

### `registry/hirael/bases/radix/templates/rivr/rivr.tsx`

```tsx
// Rivr from Hirael <https://hirael.com/templates/rivr>
// MIT · Mohammad Shehadeh · https://github.com/MohammadShehadeh/hirael

'use client';

import { MotionConfig } from 'motion/react';

import { Cta } from './cta';
import { Features } from './features';
import { Footer } from './footer';
import { Hero } from './hero';
import { Metrics } from './metrics';
import { RivrStyles } from './styles';

const Rivr = () => {
  return (
    <div className="rivr relative min-h-svh bg-background text-foreground antialiased">
      <RivrStyles />
      <MotionConfig reducedMotion="user">
        <Hero />
        <Metrics />
        <Features />
        <Cta />
        <Footer />
      </MotionConfig>
    </div>
  );
};

export default Rivr;
```

### `registry/hirael/bases/radix/templates/rivr/navbar.tsx`

```tsx
// Rivr from Hirael <https://hirael.com/templates/rivr>
// MIT · Mohammad Shehadeh · https://github.com/MohammadShehadeh/hirael

'use client';

import { ChevronRight } from 'lucide-react';

import { PillButton, RivrMark } from './primitives';

const NAV_ITEMS: { label: string; hasDropdown?: boolean }[] = [
  { label: 'Ecosystem' },
  { label: 'Economics', hasDropdown: true },
  { label: 'Developers' },
  { label: 'Governance' },
];

export const Navbar = () => {
  return (
    <nav
      data-slot="rivr-nav"
      className="relative z-20 flex w-full items-center justify-between gap-4 px-5 py-5 md:px-8"
    >
      <a href="#home" className="flex items-center gap-2 text-foreground" aria-label="RIVR home">
        <RivrMark className="size-6" />
        <span className="text-lg font-semibold tracking-tight">RIVR</span>
      </a>

      <ul className="hidden items-center gap-8 text-sm text-foreground/80 lg:flex">
        {NAV_ITEMS.map((item) => (
          <li
            key={item.label}
            className="group flex cursor-pointer items-center gap-1 transition-colors hover:text-foreground"
          >
            {item.label}
            {item.hasDropdown && (
              <ChevronRight className="size-4 transition-transform group-hover:translate-x-0.5 rtl:rotate-180 rtl:group-hover:-translate-x-0.5" />
            )}
          </li>
        ))}
      </ul>

      <PillButton label="Book Demo" />
    </nav>
  );
};
```

### `registry/hirael/bases/radix/templates/rivr/hero.tsx`

```tsx
// Rivr from Hirael <https://hirael.com/templates/rivr>
// MIT · Mohammad Shehadeh · https://github.com/MohammadShehadeh/hirael

'use client';

import type * as React from 'react';
import { ArrowUpRight, ChevronRight, Sparkles } from 'lucide-react';

import { cn } from '@/lib/utils';

import { Navbar } from './navbar';

const HERO_VIDEO = 'https://hirael.com/media/templates/rivr/hero.mp4';

const EASE = 'ease-out fill-mode-both motion-reduce:animate-none';
const RISE = `animate-in fade-in slide-in-from-bottom-5 ${EASE}`;

const delay = (ms: number): React.CSSProperties => ({ animationDelay: `${ms}ms` });

const HeroBadge = () => {
  return (
    <div
      data-slot="hero-badge"
      className={cn(
        RISE,
        'mx-auto mb-5 flex w-fit items-center gap-2 rounded-full border border-white/20 bg-white/60 px-4 py-2 backdrop-blur-md duration-600',
      )}
    >
      <Sparkles className="size-4 text-foreground/80" />
      <span className="text-sm font-medium text-foreground">Fluid Staking</span>
    </div>
  );
};

const BottomLeftCard = () => {
  return (
    <div
      data-slot="hero-stat"
      style={delay(200)}
      className={cn(
        RISE,
        'duration-800',
        'absolute start-auto end-4 bottom-28 flex w-fit min-w-[150px] flex-col gap-2 rounded-[1.5rem] border border-white/30 bg-white/30 p-4 backdrop-blur-xl md:start-6 md:end-auto md:bottom-6 lg:start-10 lg:bottom-10 lg:min-w-[180px] lg:gap-3 lg:rounded-[2rem] lg:p-5',
      )}
    >
      <div className="flex flex-col">
        <span className="text-2xl font-semibold tracking-tight text-foreground md:text-3xl">5.2K</span>
        <span className="text-[10px] font-medium tracking-wider text-muted-foreground uppercase md:text-xs">
          Active Yielders
        </span>
      </div>

      <a
        href="#"
        className="flex w-fit items-center gap-2 self-start rounded-full bg-white py-1.5 ps-1.5 pe-5 transition-colors hover:bg-white/90"
      >
        <span className="flex items-center justify-center rounded-full bg-foreground/10 p-1">
          <ArrowUpRight className="size-4 text-foreground rtl:-scale-x-100" />
        </span>
        <span className="text-sm font-medium text-foreground">Join Discord</span>
      </a>
    </div>
  );
};

const BottomRightCorner = () => {
  return (
    <div
      data-slot="hero-docs"
      style={delay(400)}
      className={cn(
        RISE,
        'duration-800',
        'absolute end-0 bottom-0 flex items-center gap-3 rounded-ss-[1.5rem] bg-background p-3 ps-8 pt-5 sm:gap-4 sm:rounded-ss-[2rem] sm:p-4 sm:ps-10 sm:pt-6 md:gap-6 md:rounded-ss-[3.5rem] md:p-6 md:ps-14 md:pt-8',
      )}
    >
      <div className="pointer-events-none absolute end-0 -top-[1.5rem] size-[1.5rem] text-background sm:-top-[2rem] sm:size-[2rem] md:-top-[3.5rem] md:size-[3.5rem]">
        <svg
          width="100%"
          height="100%"
          viewBox="0 0 56 56"
          fill="none"
          xmlns="http://www.w3.org/2000/svg"
          className="rtl:-scale-x-100"
        >
          <path d="M56 56V0C56 30.9279 30.9279 56 0 56H56Z" fill="currentColor" />
        </svg>
      </div>

      <div className="pointer-events-none absolute -start-[1.5rem] bottom-0 size-[1.5rem] text-background sm:-start-[2rem] sm:size-[2rem] md:-start-[3.5rem] md:size-[3.5rem]">
        <svg
          width="100%"
          height="100%"
          viewBox="0 0 56 56"
          fill="none"
          xmlns="http://www.w3.org/2000/svg"
          className="rtl:-scale-x-100"
        >
          <path d="M56 56H0C30.9279 56 56 30.9279 56 0V56Z" fill="currentColor" />
        </svg>
      </div>

      <div className="flex size-10 items-center justify-center rounded-full border border-border bg-foreground/5 md:size-14">
        <ArrowUpRight className="size-5 text-foreground/80 md:size-6 rtl:-scale-x-100" />
      </div>

      <div className="flex flex-col">
        <span className="text-base font-medium text-foreground md:text-xl">Documentation</span>
        <a href="#" className="flex items-center gap-1 text-muted-foreground transition-colors hover:text-foreground">
          <span className="text-xs font-normal md:text-[15px]">Library</span>
          <ChevronRight className="size-3 md:size-4 rtl:rotate-180" />
        </a>
      </div>
    </div>
  );
};

export const Hero = () => {
  return (
    <section
      id="home"
      data-slot="hero"
      className="flex min-h-dvh w-full items-stretch justify-center bg-background p-3 md:p-5"
    >
      <div className="group relative flex min-h-[640px] w-full max-w-[1536px] flex-col items-center overflow-hidden rounded-[1.5rem] md:rounded-[3rem]">
        <video
          className="absolute inset-0 z-0 h-full w-full object-cover"
          src={HERO_VIDEO}
          autoPlay
          loop
          muted
          playsInline
          aria-hidden
        />
        <div
          aria-hidden
          className="absolute inset-0 z-[1] bg-gradient-to-b from-background/70 via-background/10 to-background/45"
        />

        <div className="relative z-10 flex size-full flex-col items-center">
          <Navbar />

          <div className="pointer-events-none absolute inset-0 flex flex-col items-center justify-center px-6 text-center">
            <HeroBadge />

            {/* The title and lead animate transform only: text that starts at opacity 0 holds back Largest Contentful Paint. */}
            <h1
              data-slot="hero-title"
              style={{ ...delay(100), color: 'var(--hero-title)' }}
              className={cn(
                'animate-in duration-800 zoom-in-98',
                EASE,
                'font-display mb-4 text-4xl leading-[1.05] font-semibold sm:text-5xl md:text-6xl lg:text-[80px]',
              )}
            >
              Fluid Asset Streams
            </h1>

            <p
              style={delay(300)}
              className={cn(
                'animate-in duration-800 slide-in-from-bottom-3',
                EASE,
                'max-w-xl text-base leading-relaxed text-foreground/80 sm:text-lg',
              )}
            >
              Access Smart Vaults, stake RIVR and NFTs, and turn rigid holdings into liquid cash, instantly.
            </p>
          </div>

          <BottomLeftCard />
          <BottomRightCorner />
        </div>
      </div>
    </section>
  );
};
```

### `registry/hirael/bases/radix/templates/rivr/metrics.tsx`

```tsx
// Rivr from Hirael <https://hirael.com/templates/rivr>
// MIT · Mohammad Shehadeh · https://github.com/MohammadShehadeh/hirael

'use client';

import { motion } from 'motion/react';

import { cn } from '@/lib/utils';

import { fadeUp } from './primitives';

const METRICS = [
  { value: '$2.4B', label: 'Total Value Locked' },
  { value: '8.5%', label: 'Average Realized Yield' },
  { value: '140K+', label: 'Active Participants' },
  { value: '< 2s', label: 'Finality Engine' },
];

const CELL_BORDERS = [
  '',
  'border-s border-foreground/10',
  'border-t border-foreground/10 md:border-s md:border-t-0',
  'border-s border-t border-foreground/10 md:border-t-0',
];

export const Metrics = () => {
  return (
    <section data-slot="metrics" className="mx-auto w-full max-w-[1536px] px-3 py-6 md:px-5 md:py-12">
      <div className="rounded-[1.5rem] border border-foreground/[0.05] bg-foreground/[0.02] p-8 md:rounded-[3rem] md:p-16">
        <dl className="grid grid-cols-2 md:grid-cols-4">
          {METRICS.map((metric, i) => (
            <motion.div
              key={metric.label}
              {...fadeUp(i * 0.08)}
              className={cn('flex flex-col gap-2 p-6', CELL_BORDERS[i])}
            >
              <dt className="font-display text-4xl font-semibold tracking-tight text-foreground tabular-nums md:text-5xl">
                {metric.value}
              </dt>
              <dd className="text-sm text-muted-foreground">{metric.label}</dd>
            </motion.div>
          ))}
        </dl>
      </div>
    </section>
  );
};
```

### `registry/hirael/bases/radix/templates/rivr/features.tsx`

```tsx
// Rivr from Hirael <https://hirael.com/templates/rivr>
// MIT · Mohammad Shehadeh · https://github.com/MohammadShehadeh/hirael

'use client';

import { motion } from 'motion/react';
import { Activity, ArrowUpRight, Layers, ShieldCheck } from 'lucide-react';

import { fadeUp, PillButton } from './primitives';

const CARD_BASE =
  'group relative overflow-hidden rounded-[1.5rem] bg-card p-7 transition-shadow hover:shadow-[0_8px_30px_rgb(0,0,0,0.04)] md:rounded-[2rem]';

const ICON_CHIP = 'flex size-12 items-center justify-center rounded-2xl bg-secondary text-foreground';

export const Features = () => {
  return (
    <section data-slot="features" className="mx-auto w-full max-w-[1536px] px-3 py-6 md:px-5 md:py-12">
      <motion.div
        {...fadeUp()}
        className="mb-8 flex flex-col gap-6 sm:flex-row sm:items-end sm:justify-between md:mb-12"
      >
        <h2 className="font-display max-w-2xl text-3xl leading-tight font-semibold text-foreground sm:text-4xl md:text-5xl">
          Architected for high-performance DeFi
        </h2>
        <PillButton label="Start Staking" variant="outline" className="shrink-0" />
      </motion.div>

      <div className="grid grid-cols-1 gap-3 md:grid-cols-3 md:grid-rows-2 md:gap-5">
        <motion.div
          {...fadeUp(0.05)}
          className={`${CARD_BASE} flex min-h-[28rem] flex-col justify-between md:row-span-2 md:p-9`}
        >
          <Layers className="pointer-events-none absolute -end-10 -bottom-10 size-72 text-foreground opacity-[0.02] transition-transform duration-500 group-hover:scale-110" />
          <span className={`relative ${ICON_CHIP}`}>
            <Layers className="size-6" />
          </span>
          <div className="relative">
            <h3 className="text-2xl leading-snug font-semibold text-foreground md:text-3xl">
              Unlock the liquidity of your staked assets
            </h3>
            <p className="mt-3 max-w-sm text-sm leading-relaxed text-muted-foreground">
              Borrow against staked positions and NFTs without unwinding them. Your collateral keeps earning while the
              cash is in your hands.
            </p>
          </div>
        </motion.div>

        <motion.div
          {...fadeUp(0.1)}
          className={`${CARD_BASE} flex min-h-[13rem] flex-col justify-between md:col-span-2 md:p-9`}
        >
          <Activity className="pointer-events-none absolute -end-6 -bottom-8 size-60 text-foreground opacity-[0.02] transition-transform duration-500 group-hover:scale-110" />
          <span className={`relative ${ICON_CHIP}`}>
            <Activity className="size-6" />
          </span>
          <div className="relative">
            <h3 className="text-xl font-semibold text-foreground md:text-2xl">Real-time Yields</h3>
            <p className="mt-3 max-w-md text-sm leading-relaxed text-muted-foreground">
              Rewards accrue every block and stay claimable. Watch positions compound live, with no lockups or waiting
              periods.
            </p>
          </div>
        </motion.div>

        <motion.div {...fadeUp(0.15)} className={`${CARD_BASE} flex flex-col justify-between`}>
          <span className={ICON_CHIP}>
            <ShieldCheck className="size-6" />
          </span>
          <div className="mt-6">
            <h3 className="text-xl font-semibold text-foreground">Bank-grade</h3>
            <p className="mt-2 text-sm leading-relaxed text-muted-foreground">
              Smart contracts audited by leading firms, with on-chain proofs you can verify yourself.
            </p>
            <a
              href="#"
              className="mt-5 inline-flex items-center gap-1.5 rounded-full border border-border px-4 py-2 text-sm font-medium text-foreground transition-colors hover:bg-secondary"
            >
              View Audits
              <ArrowUpRight className="size-4 rtl:-scale-x-100" />
            </a>
          </div>
        </motion.div>

        <motion.a
          href="#"
          {...fadeUp(0.2)}
          className={`${CARD_BASE} flex flex-col items-center justify-center gap-5 text-center`}
        >
          <span className="flex size-16 items-center justify-center rounded-full bg-secondary text-foreground transition-transform duration-300 group-hover:scale-110">
            <ArrowUpRight className="size-7 rtl:-scale-x-100" />
          </span>
          <div>
            <h3 className="text-xl font-semibold text-foreground">Cross-Chain</h3>
            <p className="mt-1 text-sm text-muted-foreground">Move liquidity across networks.</p>
          </div>
        </motion.a>
      </div>
    </section>
  );
};
```

### `registry/hirael/bases/radix/templates/rivr/cta.tsx`

```tsx
// Rivr from Hirael <https://hirael.com/templates/rivr>
// MIT · Mohammad Shehadeh · https://github.com/MohammadShehadeh/hirael

'use client';

import { motion } from 'motion/react';
import { ArrowUpRight } from 'lucide-react';

import { fadeUp } from './primitives';

const CTA_VIDEO = 'https://hirael.com/media/templates/rivr/cta.mp4';

export const Cta = () => {
  return (
    <section data-slot="cta" className="flex w-full items-center justify-center bg-background p-3 md:p-5">
      <div className="relative flex min-h-[600px] w-full max-w-[1536px] items-center justify-center overflow-hidden rounded-[1.5rem] p-8 md:min-h-[720px] md:rounded-[3rem]">
        <video
          className="absolute inset-0 z-0 h-full w-full object-cover"
          src={CTA_VIDEO}
          autoPlay
          loop
          muted
          playsInline
          aria-hidden
        />
        <div
          aria-hidden
          className="absolute inset-0 z-[1] bg-gradient-to-t from-foreground/70 via-foreground/45 to-foreground/55"
        />

        <motion.div {...fadeUp()} className="relative z-10 flex max-w-2xl flex-col items-center gap-8 text-center">
          <h2 className="font-display text-4xl leading-[1.05] font-semibold text-white sm:text-5xl md:text-6xl">
            Melt rigid assets into fluid yield.
          </h2>

          <div className="flex flex-wrap items-center justify-center gap-3">
            <a
              href="#"
              className="group inline-flex items-center gap-2.5 rounded-full bg-white py-1.5 ps-5 pe-1.5 text-sm font-medium text-foreground transition-colors hover:bg-white/90"
            >
              <span>Launch App</span>
              <span className="flex size-7 items-center justify-center rounded-full bg-foreground/10">
                <ArrowUpRight className="size-4 rtl:-scale-x-100" />
              </span>
            </a>
            <a
              href="#"
              className="inline-flex items-center rounded-full border border-white/20 bg-white/10 px-5 py-2.5 text-sm font-medium text-white backdrop-blur-md transition-colors hover:bg-white/20"
            >
              Read Docs
            </a>
          </div>
        </motion.div>
      </div>
    </section>
  );
};
```

### `registry/hirael/bases/radix/templates/rivr/footer.tsx`

```tsx
// Rivr from Hirael <https://hirael.com/templates/rivr>
// MIT · Mohammad Shehadeh · https://github.com/MohammadShehadeh/hirael

import { RivrMark } from './primitives';

const COLUMNS = [
  {
    heading: 'Protocol',
    links: ['Vaults', 'Staking', 'Lending', 'NFT collateral'],
  },
  { heading: 'Developers', links: ['Docs', 'SDK', 'API', 'Status'] },
  { heading: 'Community', links: ['Discord', 'Forum', 'Governance', 'Blog'] },
];

export const Footer = () => {
  return (
    <footer data-slot="footer" className="border-t border-border bg-background text-foreground">
      <div className="mx-auto w-full max-w-[1536px] px-6 py-16 md:px-10 md:py-20">
        <div className="flex flex-col gap-12 md:flex-row md:justify-between">
          <div className="max-w-xs">
            <a href="#home" className="flex w-fit items-center gap-2 text-foreground" aria-label="RIVR home">
              <RivrMark className="size-6" />
              <span className="text-lg font-semibold">RIVR</span>
            </a>
            <p className="mt-4 text-sm text-muted-foreground">
              Fluid staking and streaming yield for assets that never sit still.
            </p>
          </div>

          <nav aria-label="Footer" className="grid grid-cols-2 gap-8 sm:grid-cols-3 md:gap-16">
            {COLUMNS.map((column) => (
              <div key={column.heading}>
                <h3 className="text-sm font-semibold text-foreground">{column.heading}</h3>
                <ul className="mt-4 flex flex-col gap-3">
                  {column.links.map((link) => (
                    <li key={link}>
                      <a href="#" className="text-sm text-muted-foreground transition-colors hover:text-foreground">
                        {link}
                      </a>
                    </li>
                  ))}
                </ul>
              </div>
            ))}
          </nav>
        </div>

        <div className="mt-12 border-t border-border pt-8">
          <p className="text-sm text-muted-foreground">© 2026 RIVR. Fluid asset streams.</p>
        </div>
      </div>
    </footer>
  );
};
```

### `registry/hirael/bases/radix/templates/rivr/primitives.tsx`

```tsx
// Rivr from Hirael <https://hirael.com/templates/rivr>
// MIT · Mohammad Shehadeh · https://github.com/MohammadShehadeh/hirael

'use client';

import { ArrowUpRight } from 'lucide-react';
import type { MotionProps } from 'motion/react';

import { cn } from '@/lib/utils';
import { Button } from '@/registry/hirael/bases/radix/ui/button';

export const fadeUp = (delay = 0): MotionProps => {
  return {
    initial: { opacity: 0, y: 24 },
    whileInView: { opacity: 1, y: 0 },
    viewport: { once: true, margin: '-80px' },
    transition: { duration: 0.6, delay, ease: 'easeOut' },
  };
};

interface RivrMarkProps {
  className?: string;
}

export const RivrMark = ({ className }: RivrMarkProps) => {
  return (
    <svg viewBox="0 0 24 24" fill="none" aria-hidden className={className}>
      <circle cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="1.4" opacity="0.3" />
      <circle cx="12" cy="12" r="5.6" stroke="currentColor" strokeWidth="1.6" />
      <circle cx="12" cy="12" r="1.6" fill="currentColor" />
    </svg>
  );
};

type PillButtonVariant = 'solid' | 'outline';

interface PillButtonProps {
  label: string;
  href?: string;
  variant?: PillButtonVariant;
  className?: string;
}

export const PillButton = ({ label, href = '#', variant = 'solid', className }: PillButtonProps) => {
  return (
    <Button asChild variant={variant === 'solid' ? 'default' : 'outline'} className={cn('group h-auto', className)}>
      <a href={href}>
        <span>{label}</span>
        <span
          className={cn(
            'flex size-7 items-center justify-center rounded-full',
            variant === 'solid' ? 'bg-white/20' : 'bg-foreground/10',
          )}
        >
          <ArrowUpRight className="size-4 rtl:-scale-x-100" />
        </span>
      </a>
    </Button>
  );
};
```

### `registry/hirael/bases/radix/templates/rivr/styles.tsx`

```tsx
// Rivr from Hirael <https://hirael.com/templates/rivr>
// MIT · Mohammad Shehadeh · https://github.com/MohammadShehadeh/hirael

const RIVR_CSS = `
.rivr {
  --background: hsl(0 0% 94%);
  --foreground: hsl(218 48% 24%);
  --card: hsl(0 0% 100%);
  --card-foreground: hsl(218 48% 24%);
  --popover: hsl(0 0% 100%);
  --popover-foreground: hsl(218 48% 24%);
  --primary: hsl(218 48% 24%);
  --primary-foreground: hsl(0 0% 100%);
  --secondary: hsl(212 26% 93%);
  --secondary-foreground: hsl(218 48% 24%);
  --muted: hsl(212 26% 93%);
  --muted-foreground: hsl(215 16% 42%);
  --accent: hsl(212 32% 91%);
  --accent-foreground: hsl(218 48% 24%);
  --border: hsl(214 24% 88%);
  --input: hsl(214 24% 88%);
  --ring: hsl(218 48% 40%);
  --hero-title: hsl(220 9% 40%);
  font-family: "Helvetica Neue", Helvetica, Arial, ui-sans-serif, system-ui, sans-serif;
}
.rivr .font-display {
  font-family: "Helvetica Neue", Helvetica, Arial, ui-sans-serif, system-ui, sans-serif;
  letter-spacing: -0.02em;
}
`;

export const RivrStyles = () => {
  return <style dangerouslySetInnerHTML={{ __html: RIVR_CSS }} />;
};
```
