Skip to content

Getting started

Install the OTF SDK packages, wire up theming, and ship your first screen.

The OTF SDK is published as scoped packages on npm under @otfdashkit/*. Install the ones you need for your platform.

Bought a kit? Purchased kits are full-stack templates. Read the templates overview to see what you get and how to start from your kit repo.

Web project (Next.js, Vite, Remix, …)

npm install @otfdashkit/ui @otfdashkit/tokens

The web components are styled with Tailwind CSS v3. Install it, then add the OTF preset, the animation plugin and the component sources to your Tailwind config:

npm install -D tailwindcss@3 tailwindcss-animate postcss autoprefixer
tailwind.config.ts
import animate from 'tailwindcss-animate'
import { otfPreset } from '@otfdashkit/tokens/tailwind-preset'

export default {
  presets: [otfPreset],
  plugins: [animate],
  content: ['./app/**/*.{ts,tsx}', './node_modules/@otfdashkit/ui/src/**/*.{ts,tsx}'],
}

Tailwind v3 runs as a PostCSS plugin, so the app also needs a PostCSS config:

postcss.config.mjs
export default {
  plugins: { tailwindcss: {}, autoprefixer: {} },
}

If your project was scaffolded with Tailwind v4 (for example a current create-next-app --tailwind), replace its @tailwindcss/postcss config and its @import "tailwindcss" line with the v3 setup on this page.

Import the preset from @otfdashkit/tokens/tailwind-preset, not from @otfdashkit/tokens: the package root also loads the native config, which a web-only install can't resolve.

Add the token CSS import before the component CSS in your global stylesheet:

app/globals.css
@import '@otfdashkit/tokens/web.css';
@import '@otfdashkit/ui/styles';

@tailwind base;
@tailwind components;
@tailwind utilities;

/* your own styles below */

Set the default theme on the document before the first paint so users don't see a flash of unstyled colors:

app/layout.tsx
<script
  dangerouslySetInnerHTML={{
    __html: `
      const t = localStorage.getItem('otf-theme') || 'theme-minimal'
      const s = localStorage.getItem('otf-color-scheme') || 'dark'
      document.documentElement.className = \`\${t} \${s}\`
    `,
  }}
/>

You're done. Import a component:

app/page.tsx
import { Persona, Stat, EmptyState } from '@otfdashkit/ui'

export default function Page() {
  return (
    <div className="p-6 grid gap-4">
      <Stat label="Active users" value="12,406" delta="+12%" />
      <EmptyState title="No projects yet" description="Create your first project to get started." />
    </div>
  )
}

React Native project (Expo)

npm install @otfdashkit/ui-native @otfdashkit/tokens

@otfdashkit/ui-native is built on Tamagui. Wire the provider once in your root layout:

app/_layout.tsx
import { Slot } from 'expo-router'
import { OTFProvider } from '@otfdashkit/ui-native'

export default function RootLayout() {
  return (
    <OTFProvider>
      <Slot />
    </OTFProvider>
  )
}

Then import primitives the same way you would on web:

import { YStack, Text, Card } from '@otfdashkit/ui-native'

export default function Screen() {
  return (
    <YStack padding="$4" gap="$3">
      <Text fontSize="$8" fontWeight="700">Welcome</Text>
      <Card padding="$4">Hello from OTF.</Card>
    </YStack>
  )
}

Both platforms in one repo

If you're building one product across web + native (which is what the OTF kits do), use a monorepo and consume both packages from the same workspace. Share business logic, screens, and theme tokens — keep platform-specific glue thin. See the Templates page for the canonical layout the kits use.

Learn more

FAQ

Free with your email

Get the free AI configs pack

The AI files every kit ships with. Drop them in and your AI tool knows your project.

  • CLAUDE.mdProject context
  • .cursorrulesRules for Cursor
  • prompts/Task prompts

No spam. Unsubscribe any time.