Skip to content

Latest commit

Β 

History

History
121 lines (91 loc) Β· 4.84 KB

user-metadata.md

File metadata and controls

121 lines (91 loc) Β· 4.84 KB

User Metadata Configuration

Level: πŸ”΄ Advanced | Time: ⏱️ 15 min | Prerequisites: Configuration

This guide explains how to configure additional user fields that are captured during signup.


What You'll Learn

  • βœ… Add custom fields to user signup
  • βœ… Configure metadata storage
  • βœ… Use centralized user field configuration

Overview

FlowStack uses a centralized configuration for user metadata fields. Instead of adding columns to the database for each custom field, all additional data is stored in a flexible metadata JSON column.

Configuration Location: packages/config/src/config/user-metadata.ts

Adding a New Field

  1. Open packages/config/src/config/user-metadata.ts
  2. Add your field to the USER_METADATA_FIELDS array:
export const USER_METADATA_FIELDS: UserMetadataField[] = [
  // Existing field
  {
    key: "organizationName",
    label: "Organization Name",
    placeholder: "Enter your organization name",
    description: "This will be your workspace name",
    required: true,
    type: "string",
    createsOrganization: true,
  },
  // Add your new field
  {
    key: "companySize",
    label: "Company Size",
    placeholder: "e.g., 1-10, 11-50, 50+",
    required: false,
    type: "string",
  },
];
  1. The field will automatically appear in:
    • Backend auth config (additionalFields)
    • Frontend signup forms (web and tanstack apps)

Field Options

Property Type Required Description
key string Yes Unique identifier stored in metadata JSON
label string Yes Display label for the form
placeholder string No Placeholder text for the input
description string No Helper text shown below the input
required boolean No Whether the field is required (default: false)
type "string" | "number" | "boolean" No Field data type (default: "string")
createsOrganization boolean No If true, triggers organization creation on signup
returned boolean No Whether to return in API responses (default: false)

How It Works

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  @repo/config/src/config/user-metadata.ts                   β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”‚
β”‚  β”‚  USER_METADATA_FIELDS = [{ key, label, ... }]       β”‚    β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                           β”‚
           β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
           β–Ό               β–Ό               β–Ό
   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
   β”‚  @repo/auth   β”‚ β”‚   apps/web    β”‚ β”‚ apps/tanstack β”‚
   β”‚ additionalFieldsβ”‚ β”‚ signup form  β”‚ β”‚  signup form  β”‚
   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

API Reference

getAuthUserFields()

Returns field configuration for Better Auth's user.additionalFields:

import { getAuthUserFields } from "@repo/config";

const auth = betterAuth({
  user: {
    additionalFields: getAuthUserFields(),
  },
});

getUIUserFields()

Returns field configuration for AuthUIProvider:

import { getUIUserFields } from "@repo/config";

const additionalFields = getUIUserFields();

getOrganizationCreationFields()

Returns keys of fields that trigger organization creation:

import { getOrganizationCreationFields } from "@repo/config";

const orgFields = getOrganizationCreationFields();
// Returns: ["organizationName"]