Ink Web

Getting Started

How to set up your project to use ink-ui components

Configure the Alias

Before installing components, you need to configure your project to alias ink to ink-web. This allows the components to work both in Node.js (with the real ink package) and in the browser (with ink-web).

Add the alias to your next.config.mjs:

next.config.mjs
/** @type {import('next').NextConfig} */
const config = {
  turbopack: { 
    resolveAlias: { 
      ink: 'ink-web', 
    }, 
  }, 
};

export default config;

Add the alias to your next.config.mjs:

next.config.mjs
/** @type {import('next').NextConfig} */
const config = {
  webpack: (config) => { 
    config.resolve.alias = { 
      ...config.resolve.alias, 
      ink: 'ink-web', 
    }; 
    return config; 
  }, 
};

export default config;

Add the alias to your vite.config.ts:

vite.config.ts
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';

export default defineConfig({
  plugins: [react()],
  resolve: { 
    alias: { 
      ink: 'ink-web', 
    }, 
  }, 
});

Install ink (for types)

Install ink as a dev dependency to get TypeScript types:

npm install -D ink
yarn add -D ink
pnpm add -D ink
bun add -D ink

Initialize shadcn

If you haven't already, initialize shadcn in your project:

npx shadcn@latest init
npx shadcn@latest init
pnpm dlx shadcn@latest init
bunx shadcn@latest init

Add Components

Now you can add components from the ink-ui registry:

npx shadcn@latest add https://raw.githubusercontent.com/cjroth/ink-web/main/packages/ink-ui/registry/spinner.json
npx shadcn@latest add https://raw.githubusercontent.com/cjroth/ink-web/main/packages/ink-ui/registry/spinner.json
pnpm dlx shadcn@latest add https://raw.githubusercontent.com/cjroth/ink-web/main/packages/ink-ui/registry/spinner.json
bunx shadcn@latest add https://raw.githubusercontent.com/cjroth/ink-web/main/packages/ink-ui/registry/spinner.json

This will add the component to your components/ui folder.

Use the Component

app/terminal.tsx
"use client";

import { Box } from "ink"; 
import { InkTerminalBox } from "ink-web";
import { Spinner } from "@/components/ui/spinner"; 
import "ink-web/css";
import "xterm/css/xterm.css";

export default function Terminal() {
  return (
    <InkTerminalBox focus>
      <Box flexDirection="column">
        <Spinner text="Loading..." /> // [!code highlight]
      </Box>
    </InkTerminalBox>
  );
}

How It Works

The components import from ink:

import { Box, Text } from 'ink';

Your bundler alias redirects these imports to ink-web at build time, which includes all the browser-compatible shims and polyfills needed to run Ink in the browser.

This approach means:

  • Components work in both Node.js (real ink) and browser (ink-web)
  • You get full TypeScript support from the ink types
  • No changes needed to component source code