Skip to content

Getting Started with Appkit

Welcome to Appkit! This guide will take you from zero to productive with the Appkit toolkit. Whether you're new to Nuxt or an experienced developer, you'll learn how to leverage Appkit's powerful features to build applications faster and more reliably.

What is Appkit?

Appkit is a comprehensive toolkit for Nuxt applications that provides:

  • 🔥 Firebase Integration - Type-safe Firestore operations with Arkfire
  • 📝 Form System - Advanced form components and validation with Arkform
  • 🛠️ Utility Tools - Common app utilities like caching, messaging, and ID generation
  • 🎨 UI Components - Reusable Vue components for common patterns
  • 📊 TypeScript Utils - Error handling, result patterns, and type utilities

Think of Appkit as your Swiss Army knife for Nuxt development - it gives you battle-tested tools that work together seamlessly.

Architecture Overview

Appkit follows a modular architecture where you selectively enable features based on your needs:

Your Nuxt App
├── app/
│   └── appkit/           # 🎯 Your app-specific configurations
│       ├── appkit.config.ts    # Feature toggles
│       ├── $user.ts           # User system setup
│       ├── $toast.ts          # Toast notifications
│       └── $email.ts          # Email system
├── nuxt.config.ts        # Add appkit module
└── package.json          # Install appkit

Key Concept: The app/appkit/ directory is where your application meets Appkit. Here you configure which features to use and how they should work in your specific app.

Quick Start

Step 1: Installation

bash
npm install @hexlabs/appkit

Step 2: Add to Nuxt Config

ts
// nuxt.config.ts
export default defineNuxtConfig({
  modules: [
    '@hexlabs/appkit'
  ]
})

Step 3: Create Appkit Directory

Create the app/appkit/ directory in your Nuxt project:

bash
mkdir app/appkit

Step 4: Configure Features

Create your configuration file to enable the features you want (all features are disabled by default):

ts
// app/appkit/appkit.config.ts
import { defineAppkitConfig } from '#appkit/config'

export default defineAppkitConfig({
  // Enable Firebase integration
  arkfire: { enabled: true },
  
  // Enable form components  
  arkform: { enabled: true },
  
  // Enable utility tools
  tools: { enabled: true },
  
  // Enable UI components
  components: { enabled: true }
})

🎉 That's it! You now have Appkit installed and ready to use.

Understanding the Appkit Directory

The app/appkit/ directory is special. Everything you export from files in this directory gets auto-imported throughout your entire Nuxt application.

File Naming Convention

Appkit uses a $-prefix naming convention for its main objects:

  • $user.ts - User authentication and permissions
  • $toast.ts - Toast notification system
  • $email.ts - Email sending system
  • $modal.ts - Modal dialogs
  • $cache.ts - Caching utilities

This convention makes it easy to identify Appkit objects and avoids naming conflicts.

Your First Appkit Setup

Let's build a simple toast notification system to see how Appkit works:

1. Create a Toast Component

First, create a Vue component for your toast:

vue
<!-- components/toasts/SuccessToast.vue -->
<template>
  <div class="toast toast-success">
    <div class="toast-icon">✅</div>
    <div class="toast-content">
      <h4>{{ title }}</h4>
      <p>{{ message }}</p>
    </div>
  </div>
</template>

<script setup lang="ts">
interface Props {
  title: string
  message: string
}

defineProps<Props>()
</script>

<style scoped>
.toast {
  display: flex;
  align-items: center;
  padding: 1rem;
  margin: 0.5rem;
  border-radius: 0.5rem;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
  max-width: 400px;
}

.toast-success {
  background: #f0f9ff;
  border: 1px solid #0ea5e9;
}

.toast-icon {
  font-size: 1.5rem;
  margin-right: 0.75rem;
}

.toast-content h4 {
  margin: 0 0 0.25rem 0;
  font-weight: 600;
  color: #0f172a;
}

.toast-content p {
  margin: 0;
  color: #475569;
}
</style>

2. Configure Your Toast System

Now configure the toast system in your appkit directory:

ts
// app/appkit/$toast.ts
import { defineToasts } from '#appkit/tools'
import SuccessToast from '~/components/toasts/SuccessToast.vue'
import ErrorToast from '~/components/toasts/ErrorToast.vue'

export const { $toast } = defineToasts({
  success: SuccessToast,
  error: ErrorToast
})

3. Use Toasts Anywhere in Your App

Thanks to auto-imports, you can now use $toast anywhere:

vue
<!-- pages/index.vue -->
<template>
  <div class="page">
    <h1>Welcome to My App</h1>
    <button @click="showSuccess" class="btn btn-primary">
      Show Success Toast
    </button>
  </div>
</template>

<script setup>
function showSuccess() {
  $toast('success').open({
    props: {
      title: 'Success!',
      message: 'Your action was completed successfully.'
    },
    duration: 3000
  })
}
</script>

✨ Magic! Notice how:

  • No imports needed - $toast is auto-available
  • Type-safe props - TypeScript knows about your component props
  • Clean API - Simple, intuitive method calls
  • Auto-dismissal - Toasts close automatically after the specified duration

Note: The $toast().close() method is currently under development and not functional.

Core Concepts

1. Define Functions

Appkit uses "define functions" to set up major features:

ts
// These are the main "define" functions:
defineUser()     // User system with roles & permissions
defineToasts()   // Toast notification system
defineEmail()    // Email system with templates (requires HEXLABS_KEY)
defineModals()   // Modal dialog system

Why "define"? These functions set up complex systems at build time, allowing for optimization and type inference.

2. Configuration-Driven

Everything in Appkit is configuration-driven:

ts
// Instead of imperative setup code...
const userSystem = new UserSystem()
userSystem.addRole('admin', { permissions: ['all'] })
userSystem.addRole('user', { permissions: ['read'] })

// You use declarative configuration...
export const { $user } = defineUser({
  roles: {
    admin: { permissions: ['**'] },
    user: { permissions: ['read'] }
  }
})

This approach makes your code more predictable, testable, and maintainable.

3. Auto-Imports

Everything exported from app/appkit/ is automatically imported throughout your app:

ts
// app/appkit/$user.ts
export const { $user } = defineUser({ ... })

// pages/profile.vue - NO IMPORT NEEDED!
<script setup>
// $user is automatically available
const currentUserRef = $user.ref() // Reactive reference  
const currentUser = $user.data() // Current snapshot data
</script>

Feature Modules Deep Dive

Arkfire (Firebase Integration)

Arkfire provides type-safe Firebase operations:

ts
// app/appkit/$user.ts
export const { $user } = defineUser({
  roles: {
    admin: {},
    user: {},
    guest: {}
  },
  
  access: {
    admin: ['**'], // Access to all routes
    user: ['/dashboard/**', '/profile/**'],
    guest: ['/public/**']
  }
})
ts
// app/appkit/$firestore.ts  
import { defineArkfire } from '#appkit/arkfire'

// Define your Firestore schema
type Schema = {
  posts: {
    title: string
    content: string
    authorId: string
  }
}

export const { $col, $doc, $query, $ref } = defineArkfire<Schema>()
ts
// Use anywhere in your app (CLIENT-SIDE ONLY)
const postsResult = await $col('posts').get()
if (postsResult.success) {
  console.log(postsResult.data) // Array of posts
} else {
  console.error(postsResult.error) // Error message
}

const userRef = $user.ref() // Reactive reference to current user
const canAccess = await $user.canAccess('/admin/dashboard')

Arkform (Advanced Forms)

Arkform provides powerful form components with built-in validation:

vue
<template>
  <arkform name="userForm" :schema="userSchema" :submit="handleSubmit">
    <field name="name" />
    <field name="email" />
    <field name="age" is="input" />
    <go>Create Account</go>
  </arkform>
</template>

<script setup>
import { type } from 'arktype'

const userSchema = type({
  name: 'string>0',
  email: 'string.email', 
  age: 'number>=18'
})

async function handleSubmit(data: typeof userSchema.infer) {
  // Data is automatically validated and type-safe!
  console.log('Form data:', data)
  // Handle form submission
}
</script>

Tools (Utility Functions)

The tools module provides essential utilities:

ts
// ID Generation
const userId = $id()
const shortId = $id('nano', 8)

// Caching
$cache.set('user:123', userData, 300) // 5 minutes
const user = $cache.get('user:123')

// Environment
const env = $env()
if (env.public.dev) {
  console.log('Development mode')
}

// Feature Flags
if ($flags.get('newDashboard')) {
  // Show new dashboard
}

// Error Handling
const result = await $trap(async () => {
  return await riskyOperation()
})

if (result.success) {
  console.log('Success:', result.data)
} else {
  console.error('Error:', result.error)
}

Best Practices

1. Start Small, Scale Up

Begin with just the tools you need:

ts
// Start simple
export default defineAppkitConfig({
  tools: { enabled: true }
})

// Add features as you need them
export default defineAppkitConfig({
  arkfire: { enabled: true },
  arkform: { enabled: true },
  tools: { enabled: true }
})

2. Organize by Feature

Group related configurations together:

app/appkit/
├── appkit.config.ts    # Main configuration
├── $user.ts           # User system
├── $email.ts          # Email system
└── $notifications.ts  # Notification system

3. Use TypeScript

Appkit is built for TypeScript. Use it for the best experience:

ts
// Get full type safety
const { $user } = defineUser({
  roles: {
    admin: {},
    user: {}
  } as const  // This ensures type inference works properly
})

// TypeScript knows the exact role names
type UserRole = 'admin' | 'user'

Common Patterns

Authentication Flow

ts
// app/appkit/$user.ts
export const { $user } = defineUser({
  roles: {
    authenticated: {},
    anonymous: {}
  }
})

// middleware/auth.ts
export default defineNuxtRouteMiddleware((to, from) => {
  const user = $user.getCurrent()
  
  if (!user && to.path !== '/login') {
    return navigateTo('/login')
  }
})

Data Fetching

ts
// composables/usePost.ts
export async function usePost(id: string) {
  return await $doc('posts', id).get()
}

// pages/post/[id].vue
<script setup>
const route = useRoute()
const post = await usePost(route.params.id)
</script>

Error Handling

ts
// composables/useApi.ts
export async function useApi<T>(fn: () => Promise<T>) {
  const result = await $trap(fn)
  
  if (!result.success) {
    $toast('error').open({
      props: {
        title: 'Error',
        message: result.error
      }
    })
    return null
  }
  
  return result.data
}

What's Next?

Now that you understand the basics, dive deeper into specific modules:

  1. Tool Kit - Essential utilities and helpers
  2. Arkfire - Firebase integration and user management
  3. Arkform - Advanced form system
  4. TS Utils - TypeScript utilities and error handling

Get Help

  • Documentation - Browse the detailed docs for each module
  • Examples - Check the playground app for working examples
  • GitHub - Report issues or contribute on GitHub

Happy coding! 🚀