From f3b8a84539d852c81edbbe195e88137694ece86a Mon Sep 17 00:00:00 2001 From: francy51 Date: Sat, 21 Mar 2026 13:04:40 -0400 Subject: [PATCH] Remaining commit items --- .dockerignore | 11 ++++++ doc/deployment-benchmark-and-coolify.md | 52 +++++++++++++++++++++++++ drizzle/0012_crazy_molecule_man.sql | 17 +------- next-env.d.ts | 2 +- 4 files changed, 65 insertions(+), 17 deletions(-) create mode 100644 doc/deployment-benchmark-and-coolify.md diff --git a/.dockerignore b/.dockerignore index f4719a3..dd6325c 100644 --- a/.dockerignore +++ b/.dockerignore @@ -3,6 +3,7 @@ .cache .swc .workflow-data +rust/target # Dependencies node_modules @@ -21,12 +22,22 @@ data .git .gitignore .gitea +.github +.claude # Test and local tooling artifacts .playwright-cli e2e output +test +playwright.config.ts +vitest.config.mts +*.test.ts # Docs and generated metadata README.md +agents.md +E2E_UX_REPORT_*.md +doc +docs tsconfig.tsbuildinfo diff --git a/doc/deployment-benchmark-and-coolify.md b/doc/deployment-benchmark-and-coolify.md new file mode 100644 index 0000000..56a66d1 --- /dev/null +++ b/doc/deployment-benchmark-and-coolify.md @@ -0,0 +1,52 @@ +# Deployment Benchmark And Coolify Notes + +## Local build timings + +Measured on this workstation on 2026-03-21: + +- `bun run build` cold-ish run: `26.00s` wall time +- `bun run build` warm run: `20.68s` wall time +- Turbopack compile phase inside those runs: `8.8s` cold-ish, `7.8s` warm + +Observed repeated work on every build: + +- taxonomy generation +- workflow manifest generation +- TypeScript validation performed by Next during build +- static page generation + +## Docker attempt + +The local Docker daemon did not respond during validation. `docker build` and `docker info` both stalled until externally timed out, so the image could not be run end-to-end on this machine in this session. + +That means the application build was validated locally, but container execution still depends on a healthy Docker engine on the target host. + +## Changes made for deployment + +- Added a `prod-deps` stage so the runtime image uses production dependencies instead of the full development install. +- Bundled `scripts/bootstrap-production.ts` into `bootstrap-production.js` during image build so the runtime image no longer needs the full TypeScript source tree just to run startup bootstrap. +- Changed the runtime command to execute the bundled bootstrap directly and then `exec` the standalone Next server. +- Set `HOSTNAME=0.0.0.0` in the runtime image so direct Dockerfile-based deployments behave correctly without compose overrides. +- Reduced the Docker build context by excluding docs, tests, local metadata, and `rust/target`. + +## Coolify requirements + +This project is viable on Coolify if it is deployed as a multi-service Docker Compose stack, not as a single app without Postgres. + +Required runtime conditions: + +- single replica only +- persistent Docker volumes for `/app/data` and Postgres data +- `WORKFLOW_TARGET_WORLD=@workflow/world-postgres` +- `WORKFLOW_POSTGRES_URL=postgres://workflow:workflow@workflow-postgres:5432/workflow` +- `DATABASE_URL=file:/app/data/fiscal.sqlite` +- valid `BETTER_AUTH_SECRET` +- `BETTER_AUTH_BASE_URL` and `BETTER_AUTH_TRUSTED_ORIGINS` set to the final public Coolify URL + +## Highest-impact deployment optimizations + +1. Keep build cache warm on the same Coolify builder. The Dockerfile now benefits from Bun dependency cache mounts, a separate production dependency stage, and `.next/cache`. +2. Avoid invalidating image builds with non-runtime file changes. The updated `.dockerignore` keeps docs, tests, and local artifacts out of the build context. +3. Consider moving taxonomy generation out of the hot path if the data does not change on every deploy. It currently runs on every application build. +4. Consider splitting bootstrap responsibilities further if startup latency becomes a problem. Right now startup still performs workflow setup and SQLite migrations before the app binds its port. +5. If horizontal scaling is required later, move the app database off SQLite. Coolify can run this as-is, but only safely as a single-writer instance. diff --git a/drizzle/0012_crazy_molecule_man.sql b/drizzle/0012_crazy_molecule_man.sql index 84f8a4e..659bfe5 100644 --- a/drizzle/0012_crazy_molecule_man.sql +++ b/drizzle/0012_crazy_molecule_man.sql @@ -1,18 +1,3 @@ -CREATE TABLE `company_financial_bundle` ( - `id` integer PRIMARY KEY AUTOINCREMENT NOT NULL, - `ticker` text NOT NULL, - `surface_kind` text NOT NULL, - `cadence` text NOT NULL, - `bundle_version` integer NOT NULL, - `source_snapshot_ids` text NOT NULL, - `source_signature` text NOT NULL, - `payload` text NOT NULL, - `created_at` text NOT NULL, - `updated_at` text NOT NULL -); ---> statement-breakpoint -CREATE UNIQUE INDEX `company_financial_bundle_uidx` ON `company_financial_bundle` (`ticker`,`surface_kind`,`cadence`);--> statement-breakpoint -CREATE INDEX `company_financial_bundle_ticker_idx` ON `company_financial_bundle` (`ticker`,`updated_at`);--> statement-breakpoint CREATE TABLE `company_overview_cache` ( `id` integer PRIMARY KEY AUTOINCREMENT NOT NULL, `user_id` text NOT NULL, @@ -358,4 +343,4 @@ ALTER TABLE `watchlist_item` ADD `status` text DEFAULT 'backlog' NOT NULL;--> st ALTER TABLE `watchlist_item` ADD `priority` text DEFAULT 'medium' NOT NULL;--> statement-breakpoint ALTER TABLE `watchlist_item` ADD `updated_at` text NOT NULL;--> statement-breakpoint ALTER TABLE `watchlist_item` ADD `last_reviewed_at` text;--> statement-breakpoint -CREATE INDEX `watchlist_user_updated_idx` ON `watchlist_item` (`user_id`,`updated_at`); \ No newline at end of file +CREATE INDEX `watchlist_user_updated_idx` ON `watchlist_item` (`user_id`,`updated_at`); diff --git a/next-env.d.ts b/next-env.d.ts index c4b7818..9edff1c 100644 --- a/next-env.d.ts +++ b/next-env.d.ts @@ -1,6 +1,6 @@ /// /// -import "./.next/dev/types/routes.d.ts"; +import "./.next/types/routes.d.ts"; // NOTE: This file should not be edited // see https://nextjs.org/docs/app/api-reference/config/typescript for more information.