Project Structure
Understand the frontend, gencow backend, config, and deploy files in a Gencow project
Overview
A Gencow project follows a simple convention: your backend lives in gencow/, and everything else (the recommended Vite + React frontend, configs) lives alongside it.
my-app/
├── gencow/ ← Backend code
│ ├── schema.ts ← Database tables (Drizzle ORM)
│ ├── generated/ ← Server codegen (do not edit by hand)
│ │ ├── auth-schema.ts ← Auth tables (from gencow/auth.ts)
│ │ └── db-schema.gen.ts ← Aggregated schema for typed ctx.db (codegen)
│ ├── auth.ts ← Auth configuration (defineAuth)
│ ├── runtime.ts ← Typed `procedure`, `httpRoute`, and `createCrud` bound to your schema + auth
│ ├── index.ts ← Re-exports all modules
│ ├── tasks.ts ← Your queries & mutations
│ ├── crons.ts ← Scheduled jobs
│ ├── seed.ts ← Seed data (optional)
│ ├── api.ts ← ⚡ Auto-generated (do not edit)
│ ├── README.md ← ⚡ Auto-generated AI guide
│ └── SECURITY.md ← Security checklist
├── .gencow/ ← Runtime data (gitignored)
│ ├── uploads/ ← File storage
│ ├── server.js ← Bundled server copy
│ └── dashboard/ ← Admin dashboard assets
├── migrations/ ← SQL migration files
├── src/ ← Vite + React frontend (recommended)
│ ├── main.tsx ← React entry point
│ ├── App.tsx ← App shell
│ └── gencow/ ← Generated frontend API client
├── gencow.config.js ← Project configuration
├── gencow.json ← Cloud app ID (created on deploy)
├── drizzle.config.ts ← Database config
├── package.json
├── tsconfig.json
├── .env ← Environment variables (local only)
└── .gitignoreConfiguration Files
gencow.config.js
The main project configuration file:
/** @type {import('@gencow/core').GencowConfig} */
export default {
// Path to your backend functions directory
functionsDir: "./gencow",
// Path to your Drizzle schema file
schema: "./gencow/schema.ts",
codegen: {
// Optional output directory for generated frontend types
outDir: "./src/gencow",
// Experimental: set false if you fully own gencow/generated/auth-schema.ts
authSchema: true,
},
// File storage directory
storage: "./.gencow/uploads",
// Database configuration
db: { url: "./.gencow/data" },
// API server port
port: 5456,
};The JSDoc @type annotation gives editors full autocomplete and inline docs without adding a runtime import. Because the file is plain JavaScript, you can use variables, process.env, or any other dynamic expression. The CLI loads gencow.config.js with a dynamic import(). Projects from gencow init ship export default together with "type": "module" in package.json. In a CommonJS-only package you can still use module.exports = { ... }; Node interop exposes that as the default export. Legacy gencow.config.ts files (using defineConfig({ ... }) from @gencow/core) are still loaded for backward compatibility, but support only literal values; migrate to gencow.config.js when you need dynamic configuration.
| Option | Default | Description |
|---|---|---|
functionsDir |
"./gencow" |
Directory containing your backend code |
schema |
"./gencow/schema.ts" |
Path to Drizzle schema file |
codegen.outDir |
"./src/gencow" |
Output directory for generated frontend codegen artifacts |
codegen.authSchema |
true |
Experimental. When true, regenerate gencow/generated/auth-schema.ts from gencow/auth.ts during codegen |
storage |
"./.gencow/uploads" |
File storage directory |
db.url |
"./.gencow/data" |
Database data directory |
port |
5456 |
Dev server port |
Hover
GencowConfigingencow.config.jsto see supported keys, comments, and examples directly from@gencow/core.
gencow.json
Auto-created when you run gencow dev or gencow deploy. Contains your cloud app identity:
{
"appId": "null-mint-9625",
"displayName": "my-app",
"platformUrl": "https://gencow.app"
}Do not edit
appId— it's a unique identifier assigned by the platform. Changing it will create a new app on next deploy.
drizzle.config.ts
Database configuration for Drizzle Kit (migrations):
import { defineConfig } from "drizzle-kit";
export default defineConfig({
dialect: "postgresql",
schema: ["./gencow/schema.ts", "./gencow/generated/auth-schema.ts"],
out: "./migrations",
// Database connection
...(process.env.DATABASE_URL
? { dbCredentials: { url: process.env.DATABASE_URL } }
: {}),
});The gencow/ Folder
schema.ts — Database Tables
Define your tables using Drizzle's pgTable with ownerRls() for automatic Row-Level Security:
import { pgTable, serial, text, boolean, timestamp } from "drizzle-orm/pg-core";
import { ownerRls } from "@gencow/core";
import { user } from "./generated/auth-schema";
export const tasks = pgTable("tasks", {
id: serial("id").primaryKey(),
title: text("title").notNull(),
done: boolean("done").default(false).notNull(),
userId: text("user_id")
.notNull()
.references(() => user.id, { onDelete: "cascade" }),
createdAt: timestamp("created_at").defaultNow().notNull(),
}, (t) => ownerRls(t.userId));Note:
ownerRls()generates PostgreSQL RLS policies for automatic per-user data isolation. Combined withcreateCrud(tasks), all CRUD operations enforce authentication and ownership — no manual filtering needed.
gencow/generated/auth-schema.ts — Auth Tables
Auto-generated by gencow init and gencow codegen from gencow/auth.ts. Contains user, session, account, and verification tables required by better-auth. Do not remove or modify unless you opt out of auth schema generation.
gencow/generated/db-schema.gen.ts — Typed Schema Map
Auto-generated aggregate of your Drizzle schema files (including auth tables). Used by gencow/runtime.ts for typed ctx.db. Do not edit manually.
auth.ts — Auth Configuration
Customize authentication behavior:
import { defineAuth } from "@gencow/core";
export default defineAuth({
emailAndPassword: { enabled: true },
// emailVerification: { sendVerificationEmail: async ({ email, url }) => { ... } },
});index.ts — Module Re-exports
Critical file — tells the server which modules to register:
export * as tasks from "./tasks";
export * as files from "./files";
// export * as chat from "./chat";Pattern: Always use
export * as moduleName(notexport * as tasksModuleorexport * as TasksMod).
crons.ts — Cron Jobs
Define scheduled tasks:
import { cronJobs } from "@gencow/core";
const crons = cronJobs();
crons.interval("syncData", { minutes: 30 }, "data.sync");
crons.daily("report", { hour: 9 }, "reports.generate");
export default crons; // ← Required!seed.ts — Seed Data (Optional)
Populate the database with test data:
import { tasks } from "./schema";
export default async function seed(ctx) {
await ctx.db.insert(tasks).values([
{ title: "First task", userId: "test-user" },
]);
}Run with gencow db:seed.
api.ts — Auto-Generated (⚡ Do Not Edit)
Generated by gencow dev on every file change. Provides type-safe API references for your React frontend:
// Generated by Gencow — do not edit manually.
import { defineProcedureQuery, defineProcedureMutation } from "@gencow/client";
import type * as Operations from "./operations.d.ts";
export const api = {
tasks: {
list: defineProcedureQuery<Operations.TasksListOutput>("tasks.list"),
create: defineProcedureMutation<Operations.TasksCreateOutput>("tasks.create"),
toggle: defineProcedureMutation<Operations.TasksToggleOutput>("tasks.toggle"),
remove: defineProcedureMutation<Operations.TasksRemoveOutput>("tasks.remove"),
},
} as const;README.md — Auto-Generated AI Guide (⚡ Do Not Edit)
Generated alongside api.ts. Contains a comprehensive vibe-coding guide that you can paste into AI assistants. Includes API reference, React hook usage, auth setup, cron patterns, and deployment commands.
The .gencow/ Folder (Gitignored)
| Path | Purpose |
|---|---|
.gencow/uploads/ |
Uploaded files (via ctx.storage.store()) |
.gencow/server.js |
Bundled server copy (for standalone projects) |
.gencow/dashboard/ |
Admin dashboard static assets |
Environment Variables
.env
# Gencow auto-populates this after deploy:
VITE_API_URL=https://my-app-id.gencow.app
# Your secrets:
OPENAI_API_KEY=sk-your-key-here
DATABASE_URL=postgres://user:pass@host/dbProduction Environment
Manage via CLI:
gencow env set OPENAI_API_KEY=sk-... # → cloud
gencow env set DATABASE_URL=postgres://... # → cloud
gencow env list # → cloud env vars
gencow env push # Push all .env vars to cloudSecurity:
.envis gitignored. Production environment variables are encrypted at rest. Never expose secrets in frontend code.Local dev: Edit
.envfile directly —gencow devloads it automatically.
Next Steps
- Schema Guide — Advanced table patterns
- Queries & Mutations — Read and write data
- Authentication — Auth setup in detail