Skip to main content

Design Philosophy

Every technical decision encodes a belief. Here’s what we believe.
Terra isn’t just a forms platform—it’s an opinionated take on how government intake infrastructure should work. This page explains the principles that guide our technical decisions.

Principle 1: Applicant Data Is Sacred

Government benefit applications contain the most sensitive information people share: Social Security numbers, income documentation, disability status, immigration records. A data breach doesn’t just expose information—it can result in identity theft, benefit denial, or deportation. This principle shapes everything:
DecisionRationale
Private storage bucketsFiles are never publicly accessible, even by accident
Signed URLs with 60s expiryLeaked URLs become useless within a minute
Submissions succeed independentlyExternal service failures don’t lose applicant data
Defense-in-depth securityMultiple layers mean single bugs don’t cause breaches
When we face a tradeoff between convenience and data protection, data protection wins. Every time.

Principle 2: Fail Secure, Not Fail Open

Security bugs are inevitable. The question is: when something goes wrong, what happens? Fail open means errors grant access. A crashed permission check lets the user through. Fail secure means errors deny access. A crashed permission check redirects to login. We chose fail secure:
// Every permission check follows this pattern
export async function requireAdmin() {
  try {
    const session = await getSession();
    const user = await getUserWithRole(session.user.id);

    if (user?.role !== 'admin' && user?.role !== 'super_admin') {
      throw new Error('Forbidden');
    }

    return user;
  } catch (error) {
    // ANY error = no access
    throw new Error('Unauthorized');
  }
}
This extends to every security decision:
  • Unknown role? Treat as applicant (lowest privilege)
  • Can’t parse redirect URL? Go to home page
  • File path looks suspicious? Reject the upload
  • Session decryption fails? Redirect to login

Principle 3: Explicit Over Magic

Frameworks love magic. Automatic code splitting, implicit data fetching, hidden configuration. Magic is convenient until it breaks—then you’re debugging something you don’t understand. Terra prefers explicit patterns: Server actions, not API routes
// Explicit: you see exactly what's happening
"use server";

export async function updateFormStatus(formId: string, status: FormStatus) {
  const user = await requireAdmin();

  await supabaseAdmin
    .from('forms')
    .update({ status })
    .eq('id', formId);

  await logAudit(user.id, 'form.status.updated', { formId, status });

  return { success: true };
}
Manual permission checks, not middleware magic
// We check permissions in every action, explicitly
export async function getSubmissions(formId: string) {
  const user = await requireFormAccess(formId); // Explicit check

  // Now we know the user has access
  const submissions = await fetchSubmissions(formId);
  return submissions;
}
Zustand stores, not Context gymnastics
// State management is explicit and inspectable
const useFormBuilder = create((set) => ({
  schema: initialSchema,
  selectedFieldId: null,

  addField: (field) => set((state) => ({
    schema: { ...state.schema, elements: [...state.schema.elements, field] }
  })),
}));
When you read Terra code, you should understand what’s happening without knowing framework internals.

Principle 4: JSON for Flexibility, Zod for Safety

Government forms are weird. Conditional sections, repeatable groups, custom validation rules, translated labels. A normalized database schema would require migrations for every new form feature. We use JSONB for flexibility:
// The entire form definition is one JSON tree
const form = {
  id: "rental-assistance",
  schema: {
    elements: [
      { type: "text", id: "name", label: { en: "Full Name" } },
      { type: "group", id: "household", elements: [...] },
      { type: "repeated", id: "income-sources", min: 1, max: 5, template: {...} }
    ]
  }
};
But JSON is stringly-typed. You can put anything in there. So we validate with Zod:
// Runtime validation catches schema errors
export const FormElementSchema = z.discriminatedUnion("type", [
  TextFieldSchema,
  ChoiceFieldSchema,
  GroupFieldSchema,
  RepeatedFieldSchema,
  // ... 20+ field types
]);

// This runs on every schema load
const validated = FormElementSchema.parse(element);
The combination gives us:
  • Flexibility: Add new field types without migrations
  • Safety: Invalid schemas fail fast with clear errors
  • Portability: Export/import forms as JSON files
  • Versioning: Store draft and published schemas side by side

Principle 5: Async by Default

External services fail. Airtable rate limits. Twilio has outages. Webhook endpoints timeout. If form submission depends on external services, applicants suffer for infrastructure problems. Our solution: submissions are synchronous, everything else is async. Benefits:
  • Applicants see success in ~300ms regardless of integration health
  • Failed operations retry automatically with exponential backoff
  • Dead-letter queue captures persistent failures for manual review
  • Integration outages don’t create support tickets

Principle 6: Server-First, Client-Lite

React traditionally runs in the browser. The server sends HTML, then JavaScript hydrates it into an interactive app. This creates security risks: secrets can leak into client bundles, API keys can be extracted, business logic can be reverse-engineered. Terra uses React Server Components (RSC) to keep sensitive logic on the server:
// This component runs ONLY on the server
export default async function SubmissionsPage({ params }) {
  // Database query happens server-side
  const submissions = await getSubmissions(params.formId);

  // Only the rendered HTML goes to the client
  return <SubmissionsTable data={submissions} />;
}
Client components exist for interactivity (form inputs, drag-drop, modals) but they receive pre-fetched data rather than making their own API calls. What stays on the server:
  • Database credentials and queries
  • Permission checks
  • File signed URL generation
  • Integration API keys
  • Encryption/decryption
What runs on the client:
  • Form input handling (react-hook-form)
  • Drag-and-drop (dnd-kit)
  • UI state (modals, tabs, accordions)
  • File uploads (after receiving signed URL)

Principle 7: White-Label as a Feature

Government agencies have strong brand requirements. Their forms should look like “their” forms, not a third-party service. Terra is designed to be invisible. Branding is configurable at every level:
  • Organization: Logo, colors, fonts
  • Folder (workspace): Override logo, custom domain
  • Form: Override any setting, form-specific domain
Custom domains are first-class:
housing.example.gov → routes to Housing folder
benefits.example.gov → routes to Benefits folder
apply.example.gov/rental → routes to specific form
Email templates are brandable:
<SubmissionReceipt
  logo={organization.branding.logo}
  primaryColor={organization.branding.primaryColor}
  supportUrl={form.supportUrl}
/>
The applicant never sees “Terra” or “Unify”—just their agency’s brand.

Principle 8: Multi-Language by Design

Government forms serve diverse populations. Language support isn’t a plugin—it’s baked into the data model. Every user-facing string is an I18nString:
type I18nString = {
  en: string;
  es?: string;
  zh?: string;
  // ... any language code
};

// Field labels, placeholders, error messages, help text
const field = {
  type: "text",
  label: { en: "Full Name", es: "Nombre Completo" },
  placeholder: { en: "Enter your name", es: "Ingrese su nombre" },
};
Translation workflow:
  1. Create form in English
  2. Add languages to form settings
  3. Auto-translate with DeepL (or translate manually)
  4. Applicants switch languages at runtime
The form builder shows all languages simultaneously—no switching modes to edit translations.

Principle 9: Audit Everything

When something goes wrong (and it will), you need to know what happened. Terra logs every significant action:
// Audit log entry structure
{
  user_id: "usr_123",
  action: "form.schema.updated",
  resource_type: "form",
  resource_id: "form_456",
  changes: {
    before: { status: "draft" },
    after: { status: "published" }
  },
  ip_address: "192.168.1.1",
  user_agent: "Mozilla/5.0...",
  created_at: "2025-01-02T10:30:00Z"
}
Every form edit, status change, permission grant, and file access is recorded. Audit logs are immutable (append-only table) and retained indefinitely. This enables:
  • Debugging: “Who changed this field label?”
  • Compliance: “Show all accesses to this applicant’s data”
  • Security: “What did this user do before we revoked access?”

Principle 10: Boring Technology (Mostly)

Innovation is expensive. Every new technology requires learning, debugging, and maintenance. Terra uses boring, proven technologies wherever possible:
LayerTechnologyWhy
FrameworkNext.jsMassive ecosystem, Vercel support
DatabasePostgreSQL30 years of battle-testing
ValidationZodSimple, composable, TypeScript-first
StylingTailwindUtility-first, no CSS debugging
StateZustandMinimal API, great DevTools
EmailReact EmailJust React, render to HTML
We reserve complexity for problems that need it:
  • Form schema (novel problem → custom solution)
  • Async queue (specific requirements → custom table)
  • AI form import (genuinely complex → novel approach)
But auth? We use WorkOS. Storage? Supabase. Email delivery? Resend. These are solved problems—we don’t need to re-solve them.

Summary

PrincipleOne-liner
Applicant Data Is SacredProtect data above all else
Fail SecureErrors deny access, never grant it
Explicit Over MagicCode should be readable without framework knowledge
JSON + ZodFlexibility with safety
Async by DefaultSubmissions succeed, integrations retry
Server-FirstKeep secrets and logic on the server
White-LabelAgencies own their brand
Multi-Language by DesignI18n isn’t an afterthought
Audit EverythingKnow what happened
Boring TechnologyInnovate only where necessary

Next Steps