---
id: "0022"
title: "Init Pipelines"
status: completado
type: feature
domain: []
scope: multi-app
priority: alta
depends: []
blocks: []
related: []
created: 2026-05-17
updated: 2026-05-17
tags: []
---
# 0022 — Init Pipelines

## Metadata

| Campo | Valor |
|-------|-------|
| **ID** | 0022 |
| **Estado** | pendiente |
| **Prioridad** | alta |
| **Tipo** | feature |

## Dependencias

| ID | Titulo | Estado | Requerido |
|----|--------|--------|-----------|
| 0009 | HTTP Server Foundation | pendiente | si |
| 0010 | Auth System | pendiente | si |
| 0015 | Database Migrations | pendiente | si |

**Bloqueada por:** `#0009` (http_serve, http_router, http_json_response, http_middleware_chain), `#0010` (jwt_middleware, password_hash, session_create), `#0015` (migration_create, migration_up, migration_status). Los pipelines de init generan boilerplate que importa y compone estas funciones — sin ellas, el codigo scaffoldeado no compilaria.

**Desbloquea:** cualquier app nueva del registry se puede crear con un solo comando en vez de copiar y adaptar una app existente.

---

## Objetivo

Cuatro bash pipelines que scaffold apps completas en `apps/` con un solo comando. Cada uno genera la estructura de directorios, archivos boilerplate, `app.md` con frontmatter correcto, y verifica que el resultado compila. Misma filosofia que `init_jupyter_analysis_bash_pipelines`: componer funciones atomicas del registry para producir un entorno listo para trabajar.

## Contexto

- Existen tres init pipelines: `init_go_project_bash_pipelines` (repo Go generico), `init_go_module_bash_pipelines` (modulo Go simple), `init_jupyter_analysis_bash_pipelines` (analysis Jupyter). Todos scaffoldean estructuras basicas.
- **No existe ningun pipeline para scaffoldear apps del registry** con HTTP server, auth, DB, frontend, Wails o TUI. Cada app nueva se construye copiando otra y adaptando manualmente.
- Las apps existentes (`deploy_server`, `sqlite_api`, `rapid_dashboards`, `pipeline_launcher`) comparten patrones repetitivos: main.go con graceful shutdown, config desde env vars, health check, migrations, app.md.
- Con las funciones de 0009 (HTTP), 0010 (auth) y 0015 (migrations) disponibles, el boilerplate de una app API es predecible y automatizable.
- El registry ya tiene funciones Wails completas (`scaffold_wails_app_go_infra`, `install_wails_bash_infra`, `wails_build_go_infra`, hooks `use_wails_*_ts_ui`, `wails_provider_ts_ui`) y TUI (`new_base_model_go_tui`, `run_fullscreen_go_tui`, temas, spinners, listas).

## Arquitectura

```
bash/functions/pipelines/
├── init_api_app.sh              — NEW: scaffold Go HTTP API app
├── init_api_app.md              — NEW
├── init_web_app.sh              — NEW: scaffold full-stack app (Go API + React)
├── init_web_app.md              — NEW
├── init_desktop_app.sh          — NEW: scaffold Wails desktop app
├── init_desktop_app.md          — NEW
├── init_cli_app.sh              — NEW: scaffold Go CLI/TUI app
├── init_cli_app.md              — NEW
```

Todas son `kind: pipeline`, `purity: impure`, `lang: bash`, `domain: pipelines`.

### Patron de composicion

Cada pipeline sigue el mismo patron que `init_jupyter_analysis`:

1. Source funciones atomicas del registry via `source "$REGISTRY_ROOT/bash/functions/..."`
2. Parsear argumentos (nombre obligatorio, flags opcionales)
3. Crear estructura de directorios con `mkdir -p`
4. Escribir archivos boilerplate con heredocs
5. Generar `app.md` con frontmatter correcto
6. Ejecutar `fn index` para registrar la app
7. Verificar con `go vet` / `pnpm build` / `wails build` segun corresponda

---

## Diseno

### Pipeline 1: `init_api_app`

Scaffold de Go HTTP API app en `apps/`.

**Uso:**

```bash
fn run init_api_app my_service
fn run init_api_app my_service --port 8080 --with-auth --with-db
```

**Archivos generados:**

```
apps/{nombre}/
├── main.go              — Entry point: config → router → middleware → http_serve con graceful shutdown
├── handlers.go          — Handler GET /health + handler de ejemplo GET /api/v1/status
├── config.go            — Struct Config con tags + carga desde .env / env vars
├── migrations/
│   └── 001_initial.sql  — CREATE TABLE ejemplo con id, created_at, updated_at
├── app.md               — Frontmatter con tag service, uses_functions, dir_path
├── Makefile             — Targets: build, run, test, vet, clean
├── .env.example         — Variables de entorno documentadas (PORT, DB_PATH, etc.)
└── .gitignore           — Binario, .env, *.db-shm, *.db-wal
```

**Funciones del registry compuestas:**

| Funcion | Para que |
|---------|---------|
| `assert_command_exists_bash_shell` | Verificar que `go` esta instalado |
| `http_serve_go_infra` (0009) | Codigo de graceful shutdown en main.go |
| `http_router_go_infra` (0009) | Registro de rutas en main.go |
| `http_json_response_go_infra` (0009) | Helper en handlers.go |
| `http_error_response_go_infra` (0009) | Helper en handlers.go |
| `http_middleware_chain_go_infra` (0009) | Composicion de middlewares en main.go |
| `http_logger_middleware_go_infra` (0009) | Logging en main.go |
| `http_cors_middleware_go_infra` (0009) | CORS en main.go |
| `migration_up_go_infra` (0015) | Aplicar migrations en main.go al arrancar |
| `config_load_go_infra` (0018) | Carga de config en config.go (si existe) |

**Flags opcionales:**

| Flag | Efecto |
|------|--------|
| `--port N` | Puerto por defecto en config y .env.example (default: 8080) |
| `--with-auth` | Anade jwt_middleware, handlers de login/register, tabla users en migration |
| `--with-db` | Anade operations.db setup, store.go con helpers CRUD basicos |
| `--with-ops` | Anade `fn ops init` para crear operations.db con schema completo |

**main.go generado (esquema):**

```go
package main

import (
    "context"
    "log"
    "os"
    "os/signal"

    "fn_registry/functions/infra"
)

func main() {
    cfg := LoadConfig()

    // Migrations
    if err := infra.MigrationUp(cfg.DBPath, "migrations"); err != nil {
        log.Fatal(err)
    }

    // Routes
    routes := []infra.Route{
        {Method: "GET", Path: "/health", Handler: healthHandler},
        {Method: "GET", Path: "/api/v1/status", Handler: statusHandler},
    }
    mux := infra.HttpRouter(routes)

    // Middleware
    middleware := infra.HttpMiddlewareChain(
        infra.HttpCorsMiddleware(cfg.CORSOrigins, []string{"GET", "POST", "PUT", "DELETE"}),
        infra.HttpLoggerMiddleware(os.Stdout),
    )

    // Serve
    ctx, cancel := signal.NotifyContext(context.Background(), os.Interrupt)
    defer cancel()

    log.Printf("starting %s on :%s", cfg.AppName, cfg.Port)
    if err := infra.HttpServe(":"+cfg.Port, middleware(mux), ctx); err != nil {
        log.Fatal(err)
    }
}
```

---

### Pipeline 2: `init_web_app`

Scaffold de full-stack app: Go API backend + React frontend con Mantine.

**Uso:**

```bash
fn run init_web_app my_dashboard
fn run init_web_app my_dashboard --port 8080 --with-auth
```

**Archivos generados:**

```
apps/{nombre}/
├── main.go              — Igual que init_api_app + serve static files del frontend build
├── handlers.go          — Health + API handlers de ejemplo
├── config.go            — Config con FRONTEND_DIR
├── migrations/
│   └── 001_initial.sql
├── app.md               — tag service, uses frontend
├── Makefile             — Targets: build, build-frontend, run, dev, test, clean
├── .env.example
├── .gitignore
├── docker-compose.yml   — Dev: Go API hot-reload + frontend dev server
└── frontend/
    ├── package.json     — pnpm, vite, react, @mantine/core, @mantine/charts, @fn_library
    ├── vite.config.ts   — API proxy a localhost:${port}
    ├── tsconfig.json
    ├── index.html
    ├── postcss.config.cjs
    └── src/
        ├── main.tsx     — FnMantineProvider + App mount
        ├── App.tsx      — Router basico con pagina de ejemplo
        ├── theme.ts     — createTheme() con colores del proyecto
        └── pages/
            └── Home.tsx — Pagina de ejemplo usando crud_page_ts_ui o dashboard_layout_ts_ui
```

**Funciones adicionales compuestas (sobre init_api_app):**

| Funcion | Para que |
|---------|---------|
| `mantine_provider_ts_ui` | Provider raiz en main.tsx |
| `crud_page_ts_ui` | Pagina de ejemplo funcional |
| `app_shell_ts_ui` | Layout con navbar y header |
| `data_table_ts_ui` | Tabla de datos en la pagina de ejemplo |

**vite.config.ts generado:**

```ts
import { defineConfig } from "vite";
import react from "@vitejs/plugin-react";
import path from "path";

export default defineConfig({
  plugins: [react()],
  resolve: {
    alias: {
      "@fn_library": path.resolve(__dirname, "../../frontend/functions/ui"),
    },
  },
  server: {
    proxy: {
      "/api": {
        target: "http://localhost:${PORT}",
        changeOrigin: true,
      },
      "/health": {
        target: "http://localhost:${PORT}",
      },
    },
  },
});
```

**docker-compose.yml generado:**

```yaml
services:
  api:
    build: .
    ports:
      - "${PORT}:${PORT}"
    env_file: .env
    volumes:
      - ./migrations:/app/migrations
  frontend:
    image: node:20-alpine
    working_dir: /app
    command: sh -c "corepack enable && pnpm install && pnpm dev"
    ports:
      - "5173:5173"
    volumes:
      - ./frontend:/app
```

---

### Pipeline 3: `init_desktop_app`

Scaffold de Wails desktop app con Go backend y React frontend con @fn_library.

**Uso:**

```bash
fn run init_desktop_app my_tool
fn run init_desktop_app my_tool --with-db
```

**Archivos generados:**

```
apps/{nombre}/
├── main.go              — Wails entry point con embed del frontend
├── app.go               — Struct App con bindings base (Greet, GetVersion)
├── wails.json           — Config Wails apuntando a frontend/
├── go.mod
├── app.md               — framework: wails, uses wails hooks
├── .gitignore
└── frontend/
    ├── package.json     — pnpm, vite, react, @mantine/core, @fn_library
    ├── vite.config.ts
    ├── tsconfig.json
    ├── index.html
    └── src/
        ├── main.tsx     — WailsProvider + FnMantineProvider + App
        ├── App.tsx      — Ejemplo usando useWailsQuery + data_table
        └── theme.ts     — createTheme()
```

**Funciones del registry compuestas:**

| Funcion | Para que |
|---------|---------|
| `scaffold_wails_app_go_infra` | Genera estructura base Wails (main.go, app.go, wails.json, go.mod) |
| `install_wails_bash_infra` | Verifica/instala Wails CLI y deps de sistema |
| `wails_provider_ts_ui` | Provider React para IPC cache |
| `use_wails_query_ts_ui` | Hook de ejemplo en App.tsx |
| `mantine_provider_ts_ui` | Provider Mantine |
| `wails_bind_crud_go_infra` | Genera bindings CRUD si `--with-db` |

**Flags opcionales:**

| Flag | Efecto |
|------|--------|
| `--with-db` | Anade SQLite con migrations, bindings CRUD generados por `wails_bind_crud_go_infra` |

---

### Pipeline 4: `init_cli_app`

Scaffold de Go CLI app con subcomandos y componentes TUI de Bubbletea.

**Uso:**

```bash
fn run init_cli_app my_cli
fn run init_cli_app my_cli --with-tui
```

**Archivos generados:**

```
apps/{nombre}/
├── main.go              — Entry point con subcommand routing (os.Args)
├── cmd_version.go       — Subcomando: version
├── cmd_status.go        — Subcomando de ejemplo: status (imprime info)
├── app.md               — framework vacio (CLI puro) o bubbletea (con --with-tui)
├── Makefile             — Targets: build, run, install, test, clean
├── .gitignore
└── go.mod
```

**Con `--with-tui`:**

```
apps/{nombre}/
├── main.go              — Entry point con run_fullscreen o run_model
├── model.go             — BaseModel + Update + View con tema oscuro
├── cmd_version.go       — Subcomando no-TUI
├── app.md               — framework: bubbletea
├── Makefile
├── .gitignore
└── go.mod
```

**Funciones del registry compuestas:**

| Funcion | Para que |
|---------|---------|
| `assert_command_exists_bash_shell` | Verificar Go |
| `new_base_model_go_tui` | Modelo base en model.go |
| `dark_styles_go_tui` | Tema oscuro por defecto |
| `run_fullscreen_go_tui` | Arranque fullscreen en main.go |
| `new_spinner_go_tui` | Componente de ejemplo |
| `new_filtered_list_go_tui` | Componente de ejemplo |

**main.go generado (sin TUI):**

```go
package main

import (
    "fmt"
    "os"
)

var version = "dev"

func main() {
    if len(os.Args) < 2 {
        printUsage()
        os.Exit(1)
    }

    switch os.Args[1] {
    case "version":
        cmdVersion()
    case "status":
        cmdStatus()
    default:
        fmt.Fprintf(os.Stderr, "unknown command: %s\n", os.Args[1])
        printUsage()
        os.Exit(1)
    }
}

func printUsage() {
    fmt.Println("Usage: {nombre} <command>")
    fmt.Println()
    fmt.Println("Commands:")
    fmt.Println("  version   Print version")
    fmt.Println("  status    Show status")
}
```

---

## Tareas

### Fase 1: `init_api_app` (pipeline base)

- [ ] **1.1** Crear `bash/functions/pipelines/init_api_app.sh` con source de funciones atomicas, parseo de argumentos, y generacion de estructura
- [ ] **1.2** Escribir heredocs para `main.go`, `handlers.go`, `config.go` que importen funciones de 0009 y 0015
- [ ] **1.3** Generar `app.md` con frontmatter correcto (tag `service`, `uses_functions` con IDs reales, `dir_path`)
- [ ] **1.4** Generar `Makefile`, `.env.example`, `.gitignore`, `migrations/001_initial.sql`
- [ ] **1.5** Flag `--with-auth`: anadir imports de 0010, handlers de login/register, tabla users en migration
- [ ] **1.6** Flag `--with-db`: anadir `store.go` con helpers CRUD, setup de SQLite al arrancar
- [ ] **1.7** Ejecutar `go vet -tags fts5` al final como verificacion
- [ ] **1.8** Crear `init_api_app.md` con frontmatter de pipeline

### Fase 2: `init_web_app` (extiende init_api_app)

- [ ] **2.1** Crear `bash/functions/pipelines/init_web_app.sh` que primero invoca la logica de `init_api_app` y luego anade el frontend
- [ ] **2.2** Generar `frontend/` con `package.json` (pnpm, vite, react, mantine, @fn_library alias)
- [ ] **2.3** Generar `vite.config.ts` con proxy al backend y alias `@fn_library`
- [ ] **2.4** Generar `src/main.tsx` con `FnMantineProvider`, `src/App.tsx` con `AppShell`, `src/pages/Home.tsx` con ejemplo
- [ ] **2.5** Generar `docker-compose.yml` para desarrollo
- [ ] **2.6** Actualizar `main.go` para servir static files del frontend build
- [ ] **2.7** Ejecutar `pnpm install && pnpm build` como verificacion del frontend
- [ ] **2.8** Crear `init_web_app.md` con frontmatter de pipeline

### Fase 3: `init_desktop_app`

- [ ] **3.1** Crear `bash/functions/pipelines/init_desktop_app.sh` que invoca `scaffold_wails_app_go_infra` y anade frontend React
- [ ] **3.2** Verificar/instalar Wails con `install_wails_bash_infra`
- [ ] **3.3** Generar frontend con `WailsProvider` + `FnMantineProvider` y ejemplo con `useWailsQuery`
- [ ] **3.4** Flag `--with-db`: invocar `wails_bind_crud_go_infra` para generar bindings
- [ ] **3.5** Ejecutar `wails build` como verificacion
- [ ] **3.6** Crear `init_desktop_app.md` con frontmatter de pipeline

### Fase 4: `init_cli_app`

- [ ] **4.1** Crear `bash/functions/pipelines/init_cli_app.sh` con generacion de estructura CLI basica
- [ ] **4.2** Generar `main.go` con routing de subcomandos, `cmd_version.go`, `cmd_status.go`
- [ ] **4.3** Flag `--with-tui`: generar `model.go` con `new_base_model`, `dark_styles`, `run_fullscreen`
- [ ] **4.4** Ejecutar `go vet` como verificacion
- [ ] **4.5** Crear `init_cli_app.md` con frontmatter de pipeline

### Fase 5: Integracion

- [ ] **5.1** `fn index` y verificar que los 4 pipelines aparecen en registry.db con kind=pipeline, purity=impure
- [ ] **5.2** Verificar `fn run init_api_app test_app` end-to-end: genera, compila, limpia
- [ ] **5.3** Verificar `fn run init_web_app test_web` end-to-end
- [ ] **5.4** Verificar `fn run init_desktop_app test_desktop` end-to-end
- [ ] **5.5** Verificar `fn run init_cli_app test_cli` end-to-end

### Fase 6: Documentacion de uso rapido

Cada pipeline debe ser usable sin leer el issue completo. La documentacion va en dos niveles: el `.md` de cada funcion (fuente de verdad para `fn show`) y una guia consolidada.

- [ ] **6.1** En cada `.md` de pipeline (`init_api_app.md`, etc.) documentar en la seccion `documentation` del frontmatter:
  - Sinopsis: `fn run init_api_app <nombre> [--port N] [--with-auth] [--with-db]`
  - Descripcion de cada flag y su efecto concreto (que archivos anade, que imports genera)
  - Listado de archivos generados con una linea de descripcion cada uno
  - Post-setup: que comandos ejecutar despues (`make run`, `make dev`, `wails dev`, etc.)
  - Ejemplo rapido: un bloque copy-paste de 3-4 lineas que crea la app y la arranca
- [ ] **6.2** En el campo `params` del frontmatter de cada pipeline, documentar cada argumento y flag con `name` y `desc` semantico para que `fn check params` pase y la info sea buscable via FTS5
- [ ] **6.3** En el campo `example` del frontmatter, poner el caso de uso mas comun (una linea):
  - `init_api_app`: `fn run init_api_app my_service --with-db`
  - `init_web_app`: `fn run init_web_app my_dashboard --with-auth`
  - `init_desktop_app`: `fn run init_desktop_app my_tool`
  - `init_cli_app`: `fn run init_cli_app my_cli --with-tui`
- [ ] **6.4** Crear `docs/init-pipelines.md` como guia consolidada de referencia rapida con:
  - Tabla resumen de los 4 pipelines (nombre, que genera, flags disponibles)
  - Arbol de decision: "quiero una API" → init_api_app, "quiero frontend" → init_web_app, "quiero desktop" → init_desktop_app, "quiero CLI" → init_cli_app
  - Seccion de combinaciones comunes (API + auth + DB, web dashboard, desktop con SQLite, CLI con TUI)
  - FAQ: como anadir auth despues, como cambiar el puerto, como anadir operations.db, como agregar mas paginas al frontend
- [ ] **6.5** Verificar que `fn show init_api_app_bash_pipelines` (y los otros 3) muestra la documentacion completa con params, ejemplo y notas de uso

---

## Ejemplo de uso

```bash
# API service con auth y database
fn run init_api_app billing_api --port 8090 --with-auth --with-db
cd apps/billing_api
make run
# → starting billing_api on :8090
# → curl localhost:8090/health → {"status":"ok"}

# Full-stack dashboard
fn run init_web_app inventory_dashboard --with-auth
cd apps/inventory_dashboard
make dev
# → API en :8080, frontend en :5173 con proxy

# Desktop app con base de datos
fn run init_desktop_app data_explorer --with-db
cd apps/data_explorer
wails dev
# → App de escritorio con React + SQLite

# CLI con TUI
fn run init_cli_app deploy_helper --with-tui
cd apps/deploy_helper
make run -- status
# → TUI fullscreen con lista filtrable
```

**Cada pipeline genera su `app.md` listo para `fn index`:**

```yaml
---
name: billing_api
lang: go
domain: tools
description: "API de facturacion."
tags: [service]
uses_functions:
  - http_serve_go_infra
  - http_router_go_infra
  - http_middleware_chain_go_infra
  - http_cors_middleware_go_infra
  - http_logger_middleware_go_infra
  - http_json_response_go_infra
  - http_error_response_go_infra
  - migration_up_go_infra
uses_types: []
framework: "net/http"
entry_point: "main.go"
dir_path: "apps/billing_api"
---
```

---

## Decisiones de diseno

- **Bash, no Go:** los init pipelines generan archivos con heredocs — bash es el lenguaje natural para esto. Go seria overengineering para scaffolding de texto. Coherente con `init_jupyter_analysis` y los demas init existentes.
- **Composicion sobre monolito:** cada pipeline sourcea funciones atomicas del registry (`assert_command_exists`, `scaffold_wails_app`, etc.) en vez de reimplementar. Si una funcion atomica mejora, todos los pipelines se benefician.
- **init_web_app extiende init_api_app:** el pipeline web reutiliza la logica del API (misma estructura backend) y anade la capa frontend encima. No duplica codigo.
- **Verificacion al final:** cada pipeline termina con `go vet`, `pnpm build`, o `wails build` para garantizar que el scaffold compila. Si falla, el pipeline reporta el error antes de declarar exito.
- **Flags opcionales con defaults sensatos:** el caso base (sin flags) genera una app funcional minima. `--with-auth`, `--with-db`, `--with-tui` anaden capas incrementales. El usuario no necesita decidir todo upfront.
- **@fn_library como alias, no copia:** el frontend generado referencia `@fn_library` via alias en `vite.config.ts` apuntando a `frontend/functions/ui/` del registry. Los componentes se comparten, no se duplican.
- **app.md generado automaticamente:** el frontmatter incluye `uses_functions` con los IDs reales de las funciones que el boilerplate importa. `fn index` los valida al registrar la app.
- **Sin framework CLI externo para init_cli_app:** routing de subcomandos con `os.Args` y switch — consistente con las apps existentes del registry que no usan cobra/urfave. Para TUI se usa Bubbletea que ya esta en el registry.

## Riesgos

- **Dependencias no implementadas:** los tres issues de dependencia (0009, 0010, 0015) estan pendientes. Si alguna funcion cambia de firma durante su implementacion, los heredocs de los pipelines necesitaran ajuste. **Mitigacion:** implementar los pipelines despues de que las dependencias esten merged, o mantener los heredocs parametricos para absorber cambios menores.
- **Heredocs fragiles:** generar Go/TS/YAML con heredocs bash es propenso a errores de indentacion, escape de variables y quoting. **Mitigacion:** cada pipeline incluye verificacion final (`go vet` / `pnpm build`) que detecta errores de sintaxis inmediatamente. Tests end-to-end en fase 5.
- **Frontend desactualizado respecto a @fn_library:** si los componentes de `frontend/functions/ui/` evolucionan, el boilerplate generado puede quedar desactualizado. **Mitigacion:** el boilerplate es minimo (un Provider, un AppShell, una pagina de ejemplo) — el usuario lo extiende con los componentes actuales del registry.
- **Wails como dependencia de sistema:** `init_desktop_app` requiere GTK3 + WebKit2GTK instalados en Linux. `install_wails_bash_infra` lo maneja, pero puede fallar en distros no soportadas. **Mitigacion:** el pipeline verifica la instalacion al inicio y falla rapido con mensaje descriptivo.
- **Colision de nombres:** si el usuario elige un nombre que ya existe en `apps/`, el pipeline sobreescribiria archivos. **Mitigacion:** verificar si `apps/{nombre}/` existe al inicio y abortar con error si ya existe.
