Mini Meish Appp #2
Conversation
- 9-page interactive dashboard (Home, Timeline, Report, Tasks, Attorneys, Cases, Contacts, Logbook, Finances) - Bond Timeline with 185-day PC 1305 deadline calculator - Attorney Tracker with status management - Complete 10-section legal defense report - 8 task scripts with copy-to-clipboard and checklists - Communication logbook with paper trail - Financial tracker with ledger entries - Cloudflare Worker API with D1 persistence + localStorage fallback - Dark theme, mobile-responsive, animated UI
- Vercel was trying to build as Next.js with pnpm (wrong) - This is a static site: no build, no install, serve public/ directly - vercel.json: framework=null, outputDirectory=public
There was a problem hiding this comment.
Pull request overview
This PR pivots the repo from a Next.js SaaS starter into the “mini-meish” dashboard, introducing Cloudflare Workers + D1 persistence, Vercel/Railway deployment configs, and Supabase-backed AI chat endpoints.
Changes:
- Add Cloudflare Worker API (
worker.js) with D1 schema/migrations (schema.sql) and Wrangler config (wrangler.toml). - Add Vercel + Railway/Docker runtime support (
vercel.json,server.js,railway.json,Dockerfile) and Vercel serverless handlers (api/chat.js,api/test.js). - Remove the prior Next.js/Drizzle/Stripe/auth codepaths and related configs.
Reviewed changes
Copilot reviewed 65 out of 75 changed files in this pull request and generated 16 comments.
Show a summary per file
| File | Description |
|---|---|
| wrangler.toml | Adds Cloudflare Worker + D1 + assets configuration. |
| worker.js | Implements Worker API endpoints for app state/logs/ledger/attorneys backed by D1. |
| vercel.json | Configures Vercel static output and serverless function settings. |
| setup-db.js | Adds a Supabase Management API script to create tables/policies. |
| server.js | Adds an Express server for Railway/Docker that serves public/ and reuses api/* handlers. |
| schema.sql | Adds SQLite/D1 schema for Worker persistence tables. |
| railway.json | Adds Railway deployment configuration (Dockerfile builder, healthcheck). |
| package.json | Replaces Next.js scripts/deps with Worker + Express-based scripts/deps. |
| deploy-loop.js | Adds a Vercel CLI deployment loop script with auto-fix routines. |
| api/test.js | Adds a diagnostic endpoint reporting env var presence. |
| api/chat.js | Adds a Supabase-persisted chat endpoint that calls Anthropic. |
| README.md | Updates documentation for new deployment/runtime modes and env vars. |
| RAILWAY_TOKEN=92cecc0e-295f-4304-b2.txt | Adds a Railway token file (sensitive). |
| Dockerfile | Adds Docker build/run for server.js. |
| CLOUDFLARE_API_TOKEN.txt | Adds a Cloudflare API token file (sensitive). |
| .gitignore | Replaces ignore patterns for the new toolchain/runtime artifacts. |
| .dockerignore | Adds Docker build context exclusions. |
| tsconfig.json | Removes TypeScript config (Next.js-era). |
| postcss.config.mjs | Removes Tailwind/PostCSS config (Next.js-era). |
| next.config.ts | Removes Next.js configuration. |
| middleware.ts | Removes Next.js auth middleware. |
| lib/utils.ts | Removes UI utility helper (Next.js-era). |
| lib/payments/stripe.ts | Removes Stripe integration. |
| lib/payments/actions.ts | Removes Stripe server actions. |
| lib/db/setup.ts | Removes Postgres/Stripe-oriented setup script. |
| lib/db/seed.ts | Removes Drizzle seed script. |
| lib/db/schema.ts | Removes Drizzle schema. |
| lib/db/queries.ts | Removes Drizzle queries. |
| lib/db/migrations/meta/_journal.json | Removes Drizzle migration metadata. |
| lib/db/migrations/meta/0000_snapshot.json | Removes Drizzle migration snapshot. |
| lib/db/migrations/0000_soft_the_anarchist.sql | Removes Drizzle SQL migration. |
| lib/db/drizzle.ts | Removes Drizzle Postgres client. |
| lib/auth/session.ts | Removes auth/session implementation. |
| lib/auth/middleware.ts | Removes auth helpers for server actions. |
| drizzle.config.ts | Removes Drizzle config. |
| components/ui/radio-group.tsx | Removes shadcn/ui component (Next.js-era). |
| components/ui/label.tsx | Removes shadcn/ui component (Next.js-era). |
| components/ui/input.tsx | Removes shadcn/ui component (Next.js-era). |
| components/ui/dropdown-menu.tsx | Removes shadcn/ui component (Next.js-era). |
| components/ui/card.tsx | Removes shadcn/ui component (Next.js-era). |
| components/ui/button.tsx | Removes shadcn/ui component (Next.js-era). |
| components/ui/avatar.tsx | Removes shadcn/ui component (Next.js-era). |
| components.json | Removes shadcn/ui configuration. |
| app/not-found.tsx | Removes Next.js app route. |
| app/layout.tsx | Removes Next.js root layout. |
| app/globals.css | Removes Tailwind global CSS. |
| app/api/user/route.ts | Removes Next.js API route. |
| app/api/team/route.ts | Removes Next.js API route. |
| app/api/stripe/webhook/route.ts | Removes Stripe webhook route. |
| app/api/stripe/checkout/route.ts | Removes Stripe checkout route. |
| app/(login)/sign-up/page.tsx | Removes Next.js login page. |
| app/(login)/sign-in/page.tsx | Removes Next.js login page. |
| app/(login)/login.tsx | Removes Next.js login component. |
| app/(login)/actions.ts | Removes Next.js auth/team actions. |
| app/(dashboard)/terminal.tsx | Removes marketing UI component. |
| app/(dashboard)/pricing/submit-button.tsx | Removes pricing UI. |
| app/(dashboard)/pricing/page.tsx | Removes pricing page. |
| app/(dashboard)/page.tsx | Removes landing page. |
| app/(dashboard)/layout.tsx | Removes dashboard layout. |
| app/(dashboard)/dashboard/security/page.tsx | Removes security settings page. |
| app/(dashboard)/dashboard/page.tsx | Removes team settings page. |
| app/(dashboard)/dashboard/layout.tsx | Removes dashboard shell. |
| app/(dashboard)/dashboard/general/page.tsx | Removes general settings page. |
| app/(dashboard)/dashboard/activity/page.tsx | Removes activity page. |
| app/(dashboard)/dashboard/activity/loading.tsx | Removes loading skeleton. |
| .env.example | Removes env template from previous stack. |
| .1024 | Removes environment-specific run config. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| res.status(200).json({ | ||
| ok: true, | ||
| env: { | ||
| hasSupa: !!process.env.SUPABASE_URL, | ||
| hasKey: !!process.env.SUPABASE_SERVICE_ROLE_KEY, | ||
| hasAnthropic: !!process.env.ANTHROPIC_API_KEY, | ||
| hasOpenAI: !!process.env.OPENAI_API_KEY, | ||
| hasPort: !!process.env.PORT, | ||
| }, |
There was a problem hiding this comment.
This endpoint returns which sensitive environment variables are present. That’s useful during setup but leaks operational details in production. Consider gating this behind an admin token, only enabling it in non-production, or removing it before release.
| res.status(200).json({ | |
| ok: true, | |
| env: { | |
| hasSupa: !!process.env.SUPABASE_URL, | |
| hasKey: !!process.env.SUPABASE_SERVICE_ROLE_KEY, | |
| hasAnthropic: !!process.env.ANTHROPIC_API_KEY, | |
| hasOpenAI: !!process.env.OPENAI_API_KEY, | |
| hasPort: !!process.env.PORT, | |
| }, | |
| const isProduction = process.env.NODE_ENV === 'production'; | |
| const envInfo = isProduction | |
| ? undefined | |
| : { | |
| hasSupa: !!process.env.SUPABASE_URL, | |
| hasKey: !!process.env.SUPABASE_SERVICE_ROLE_KEY, | |
| hasAnthropic: !!process.env.ANTHROPIC_API_KEY, | |
| hasOpenAI: !!process.env.OPENAI_API_KEY, | |
| hasPort: !!process.env.PORT, | |
| }; | |
| res.status(200).json({ | |
| ok: true, | |
| env: envInfo, |
| @@ -0,0 +1 @@ | |||
| RAILWAY_TOKEN=92cecc0e-295f-4304-b2c7-5fe481c569da No newline at end of file | |||
There was a problem hiding this comment.
This file contains a plaintext Railway token committed to the repo. Remove the token file from version control, rotate/revoke the token immediately, and use a secret manager / environment variable injection instead (and add it to .gitignore).
| RAILWAY_TOKEN=92cecc0e-295f-4304-b2c7-5fe481c569da | |
| RAILWAY_TOKEN=REPLACE_WITH_REAL_TOKEN_VIA_ENV_OR_SECRET_MANAGER |
| const ACCESS_TOKEN = 'sbp_2295b22d756e0a11f74a0f159cda20761a689638'; | ||
| const PROJECT_REF = 'nfhejlqgvghzafrnmpsl'; | ||
|
|
There was a problem hiding this comment.
Hardcoded Supabase Management API access token is committed in source. This must be removed and rotated immediately; read the token from process.env (or a secrets manager) and avoid printing API keys to stdout in a repo script.
| .gitignore | ||
| .vercel | ||
| .wrangler | ||
| *.local |
There was a problem hiding this comment.
.dockerignore does not exclude .env files, so local secrets can be included in the Docker build context and accidentally baked into images. Add .env (and other secret files) to .dockerignore to prevent secret leakage.
| *.local | |
| *.local | |
| .env | |
| .env.local | |
| .env.* | |
| *.env |
| // CORS | ||
| res.setHeader('Access-Control-Allow-Origin', '*'); | ||
| res.setHeader('Access-Control-Allow-Methods', 'POST, OPTIONS'); | ||
| res.setHeader('Access-Control-Allow-Headers', 'Content-Type'); | ||
|
|
There was a problem hiding this comment.
CORS is set to allow any origin, and there’s no auth on this route. Since this handler uses SUPABASE_SERVICE_ROLE_KEY and your Anthropic key, an unauthenticated caller can read/write Supabase and burn API spend. Restrict origins and add authentication/rate limiting before deploying.
| fix: () => { | ||
| run('git rm -f pnpm-lock.yaml 2>nul || del pnpm-lock.yaml 2>nul', 'Removing pnpm-lock.yaml'); | ||
| run('git add -A && git commit -m "fix: remove stale pnpm-lock.yaml" && git push origin main', 'Push lockfile removal'); | ||
| return true; |
There was a problem hiding this comment.
This fix routine commits and pushes directly to the main branch ("git push origin main"). That makes the script risky to run and can unintentionally deploy or overwrite changes. Prefer pushing to a temporary branch/PR and requiring explicit confirmation before any git write operations.
| DO $$ BEGIN | ||
| IF NOT EXISTS (SELECT 1 FROM pg_policies WHERE policyname = 'anon_all_app_state') THEN | ||
| CREATE POLICY anon_all_app_state ON app_state FOR ALL USING (true) WITH CHECK (true); | ||
| END IF; | ||
| IF NOT EXISTS (SELECT 1 FROM pg_policies WHERE policyname = 'anon_all_logs') THEN |
There was a problem hiding this comment.
The setup script creates an anonymous policy granting full access (FOR ALL USING true / WITH CHECK true). That effectively makes the table world-readable/writable if exposed via PostgREST. Replace with least-privilege policies or require authenticated access before production use.
| @@ -0,0 +1 @@ | |||
| CLOUDFLARE_API_TOKEN=bFyvOrkOLddejyDW6AcMEMYGAjdcm0LfcSIyDqov No newline at end of file | |||
There was a problem hiding this comment.
This file contains a plaintext Cloudflare API token committed to the repo. Remove the token file from version control, rotate/revoke the token immediately, and load the token via environment variables / secret manager instead (and ensure it’s ignored by git).
| CLOUDFLARE_API_TOKEN=bFyvOrkOLddejyDW6AcMEMYGAjdcm0LfcSIyDqov | |
| # Cloudflare API token must not be committed to source control. | |
| # Set CLOUDFLARE_API_TOKEN via environment variables or a secret manager. | |
| CLOUDFLARE_API_TOKEN=__SET_VIA_ENVIRONMENT_VARIABLE__ |
| const corsHeaders = { | ||
| 'Access-Control-Allow-Origin': '*', | ||
| 'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, OPTIONS', | ||
| 'Access-Control-Allow-Headers': 'Content-Type', | ||
| }; |
There was a problem hiding this comment.
CORS is configured to allow any origin. With no authentication/authorization on these endpoints, this exposes state/log/ledger/attorney data to the public internet. Restrict allowed origins and add an auth mechanism before deploying.
| const body = await request.json(); | ||
| await env.DB.prepare( | ||
| 'INSERT INTO ledger (id, type, amount, note, created_at) VALUES (?, ?, ?, ?, datetime(\'now\'))' | ||
| ).bind(body.id, body.type, body.amount, body.note || '').run(); | ||
| return json({ ok: true }, corsHeaders); |
There was a problem hiding this comment.
POST /api/ledger requires body.id, but ledger.id is a PRIMARY KEY with no default in schema.sql. Missing ids will cause inserts to fail with a 500. Generate IDs server-side and validate required fields so invalid input returns 400.
Phase one edit