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)
└── .gitignore

Configuration 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 GencowConfig in gencow.config.js to 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 with createCrud(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 (not export * as tasksModule or export * 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/db

Production 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 cloud

Security: .env is gitignored. Production environment variables are encrypted at rest. Never expose secrets in frontend code.

Local dev: Edit .env file directly — gencow dev loads it automatically.

Next Steps