Skip to content

Fullstack Init

A detailed walkthrough of everything gkm init does when scaffolding a fullstack application.

Overview

The fullstack template creates a production-ready monorepo with three applications and two shared packages. It sets up authentication, database isolation, encrypted secrets, Docker services, and development tooling — all wired together and ready to run with a single gkm dev command.

Interactive Prompts

Running gkm init my-app walks you through these prompts in order:

#PromptOptionsDefault
1Project nameFree text (npm naming rules)my-app
2TemplateAPI, FullstackAPI
3ServicesPostgreSQL, Redis, Mailpit (multi-select)All selected
4Package managerpnpm, npm, yarn, bunAuto-detected
5Deployment targetDokploy, Configure laterDokploy
6TelescopeYes / NoYes
7LoggerPino (recommended), ConsolePino
8Routes structureCentralized (endpoints), Centralized (routes), Domain-basedCentralized (endpoints)

All prompts can be skipped with --yes to use defaults:

bash
gkm init my-app --template fullstack --yes

INFO

Selecting Fullstack automatically enables monorepo mode. The --monorepo flag is not needed.

What Gets Generated

Directory Structure

my-app/
├── apps/
│   ├── api/                     # Backend API
│   │   ├── src/
│   │   │   ├── config/
│   │   │   │   ├── env.ts       # EnvironmentParser singleton
│   │   │   │   ├── logger.ts    # Logger instance (Pino or Console)
│   │   │   │   ├── telescope.ts # Telescope dashboard setup
│   │   │   │   └── studio.ts    # Studio data browser setup
│   │   │   ├── services/
│   │   │   │   ├── database.ts  # Kysely database service
│   │   │   │   └── auth.ts      # Auth client service
│   │   │   ├── router.ts        # EndpointFactory with session/auth
│   │   │   ├── endpoints/
│   │   │   │   ├── health.ts    # GET /health
│   │   │   │   ├── users/
│   │   │   │   │   ├── list.ts  # GET /users
│   │   │   │   │   └── get.ts   # GET /users/:id
│   │   │   │   └── profile.ts   # Protected endpoint
│   │   │   └── test/
│   │   │       ├── globalSetup.ts
│   │   │       └── fixtures/
│   │   ├── package.json
│   │   ├── tsconfig.json
│   │   └── gkm.config.ts
│   ├── auth/                    # Authentication service
│   │   ├── src/
│   │   │   ├── config/
│   │   │   │   ├── env.ts
│   │   │   │   └── logger.ts
│   │   │   ├── auth.ts          # better-auth with magic link
│   │   │   └── index.ts         # Hono server entry
│   │   ├── package.json
│   │   └── tsconfig.json
│   └── web/                     # Next.js frontend
│       ├── src/
│       │   ├── app/
│       │   │   ├── layout.tsx   # Root layout with Providers
│       │   │   ├── page.tsx     # Home page
│       │   │   ├── globals.css  # Imports UI package styles
│       │   │   └── providers.tsx
│       │   ├── api/
│       │   │   └── index.ts     # Typed API client
│       │   ├── config/
│       │   │   ├── client.ts    # NEXT_PUBLIC_* config
│       │   │   └── server.ts    # Server-side secrets
│       │   └── lib/
│       │       ├── query-client.ts
│       │       └── auth-client.ts
│       ├── next.config.ts
│       ├── postcss.config.mjs
│       ├── tsconfig.json
│       └── package.json
├── packages/
│   ├── models/                  # Shared Zod schemas
│   │   ├── src/
│   │   │   ├── common.ts       # Id, Timestamps, Pagination
│   │   │   └── user.ts         # User, CreateUser, UpdateUser
│   │   ├── package.json
│   │   └── tsconfig.json
│   └── ui/                      # Shared React UI components
│       ├── src/
│       │   ├── components/      # shadcn/ui components
│       │   ├── lib/utils.ts     # cn() class merging
│       │   ├── styles/
│       │   │   └── globals.css  # Tailwind + CSS variables
│       │   └── index.ts
│       ├── .storybook/
│       ├── stories/
│       ├── components.json      # shadcn/ui config
│       ├── tailwind.config.ts
│       ├── postcss.config.mjs
│       └── package.json
├── docker/
│   ├── postgres/
│   │   └── init.sh              # Per-app user/schema creation
│   └── .env                     # Generated DB passwords
├── docker-compose.yml           # PostgreSQL 16, Redis 7, Mailpit
├── .gkm/
│   └── secrets/
│       └── development.json     # Encrypted development secrets
├── .vscode/
│   ├── settings.json            # Biome formatter, editor defaults
│   └── extensions.json          # Recommended extensions
├── package.json                 # Root workspace
├── pnpm-workspace.yaml
├── tsconfig.json                # Base TS config (ES2022, strict)
├── vitest.config.ts
├── turbo.json                   # Task orchestration with caching
├── biome.json                   # 2-space, single quotes, semicolons
├── gkm.config.ts                # defineWorkspace() config
└── .gitignore

Step-by-Step Execution

Here's what happens internally, in order:

1. Validate Input

  • Project name is validated against npm naming conventions (alphanumeric, hyphens, underscores)
  • Target directory must not already exist
  • Reserved names are blocked (node_modules, .git, package.json, src)

2. Generate Database Credentials

For fullstack projects with database enabled, two sets of credentials are generated:

  • api user — random password, connects to public schema
  • auth user — random password, connects to auth schema

Both users share the same database ({project_name}_dev) but are isolated by schema.

3. Generate Root Monorepo Files

FilePurpose
package.jsonRoot workspace with shared scripts (dev, build, test)
pnpm-workspace.yamlDefines apps/* and packages/* as workspaces
tsconfig.jsonBase config — target ES2022, module NodeNext, strict mode
vitest.config.tsTest runner configuration
turbo.jsonTask orchestration with caching rules
biome.jsonFormatter and linter (2-space indent, single quotes, semicolons)
.gitignoreStandard Node.js ignores + .gkm/
.vscode/settings.jsonBiome as default formatter, editor defaults
.vscode/extensions.jsonRecommended VSCode extensions
gkm.config.tsWorkspace config with defineWorkspace()

The workspace config wires all three apps together:

typescript
import { defineWorkspace } from '@geekmidas/cli/config';

export default defineWorkspace({
  name: 'my-app',
  apps: {
    api: {
      path: 'apps/api',
      type: 'backend',
      port: 3000,
      routes: './src/endpoints/**/*.ts',
      envParser: './src/config/env',
      logger: './src/config/logger',
      telescope: true,
    },
    auth: {
      type: 'auth',
      path: 'apps/auth',
      port: 3002,
      provider: 'better-auth',
      entry: './src/index.ts',
      requiredEnv: ['DATABASE_URL', 'BETTER_AUTH_SECRET'],
    },
    web: {
      type: 'frontend',
      path: 'apps/web',
      port: 3001,
      framework: 'nextjs',
      dependencies: ['api', 'auth'],
    },
  },
  services: { db: true, cache: true },
});

4. Generate Shared Models Package

Creates packages/models/ with reusable Zod schemas:

common.tsIdSchema, IdParamsSchema, TimestampsSchema, PaginationSchema, PaginatedResponseSchema

user.tsUserSchema, CreateUserSchema, UpdateUserSchema, UserResponseSchema

All schemas export corresponding TypeScript types. Published as @{projectName}/models within the workspace.

5. Generate Docker Files

docker-compose.yml — provisions three services:

ServiceImagePurpose
PostgreSQLpostgres:16Single database with per-app users
Redisredis:7Caching backend
Mailpitaxllent/mailpitEmail testing (dev only)

docker/postgres/init.sh — runs on first container start to create:

  • api user with access to public schema
  • auth user with access to auth schema (with search_path=auth)

docker/.env — stores generated database passwords for the init script.

6. Generate API App (apps/api)

The API app is built on @geekmidas/constructs with the Hono framework.

Configuration files:

  • gkm.config.ts — endpoint routes, env parser, logger, Telescope, Studio
  • tsconfig.json — inherits root config
  • package.json — deps, scripts, exports

Source files:

  • config/env.tsEnvironmentParser singleton with database, cache, and auth config
  • config/logger.ts — Pino or Console logger based on prompt selection
  • config/telescope.ts — Telescope debugging dashboard (if enabled)
  • config/studio.ts — Studio database browser (if database enabled)
  • services/database.ts — Kysely database service with PostgreSQL dialect
  • services/auth.ts — Auth client for calling the auth service
  • router.tsEndpointFactory with default JWT authorizer and session support
  • endpoints/health.ts — basic health check
  • endpoints/users/list.ts and get.ts — example CRUD endpoints
  • endpoints/profile.ts — protected endpoint requiring authentication

Test files:

  • test/globalSetup.ts — test database setup and teardown
  • test/fixtures/ — test helpers

Key dependencies:

PackagePurpose
@geekmidas/constructsEndpoint builder (e export)
@geekmidas/servicesService discovery
@geekmidas/envkitEnvironment parsing
@geekmidas/authJWT verification
@geekmidas/telescopeRequest debugging
@geekmidas/studioDatabase browser
@geekmidas/auditAudit logging
@geekmidas/rate-limitRate limiting
honoHTTP framework
kysely + pgDatabase ORM
pinoStructured logging (if selected)
zodSchema validation

Scripts: devgkm dev, buildgkm build, testvitest, typechecktsc --noEmit, lintbiome lint ., fmtbiome format . --write

7. Generate Auth App (apps/auth)

A standalone authentication service built with better-auth and magic link authentication.

typescript
// apps/auth/src/auth.ts
export const auth = betterAuth({
  database: new pg.Pool({ connectionString: process.env.DATABASE_URL }),
  baseURL: process.env.BETTER_AUTH_URL,
  trustedOrigins: process.env.BETTER_AUTH_TRUSTED_ORIGINS.split(','),
  secret: process.env.BETTER_AUTH_SECRET,
  plugins: [
    magicLink({
      expiresIn: 300, // 5 minutes
      sendMagicLink: async ({ email, url }) => {
        // Logs to console in dev, integrate emailkit for production
        console.log('Magic link for', email, ':', url);
      },
    }),
  ],
});

The Hono entry point mounts auth routes at /api/auth/* with CORS for trusted origins and a /health endpoint.

Key dependencies: better-auth, hono, @hono/node-server, kysely, pg

Scripts: devgkm dev --entry ./src/index.ts, db:migratenpx @better-auth/cli migrate, db:generatenpx @better-auth/cli generate

8. Generate Web App (apps/web)

A Next.js 16 frontend with React 19, React Query, and better-auth client.

Key features:

  • Path aliases: ~/*./src/*, @{name}/ui, @{name}/models
  • Tailwind CSS v4 via PostCSS plugin
  • React Query with 60s stale time
  • better-auth client with magic link plugin
  • Separate server and client config files
  • Transpiles workspace packages via next.config.ts

Key dependencies: next, react, react-dom, @tanstack/react-query, better-auth, @geekmidas/client, @geekmidas/envkit, tailwindcss

9. Generate UI Package (packages/ui)

A shared React component library with Tailwind CSS v4 and Storybook.

Includes:

  • shadcn/ui components (Button, Card, Input, Dialog, etc.)
  • Radix UI primitives for accessibility
  • Lucide React icons
  • cn() utility for class merging (clsx + tailwind-merge)
  • CSS variables for theming (light/dark mode)
  • Storybook for component development

Key dependencies: @radix-ui/*, tailwindcss, lucide-react, class-variance-authority

10. Initialize Encrypted Secrets

Secrets are encrypted and stored at .gkm/secrets/development.json. The decryption key is stored outside the project at ~/.gkm/{projectName}/development.key.

Auto-generated secrets:

KeyValue
NODE_ENVdevelopment
PORT3000
LOG_LEVELdebug
JWT_SECRETRandom
API_DATABASE_URLpostgresql://api:<pass>@localhost:5432/{name}_dev
API_DB_PASSWORDRandom
AUTH_DATABASE_URLpostgresql://auth:<pass>@localhost:5432/{name}_dev
AUTH_DB_PASSWORDRandom
AUTH_PORT3002
AUTH_URLhttp://localhost:3002
BETTER_AUTH_SECRETRandom
BETTER_AUTH_URLhttp://localhost:3002
BETTER_AUTH_TRUSTED_ORIGINShttp://localhost:3000,http://localhost:3001

Service credentials for PostgreSQL and Redis are also included.

11. Install Dependencies

Unless --skip-install is passed, the CLI runs the package manager's install command:

bash
pnpm install  # (or npm/yarn/bun based on selection)

12. Format Generated Code

After installation, all generated files are formatted with Biome:

bash
npx @biomejs/biome format --write --unsafe .

13. Initialize Git Repository

A git repository is initialized with an initial commit:

bash
git init
git branch -M main
git add .
git commit -m "🎉 Project created with @geekmidas/toolbox"

14. Print Next Steps

The CLI prints a summary with next steps:

──────────────────────────────────────────────────

✅ Project created successfully!

Next steps:

  cd my-app
  # Start PostgreSQL (if not running)
  docker compose up -d postgres
  pnpm dev

📁 Project structure:
  my-app/
  ├── apps/
  │   ├── api/          # Backend API
  │   ├── auth/         # Auth service (better-auth)
  │   └── web/          # Next.js frontend
  ├── packages/
  │   ├── models/       # Shared Zod schemas
  │   └── ui/           # Shared UI components
  ├── .gkm/secrets/     # Encrypted secrets
  ├── gkm.config.ts     # Workspace config
  └── turbo.json        # Turbo config

🔐 Secrets management:
  gkm secrets:show --stage development  # View secrets
  gkm secrets:set KEY VALUE --stage development  # Add secret
  gkm secrets:init --stage production  # Create production secrets

🚀 Deployment:
  pnpm deploy

📚 Documentation: https://geekmidas.github.io/toolbox/

CLI Options

All prompts can be overridden with command-line flags:

bash
gkm init <project-name> [options]
OptionDescription
--template <name>Template: api, fullstack, minimal, serverless, worker
--yes, -ySkip all prompts, use defaults
--skip-installSkip dependency installation
--monorepoForce monorepo setup (API template only, fullstack is always monorepo)
--api-path <path>API app path in monorepo (default: apps/api)
--pm <manager>Package manager: pnpm, npm, yarn, bun

Defaults with --yes

When running with --yes, these defaults are used:

SettingDefault
Templateapi (must pass --template fullstack explicitly)
ServicesAll enabled (PostgreSQL, Redis, Mailpit)
Package managerpnpm
Deploy targetDokploy
TelescopeEnabled
LoggerPino
Routes structureCentralized (endpoints)

Team Onboarding

After pushing your project to git, team members can get up and running with:

bash
git clone <repo-url>
cd my-app
pnpm install
gkm setup
gkm dev

See the Development Server — Team Onboarding guide for details on secret sharing, SSM sync, and troubleshooting.