Skip to content

Installation

Terminal window
npx @spaceinvoices/react-ui@latest init
npx @spaceinvoices/react-ui@latest add customers/create-customer-form
npx @spaceinvoices/react-ui@latest add invoices/create-invoice-screen

The published @spaceinvoices/react-ui package provides a shadcn-style installer that copies files into your project. It resolves the complete local import graph, copies the UI primitives used by the selected feature, and installs missing npm dependencies. The generated result lives in your app, not behind a runtime abstraction.

Use the installer when you want a faster start. Use the manual path when you want maximum control over exactly what gets copied.

Manual Fallback

The React UI kit is designed for ownership, not package-style runtime installation. The manual workflow is still fully supported:

  1. install the minimum dependencies
  2. copy the files you need into your app
  3. adjust imports to your aliases and UI primitives

Setup

1. Install Dependencies

Install Dependenciesbash
# Runtime closure for the full copy-paste tree. Versions mirror the canonical
# production dependencies in packages/ui/package.json.
npm install \
  @base-ui/react@^1.7.0 \
  @hookform/resolvers@^5.7.1 \
  @radix-ui/react-label@^2.1.15 \
  @radix-ui/react-slot@^1.3.3 \
  @spaceinvoices/js-sdk@14.26.0 \
  @tanstack/react-query@^5.101.4 \
  class-variance-authority@^0.7.1 \
  clsx@^2.1.1 \
  cmdk@^1.1.1 \
  date-fns@^4.4.0 \
  lucide-react@^1.28.0 \
  markdown-it@^14.1.1 \
  next-themes@^0.4.6 \
  react@^19.2.8 \
  react-cookie@^8.1.2 \
  react-day-picker@^10.0.1 \
  react-hook-form@^7.84.0 \
  react-image-crop@^11.1.2 \
  react-dom@^19.2.8 \
  recharts@3.10.1 \
  sonner@^2.0.7 \
  tailwind-merge@^3.6.0 \
  vaul@^1.1.2 \
  zod@4.3.6

# TypeScript consumers need these declarations if they are not already in the
# host app (they are the focused type closure, not the UI package's full dev set).
npm install --save-dev \
  @types/markdown-it@^14.1.2 \
  @types/react@^19.2.18 \
  @types/react-dom@^19.2.4

# The copy recipe includes the exact UI primitives imported by the source tree.
# Do not run shadcn init/add over those copied files; keep them or replace them
# deliberately with equivalent components from your own design system.

2. UI Components (manual installs only)

The manual recipe copies the exact Base UI base-vega-style primitives used by the source tree. It also copies the kit-owned components/form, components/overlays, and components/action-menu helpers. Keep these files, or replace them deliberately with equivalent components from your own design system and update the copied imports. Do not run a generator over the copied files unless you intend to replace and re-validate the complete closure.

3. Clone the Repository

Terminal window
git clone https://github.com/space-invoices/react-ui.git

4. Copy What You Need

Copy componentsbash
#!/usr/bin/env bash
# @title Copy Components
# @language bash

set -eu

# Run from the directory containing the cloned react-ui repository, or pass
# source and destination roots explicitly:
#   ./copy-components.sh react-ui your-project
SOURCE_ROOT="${1:-react-ui}"
DEST_ROOT="${2:-your-project}"

mkdir -p \
  "$DEST_ROOT/src/components" \
  "$DEST_ROOT/src/lib" \
  "$DEST_ROOT/src/providers" \
  "$DEST_ROOT/src/hooks" \
  "$DEST_ROOT/src/utils"

# Shared runtime and generated files are part of the manual consumer closure.
cp -R "$SOURCE_ROOT/src/lib/." "$DEST_ROOT/src/lib/"
cp -R "$SOURCE_ROOT/src/providers/." "$DEST_ROOT/src/providers/"
cp -R "$SOURCE_ROOT/src/hooks/." "$DEST_ROOT/src/hooks/"
cp -R "$SOURCE_ROOT/src/generated/." "$DEST_ROOT/src/generated/"
cp -R "$SOURCE_ROOT/src/common/." "$DEST_ROOT/src/common/"
cp -R "$SOURCE_ROOT/src/utils/." "$DEST_ROOT/src/utils/"

# Keep feature code under the documented consumer-owned namespace. The full
# components tree is intentional: shared providers/hooks have relative imports
# into sibling feature folders, so copying only the visible invoice folder is
# not a type-checkable consumer closure. It includes the owned form, overlay,
# action-menu, document, and feature-component directories.
mkdir -p "$DEST_ROOT/src/components/space-invoices" "$DEST_ROOT/src/components/ui"
cp -R "$SOURCE_ROOT/src/components/." "$DEST_ROOT/src/components/space-invoices/"

# The feature imports shadcn-style primitives from the app's normal
# components/ui path; copy the complete primitive folder for a working recipe.
cp -R "$SOURCE_ROOT/src/components/ui/." "$DEST_ROOT/src/components/ui/"

The example copies the runtime closure (lib/, providers/, hooks/, generated/, common/, and utils/), the full components/ tree (including the form, overlays, action-menu, documents, and feature helpers), and the components/ui/ primitives into src/components/space-invoices and src/components/ui. Copying the full feature tree keeps provider and hook sibling imports type-checkable. It accepts the cloned repository and app roots as optional arguments.

5. Update Import Paths

Update importsbash
#!/usr/bin/env bash
# @title Update Import Paths
# @language bash

set -eu

DEST_ROOT="${1:-your-project}"
SOURCE_DIR="$DEST_ROOT/src"

rewrite_aliases() {
  find "$@" -type f \( -name "*.ts" -o -name "*.tsx" \) -print0 \
    | xargs -0 perl -pi -e 's__PROTECTED_3__
}

__PROTECTED_4__
__PROTECTED_5__
__PROTECTED_6__
__PROTECTED_7__
__PROTECTED_8__
rewrite_aliases \
  "$SOURCE_DIR/lib" "$SOURCE_DIR/providers" "$SOURCE_DIR/hooks" \
  "$SOURCE_DIR/generated" "$SOURCE_DIR/common" "$SOURCE_DIR/utils" \
  "$SOURCE_DIR/components/space-invoices" "$SOURCE_DIR/components/ui"

find "$SOURCE_DIR/components/space-invoices" -type f \( -name "*.ts" -o -name "*.tsx" \) -print0 \
  | xargs -0 perl -pi -e 's#from "\.\./lib/#from "@/lib/#g; s#from "\.\./\.\./lib/#from "@/lib/#g; s#from "\.\./\.\./\.\./lib/#from "@/lib/#g; s#from "\.\./providers/#from "@/providers/#g; s#from "\.\./\.\./providers/#from "@/providers/#g; s#from "\.\./hooks/#from "@/hooks/#g; s#from "\.\./\.\./hooks/#from "@/hooks/#g; s#from "\.\./\.\./\.\./hooks/#from "@/hooks/#g; s#from "\.\./generated/#from "@/generated/#g; s#from "\.\./\.\./generated/#from "@/generated/#g'

# For a different app alias, run this script first and then update the eight
# destination prefixes above in one place.

The import update example processes every copied .ts and .tsx file under the feature, provider, and shared-helper destinations. It maps feature imports to @/components/space-invoices/*, primitives to @/components/ui/*, and runtime files to their @/providers, @/lib, @/hooks, @/generated, @/common, and @/utils destinations.

Minimum Working Install

If you want the smallest setup that still works cleanly, copy:

PathWhy
src/providers/space-invoices-provider.tsxSDK runtime and auth wiring
src/hooks/*.tsshared query/mutation helpers used by copied features
src/lib/utils.tsshared cn() utility (install clsx and tailwind-merge)
src/lib/locale.tslocale normalization used by translations
src/lib/translation.tscomponent-level i18n helper
src/common/ and src/components/documents/shared form/document helpers
src/components/form/sticky-form-footer.tsxstandalone and host-owned save/draft footer actions
src/components/overlays/Base UI-compatible tooltip, popover, and alert-dialog wrappers
src/generated/schemas/*generated Zod schemas used by copied forms

Then add only the feature folders you actually need.

Source of Truth

  • this monorepo contains the canonical component, registry, and installer source
  • the standalone repository is a verified release artifact produced from this source
  • both paths should result in owned application code, not a locked runtime dependency

Required Files

Always copy these core files:

PathPurpose
src/providers/space-invoices-provider.tsxModular SDK runtime setup
src/providers/entities-provider.tsxActive entity context
src/providers/form-footer-context.tsxSave/draft registration for host layouts
src/hooks/*.tsShared hooks
src/lib/utils.tscn() utility (clsx and tailwind-merge)
src/lib/locale.tsLocale normalization
src/lib/translation.tsi18n helper
src/generated/schemas/*Generated Zod schemas used by form components

Translations

The copy-paste components are designed to work without app-level i18n setup:

  • English/default strings should work out of the box
  • built-in locale files are optional overlays
  • your app can pass locale to use bundled translations where available
  • your app can pass t to override component wording with its own translation layer

So for a minimal install, you do not need to copy locale files unless you want built-in non-English copy immediately.

Optional Components

Copy only what you need:

FolderComponents
components/space-invoices/invoices/Invoice forms and lists
components/space-invoices/customers/Customer management
components/space-invoices/items/Product/service catalog
components/space-invoices/payments/Payment recording
components/space-invoices/estimates/Estimates and proforma invoices
components/space-invoices/dashboard/Charts and stats
components/space-invoices/table/Data table infrastructure

Next Steps

Continue to Provider Setup to configure the recommended providers.