Kewti

Docs

Contributing Guide

Guidelines for contributing components, CLI tools, fonts, and documentation to Kewti.

Monorepo Architecture

Kewti is structured as a pnpm workspace powered by Turborepo:

PathDescription
packages/uiCore component library source (packages/ui/src/components/).
packages/cliKewti CLI package (npx kewti-cli add ...).
packages/fontsOptimized Ge'ez and Amharic web font assets.
apps/registryRegistry generator and JSON bundle builder for CLI distribution.
apps/kewti-docsDocumentation site built with Next.js and Fumadocs.
apps/webWeb app and visual showcase, including hosted API endpoints.

Setup & Development

1. Clone & Install

git clone https://github.com/coderade1905/kewti.git
cd kewti
pnpm install

2. Start Dev Servers

pnpm dev

3. Verification Commands

  • pnpm build: Build all workspace packages and applications.
  • pnpm typecheck: Run TypeScript type checking.
  • pnpm lint: Run ESLint across packages.

Adding New Components

Follow this step-by-step workflow to contribute a new component:

Step 1: Create Component Source

Create your component in packages/ui/src/components/kewti-<name>/component.tsx:

import * as React from "react"
import { cn } from "@/lib/utils"

export interface KewtiExampleProps extends React.HTMLAttributes<HTMLDivElement> {
  // Add component props
}

export function KewtiExample({ className, ...props }: KewtiExampleProps) {
  return (
    <div className={cn("p-4 rounded-lg border", className)} {...props} />
  )
}

Design & Code Standards:

  • Tailwind CSS: Use Tailwind classes with full dark: mode variant support.
  • Self-Contained: Ensure component files do not rely on implicit external imports so CLI copy-pasting works cleanly.

Step 2: Register in Registry

Every UI component must be registered in apps/registry/registry-ui.ts so that the registry build script (pnpm --filter registry build) can process it into distribution JSON files (registry.json and registry-combined.json) used by the CLI.

Registry File Location

  • File: apps/registry/registry-ui.ts

Registry Item Schema (RegistryItem)

Each item in the uiRegistry array must adhere to the RegistryItem type:

export type RegistryItem = {
  name: string;                   // Component name (e.g., "kewti-example")
  type: "components:ui";          // Registry item type
  dependencies?: string[];        // Third-party npm dependencies
  registryDependencies?: string[];// Internal registry dependencies
  files: string[];                // Relative paths to component source files
};

Step-by-Step Registration Guide

  1. Add Entry to uiRegistry: Open apps/registry/registry-ui.ts and add your component configuration to uiRegistry:

    {
      name: "kewti-example",
      type: "components:ui",
      dependencies: ["lucide-react"],
      registryDependencies: ["fonts"],
      files: ["kewti-example/component.tsx"],
    }
  2. Configure Property Fields:

    • name (required): The unique component identifier (e.g., "kewti-time", "kewti-calender"). Must match the component directory name in packages/ui/src/components/.
    • type (required): Must be set to "components:ui".
    • dependencies (optional): Array of external npm packages required by this component (e.g., ["lucide-react", "kenat"]). When installed via CLI, these are automatically installed in the user's project.
    • registryDependencies (optional): Array of internal Kewti registry items required by this component (e.g., ["fonts"]). The CLI recursively fetches and installs these items prior to installing the component.
    • files (required): Array of relative paths from packages/ui/src/components/ for all source files comprising the component.

    Note: The primary entry file for the component should be named component.tsx in the component root directory. This enables the CLI to automatically generate the barrel export in src/kewti/ui/index.ts.

  3. Build Registry Output: Run the registry build script to ensure JSON bundles build without errors:

    pnpm --filter registry build

Step 3: Test CLI Fetching

Build the CLI to test component installation:

pnpm --filter cli build

Step 4: Write Documentation

Add an MDX document under apps/kewti-docs/content/docs/components/kewti-<name>.mdx detailing:

  • Live <CodePlayground /> preview.
  • Installation command (npx kewti-cli add <name>).
  • Usage examples and props table.

Adding API Data Endpoints

Certain components (like KewtiSelect or KewtiLocationSelector) rely on fetching structured reference data (e.g., Ethiopian banks, universities, or locations). We host these data APIs directly within our Next.js web app under apps/web/app/api/.

To contribute a new data API endpoint:

Step 1: Create the Data Source

Create a structured JSON file (e.g., universities.json) inside the new API route directory apps/web/app/api/<endpoint-name>/.

Step 2: Create the Route Handler

Create a route.ts file in the same directory. It must include CORS headers so that the kewti-docs site, code playgrounds, and external users can fetch the data safely.

Here is a standard example for an API route (apps/web/app/api/universities/route.ts):

import { NextResponse } from "next/server"
import universityData from "./universities.json"

// Helper function to set CORS headers on any response
function setCorsHeaders(response: NextResponse) {
  response.headers.set("Access-Control-Allow-Origin", "*")
  response.headers.set("Access-Control-Allow-Methods", "GET, OPTIONS")
  response.headers.set("Access-Control-Allow-Headers", "Content-Type")
  return response
}

export async function GET() {
  try {
    // Create the response with your JSON data
    const response = NextResponse.json(universityData)

    // Append CORS headers for cross-origin / cross-port requests
    return setCorsHeaders(response)
  } catch (error) {
    const errorResponse = NextResponse.json(
      { error: "Failed to load data" },
      { status: 500 }
    )
    return setCorsHeaders(errorResponse)
  }
}

// Handle the preflight browser check request
export async function OPTIONS() {
  const response = new NextResponse(null, { status: 204 })
  return setCorsHeaders(response)
}

Adding New Fonts

To contribute an Amharic or Ge'ez web font to Kewti:

Step 1: Add Font Files

Create a directory inside packages/fonts/<Font_Name>/ containing font files (.ttf, .otf, .woff2) and the license:

packages/fonts/Balderasu/
├── Balderasu_Regular.ttf
└── license.txt

Step 2: Register Font in Registry

Add an entry to fontsRegistry inside apps/registry/registry-fonts.ts:

{
  name: "Balderasu",
  title: "Balderasu",
  folder: "Balderasu",
  license: "SIL Open Font License",
  licenseFile: "license.txt",
  fontType: "truetype", // "truetype" | "opentype" | "woff2"
  files: [
    {
      file: "Balderasu_Regular.ttf",
      variant: "regular",
    },
  ],
}

Step 3: Build & Test

  1. Build registry files:
    pnpm --filter registry build
  2. Test CLI font installation:
    npx kewti-cli font Balderasu

Submitting Pull Requests

  • Keep pull requests scoped to a single feature, component, font, API data endpoint, or fix.
  • Always run pnpm typecheck and pnpm build before opening a pull request.
  • Follow existing codebase patterns and formatting standards.

On this page