Loading...
Loading...
Bootstrap a Bun workspaces monorepo — Elysia API (one file per route group), Vite/React/Tailwind v4 web with coss UI as the base component library and lucide-react icons, Drizzle/Postgres db package, per-workspace zod-validated config/env.ts, shared zod schemas validated at both ends, shared pino logger with request correlation, Better Auth, centralized useRoutes.ts, React context-module vs hook conventions, SPA SEO via Cloudflare Worker + API share.html, bun:test, mandatory code-comment spec (file headers, doc comments, TODO/ASSUMPTION/CONFIRM tags), ESLint flat + Prettier, one-command `bun run check`, dev.sh multi-port stack, Conductor settings.toml. Use when asked to scaffold/start a new Bun monorepo, add a workspace/route/context to one, fix SPA social cards, or set up this stack.
npx skill4agent add aufacicenta/bun-workspace-bootstrap-skill bun-monorepo-bootstrapapps/*packages/*exports<root>/
├── package.json # workspaces + aggregate scripts
├── eslint.config.js # flat config, root-only
├── prettier.config.js # root-only
├── .prettierignore .gitignore .env.example
├── dev.sh # full local stack, port-derived
├── .conductor/settings.toml
├── .vscode/{settings,extensions}.json
├── AGENTS.md CLAUDE.md README.md
├── apps/
│ ├── api/ # Bun + Elysia modular monolith, exports `type App`
│ ├── web/ # Vite + React + Tailwind v4 + coss UI + lucide-react
│ └── worker/ # Bun long-running loop (indexer/outbox/cron)
├── packages/
│ ├── shared/ # zod schemas, env schema+loader, logger, pure domain logic
│ └── db/ # drizzle schema, migrations, seed/backfill scripts
├── edge-worker/ # optional; Cloudflare Worker, NOT a workspace (own lockfile)
└── docs/{adr,runbooks}/src/config/env.tsprocess.envpackages/dbsharedsharedreferences/frontend-patterns.mduseRoutes.tslib/api/*references/code-comments.mdTODOASSUMPTIONCONFIRMFIXMEreferences/seo-edge-worker.mdindex.html<Seo>share.htmlog-image.pngpackage.json@<proj>check{
"name": "@<proj>/root",
"private": true,
"type": "module",
"workspaces": ["apps/*", "packages/*"],
"scripts": {
"lint": "bun run --workspaces lint:fix",
"eslint": "bun run --workspaces lint",
"format": "bun run --workspaces format",
"format:check": "bun run --workspaces format:check",
"typecheck": "bun run --workspaces typecheck",
"test": "bun run --filter '@<proj>/shared' --filter '@<proj>/api' test",
"check": "F=0; bun run lint || F=1; bun run format || F=1; bun run typecheck || F=1; bun run test || F=1; exit $F",
"db:generate": "bun run --filter '@<proj>/db' db:generate",
"db:migrate": "bun run --filter '@<proj>/db' db:migrate",
"dev:api": "bun run --filter '@<proj>/api' dev",
"dev:web": "bun run --filter '@<proj>/web' dev"
},
"devDependencies": {
"@eslint/js": "latest",
"@types/bun": "latest",
"eslint": "latest",
"eslint-config-prettier": "latest",
"eslint-plugin-react-hooks": "latest",
"eslint-plugin-simple-import-sort": "latest",
"eslint-plugin-unused-imports": "latest",
"globals": "latest",
"prettier": "latest",
"prettier-plugin-tailwindcss": "latest",
"typescript": "latest",
"typescript-eslint": "latest"
}
}bun run --workspaces <s><s>lintlint:fixformatformat:checktypechecktest--filter--workspaces"@<proj>/shared": "workspace:*"eslint.config.jsimport eslint from "@eslint/js";
import eslintConfigPrettier from "eslint-config-prettier";
import reactHooks from "eslint-plugin-react-hooks";
import simpleImportSort from "eslint-plugin-simple-import-sort";
import unusedImports from "eslint-plugin-unused-imports";
import globals from "globals";
import tseslint from "typescript-eslint";
export default tseslint.config(
{ ignores: ["**/node_modules/**", "**/dist/**", "**/coverage/**", "apps/web/public/**"] },
eslint.configs.recommended,
...tseslint.configs.recommended,
eslintConfigPrettier,
{
rules: {
"padding-line-between-statements": [
"error",
{ blankLine: "always", prev: "*", next: "return" },
],
},
},
{
files: ["apps/**/*.{ts,tsx}", "packages/**/*.ts"],
plugins: { "simple-import-sort": simpleImportSort, "unused-imports": unusedImports },
rules: {
"simple-import-sort/imports": "error",
"simple-import-sort/exports": "error",
"@typescript-eslint/no-unused-vars": "off",
"unused-imports/no-unused-imports": "error",
"unused-imports/no-unused-vars": [
"warn",
{ vars: "all", varsIgnorePattern: "^_", args: "after-used", argsIgnorePattern: "^_" },
],
"@typescript-eslint/ban-ts-comment": [
"error",
{ "ts-nocheck": "allow-with-description", minimumDescriptionLength: 10 },
],
},
},
{
files: ["apps/**/*.{ts,tsx}", "packages/**/*.ts"],
// The shared logger is the only sanctioned writer (§4).
ignores: ["packages/shared/src/logger/browser.ts"],
rules: { "no-console": "error" },
},
{
files: ["apps/api/**/*.ts", "apps/worker/**/*.ts", "packages/**/*.ts"],
languageOptions: { globals: { ...globals.node, ...globals.es2021, Bun: "readonly" } },
},
{
files: ["apps/web/**/*.{ts,tsx}"],
plugins: { "react-hooks": reactHooks },
rules: { ...reactHooks.configs["recommended-latest"].rules },
languageOptions: { globals: { ...globals.browser, ...globals.es2021 } },
},
);prettier.config.jstailwindStylesheet/** @type {import("prettier").Config} */
export default {
semi: true,
singleQuote: false,
trailingComma: "all",
printWidth: 100,
tabWidth: 2,
plugins: ["prettier-plugin-tailwindcss"],
tailwindStylesheet: "./apps/web/src/styles.css",
};.prettierignorenode_modulesdistoutcoverage.git**/bun.lock*.min.js**/*.md.gitignore.env.localdb/.env.local.envnode_modules
.eslintcache
.DS_Store
dist
out
coverage
# Secrets: deny all, re-allow templates only.
.env
.env.*
**/.env
**/.env.*
!.env.example
!**/.env.example
.dev.vars
**/.dev.vars
# Agent/tooling scratch space — may hold pasted credentials or customer data.
.context/.vscode/settings.jsoneditor.formatOnSaveesbenp.prettier-vscodeeditor.codeActionsOnSave: {"source.fixAll.eslint": "explicit"}eslint.useFlatConfig: trueprettier.requireConfig: true.vscode/extensions.jsondbaeumer.vscode-eslintesbenp.prettier-vscodetsconfig.base.jsontsc --noEmitpackage.jsonexportspathsapps/apiapps/workerpackages/*{
"compilerOptions": {
"lib": ["ESNext"],
"target": "ESNext",
"module": "Preserve",
"moduleDetection": "force",
"types": ["bun"],
"moduleResolution": "bundler",
"allowImportingTsExtensions": true,
"verbatimModuleSyntax": true,
"noEmit": true,
"strict": true,
"skipLibCheck": true,
"noFallthroughCasesInSwitch": true,
"noUncheckedIndexedAccess": true,
"noImplicitOverride": true
},
"include": ["src/**/*.ts"]
}"lib": ["ESNext", "DOM", "DOM.Iterable"]"jsx": "react-jsx""types": ["bun", "react", "react-dom"]"include"src/**/*.tsxvite.config.tspackages/dbdrizzle.config.tsincludepackage.json@<proj>/sharedprivate"type": "module"exports@<proj>/shared/configzoddotenv"exports": {
".": "./src/index.ts",
"./config": "./src/config/index.ts",
"./logger": {
"browser": "./src/logger/browser.ts",
"default": "./src/logger/server.ts"
},
"./schemas": "./src/schemas/index.ts"
}src/config/load-env-files.tsimport fs from "node:fs";
import path from "node:path";
import { parse as parseDotenv } from "dotenv";
const stripExportPrefixes = (raw: string) => raw.replace(/^\s*export\s+/gm, "");
const loadEnvFile = (filePath: string): void => {
if (!fs.existsSync(filePath)) return;
const parsed = parseDotenv(stripExportPrefixes(fs.readFileSync(filePath, "utf8")));
for (const [key, value] of Object.entries(parsed)) {
if (process.env[key] === undefined) process.env[key] = value;
}
};
export const loadEnvFiles = (paths: string[]): void => {
for (const filePath of paths) loadEnvFile(filePath);
};stripExportPrefixes.env.prodsourceexport src/config/env.tssrc/config/env.tsprocess.envsafeParseenv{ env }apps/api/src/config/env.ts apiEnvSchema -> export const env
apps/worker/src/config/env.ts workerEnvSchema -> export const env (+ config)
packages/db/src/config/env.ts dbEnvSchema -> export const env
packages/shared/src/config/env-schema.ts -> shared slice, no parse
apps/web/src/config/index.ts import.meta.env -> export const config
packages/db/drizzle.config.ts own loader -> runs outside the appprocess.envimport.meta.dirimport path from "node:path";
import { loadEnvFiles, sharedEnvSchema } from "@<proj>/shared/config";
import { z } from "zod";
const appDir = path.resolve(import.meta.dir, "..", "..");
const rootDir = path.resolve(appDir, "..", "..");
loadEnvFiles([
path.join(appDir, ".env.local"),
path.join(appDir, ".env"),
path.join(rootDir, ".env.local"),
path.join(rootDir, ".env"),
]);
const apiEnvSchema = sharedEnvSchema.extend({
NODE_ENV: z.string().default("development"),
PORT: z.coerce.number().int().positive().default(4000),
HOST: z.string().min(1).default("0.0.0.0"),
DATABASE_URL: z.string().min(1),
BETTER_AUTH_SECRET: z.string().min(1),
/** Public SPA origin. No trailing slash — normalized here, not at call sites. */
CORS_ORIGIN: z
.string()
.min(1)
.default("http://localhost:5174")
.transform((v) => v.replace(/^["']+|["']+$/g, "").trim().replace(/\/+$/, "")),
});
const parsed = apiEnvSchema.safeParse(process.env);
if (!parsed.success) {
const details = parsed.error.issues
.map((issue) => `${issue.path.join(".") || "(root)"}: ${issue.message}`)
.join("; ");
throw new Error(`Invalid API environment configuration: ${details}`);
}
export const env = parsed.data;process.env.X!?? "default"packages/shared/src/config/env-schema.ts.extend()z.coerce.number().transform((v) => v === "true")Set.env.localundefined.min(1)const optionalSecret = z
.string()
.trim()
.transform((v) => (v.length > 0 ? v : undefined))
.optional();.env.exampleconfigenvconfigconfiglogger.info({ config })import.meta.envapps/web/src/config/as constVITE_*import.meta.envdrizzle.config.tssrc/schemas/api/*.tssrc/schemas/index.tsexport const publicFightersQuerySchema = z.object({
sort: z.enum(["latest", "wins", "rating"]).optional(),
limit: z.coerce.number().int().min(1).max(100).default(30),
});
export type PublicFightersQuery = z.infer<typeof publicFightersQuerySchema>;
export const publicFightersResponseSchema = z.object({ fighters: z.array(publicFighterSchema) });
export type PublicFightersResponse = z.infer<typeof publicFightersResponseSchema>;<resource><Verb>RequestSchema<resource><Verb>ResponseSchema<resource>QuerySchemapackages/shared/src/schemas/| Where | How |
|---|---|
| Elysia |
| |
| tests | build fixtures from the same schema, so a contract change breaks tests, not production |
.parse()undefinedas Responsepackages/sharedbun run checksharedpinoconsoleno-consolesharedpinopino-prettysrc/logger/types.tsexport type LogFields = Record<string, unknown>;
export interface Logger {
trace(fields: LogFields, msg?: string): void;
debug(fields: LogFields, msg?: string): void;
info(fields: LogFields, msg?: string): void;
warn(fields: LogFields, msg?: string): void;
error(fields: LogFields, msg?: string): void;
child(bindings: LogFields): Logger;
}src/logger/server.tsimport pino from "pino";
import type { Logger } from "./types";
// Reads the shared env slice — the logger is a config consumer like any other
// module, it never touches process.env itself (§3).
import { env } from "../config";
export const logger: Logger = pino({
level: env.LOG_LEVEL,
base: { service: env.SERVICE_NAME, env: env.NODE_ENV },
// Redaction is structural, not per-call-site: assume someone will eventually
// log a whole request or config object, and make that safe in advance.
redact: {
paths: [
"req.headers.authorization",
"req.headers.cookie",
"*.password",
"*.token",
"*.secret",
"*.privateKey",
],
censor: "[redacted]",
},
// Prod emits raw NDJSON for the collector; dev gets a human transport.
transport:
env.NODE_ENV === "development"
? { target: "pino-pretty", options: { colorize: true, translateTime: "HH:MM:ss" } }
: undefined,
});src/logger/browser.tsimport type { Logger, LogFields } from "./types";
// Dev: everything. Prod: warn and error only.
const MIN_LEVEL = import.meta.env?.DEV ? 0 : 3;
const make = (bindings: LogFields): Logger => {
const emit =
(level: number, method: "debug" | "info" | "warn" | "error") =>
(fields: LogFields, msg?: string) => {
if (level < MIN_LEVEL) return;
// eslint-disable-next-line no-console -- the single sanctioned console writer
console[method](msg ?? "", { ...bindings, ...fields });
};
return {
trace: emit(0, "debug"),
debug: emit(1, "debug"),
info: emit(2, "info"),
warn: emit(3, "warn"),
error: emit(4, "error"),
child: (extra) => make({ ...bindings, ...extra }),
};
};
export const logger = make({});src/logger/index.ts./types./serverexportspackages/shared/package.json"./logger": {
"browser": "./src/logger/browser.ts",
"default": "./src/logger/server.ts"
}src/config/env-schema.tsLOG_LEVEL: z.enum(["trace", "debug", "info", "warn", "error"]).default("info"),
SERVICE_NAME: z.string().min(1).default("api"), // shows up as `service` on every lineconsole.log// apps/api/src/plugins/logging.ts
import { Elysia } from "elysia";
import { logger } from "@<proj>/shared/logger";
export const loggingPlugin = new Elysia({ name: "logging" })
.derive({ as: "global" }, ({ request, set }) => {
// Honour an inbound id so a trace survives across services; echo it back so
// a user can quote it in a bug report and land on the exact request.
const requestId = request.headers.get("x-request-id") ?? crypto.randomUUID();
set.headers["x-request-id"] = requestId;
return {
log: logger.child({
requestId,
method: request.method,
path: new URL(request.url).pathname,
}),
};
})
.onAfterResponse({ as: "global" }, ({ log, set }) => {
log.info({ status: set.status }, "request");
})
.onError({ as: "global" }, ({ log, code, error }) => {
log.error(
{ code, err: error instanceof Error ? { message: error.message, stack: error.stack } : error },
"unhandled",
);
});src/index.tscors{ log }apps/workerlogger.child({ job, runId })log.info({ userId }, "username claimed")log.errorerrError{}configno-consoleeslint.config.js{
files: ["apps/**/*.{ts,tsx}", "packages/**/*.ts"],
ignores: ["packages/shared/src/logger/browser.ts"],
rules: { "no-console": "error" },
},drizzle-orm@neondatabase/serverlesspostgres@<proj>/shareddrizzle-kit"scripts": {
"db:generate": "drizzle-kit generate",
"db:migrate": "drizzle-kit migrate",
"db:push": "drizzle-kit push",
"db:studio": "drizzle-kit studio"
}drizzle.config.tsexport default defineConfig({
out: "./drizzle",
schema: "./src/schema/index.ts",
dialect: "postgresql",
dbCredentials: { url: env.DATABASE_URL },
verbose: true,
strict: true,
});src/schema/<table>.tssrc/schema/index.tsexport *src/db.tsdrizzle({ client: pool, schema })dbexport type Database = typeof dbsrc/index.tsdbDatabaseexport * from "./schema"and, eq, desc, sql, …drizzle-ormbun run db:generatedrizzle/*.sqlmeta/drizzle-kit migrate55P04src/migrate.tsdrizzle.__drizzle_migrationsdb:migrate:safeelysia@elysiajs/corsbetter-authjose@<proj>/db@<proj>/shared"dev": "bun --watch src/index.ts""start": "bun src/index.ts""test": "bun test"src/routes/Elysiaprefixsrc/index.ts.use()src/routes/
├── public/ # unauthenticated; one file per resource
│ ├── config.ts # publicConfigRoutes — prefix "/public"
│ └── fighters.ts # publicFighterRoutes — prefix "/public/fighters"
├── users/index.ts # userRoutes — prefix "/users"
├── wallet/index.ts # walletRoutes — prefix "/wallet"
└── internal/wallet.ts # service-to-service, separate authroutes/<group>.tsroutes/<group>/index.tsprefixapiRoutesbodyqueryresponseexport const publicConfigRoutes = new Elysia({ prefix: "/public" }).get(
"/config",
() => ({ feeBps: getFeeBps() }) satisfies PublicConfigResponse,
{ response: { 200: publicConfigResponseSchema } },
);
export const userRoutes = new Elysia({ prefix: "/users" }).post(
"/me/username",
async ({ body }) => await claimUsername(body.username),
{ body: claimUsernameRequestSchema, response: { 200: userProfileResponseSchema } },
);responsebodyquerysatisfies <InferredType>src/index.tsexport type App = typeof appconst guarded = new Elysia({ name: "guarded-http" }).use(userRoutes).use(walletRoutes);
const app = new Elysia()
.use(loggingPlugin)
.use(cors({ origin: (req) => req.headers.get("Origin")?.replace(/\/+$/, "") === env.CORS_ORIGIN }))
.get("/health", () => ({ ok: true }))
.use(authRoutes)
.use(publicRoutes)
.use(guarded);
app.listen({ port: env.PORT, hostname: env.HOST });
export type App = typeof app;src/{routes,lib,plugins,config,ws}/lib/bun:test.all("/api/auth/*", ({ request }) => auth.handler(request))josereferences/frontend-patterns.mdreactreact-domreact-router-domtailwindcss@tailwindcss/vitebetter-auth@<proj>/sharedvite@vitejs/plugin-react@types/react{,-dom}apps/web/src/
├── main.tsx # global providers wrap <RouterProvider>
├── router.tsx # route tree; guards compose here
├── styles.css # @import "tailwindcss"; + @theme tokens
├── pages/ # one file per screen
├── components/ # app-specific composites only; primitives come from coss UI
├── context/<Name>/ # 4-file context modules (see reference)
├── hooks/ # useRoutes.ts + plain state hooks
├── lib/api/ # typed fetch wrappers + client.ts token holder
└── config/ # import.meta.env reads, in one placetailwind.config.js@import "tailwindcss";src/styles.css@theme { }export default defineConfig(({ mode }) => {
const env = loadEnv(mode, __dirname, "");
const apiTarget = env.VITE_API_PROXY_TARGET ?? env.VITE_API_URL ?? "http://localhost:4000";
return {
plugins: [react(), tailwindcss()],
server: {
port: 5174,
proxy: {
"/health": { target: apiTarget, changeOrigin: true },
"/ws": { target: apiTarget, ws: true, changeOrigin: true },
},
},
};
});/users/users/newsrc/components/bunx --bun skills add cosscom/coss<Button>@themesrc/styles.csssrc/components/ui/lucide-react<svg>bun add lucide-react --cwd apps/webimport { Check, ChevronDown } from "lucide-react"import * as IconsclassName="size-4 text-muted-foreground"sizecolor@themearia-hidden="true"<svg>lucide-reactsrc/components/ui/icons/classNameflexflex-colgap-*flex-wrapgridgridflex items-center justify-centergap-*src/hooks/useRoutes.tsroutesapiRouteswsRoutesAPI_BASEWS_BASEimport.meta.env.VITE_API_URLencodeURIComponentapiRouteslib/api/*.tsVITE_src/hooks/XContext.tsxXContext.types.tsXContextController.tsxuseXContext.tsxmain.tsxbetter-auth/reactAuthContextControllerlib/api/client.tsRequireAuthRequireVerifiedEmailRequireHandlereferences/frontend-patterns.mdindex.html<head>og:imageog:url<Seo>noindexedge-worker/share.htmlreturn fetch(request)og-image.pngpackages/sharedbun.lock@cloudflare/workers-typesbunbun run checkshare.htmlwrangler.tomlreferences/seo-edge-worker.md"dev": "bun --watch src/index.ts"src/config/env.tsconfigenv--watchCONDUCTOR_PORTchmod +x dev.sh#!/usr/bin/env bash
set -euo pipefail
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
cd "$ROOT"
if [[ -f "$ROOT/.env.local" ]]; then
echo "==> Loading env from .env.local"
set -a
# shellcheck disable=SC1091
source "$ROOT/.env.local"
set +a
fi
# Production-DB interlock: this script starts the worker, which performs real
# side effects with no leader election. A shell that sourced .env.prod for a
# migration still exports the prod DATABASE_URL. Compare hosts, refuse on match.
db_host_of() { printf '%s' "$1" | sed -E 's#^[a-z+]+://([^@]*@)?([^:/?]+).*#\2#'; }
if [[ -n "${DATABASE_URL:-}" && -f "$ROOT/.env.prod" && "${ALLOW_PROD_DB:-}" != "1" ]]; then
prod_url="$(grep -E '^[[:space:]]*(export[[:space:]]+)?DATABASE_URL=' "$ROOT/.env.prod" |
tail -1 | sed -E 's#^[^=]*=##; s#^"##; s#"$##')"
if [[ -n "$prod_url" && "$(db_host_of "$DATABASE_URL")" == "$(db_host_of "$prod_url")" ]]; then
echo "ERROR: dev.sh refuses to run against the PRODUCTION database." >&2
echo " Open a clean shell. Override: ALLOW_PROD_DB=1 ./dev.sh" >&2
exit 1
fi
fi
BASE_PORT="${CONDUCTOR_PORT:-5174}"
WEB_PORT="$BASE_PORT"
API_PORT="$((BASE_PORT + 1))"
export PORT="$API_PORT"
export VITE_API_URL="http://localhost:$API_PORT"
export VITE_API_PROXY_TARGET="http://localhost:$API_PORT"
export VITE_SITE_URL="http://localhost:$WEB_PORT"
export CORS_ORIGIN="http://localhost:$WEB_PORT"
pids=()
cleanup() { trap - INT TERM EXIT; kill "${pids[@]}" 2>/dev/null || true; }
trap cleanup INT TERM EXIT
echo "==> api on :$API_PORT"
bun run --filter '@<proj>/api' dev & pids+=($!)
echo "==> worker"
bun run --filter '@<proj>/worker' dev & pids+=($!)
echo "==> web on :$WEB_PORT"
bun run --filter '@<proj>/web' dev -- --port "$WEB_PORT" & pids+=($!)
# `wait -n` is unavailable in macOS's bundled bash 3.2 — poll instead.
while kill -0 "${pids[@]}" 2>/dev/null; do sleep 1; done"$schema" = "https://conductor.build/schemas/settings.repo.schema.json"
# Copy gitignored LOCAL env files into every new workspace.
# Never use a bare `.env*` glob: it also matches `.env.prod`, putting the
# production credential on disk in every workspace while `run` starts the worker.
file_include_globs = ".env.local\npackages/db/.env.local\n"
[scripts]
setup = "git -C \"$CONDUCTOR_ROOT_PATH\" fetch --prune origin && git -C \"$CONDUCTOR_ROOT_PATH\" pull --ff-only || true; bun install"
run = "./dev.sh"
run_mode = "concurrent"references/code-comments.md| Tag | Means |
|---|---|
| deferred work — say what it blocks or degrades |
| spec was silent — say what was assumed and what changes if it's wrong |
| needs a human decision — say the question and the current placeholder behaviour |
| known-wrong, shipped anyway — say why, and the correct shape |
// ASSUMPTION: fees are charged on the gross amount, not net of gas. The spec
// didn't say. If it's net, `feeBps` moves below the gas subtraction here and
// every stored fee row needs a backfill.TODO.mdASSUMPTIONCONFIRMCONFIRM:git grep -nE "TODO:|FIXME:|ASSUMPTION:|CONFIRM:"bun:testsrc/**/<unit>.test.tslib/import { describe, expect, test } from "bun:test";CLAUDE.mdAGENTS.mdbun run checkTODO:ASSUMPTION:CONFIRM:FIXME:bun run db:generateapps/api/src/routes/bodyqueryresponse@<proj>/shared/schemasuseRoutes.tslib/api/*fetch.parse()bunx --bun skills add cosscom/cosslucide-reactsrc/config/env.ts.env.exampleprocess.envimport.meta.envconsole.loglogger@<proj>/shared/logger{ log }flexflex-colgap-*grididmkdirgit initpackages/sharedpackages/dbapps/apiapps/webapps/workerbunx --bun skills add cosscom/cossapps/webapps/apibunx @better-auth/cli generatepackages/db/src/schema/auth.tsschema/index.ts.env.example.env.localbun installbun run --filter '@<proj>/db' db:generate && db:migratebun run checkgit grep -nE "TODO:|FIXME:|ASSUMPTION:|CONFIRM:"CONFIRM: