FrontendData Fetching
Type System
Zod schemas and inferred TypeScript types.
HyperSaaS uses Zod schemas as the single source of truth for data types. TypeScript types are inferred from schemas, ensuring zero drift between validation and type definitions.
Schema Organization
src/lib/validations/
├── common.ts # Base schema, enums (roles, statuses, providers)
├── auth.ts # Login, register, password reset schemas
├── workspaces.ts # Workspace, team, membership, invitation schemas
├── chat.ts # Chat session, message, AI settings schemas
├── documents.ts # Document, knowledge base schemas
├── billing.ts # Subscription, plan, price schemas
└── contact.ts # Contact form schemaPattern: Schema → Type
// lib/validations/chat.ts
import { z } from "zod";
export const chatSessionSchema = z.object({
id: z.string().uuid(),
name: z.string().nullable(),
status: z.enum(["active", "completed", "archived"]),
ai_provider: z.enum(["openai", "anthropic", "google", "groq", "deepseek"]),
ai_model: z.string(),
agent_framework: z.enum(["none", "langgraph", "pydantic_ai"]),
system_prompt: z.string(),
temperature: z.number().nullable(),
max_tokens: z.number().nullable(),
top_p: z.number().nullable(),
frequency_penalty: z.number().nullable(),
presence_penalty: z.number().nullable(),
stream: z.boolean(),
model_parameters: z.record(z.any()),
is_shared: z.boolean(),
is_public: z.boolean(),
shareable_link_id: z.string().uuid(),
created_at: z.string(),
updated_at: z.string(),
});
// Type inferred from schema
export type ChatSession = z.infer<typeof chatSessionSchema>;Common Schemas
Base Schema
// lib/validations/common.ts
export const baseSchema = z.object({
id: z.string().uuid(),
created_at: z.string(),
updated_at: z.string(),
});Enum Schemas
export const aiProviderSchema = z.enum([
"openai", "anthropic", "google", "groq", "deepseek"
]);
export const agentFrameworkSchema = z.enum([
"none", "langgraph", "pydantic_ai"
]);
export const messageRoleSchema = z.enum([
"user", "assistant", "system", "tool"
]);
export const processingStatusSchema = z.enum([
"pending", "processing", "completed", "failed"
]);Key Types
Auth Types
// lib/types/auth.ts
interface UserDetails {
id: string;
email: string;
name: string;
username: string;
image?: string;
subscription_status?: string;
has_active_subscription?: boolean;
}
interface LoginFormData {
email: string;
password: string;
}
interface RegisterFormData {
email: string;
name: string;
password: string;
re_password: string;
}Workspace Types
// lib/types/workspaces.ts
interface Workspace {
id: string;
name: string;
slug: string;
owner: string;
status: "active" | "archived";
memberships: WorkspaceMembership[];
teams: Team[];
created_at: string;
updated_at: string;
}
interface WorkspaceMembership {
id: string;
user: string;
workspace: string;
role: "admin" | "member";
}Chat Types
// lib/types/chat.ts
interface Message {
id: string;
session: string;
role: "user" | "assistant" | "system" | "tool";
content: string;
parent_message: string | null;
sequence_number: number;
attachments: any[];
map_data: Record<string, any> | null;
created_at: string;
}Document Types
// lib/types/documents.ts
interface KnowledgeBase {
id: string;
name: string;
description: string;
is_shared_with_workspace: boolean;
document_count: number;
created_at: string;
}
interface Document {
id: string;
name: string;
source_type: "file" | "web_url" | "youtube";
source_url: string;
file_type: string;
processing_status: "pending" | "processing" | "completed" | "failed";
chunk_count: number;
created_at: string;
}Billing Types
// lib/types/billing.ts
interface Subscription {
subscription_id: string;
status: "active" | "trialing" | "past_due" | "canceled" | "incomplete" | "ended";
period_start: string;
period_end: string;
cancel_at_period_end: boolean;
trial_start: string | null;
trial_end: string | null;
}Input Validation Schemas
Schemas for form inputs use stricter validation:
// lib/validations/chat.ts
export const chatSessionCreateSchema = z.object({
name: z.string().min(1).max(255),
ai_provider: aiProviderSchema,
ai_model: z.string().min(1),
agent_framework: agentFrameworkSchema.default("langgraph"),
system_prompt: z.string().default(""),
temperature: z.number().min(0).max(2).nullable().default(null),
max_tokens: z.number().positive().nullable().default(null),
top_p: z.number().min(0).max(1).nullable().default(null),
model_parameters: z.string().max(10240).default("{}"), // JSON string, max 10KB
});Runtime Validation
Schemas validate API responses at runtime:
const { data } = await fetchApiData(
`/api/workspaces/${id}/chats/`,
z.array(chatSessionSchema) // Validates response shape
);
// data is ChatSession[] | null — guaranteed to match the schemaThis catches backend API changes at the data boundary rather than deep in component logic.