Installation

How to install and set up Fasla in your project.

Requirements

  • React 18 or later
  • Tailwind CSS 3.4 or later
  • TypeScript (recommended)

Using the CLI

The easiest way to add components is the CLI in the @smicolon/fasla-ui package. It takes two steps.

1. Initialize Fasla, once per project. This writes components.json, which every add reads:

npx @smicolon/fasla-ui@latest init

Set up with @smicolon/cli? If it was 0.4 or later, keep going with this command in the same project. Nothing needs re-running. If it was 0.3 or earlier, run npx @smicolon/fasla-ui@latest init once first. It repairs the project’s components.json, which the shadcn CLI can’t read until then, and moves the files those versions put in the wrong folder.

init also writes the cn helper and installs the two packages it imports with your project’s package manager. If that install fails, init prints the command to run, which is one of these:

npm install clsx tailwind-merge

On Tailwind 3, the command installs tailwind-merge@^2, as tailwind-merge 3 supports only Tailwind 4. init also replaces a tailwind-merge that is, or could become, 3:

npm install clsx tailwind-merge@^2

2. Add a component:

npx @smicolon/fasla-ui@latest add button

Or add several at once:

npx @smicolon/fasla-ui@latest add card input badge

List everything the registry offers:

npx @smicolon/fasla-ui@latest list

Theme

Components take every colour from your theme. init asks which of two layers you want and installs it. The shadcn CLI commands below install a layer too, or switch a project to the other one later. Both give you the base layer.

The shadcn commands need a project that is already set up, with a components.json. In a new project, run npx @smicolon/fasla-ui@latest init first, or npx shadcn@latest init. Run in a project without one, the shadcn CLI sets the project up itself, and the colours of the preset it picks replace Fasla’s.

Starting from scratch: use Fasla’s colours. Fasla’s light and dark palette, its radius and the Geist font, on top of the base layer:

npx shadcn@latest add https://fasla.smicolon.com/r/theme.json https://fasla.smicolon.com/r/font-geist.json

On Next.js 14, set the project up with npx @smicolon/fasla-ui@latest init, not shadcn init: shadcn’s setup writes Tailwind 4 styles and loads Geist from next/font, and Next.js 14 has neither, so the build fails. Then leave out font-geist.json, as the Next.js 14 template already loads Geist:

npx shadcn@latest add https://fasla.smicolon.com/r/theme.json

I have a brand: keep my colours. The base layer only: the tokens shadcn doesn’t have (success, warning, info and the soft tints), the type scale with Arabic line heights, the Arabic setting and the Cairo font. It changes no colour you already have:

npx shadcn@latest add https://fasla.smicolon.com/r/theme-base.json

The shadcn CLI asks Existing CSS variables and components will be overwritten. Continue? with No as the default, so type y. The base layer, theme-base, doesn’t change any colour your project already has.

Arabic text is set in Cairo through the --font-arabic variable. To use another Arabic font, point --font-arabic at it.

Fasla’s base components replace shadcn’s components of the same name, such as button and badge, in components/ui. add asks before it replaces a file that isn’t Fasla’s. Blocks install to their own folder, components/blocks.

Manual Installation

You can also copy components directly from the source code.

1. Install dependencies:

npm install class-variance-authority clsx tailwind-merge framer-motion

On Tailwind 3, install tailwind-merge@^2 instead. tailwind-merge 3 supports only Tailwind 4, and on Tailwind 3 it drops classes it doesn’t know, such as outline:

npm install class-variance-authority clsx tailwind-merge@^2 framer-motion

2. Add the cn utility to your project:

// lib/utils.ts
import { type ClassValue, clsx } from "clsx"
import { extendTailwindMerge } from "tailwind-merge"

const twMerge = extendTailwindMerge({
  extend: { classGroups: { "font-size": [{ text: ["xxs", "link", "list-header"] }] } },
})

export function cn(...inputs: ClassValue[]) {
  return twMerge(clsx(inputs))
}

3. Copy each component from its file in the registry, such as https://fasla.smicolon.com/r/button.json for Button. https://fasla.smicolon.com/r/registry.json lists them all.

In each file, files holds the source in content and the path to save it at in target. dependencies lists the packages to install, and registryDependencies the other Fasla components it needs, which you copy the same way.