Skip to content

Rearchitect services and deployments#139

Merged
BetrixDev merged 29 commits into
reimaginedfrom
cloudflare-deployments
Sep 27, 2025
Merged

Rearchitect services and deployments#139
BetrixDev merged 29 commits into
reimaginedfrom
cloudflare-deployments

Conversation

@BetrixDev
Copy link
Copy Markdown
Owner

@BetrixDev BetrixDev commented Sep 26, 2025

Summary by CodeRabbit

  • New Features

    • Introduced a new backend API with authentication, payments integration, and RPC endpoints for health checks, player documents, username search, and key-value storage.
    • Added player bans, join tracking, and initial player document creation with avatar support.
    • Provided Dockerized local stack (API, Postgres, Redis, migrations) and environment examples.
  • Refactor

    • Migrated web app from previous data layer to RPC; updated routing and data fetching.
    • Replaced legacy backend stack with Postgres/Redis/ORPC/BetterAuth.
  • Chores

    • Switched CI and scripts to Bun.
    • Cleaned up obsolete docs and removed deprecated apps/configs.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Sep 26, 2025

Caution

Review failed

The pull request is closed.

Walkthrough

Replaces Convex with a new ORPC/Hono-based backend in apps/backend using Drizzle/PostgreSQL and Redis, adds auth via BetterAuth and Polar, introduces plugin KV/players routers, updates the web app to ORPC, removes the fumadocs app and Convex backend package, adds Docker Compose services (postgres, redis, api, migrate), and switches CI and scripts to Bun.

Changes

Cohort / File(s) Summary
Backend: Drizzle config & DB client
apps/backend/drizzle.config.ts, apps/backend/src/db/index.ts
Adds Drizzle config and Neon Postgres client factory exporting getDb, Database type, and schema re-exports.
Backend: DB schema & migrations
apps/backend/src/db/schema/*, apps/backend/src/db/migrations/*, apps/backend/src/db/migrations/meta/*
Introduces auth and players schemas (users, sessions, accounts, verifications, players, player_bans, player_join_events), GIN index, FKs; adds initial migrations and snapshots.
Backend: Queries & helpers
apps/backend/src/db/queries/player-documents.ts, .../search-player-usernames.ts, apps/backend/src/helpers/stats-helpers.ts
Implements player document CRUD/joins, bans synchronization, username FTS search, and a stat increment helper.
Backend: App entry & context
apps/backend/src/index.ts, apps/backend/src/lib/context.ts, apps/backend/src/lib/orpc.ts
Sets up Hono app with CORS/logging; wires OpenAPI/RPC handlers; adds ORPC providers (db, kv, auth, session) and protected/plugin procedures.
Backend: Auth & integrations
apps/backend/src/lib/auth.ts, .../payments.ts, .../env.ts, .../redis.ts, .../sdks/mc-heads.ts
Adds BetterAuth with Drizzle adapter and Polar plugins, Polar SDK client, validated env loader, Redis client factory, and MC Heads fetch helper.
Backend: Plugin routers
apps/backend/src/routers/plugin/plugin-*.ts, apps/backend/src/routers/index.ts
Exposes plugin KV and players routes (get/set/delete KV; get/save player document, optional join event); adds health-check measuring DB/KV latency; exports appRouter and client types.
Backend: Dockerization
apps/backend/.dockerignore, apps/backend/Dockerfile, apps/backend/Dockerfile.migrate, docker-compose.yml
Adds Dockerfiles and compose with postgres, redis, migrate, api, and minecraft services; healthchecks and env wiring.
Web: ORPC migration
apps/web/src/router.tsx, .../routes/__root.tsx, .../routes/index.tsx, .../contexts/rpc-context.ts, .../lib/auth-client.ts, .../routeTree.gen.ts, apps/web/vite.config.ts, apps/web/tsconfig.json, apps/web/.env.example
Replaces Convex/Clerk with ORPC/react-query utilities and BetterAuth client; updates router/context, health check fetching, Vite config, TS project refs, and env vars. Removes server handler.
Remove Convex backend package
packages/backend/convex/*, packages/backend/package.json
Deletes Convex schema, queries, HTTP router, auth config, types, tsconfig, and package.json.
Remove Fumadocs app
apps/fumadocs/**
Deletes Next.js docs app, configs, pages, MDX content, and tsconfig.
Repo/CI/tooling
.github/workflows/*, package.json, turbo.json, pnpm-workspace.yaml, .gitignore, .prettierignore, .env.development.example, apps/web/.gitignore, packages/backend/.gitignore
Switches CI and scripts to Bun; updates turbo outputs; removes pnpm workspace; adjusts ignore files; adds env examples; sets workspaces and packageManager bun.
Plugin: Gradle runner & API
plugin/package.json, plugin/scripts/run-gradle.mjs, plugin/src/.../ApiService.kt
Adds Node-based Gradle wrapper runner; renames package; switches plugin API client from Convex to BASE_API_URL with API_SECRET_KEY; adds KV delete.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor Plugin as Minecraft Plugin
  participant API as Hono API (apps/backend)
  participant ORPC as ORPC Router
  participant DB as Postgres (Drizzle)
  participant KV as Redis

  Plugin->>API: HTTP (Bearer API_SECRET_KEY) GET /plugin/players/{uuid}/document?joinEvent=true
  API->>ORPC: Route dispatch (pluginPlayersRouter.getPlayerDocument)
  ORPC->>DB: getPlayerDocument(uuid)
  DB-->>ORPC: Player row + bans (or none)
  alt Not found
    ORPC->>DB: createInitialPlayerDocument(uuid)
  end
  opt joinEvent=true
    ORPC->>DB: handlePlayerJoinEvent(uuid) (tx: insert join event, inc stats)
  end
  ORPC-->>API: PlayerDocument
  API-->>Plugin: 200 JSON PlayerDocument
Loading
sequenceDiagram
  autonumber
  actor Web as Web App (React)
  participant RPC as @orpc/client
  participant API as Hono API
  participant ORPC as ORPC Router
  participant DB as Postgres
  participant KV as Redis

  Web->>RPC: useQuery(rpc.healthCheck.queryOptions())
  RPC->>API: POST /rpc (healthCheck)
  API->>ORPC: Execute healthCheck (dbProvider, kvProvider)
  ORPC->>DB: SELECT 1 (latency)
  ORPC->>KV: set/get (latency)
  ORPC-->>API: { status, dbCheckDurationMs, kvSetGetDurationMs, timestamp }
  API-->>RPC: JSON
  RPC-->>Web: Data to render
Loading
sequenceDiagram
  autonumber
  actor Plugin
  participant API
  participant ORPC
  participant KV as Redis

  Plugin->>API: POST /plugin/kv/{key} { value }
  API->>ORPC: pluginKvRouter.set
  ORPC->>KV: set(key, value)
  KV-->>ORPC: OK
  ORPC-->>API: { message: "KV set" }
  API-->>Plugin: 200 JSON
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

Suggested labels

Development

Poem

In burrows of code I thump with delight,
Drizzle and Hono now dance in the night.
ORPC trails where Convex once hopped,
Redis and Postgres—carrots neatly chopped.
Bun in my paws, I ship with a grin—
“OK,” squeaks the health check. Let’s win! 🥕✨

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed The title “Rearchitect services and deployments” succinctly captures the overarching goal of the pull request—revamping service architecture and deployment configurations—and directly corresponds to the extensive additions and modifications of Dockerfiles, docker-compose, and service-level code changes. It avoids unnecessary detail while clearly signaling the primary objective to reviewers.

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 04987ac and 187b48c.

📒 Files selected for processing (12)
  • apps/backend/src/db/queries/player-documents.ts (1 hunks)
  • apps/backend/src/db/schema/players.ts (1 hunks)
  • apps/backend/src/helpers/stats-helpers.ts (1 hunks)
  • apps/backend/src/routers/index.ts (1 hunks)
  • apps/backend/src/routers/plugin/plugin-kv-router.ts (1 hunks)
  • apps/backend/src/routers/plugin/plugin-players-router.ts (1 hunks)
  • apps/backend/src/routers/plugin/plugin-router.ts (1 hunks)
  • apps/backend/src/schemas/pagination-options.ts (1 hunks)
  • apps/backend/src/sdks/mc-heads.ts (1 hunks)
  • apps/backend/tsconfig.json (1 hunks)
  • docker-compose.yml (1 hunks)
  • plugin/src/main/kotlin/dev/betrix/superSmashMobsBrawl/services/ApiService.kt (4 hunks)

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 25

🧹 Nitpick comments (11)
package.json (1)

15-23: Move concurrently to devDependencies.

concurrently is only used by the development scripts, so it needlessly inflates the production install when kept under dependencies. Please relocate it to devDependencies (and drop the now-empty dependencies block if nothing else belongs there).

-  "dependencies": {
-    "concurrently": "^9.2.1"
-  },
   "devDependencies": {
     "alchemy": "^0.67.0",
+    "concurrently": "^9.2.1",
     "dotenv": "^17.2.1",
README.md (1)

38-38: Fix heading level and bare URL lint errors.

markdownlint is flagging the H6 jump and the bare Neon URL here. Bump the heading to H3 and wrap the URL in link markdown to keep the docs lint-clean.

-###### Obtain the NEON_API_KEY from https://neon.com
+### Obtain the NEON_API_KEY from [Neon](https://neon.com)
apps/backend/src/routers/index.ts (1)

17-21: Avoid unbounded KV writes in health check

Every GET health check currently performs a KV write with no TTL and to a very generic key, which turns a read-only probe into a stateful, billable operation that accumulates writes indefinitely. Please switch to a namespaced key and set a short expiration so the probe remains idempotent and low-cost.

-    const kvCheckStart = performance.now();
-    await env.KV.put("test", "test");
-    await env.KV.get("test");
+    const kvCheckStart = performance.now();
+    const kvKey = "health-check:last";
+    await env.KV.put(kvKey, "ok", { expirationTtl: 60 });
+    await env.KV.get(kvKey);
apps/backend/src/schemas/player-document.ts (1)

5-20: Validate dates and defaults; prefer nullish over nullable.

  • Use z.string().datetime() for ISO dates (lastJoinDate, bannedAt, expiresAt).
  • Prefer nullish for optional fields and default [] for arrays to avoid null handling in callers.

Apply:

-  lastJoinDate: z.string(),
-  headSkinBase64: z.string().nullable(),
+  lastJoinDate: z.string().datetime(),
+  headSkinBase64: z.string().nullish(),
   stats: z.record(z.string(), z.union([z.string(), z.number(), z.boolean()])),
-  banData: z
-    .array(
-      z.object({
-        id: z.string(),
-        isBanned: z.boolean(),
-        reason: z.string(),
-        expiresAt: z.string().nullable(),
-        bannedAt: z.string(),
-        bannedBy: z.string(),
-      }),
-    )
-    .nullable(),
+  banData: z
+    .array(
+      z.object({
+        id: z.string(),
+        isBanned: z.boolean(),
+        reason: z.string(),
+        expiresAt: z.string().datetime().nullish(),
+        bannedAt: z.string().datetime(),
+        bannedBy: z.string(),
+      }),
+    )
+    .default([]),
apps/wiki/astro.config.mjs (1)

8-35: Set site for correct canonical URLs and sitemaps.

Adding site improves SEO and link generation.

Apply:

 export default defineConfig({
   output: "server",
+  site: "https://wiki.ssmbrawl.com",
   adapter: cloudflare({
     imageService: "compile",
   }),
apps/web/src/contexts/rpc-context.ts (2)

2-3: Prefer useContext for broader React compatibility.

use() requires React 19+ context reading; useContext works across versions.

Apply:

-import { createContext, use } from "react";
+import { createContext, useContext } from "react";

9-14: Use useContext and fix error text.

Safer hook and consistent name.

Apply:

 export function useRpc(): RpcReactUtils {
-  const rpc = use(RpcContext);
+  const rpc = useContext(RpcContext);

   if (!rpc) {
-    throw new Error("ORPCContext is not set up properly");
+    throw new Error("RpcContext is not set up properly");
   }

If the app targets React 19+ and intentionally uses use(), feel free to keep it.

alchemy.run.ts (4)

22-26: Nit: task name duplication.

Both Exec blocks are named "db-generate". Rename the migrate step for clarity.

Apply:

-await Exec("db-generate", {
+await Exec("db-generate", {
   cwd: "apps/backend",
   command: "pnpm run db:generate",
 });

And below:

-await Exec("db-generate", {
+await Exec("db-migrate", {
   cwd: "apps/backend",
   command: `pnpm run db:migrate`,

83-113: Consider deriving CORS origin for non-dev.

Optionally set CORS_ORIGIN to https://{webDomainName} when stage ≠ dev to avoid misconfig if env var is absent.

Apply (requires moving webDomainName computation above backend or duplicating logic):

-    CORS_ORIGIN: process.env.CORS_ORIGIN || "http://localhost:3000",
+    CORS_ORIGIN:
+      process.env.CORS_ORIGIN ||
+      (app.stage === "dev" ? "http://localhost:3000" : `https://${app.stage === "prod" ? "ssmbrawl.com" : `${app.stage}-ssmbrawl.com"}`),

Alternatively, compute webDomainName earlier and reference it here.


13-20: Stage variable vs app.stage.

You compute stage from env and also use app.stage. Prefer a single source (app.stage) to avoid drift.


61-67: Guard secrets early.

If any required secret is missing (NEON_API_KEY, BETTER_AUTH_SECRET, POLAR_ACCESS_TOKEN, PLUGIN_SECRET_KEY), fail fast with a clear error.

I can add a small preflight check if you want.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between bd048d6 and 66bdddd.

⛔ Files ignored due to path filters (7)
  • apps/wiki/public/favicon.svg is excluded by !**/*.svg
  • packages/backend/convex/_generated/api.d.ts is excluded by !**/_generated/**
  • packages/backend/convex/_generated/api.js is excluded by !**/_generated/**
  • packages/backend/convex/_generated/dataModel.d.ts is excluded by !**/_generated/**
  • packages/backend/convex/_generated/server.d.ts is excluded by !**/_generated/**
  • packages/backend/convex/_generated/server.js is excluded by !**/_generated/**
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (107)
  • .cursor/rules/convex-rules.mdc (0 hunks)
  • .env.example (1 hunks)
  • .github/workflows/deploy.yml (1 hunks)
  • .gitignore (1 hunks)
  • .prettierignore (1 hunks)
  • README.md (1 hunks)
  • alchemy.run.ts (1 hunks)
  • apps/backend/.env.example (1 hunks)
  • apps/backend/drizzle.config.ts (1 hunks)
  • apps/backend/env.d.ts (1 hunks)
  • apps/backend/package.json (1 hunks)
  • apps/backend/src/db/cache.ts (1 hunks)
  • apps/backend/src/db/index.ts (1 hunks)
  • apps/backend/src/db/migrations/0000_bitter_loners.sql (1 hunks)
  • apps/backend/src/db/migrations/0001_sweet_wendell_vaughn.sql (1 hunks)
  • apps/backend/src/db/migrations/meta/0000_snapshot.json (1 hunks)
  • apps/backend/src/db/migrations/meta/0001_snapshot.json (1 hunks)
  • apps/backend/src/db/migrations/meta/_journal.json (1 hunks)
  • apps/backend/src/db/queries/player-documents.ts (1 hunks)
  • apps/backend/src/db/queries/search-player-usernames.ts (1 hunks)
  • apps/backend/src/db/schema/auth.ts (1 hunks)
  • apps/backend/src/db/schema/index.ts (1 hunks)
  • apps/backend/src/db/schema/players.ts (1 hunks)
  • apps/backend/src/index.ts (1 hunks)
  • apps/backend/src/lib/auth.ts (1 hunks)
  • apps/backend/src/lib/context.ts (1 hunks)
  • apps/backend/src/lib/orpc.ts (1 hunks)
  • apps/backend/src/lib/payments.ts (1 hunks)
  • apps/backend/src/routers/index.ts (1 hunks)
  • apps/backend/src/routers/plugin/index.ts (1 hunks)
  • apps/backend/src/routers/plugin/player.ts (1 hunks)
  • apps/backend/src/schemas/pagination-options.ts (1 hunks)
  • apps/backend/src/schemas/player-document.ts (1 hunks)
  • apps/backend/src/sdks/mc-heads.ts (1 hunks)
  • apps/backend/tsconfig.json (1 hunks)
  • apps/fumadocs/.gitignore (0 hunks)
  • apps/fumadocs/README.md (0 hunks)
  • apps/fumadocs/content/docs/index.mdx (0 hunks)
  • apps/fumadocs/content/docs/test.mdx (0 hunks)
  • apps/fumadocs/next.config.mjs (0 hunks)
  • apps/fumadocs/package.json (0 hunks)
  • apps/fumadocs/postcss.config.mjs (0 hunks)
  • apps/fumadocs/source.config.ts (0 hunks)
  • apps/fumadocs/src/app/(home)/layout.tsx (0 hunks)
  • apps/fumadocs/src/app/(home)/page.tsx (0 hunks)
  • apps/fumadocs/src/app/api/search/route.ts (0 hunks)
  • apps/fumadocs/src/app/docs/[[...slug]]/page.tsx (0 hunks)
  • apps/fumadocs/src/app/docs/layout.tsx (0 hunks)
  • apps/fumadocs/src/app/global.css (0 hunks)
  • apps/fumadocs/src/app/layout.tsx (0 hunks)
  • apps/fumadocs/src/lib/layout.shared.tsx (0 hunks)
  • apps/fumadocs/src/lib/source.ts (0 hunks)
  • apps/fumadocs/src/mdx-components.tsx (0 hunks)
  • apps/fumadocs/tsconfig.json (0 hunks)
  • apps/web/package.json (2 hunks)
  • apps/web/src/contexts/rpc-context.ts (1 hunks)
  • apps/web/src/lib/auth-client.ts (1 hunks)
  • apps/web/src/routeTree.gen.ts (1 hunks)
  • apps/web/src/router.tsx (2 hunks)
  • apps/web/src/routes/__root.tsx (2 hunks)
  • apps/web/src/routes/index.tsx (1 hunks)
  • apps/web/src/server.ts (0 hunks)
  • apps/web/tsconfig.json (1 hunks)
  • apps/web/vite.config.ts (1 hunks)
  • apps/wiki/.gitignore (1 hunks)
  • apps/wiki/.vscode/extensions.json (1 hunks)
  • apps/wiki/.vscode/launch.json (1 hunks)
  • apps/wiki/README.md (1 hunks)
  • apps/wiki/astro.config.mjs (1 hunks)
  • apps/wiki/package.json (1 hunks)
  • apps/wiki/src/content.config.ts (1 hunks)
  • apps/wiki/src/content/docs/guides/get-started.md (1 hunks)
  • apps/wiki/src/content/docs/index.mdx (1 hunks)
  • apps/wiki/src/content/docs/kits/blaze.md (1 hunks)
  • apps/wiki/src/content/docs/kits/creeper.md (1 hunks)
  • apps/wiki/src/content/docs/kits/enderman.md (1 hunks)
  • apps/wiki/src/content/docs/kits/guardian.md (1 hunks)
  • apps/wiki/src/content/docs/kits/horse.md (1 hunks)
  • apps/wiki/src/content/docs/kits/iron-golem.md (1 hunks)
  • apps/wiki/src/content/docs/kits/magma-cube.md (1 hunks)
  • apps/wiki/src/content/docs/kits/mooshroom.md (1 hunks)
  • apps/wiki/src/content/docs/kits/pig.md (1 hunks)
  • apps/wiki/src/content/docs/kits/sheep.md (1 hunks)
  • apps/wiki/src/content/docs/kits/slime.md (1 hunks)
  • apps/wiki/src/content/docs/kits/snowman.md (1 hunks)
  • apps/wiki/src/content/docs/kits/spider.md (1 hunks)
  • apps/wiki/src/content/docs/kits/squid.md (1 hunks)
  • apps/wiki/src/content/docs/kits/villager.md (1 hunks)
  • apps/wiki/src/content/docs/kits/witch.md (1 hunks)
  • apps/wiki/src/content/docs/kits/wither-skeleton.md (1 hunks)
  • apps/wiki/src/content/docs/kits/wolf.md (1 hunks)
  • apps/wiki/src/content/docs/kits/zombie.md (1 hunks)
  • apps/wiki/src/custom.css (1 hunks)
  • apps/wiki/tsconfig.json (1 hunks)
  • package.json (1 hunks)
  • packages/backend/.gitignore (0 hunks)
  • packages/backend/convex/README.md (0 hunks)
  • packages/backend/convex/auth.config.ts (0 hunks)
  • packages/backend/convex/common.ts (0 hunks)
  • packages/backend/convex/healthCheck.ts (0 hunks)
  • packages/backend/convex/http.ts (0 hunks)
  • packages/backend/convex/kv.ts (0 hunks)
  • packages/backend/convex/players.ts (0 hunks)
  • packages/backend/convex/schema.ts (0 hunks)
  • packages/backend/convex/schemas.ts (0 hunks)
  • packages/backend/convex/tsconfig.json (0 hunks)
  • packages/backend/package.json (0 hunks)
⛔ Files not processed due to max files limit (2)
  • plugin/src/main/kotlin/dev/betrix/superSmashMobsBrawl/models/brawlData/AbilityDef.kt
  • plugin/src/main/kotlin/dev/betrix/superSmashMobsBrawl/models/player/PlayerDocument.kt
💤 Files with no reviewable changes (33)
  • packages/backend/convex/players.ts
  • apps/fumadocs/src/app/global.css
  • apps/fumadocs/README.md
  • packages/backend/convex/README.md
  • apps/fumadocs/src/app/(home)/layout.tsx
  • packages/backend/convex/schemas.ts
  • apps/fumadocs/src/lib/source.ts
  • apps/fumadocs/src/mdx-components.tsx
  • apps/fumadocs/src/app/docs/layout.tsx
  • apps/fumadocs/content/docs/test.mdx
  • packages/backend/convex/schema.ts
  • apps/fumadocs/source.config.ts
  • apps/fumadocs/src/app/(home)/page.tsx
  • packages/backend/convex/healthCheck.ts
  • apps/fumadocs/src/lib/layout.shared.tsx
  • packages/backend/.gitignore
  • apps/fumadocs/package.json
  • packages/backend/convex/common.ts
  • apps/fumadocs/postcss.config.mjs
  • .cursor/rules/convex-rules.mdc
  • apps/web/src/server.ts
  • packages/backend/convex/auth.config.ts
  • apps/fumadocs/src/app/layout.tsx
  • apps/fumadocs/src/app/api/search/route.ts
  • apps/fumadocs/.gitignore
  • packages/backend/package.json
  • apps/fumadocs/tsconfig.json
  • apps/fumadocs/next.config.mjs
  • apps/fumadocs/src/app/docs/[[...slug]]/page.tsx
  • apps/fumadocs/content/docs/index.mdx
  • packages/backend/convex/tsconfig.json
  • packages/backend/convex/http.ts
  • packages/backend/convex/kv.ts
🧰 Additional context used
📓 Path-based instructions (1)
package.json

📄 CodeRabbit inference engine (.cursor/rules/convex-rules.mdc)

Add @types/node to package.json when using Node.js built-in modules

Files:

  • package.json
🧠 Learnings (5)
📚 Learning: 2025-09-22T00:08:49.174Z
Learnt from: CR
PR: BetrixDev/ssm-brawl#0
File: .cursor/rules/convex-rules.mdc:0-0
Timestamp: 2025-09-22T00:08:49.174Z
Learning: Applies to convex/**/*.{ts,js} : Define paginated queries using paginationOptsValidator and .paginate(opts); return the paginate result object

Applied to files:

  • apps/backend/src/schemas/pagination-options.ts
📚 Learning: 2025-09-22T00:08:49.174Z
Learnt from: CR
PR: BetrixDev/ssm-brawl#0
File: .cursor/rules/convex-rules.mdc:0-0
Timestamp: 2025-09-22T00:08:49.174Z
Learning: Applies to package.json : Add types/node to package.json when using Node.js built-in modules

Applied to files:

  • package.json
📚 Learning: 2025-09-22T00:08:49.174Z
Learnt from: CR
PR: BetrixDev/ssm-brawl#0
File: .cursor/rules/convex-rules.mdc:0-0
Timestamp: 2025-09-22T00:08:49.174Z
Learning: Applies to convex/**/*.{ts,js} : Add "use node" to the top of files containing actions that use Node.js built-in modules

Applied to files:

  • package.json
📚 Learning: 2025-09-22T00:08:49.174Z
Learnt from: CR
PR: BetrixDev/ssm-brawl#0
File: .cursor/rules/convex-rules.mdc:0-0
Timestamp: 2025-09-22T00:08:49.174Z
Learning: Applies to convex/schema.ts : Import schema helpers (defineSchema, defineTable) from convex/server in the schema file

Applied to files:

  • apps/backend/src/db/schema/index.ts
📚 Learning: 2025-09-22T00:08:49.174Z
Learnt from: CR
PR: BetrixDev/ssm-brawl#0
File: .cursor/rules/convex-rules.mdc:0-0
Timestamp: 2025-09-22T00:08:49.174Z
Learning: Applies to convex/**/*.{ts,js} : Organize public Convex functions (query/mutation/action) within the convex/ directory, leveraging file-based routing

Applied to files:

  • apps/web/src/routes/__root.tsx
🧬 Code graph analysis (18)
apps/backend/src/db/queries/search-player-usernames.ts (2)
apps/backend/src/schemas/pagination-options.ts (1)
  • PaginationOptions (8-8)
apps/backend/src/db/index.ts (2)
  • db (11-15)
  • Table (17-17)
apps/backend/src/lib/context.ts (1)
apps/backend/src/lib/auth.ts (1)
  • auth (10-52)
apps/backend/src/db/index.ts (1)
apps/backend/src/db/cache.ts (1)
  • CloudflareKvCache (6-105)
apps/backend/src/routers/plugin/index.ts (1)
apps/backend/src/routers/plugin/player.ts (1)
  • pluginPlayersRouter (6-38)
apps/web/src/lib/auth-client.ts (1)
apps/backend/src/lib/payments.ts (1)
  • polarClient (7-10)
apps/backend/src/routers/plugin/player.ts (3)
apps/backend/src/lib/orpc.ts (1)
  • pluginProcedure (31-31)
apps/backend/src/schemas/player-document.ts (1)
  • playerDocumentSchema (3-20)
apps/backend/src/db/queries/player-documents.ts (2)
  • getPlayerDocument (7-33)
  • updatePlayerDocument (59-100)
apps/backend/src/index.ts (3)
apps/backend/src/lib/auth.ts (1)
  • auth (10-52)
apps/backend/src/routers/index.ts (1)
  • appRouter (7-30)
apps/backend/src/lib/context.ts (1)
  • createContext (8-17)
apps/web/src/contexts/rpc-context.ts (1)
apps/backend/src/routers/index.ts (1)
  • AppRouterClient (33-33)
apps/backend/src/lib/auth.ts (2)
apps/backend/src/db/index.ts (1)
  • db (11-15)
apps/backend/src/lib/payments.ts (1)
  • polarClient (7-10)
apps/backend/src/db/queries/player-documents.ts (5)
plugin/src/main/kotlin/dev/betrix/superSmashMobsBrawl/models/player/PlayerDocument.kt (1)
  • uuid (92-92)
apps/backend/src/schemas/player-document.ts (1)
  • PlayerDocument (22-22)
apps/backend/src/db/index.ts (2)
  • db (11-15)
  • Table (17-17)
apps/backend/src/db/schema/players.ts (2)
  • players (4-17)
  • playerBans (23-34)
apps/backend/src/sdks/mc-heads.ts (1)
  • getPlayerHeadSkinBase64 (1-14)
apps/backend/env.d.ts (1)
alchemy.run.ts (1)
  • backend (52-81)
apps/backend/src/routers/index.ts (3)
apps/backend/src/lib/orpc.ts (1)
  • publicProcedure (29-29)
apps/backend/src/db/index.ts (1)
  • db (11-15)
apps/backend/src/routers/plugin/index.ts (1)
  • pluginRouter (3-5)
apps/backend/src/lib/orpc.ts (1)
apps/backend/src/lib/context.ts (1)
  • Context (19-19)
apps/web/src/routeTree.gen.ts (1)
apps/web/src/router.tsx (1)
  • getRouter (13-41)
apps/web/src/routes/index.tsx (1)
apps/web/src/contexts/rpc-context.ts (1)
  • useRpc (9-17)
apps/web/src/router.tsx (2)
apps/backend/src/routers/index.ts (1)
  • AppRouterClient (33-33)
apps/web/src/contexts/rpc-context.ts (1)
  • RpcContext (7-7)
apps/web/src/routes/__root.tsx (1)
apps/backend/src/routers/index.ts (1)
  • AppRouterClient (33-33)
apps/backend/src/db/cache.ts (1)
apps/backend/src/db/index.ts (1)
  • Table (17-17)
🪛 dotenv-linter (3.3.0)
.env.example

[warning] 4-4: [EndingBlankLine] No blank line at the end of the file

(EndingBlankLine)


[warning] 4-4: [UnorderedKey] The CLOUDFLARE_ZONE_ID key should go before the NEON_API_KEY key

(UnorderedKey)

apps/backend/.env.example

[warning] 2-2: [UnorderedKey] The BETTER_AUTH_SECRET key should go before the CORS_ORIGIN key

(UnorderedKey)


[warning] 3-3: [UnorderedKey] The BETTER_AUTH_URL key should go before the CORS_ORIGIN key

(UnorderedKey)


[warning] 6-6: [EndingBlankLine] No blank line at the end of the file

(EndingBlankLine)


[warning] 6-6: [UnorderedKey] The PLUGIN_SECRET_KEY key should go before the POLAR_ACCESS_TOKEN key

(UnorderedKey)

🪛 markdownlint-cli2 (0.18.1)
apps/wiki/README.md

5-5: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


15-15: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

README.md

38-38: Heading levels should only increment by one level at a time
Expected: h3; Actual: h6

(MD001, heading-increment)


38-38: Bare URL used

(MD034, no-bare-urls)

🪛 GitHub Actions: autofix.ci
.github/workflows/deploy.yml

[error] 1-1: The autofix.ci action is not allowed to modify the .github directory.

🔇 Additional comments (12)
apps/wiki/.vscode/extensions.json (1)

1-4: Helpful Astro tooling recommendation

Adding the Astro VSCode extension keeps the wiki workspace aligned with the new Astro setup and improves dev ergonomics. Looks good.

.env.example (1)

1-4: Thanks for expanding the root env template

Documenting these deployment credentials up front will make local/scoped CLI runs smoother for newcomers. No further action needed.

apps/wiki/tsconfig.json (1)

1-5: Astro TS config is spot on

Extending the strict preset with the usual include/exclude mirrors Astro guidance and should keep typings tidy.

apps/backend/.env.example (1)

1-6: Backend env placeholders look complete

Capturing the auth and Polar secrets here will help avoid misconfigured deployments. All good.

.gitignore (1)

3-6: Ignore additions make sense

Keeping plugin artifacts, Alchemy state, local envs, and JSONC configs out of Git aligns with the new tooling.

apps/wiki/src/content/docs/kits/squid.md (1)

1-4: Front matter looks good.

Thanks for wiring up the Squid kit doc metadata.

apps/wiki/src/content/docs/kits/enderman.md (1)

1-4: Front matter looks good.

All metadata fields are in place for the Enderman kit page.

apps/wiki/src/content/docs/kits/iron-golem.md (1)

1-4: Front matter looks good.

Metadata for the Iron Golem kit page is correctly defined.

apps/web/tsconfig.json (1)

27-28: backend tsconfig.json already enables “composite”: true – reference build will succeed.

apps/backend/src/schemas/player-document.ts (1)

7-7: Confirm stats value shapes.

If stats are counters/times, consider z.number().int() where appropriate; otherwise current union is fine.

apps/wiki/astro.config.mjs (1)

10-12: Double-check Cloudflare imageService choice.

Verify "compile" is intended; use "cloudflare-images" if you rely on Cloudflare Images.

alchemy.run.ts (1)

46-50: Verify domain patterns exist.

Ensure DNS and Cloudflare zones support the hyphenated subdomains (e.g., stage-ssmbrawl.com, stage-wiki.ssmbrawl.com) and the intended routing.

Also applies to: 83-88, 119-123

Comment thread .github/workflows/deploy.yml Outdated
Comment thread alchemy.run.ts Outdated
Comment thread alchemy.run.ts Outdated
Comment thread alchemy.run.ts Outdated
Comment thread apps/backend/drizzle.config.ts
Comment thread apps/web/src/routes/__root.tsx
Comment thread apps/web/src/routeTree.gen.ts
Comment thread apps/web/vite.config.ts Outdated
external: ["cloudflare:workers"],
},
},
plugins: [alchemy(), tsconfigPaths(), tailwindcss(), tanstackStart(), viteReact()],
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Avoid double-registering the React plugin.

tanstackStart() injects Vite’s React plugin unless customViteReactPlugin is set to true. Because we still invoke viteReact() manually, this change now wires the React plugin twice, which breaks Fast Refresh and can trigger duplicate transform errors. Please keep customViteReactPlugin: true (or drop the manual viteReact() call).

-  plugins: [alchemy(), tsconfigPaths(), tailwindcss(), tanstackStart(), viteReact()],
+  plugins: [
+    alchemy(),
+    tsconfigPaths(),
+    tailwindcss(),
+    tanstackStart({
+      customViteReactPlugin: true,
+    }),
+    viteReact(),
+  ],
🤖 Prompt for AI Agents
In apps/web/vite.config.ts around line 14, the React plugin is being registered
twice (tanstackStart() injects Vite’s React plugin by default and viteReact() is
also included), which breaks Fast Refresh and can cause duplicate transform
errors; fix it by either removing the manual viteReact() from the plugins array
or configure tanstackStart({ customViteReactPlugin: true }) so tanstackStart
will not auto-inject React, ensuring only one React plugin is registered.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is how it's done in the new version of tanstack start

Comment thread apps/wiki/README.md Outdated
Comment on lines +5 to +7
```
pnpm create astro@latest -- --template starlight
```
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion | 🟠 Major

Add languages to fenced code blocks

markdownlint (MD040) is failing because these code fences lack a language hint. Please tag the command block as bash (or similar) and the directory tree as text so the lint pipeline passes. Based on static analysis hints.

-```
+```bash
 pnpm create astro@latest -- --template starlight

@@
- +text
.
├── public/
├── src/
@@
-└── tsconfig.json
- +└── tsconfig.json +



Also applies to: 15-26

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 markdownlint-cli2 (0.18.1)</summary>

5-5: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

</details>

</details>

<details>
<summary>🤖 Prompt for AI Agents</summary>

In apps/wiki/README.md around lines 5-7 and 15-26, the fenced code blocks are
missing language hints (causing markdownlint MD040); update the first command
block to use a bash language tag (change tobash) and update the
directory tree block to use a text tag (change totext) so the linter
recognizes the languages; apply the same change for all similar fenced blocks
mentioned (lines 15-26) ensuring each opening fence includes the appropriate
language token.


</details>

<!-- fingerprinting:phantom:poseidon:sabertoothed -->

<!-- This is an auto-generated comment by CodeRabbit -->

Comment thread apps/wiki/src/custom.css Outdated
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 66bdddd and 6b948a0.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (16)
  • .github/workflows/deploy.yml (1 hunks)
  • alchemy.run.ts (1 hunks)
  • apps/backend/drizzle.config.ts (1 hunks)
  • apps/backend/package.json (1 hunks)
  • apps/backend/src/db/index.ts (1 hunks)
  • apps/backend/src/db/queries/player-documents.ts (1 hunks)
  • apps/backend/src/db/queries/search-player-usernames.ts (1 hunks)
  • apps/backend/src/index.ts (1 hunks)
  • apps/backend/src/lib/auth.ts (1 hunks)
  • apps/backend/src/lib/context.ts (1 hunks)
  • apps/backend/src/lib/orpc.ts (1 hunks)
  • apps/backend/src/lib/payments.ts (1 hunks)
  • apps/backend/src/routers/index.ts (1 hunks)
  • apps/backend/src/routers/plugin/index.ts (1 hunks)
  • apps/backend/src/routers/plugin/player.ts (1 hunks)
  • apps/backend/src/sdks/mc-heads.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (7)
  • apps/backend/src/routers/index.ts
  • apps/backend/src/lib/context.ts
  • alchemy.run.ts
  • apps/backend/src/lib/payments.ts
  • .github/workflows/deploy.yml
  • apps/backend/drizzle.config.ts
  • apps/backend/src/routers/plugin/player.ts
🧰 Additional context used
🧬 Code graph analysis (6)
apps/backend/src/routers/plugin/index.ts (2)
apps/backend/src/lib/orpc.ts (1)
  • o (7-7)
apps/backend/src/routers/plugin/player.ts (1)
  • pluginPlayersRouter (6-40)
apps/backend/src/db/queries/search-player-usernames.ts (2)
apps/backend/src/schemas/pagination-options.ts (1)
  • PaginationOptions (8-8)
apps/backend/src/db/index.ts (1)
  • Table (18-18)
apps/backend/src/lib/auth.ts (2)
apps/backend/src/db/index.ts (1)
  • getDb (5-14)
apps/backend/src/lib/payments.ts (1)
  • polarClient (7-10)
apps/backend/src/index.ts (4)
apps/backend/src/lib/auth.ts (1)
  • getAuth (10-54)
apps/backend/src/db/index.ts (1)
  • getDb (5-14)
apps/backend/src/routers/index.ts (1)
  • appRouter (6-48)
apps/backend/src/lib/context.ts (1)
  • createContext (7-11)
apps/backend/src/lib/orpc.ts (3)
apps/backend/src/lib/context.ts (1)
  • Context (13-13)
apps/backend/src/db/index.ts (2)
  • Database (16-16)
  • getDb (5-14)
apps/backend/src/lib/auth.ts (1)
  • getAuth (10-54)
apps/backend/src/db/queries/player-documents.ts (4)
apps/backend/src/db/index.ts (2)
  • Database (16-16)
  • Table (18-18)
apps/backend/src/schemas/player-document.ts (1)
  • PlayerDocument (22-22)
apps/backend/src/db/schema/players.ts (2)
  • players (4-17)
  • playerBans (23-34)
apps/backend/src/sdks/mc-heads.ts (1)
  • getPlayerHeadSkinBase64 (1-16)
🔇 Additional comments (6)
apps/backend/package.json (1)

36-42: Drop the duplicate dotenv entry.

dotenv is already in dependencies. Keeping it in devDependencies installs it twice and keeps the lockfile noisier. Please remove the duplicate from devDependencies.

   "devDependencies": {
     "@cloudflare/workers-types": "^4.20250822.0",
     "@types/node": "^22.13.11",
     "@types/pg": "^8.15.5",
     "alchemy": "^0.67.0",
-    "dotenv": "^17.2.1",
     "drizzle-kit": "^0.31.2",
     "tsdown": "^0.15.1",
     "typescript": "^5.8.2",
     "wrangler": "^4.23.0"
   }
apps/backend/src/lib/auth.ts (1)

12-16: Fix the Drizzle provider string for BetterAuth.

drizzleAdapter only accepts "postgresql", "sqlite", or "mysql"; passing "pg" leaves the adapter on the default path and it will still emit SQLite-style SQL, breaking auth persistence against Postgres. Swap this to "postgresql" so BetterAuth generates the correct statements.

-      provider: "pg",
+      provider: "postgresql",
apps/backend/src/sdks/mc-heads.ts (1)

3-11: Guard non-OK mc-heads responses before base64 encoding

Line 3 currently reads the body even when the service returns 4xx/5xx, so we end up storing a base64-encoded HTML error instead of failing fast. Please check response.ok before converting and bail out with null on failure.

-    const responsePng = await fetch(`https://mc-heads.net/avatar/${uuid}`).then((res) =>
-      res.arrayBuffer(),
-    );
-
-    const uint8Array = new Uint8Array(responsePng);
+    const response = await fetch(`https://mc-heads.net/avatar/${uuid}`);
+
+    if (!response.ok) {
+      console.warn(
+        "mc-heads returned non-OK response",
+        response.status,
+        response.statusText,
+      );
+      return null;
+    }
+
+    const arrayBuffer = await response.arrayBuffer();
+
+    const uint8Array = new Uint8Array(arrayBuffer);
apps/backend/src/db/queries/search-player-usernames.ts (1)

10-11: Use plainto_tsquery to avoid tsquery syntax errors

Line 10 pipes raw user input through to_tsquery, which blows up on common inputs like "mario kart" (Postgres expects connectors). Switch to plainto_tsquery (or websearch_to_tsquery) so natural text works.

-      sql`to_tsvector('english', ${Table.players.username}) @@ to_tsquery('english', ${query})`,
+      sql`to_tsvector('english', ${Table.players.username}) @@ plainto_tsquery('english', ${query})`,
apps/backend/src/lib/orpc.ts (1)

9-16: Preserve full context when forwarding from middleware

Each of these middlewares calls next({ context: { … } }) with only the freshly introduced field, which drops everything else (headers, db, auth, etc.) that previous providers injected. After sessionProvider runs, a protectedProcedure handler receives { session } instead of the full request context, so anything expecting headers or db immediately breaks. This is the same regression that was flagged earlier on requireAuth—please forward the already-mutated context instead of replacing it.

-  return next({
-    context: {
-      db: context.db,
-    },
-  });
+  return next({ context });-    return next({
-      context: {
-        auth: context.auth,
-      },
-    });
+    return next({ context });-    return next({
-      context: {
-        session: context.session,
-      },
-    });
+    return next({ context });-      return next({
-        context: {
-          session: context.session,
-        },
-      });
+      return next({ context });

Also applies to: 26-30, 48-51, 64-68

apps/backend/src/db/queries/player-documents.ts (1)

67-71: Stop overwriting the historical first-join timestamp

We’re still setting firstJoinedDate to document.lastJoinDate, so every update clobbers the original “first seen” timestamp with the most recent join. Drop this assignment (or source the real first join value) so the historical record survives.

     await tx
       .update(Table.players)
       .set({
         lastJoinedDate: new Date(document.lastJoinDate),
-        firstJoinedDate: new Date(document.lastJoinDate),
         stats: document.stats,
       })

Comment thread apps/backend/src/db/index.ts Outdated
Comment thread apps/backend/src/db/queries/player-documents.ts
Comment thread apps/backend/src/index.ts
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 6b948a0 and 61aac0d.

📒 Files selected for processing (6)
  • apps/backend/src/db/index.ts (1 hunks)
  • apps/backend/src/db/queries/player-documents.ts (1 hunks)
  • apps/backend/src/index.ts (1 hunks)
  • apps/backend/src/lib/auth.ts (1 hunks)
  • apps/backend/src/lib/orpc.ts (1 hunks)
  • apps/wiki/src/custom.css (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • apps/wiki/src/custom.css
  • apps/backend/src/db/index.ts
🧰 Additional context used
🧬 Code graph analysis (4)
apps/backend/src/lib/auth.ts (2)
apps/backend/src/db/index.ts (1)
  • Database (14-14)
apps/backend/src/lib/payments.ts (1)
  • polarClient (7-10)
apps/backend/src/lib/orpc.ts (3)
apps/backend/src/lib/context.ts (1)
  • Context (13-13)
apps/backend/src/db/index.ts (2)
  • Database (14-14)
  • getDb (5-12)
apps/backend/src/lib/auth.ts (1)
  • getAuth (10-54)
apps/backend/src/db/queries/player-documents.ts (4)
apps/backend/src/db/index.ts (2)
  • Database (14-14)
  • Table (16-16)
apps/backend/src/schemas/player-document.ts (1)
  • PlayerDocument (22-22)
apps/backend/src/db/schema/players.ts (2)
  • players (4-17)
  • playerBans (23-34)
apps/backend/src/sdks/mc-heads.ts (1)
  • getPlayerHeadSkinBase64 (1-16)
apps/backend/src/index.ts (4)
apps/backend/src/lib/auth.ts (1)
  • getAuth (10-54)
apps/backend/src/db/index.ts (1)
  • getDb (5-12)
apps/backend/src/routers/index.ts (1)
  • appRouter (6-48)
apps/backend/src/lib/context.ts (1)
  • createContext (7-11)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: build-and-test
🔇 Additional comments (4)
apps/backend/src/db/queries/player-documents.ts (1)

67-70: Stop resetting firstJoinedDate to the latest join

Line 68 currently rewrites firstJoinedDate with document.lastJoinDate, so every sync erases the original first-join timestamp and makes it equal to the latest session. That destroys the historical “first seen” data this column is supposed to preserve. Please drop this assignment (or populate it from an actual document.firstJoinDate field if one exists) so we keep the original value intact.

         lastJoinedDate: new Date(document.lastJoinDate),
-        firstJoinedDate: new Date(document.lastJoinDate),
         stats: document.stats,
apps/backend/src/lib/auth.ts (1)

12-16: Use the supported Postgres provider identifier

drizzleAdapter switches on this string and only recognizes "postgresql". Leaving it as "pg" still routes you through the sqlite branch, so auth inserts/queries against Postgres will break. Please restore the correct identifier.

-      provider: "pg",
+      provider: "postgresql",
apps/backend/src/lib/orpc.ts (2)

64-67: Keep the rest of the context visible in requireAuth

This still replaces the whole context with { session }, so handlers following protectedProcedure can no longer see the DB, headers, or auth client they were given earlier. Merge instead of overwriting the object.

       return next({
         context: {
-          session: context.session,
+          ...context,
         },
       });

48-51: Preserve context when returning from sessionProvider

By returning only { session } you strip away the DB/auth/headers that protected procedures rely on. A handler that calls protectedProcedure.use(dbProvider) ends up with context.db undefined again. Merge the current context when you propagate.

     return next({
       context: {
-        session: context.session,
+        ...context,
       },
     });

Comment thread apps/backend/src/lib/orpc.ts
Comment thread apps/backend/src/lib/orpc.ts
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🧹 Nitpick comments (1)
apps/backend/Dockerfile.migrate (1)

7-9: Copy the lockfile so installs stay deterministic and cacheable.

We only copy package.json before running bun install, so the dependency graph is resolved without bun.lockb. That means every build (and CI run) can silently drift to newer dependency ranges and you also miss out on layer caching when the lockfile hasn’t changed. Please copy the lockfile alongside package.json before bun install so installs remain reproducible.

 FROM base AS deps

-COPY package.json ./
+COPY package.json bun.lockb ./

 RUN bun install
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 61aac0d and 90bd188.

⛔ Files ignored due to path filters (2)
  • bun.lock is excluded by !**/*.lock
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (24)
  • .gitignore (1 hunks)
  • README.md (1 hunks)
  • apps/backend/.dockerignore (1 hunks)
  • apps/backend/Dockerfile (1 hunks)
  • apps/backend/Dockerfile.migrate (1 hunks)
  • apps/backend/drizzle.config.ts (1 hunks)
  • apps/backend/package.json (1 hunks)
  • apps/backend/src/db/index.ts (1 hunks)
  • apps/backend/src/index.ts (1 hunks)
  • apps/backend/src/lib/auth.ts (1 hunks)
  • apps/backend/src/lib/env.ts (1 hunks)
  • apps/backend/src/lib/orpc.ts (1 hunks)
  • apps/backend/src/lib/payments.ts (1 hunks)
  • apps/backend/src/lib/redis.ts (1 hunks)
  • apps/backend/src/routers/index.ts (1 hunks)
  • apps/backend/tsconfig.json (1 hunks)
  • apps/web/.gitignore (0 hunks)
  • apps/web/package.json (2 hunks)
  • apps/web/src/router.tsx (2 hunks)
  • apps/web/vite.config.ts (1 hunks)
  • apps/wiki/astro.config.mjs (1 hunks)
  • apps/wiki/package.json (1 hunks)
  • docker-compose.yml (1 hunks)
  • package.json (1 hunks)
💤 Files with no reviewable changes (1)
  • apps/web/.gitignore
✅ Files skipped from review due to trivial changes (2)
  • apps/backend/.dockerignore
  • apps/backend/Dockerfile
🚧 Files skipped from review as they are similar to previous changes (10)
  • apps/backend/package.json
  • apps/backend/src/routers/index.ts
  • apps/backend/src/lib/auth.ts
  • apps/backend/src/db/index.ts
  • .gitignore
  • apps/wiki/package.json
  • apps/backend/tsconfig.json
  • apps/backend/src/lib/payments.ts
  • apps/backend/src/index.ts
  • README.md
🧰 Additional context used
📓 Path-based instructions (1)
package.json

📄 CodeRabbit inference engine (.cursor/rules/convex-rules.mdc)

Add @types/node to package.json when using Node.js built-in modules

Files:

  • package.json
🧠 Learnings (3)
📚 Learning: 2025-09-22T00:08:49.174Z
Learnt from: CR
PR: BetrixDev/ssm-brawl#0
File: .cursor/rules/convex-rules.mdc:0-0
Timestamp: 2025-09-22T00:08:49.174Z
Learning: Applies to package.json : Add types/node to package.json when using Node.js built-in modules

Applied to files:

  • package.json
📚 Learning: 2025-09-22T00:08:49.174Z
Learnt from: CR
PR: BetrixDev/ssm-brawl#0
File: .cursor/rules/convex-rules.mdc:0-0
Timestamp: 2025-09-22T00:08:49.174Z
Learning: Applies to convex/**/*.{ts,js} : Organize public Convex functions (query/mutation/action) within the convex/ directory, leveraging file-based routing

Applied to files:

  • apps/web/src/router.tsx
📚 Learning: 2025-09-22T00:08:49.174Z
Learnt from: CR
PR: BetrixDev/ssm-brawl#0
File: .cursor/rules/convex-rules.mdc:0-0
Timestamp: 2025-09-22T00:08:49.174Z
Learning: Applies to convex/**/*.{ts,js} : Respect file-based routing for function references (e.g., convex/example.ts export f -> api.example.f; nested paths map accordingly)

Applied to files:

  • apps/web/src/router.tsx
🧬 Code graph analysis (3)
apps/backend/src/lib/redis.ts (1)
apps/backend/src/lib/env.ts (1)
  • env (18-18)
apps/backend/src/lib/orpc.ts (5)
apps/backend/src/lib/context.ts (1)
  • Context (13-13)
apps/backend/src/lib/redis.ts (1)
  • getRedis (4-12)
apps/backend/src/db/index.ts (2)
  • Database (14-14)
  • getDb (5-12)
apps/backend/src/lib/auth.ts (1)
  • getAuth (10-53)
apps/backend/src/lib/env.ts (1)
  • env (18-18)
apps/web/src/router.tsx (2)
apps/backend/src/routers/index.ts (1)
  • AppRouterClient (51-51)
apps/web/src/contexts/rpc-context.ts (1)
  • RpcContext (7-7)
🪛 Biome (2.1.2)
apps/web/vite.config.ts

[error] 9-9: This array contains an empty slots..

The presences of empty slots may cause incorrect information and might be a typo.
Unsafe fix: Replace hole with undefined

(lint/suspicious/noSparseArray)

🔇 Additional comments (5)
apps/backend/src/lib/orpc.ts (3)

25-29: Stop clobbering context in dbProvider.

Line 27 still replaces the accumulated context with { db }, dropping headers and the kv instance. This is the same blocker called out in the previous review; we must preserve everything gathered so far.

Apply this diff:

   return next({
-    context: {
-      db: context.db,
-    },
+    context: {
+      ...context,
+    },
   });

38-42: Keep the accumulated context when setting auth.

Line 40 throws away db, kv, and headers by replacing the context with { auth }. That exact regression was already flagged; without the spread, the downstream sessionProvider can’t see the database or headers.

Apply this diff:

     return next({
-      context: {
-        auth: context.auth,
-      },
+      context: {
+        ...context,
+      },
     });

77-81: Forward the whole context inside requireAuth.

Line 79 once more shrinks the context to { session }, undoing all prior merges. When pluginProcedure composes this middleware, context.headers vanishes. Keep forwarding the merged context.

Apply this diff:

       return next({
-        context: {
-          session: context.session,
-        },
+        context: {
+          ...context,
+        },
       });
apps/web/vite.config.ts (1)

9-9: Respect TanStack Start's React plugin opt-out.
TanStack Start still auto-registers the React plugin unless you pass customViteReactPlugin: true; leaving it out while also calling viteReact() double-loads the plugin and breaks Fast Refresh. Please restore the opt-out flag.
(tanstack.com)

-  plugins: [tsconfigPaths(), tailwindcss(), tanstackStart(), nitro(), , viteReact()],
+  plugins: [
+    tsconfigPaths(),
+    tailwindcss(),
+    tanstackStart({
+      customViteReactPlugin: true,
+    }),
+    nitro(),
+    viteReact(),
+  ],
apps/backend/drizzle.config.ts (1)

8-10: Fail fast when DATABASE_URL is missing.
The non-null assertion lets undefined reach Drizzle, so the CLI fails later with an opaque connection error. Guard the env var up front and throw a clear message instead.

-import { defineConfig } from "drizzle-kit";
-
-export default defineConfig({
+import { defineConfig } from "drizzle-kit";
+
+const databaseUrl = process.env.DATABASE_URL;
+
+if (!databaseUrl) {
+  throw new Error("DATABASE_URL is not set. Configure the database connection before running drizzle-kit.");
+}
+
+export default defineConfig({
   schema: "./src/db/schema",
   out: "./src/db/migrations",
   casing: "snake_case",
   dialect: "postgresql",
   dbCredentials: {
-    url: process.env.DATABASE_URL!,
+    url: databaseUrl,
   },
 });

Comment thread apps/backend/src/lib/orpc.ts
Comment thread apps/backend/src/lib/orpc.ts
Comment thread apps/web/vite.config.ts Outdated
tanstackStart({ customViteReactPlugin: true, target: "vercel" }),
viteReact(),
],
plugins: [tsconfigPaths(), tailwindcss(), tanstackStart(), nitro(), , viteReact()],
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Remove the stray sparse slot in the plugins array.
There’s an extra comma after nitro() leaving an empty slot, so Vite receives an undefined plugin entry; drop the extra comma to keep the array dense.

-  plugins: [tsconfigPaths(), tailwindcss(), tanstackStart(), nitro(), , viteReact()],
+  plugins: [tsconfigPaths(), tailwindcss(), tanstackStart(), nitro(), viteReact()],
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
plugins: [tsconfigPaths(), tailwindcss(), tanstackStart(), nitro(), , viteReact()],
plugins: [tsconfigPaths(), tailwindcss(), tanstackStart(), nitro(), viteReact()],
🧰 Tools
🪛 Biome (2.1.2)

[error] 9-9: This array contains an empty slots..

The presences of empty slots may cause incorrect information and might be a typo.
Unsafe fix: Replace hole with undefined

(lint/suspicious/noSparseArray)

🤖 Prompt for AI Agents
In apps/web/vite.config.ts around line 9, the plugins array contains a stray
extra comma after nitro() creating an undefined plugin entry; remove the extra
comma so the array reads plugins: [tsconfigPaths(), tailwindcss(),
tanstackStart(), nitro(), viteReact()] (no empty slot) to prevent Vite from
receiving an undefined plugin.

Comment thread docker-compose.yml
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
.github/workflows/autofix.yml (1)

3-5: Restore the pull_request trigger for autofix-ci

autofix-ci/action needs PR context to push formatting fixes back to contributor branches. By restricting the workflow to push on main/reimagined, the action never runs for feature branches, so PRs lose the intended auto-formatting feedback loop. Please add back the pull_request trigger (or otherwise ensure PR events invoke this job).

🧹 Nitpick comments (2)
turbo.json (1)

8-8: Broaden the server binary output glob.

Right now only server.exe is cached, so binaries emitted on non-Windows runners (e.g., server, server-linux-x64) will be missed and need rebuilding every time. Please widen the pattern—something like server* or a dedicated bin/** directory—to cover all platforms.

.env.development.example (1)

1-6: Align env keys with dotenv-linter expectations.

dotenv-linter is flagging this file because the keys aren’t ordered alphabetically and there’s no trailing newline. Reordering the entries and adding a blank line at the end will silence those warnings and keep the lint job quiet.

-BETTER_AUTH_SECRET=
-POLAR_ACCESS_TOKEN=
-POLAR_SUCCESS_URL=
-PLUGIN_SECRET_KEY=
-REDIS_URL=
-DATABASE_URL=
+BETTER_AUTH_SECRET=
+DATABASE_URL=
+PLUGIN_SECRET_KEY=
+POLAR_ACCESS_TOKEN=
+POLAR_SUCCESS_URL=
+REDIS_URL=
+
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 90bd188 and 6f43ea9.

⛔ Files ignored due to path filters (1)
  • bun.lock is excluded by !**/*.lock
📒 Files selected for processing (16)
  • .env.development.example (1 hunks)
  • .github/workflows/autofix.yml (1 hunks)
  • .github/workflows/build-and-test.yml (2 hunks)
  • .gitignore (1 hunks)
  • apps/backend/package.json (1 hunks)
  • apps/backend/src/db/migrations/meta/0001_snapshot.json (1 hunks)
  • apps/backend/src/db/migrations/meta/_journal.json (1 hunks)
  • apps/web/.env.example (1 hunks)
  • apps/web/package.json (2 hunks)
  • apps/web/vite.config.ts (1 hunks)
  • docker-compose.yml (1 hunks)
  • package.json (1 hunks)
  • plugin/package.json (1 hunks)
  • plugin/scripts/run-gradle.mjs (1 hunks)
  • pnpm-workspace.yaml (0 hunks)
  • turbo.json (1 hunks)
💤 Files with no reviewable changes (1)
  • pnpm-workspace.yaml
🚧 Files skipped from review as they are similar to previous changes (3)
  • .gitignore
  • apps/backend/src/db/migrations/meta/0001_snapshot.json
  • apps/web/vite.config.ts
🧰 Additional context used
📓 Path-based instructions (1)
package.json

📄 CodeRabbit inference engine (.cursor/rules/convex-rules.mdc)

Add @types/node to package.json when using Node.js built-in modules

Files:

  • package.json
🧠 Learnings (2)
📚 Learning: 2025-09-22T00:09:59.281Z
Learnt from: CR
PR: BetrixDev/ssm-brawl#0
File: .cursor/rules/plugin-overview.mdc:0-0
Timestamp: 2025-09-22T00:09:59.281Z
Learning: Applies to plugin/src/main/kotlin/dev/betrix/superSmashMobsBrawl/SuperSmashMobsBrawl.kt : Keep the plugin main class at plugin/src/main/kotlin/dev/betrix/superSmashMobsBrawl/SuperSmashMobsBrawl.kt

Applied to files:

  • plugin/package.json
📚 Learning: 2025-09-22T00:08:49.174Z
Learnt from: CR
PR: BetrixDev/ssm-brawl#0
File: .cursor/rules/convex-rules.mdc:0-0
Timestamp: 2025-09-22T00:08:49.174Z
Learning: Applies to package.json : Add types/node to package.json when using Node.js built-in modules

Applied to files:

  • package.json
🪛 dotenv-linter (3.3.0)
.env.development.example

[warning] 4-4: [UnorderedKey] The PLUGIN_SECRET_KEY key should go before the POLAR_ACCESS_TOKEN key

(UnorderedKey)


[warning] 6-6: [EndingBlankLine] No blank line at the end of the file

(EndingBlankLine)


[warning] 6-6: [UnorderedKey] The DATABASE_URL key should go before the PLUGIN_SECRET_KEY key

(UnorderedKey)

apps/web/.env.example

[warning] 2-2: [EndingBlankLine] No blank line at the end of the file

(EndingBlankLine)

🔇 Additional comments (1)
apps/backend/package.json (1)

24-35: Remove the duplicate dotenv entry.
Line 24 already declares dotenv under dependencies, but Line 35 repeats it in devDependencies, which forces Bun/npm to resolve it twice and bloats the lockfile. Please keep it in a single section (runtime here) and drop the duplicate.

Apply this diff to clean it up:

   "devDependencies": {
     "@types/node": "^22.18.6",
     "@types/pg": "^8.15.5",
-    "dotenv": "^17.2.2",
     "drizzle-kit": "^0.31.5",
     "tsdown": "^0.15.5",
     "typescript": "^5.9.2",

Comment thread apps/web/.env.example Outdated
Comment on lines +1 to +2
BETTER_AUTH_SECRET=
BETTER_AUTH_URL= No newline at end of file
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Restore Vite prefixes so frontend gets the auth config.

In Vite apps only variables starting with VITE_ are exposed to the browser. Renaming these keys drops the prefix, so import.meta.env.* will be undefined at runtime and the auth client cannot reach BetterAuth. Please keep the prefix when swapping to the new auth flow.

-BETTER_AUTH_SECRET=
-BETTER_AUTH_URL=
+VITE_BETTER_AUTH_SECRET=
+VITE_BETTER_AUTH_URL=
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
BETTER_AUTH_SECRET=
BETTER_AUTH_URL=
VITE_BETTER_AUTH_SECRET=
VITE_BETTER_AUTH_URL=
🧰 Tools
🪛 dotenv-linter (3.3.0)

[warning] 2-2: [EndingBlankLine] No blank line at the end of the file

(EndingBlankLine)

🤖 Prompt for AI Agents
In apps/web/.env.example around lines 1 to 2, the environment variable names
were changed to BETTER_AUTH_* which removes the VITE_ prefix required by Vite to
expose values to the browser; restore the VITE_ prefixes so the frontend can
access them (e.g., VITE_BETTER_AUTH_SECRET and VITE_BETTER_AUTH_URL) and update
any code or docs that reference the old names to use the VITE_... variables so
import.meta.env.* provides the auth config at runtime.

Comment thread docker-compose.yml
Comment thread docker-compose.yml Outdated
Comment thread plugin/scripts/run-gradle.mjs
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 6f43ea9 and 7093d2c.

📒 Files selected for processing (5)
  • apps/web/.env.example (1 hunks)
  • docker-compose.yml (1 hunks)
  • package.json (1 hunks)
  • plugin/scripts/run-gradle.mjs (1 hunks)
  • turbo.json (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • plugin/scripts/run-gradle.mjs
🧰 Additional context used
📓 Path-based instructions (1)
package.json

📄 CodeRabbit inference engine (.cursor/rules/convex-rules.mdc)

Add @types/node to package.json when using Node.js built-in modules

Files:

  • package.json
🧠 Learnings (3)
📚 Learning: 2025-09-27T22:29:26.793Z
Learnt from: BetrixDev
PR: BetrixDev/ssm-brawl#139
File: docker-compose.yml:5-19
Timestamp: 2025-09-27T22:29:26.793Z
Learning: PostgreSQL 18 Docker image (postgres:18) is available on Docker Hub and is a valid tag for use in Docker Compose configurations.

Applied to files:

  • docker-compose.yml
📚 Learning: 2025-09-27T22:29:26.793Z
Learnt from: BetrixDev
PR: BetrixDev/ssm-brawl#139
File: docker-compose.yml:5-19
Timestamp: 2025-09-27T22:29:26.793Z
Learning: PostgreSQL 18 Docker image (postgres:18) is confirmed available on Docker Hub as of September 2025. It is the latest major PostgreSQL version and should be used instead of suggesting downgrades to postgres:17.

Applied to files:

  • docker-compose.yml
📚 Learning: 2025-09-22T00:08:49.174Z
Learnt from: CR
PR: BetrixDev/ssm-brawl#0
File: .cursor/rules/convex-rules.mdc:0-0
Timestamp: 2025-09-22T00:08:49.174Z
Learning: Applies to package.json : Add types/node to package.json when using Node.js built-in modules

Applied to files:

  • package.json
🪛 dotenv-linter (3.3.0)
apps/web/.env.example

[warning] 1-1: [EndingBlankLine] No blank line at the end of the file

(EndingBlankLine)

🔇 Additional comments (2)
apps/web/.env.example (1)

1-1: Restore Vite prefix for the BetterAuth URL.

Vite only exposes environment variables that start with VITE_. Dropping the prefix means import.meta.env won’t surface the BetterAuth URL, so the frontend auth client will read undefined at runtime. Please keep the prefix.

-BETTER_AUTH_URL=
+VITE_BETTER_AUTH_URL=
docker-compose.yml (1)

32-34: Migrate container still fails env validation

apps/backend/src/lib/env.ts continues to parse the full Better Auth/Polar/Redis schema even during migrations. When bun run db:migrate boots it imports that module (via the Drizzle config) and immediately throws a ZodError because this service only exposes DATABASE_URL. Result: the container exits before applying migrations, so docker compose up never finishes. Either relax the schema for CLI usage or inject the same env defaults you provide to api.

     environment:
+      BETTER_AUTH_SECRET: ${BETTER_AUTH_SECRET:-changeme}
+      BETTER_AUTH_URL: ${BETTER_AUTH_URL:-http://localhost:3000/api/auth}
+      POLAR_ACCESS_TOKEN: ${POLAR_ACCESS_TOKEN:-}
+      POLAR_SUCCESS_URL: ${POLAR_SUCCESS_URL:-http://localhost:3000/checkout/success}
+      POLAR_SERVER: ${POLAR_SERVER:-sandbox}
+      PLUGIN_SECRET_KEY: ${PLUGIN_SECRET_KEY:-changeme}
+      REDIS_URL: ${REDIS_URL:-redis://redis:6379/0}
       DATABASE_URL: "postgres://${POSTGRES_USER:-brawl}:${POSTGRES_PASSWORD:-brawl}@${POSTGRES_HOST:-postgres}:${POSTGRES_PORT:-5432}/${POSTGRES_DB:-brawl}"

Comment thread docker-compose.yml
Comment thread turbo.json
@BetrixDev BetrixDev merged commit 7b7c1de into reimagined Sep 27, 2025
1 of 2 checks passed
@BetrixDev BetrixDev deleted the cloudflare-deployments branch September 27, 2025 23:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant