Skip to content

ci: add CI/CD workflows and environment setup#330

Merged
saddlepaddle merged 5 commits into
mainfrom
ci-env-setup
Dec 12, 2025
Merged

ci: add CI/CD workflows and environment setup#330
saddlepaddle merged 5 commits into
mainfrom
ci-env-setup

Conversation

@saddlepaddle
Copy link
Copy Markdown
Collaborator

@saddlepaddle saddlepaddle commented Dec 12, 2025

Summary

Sets up the eventual projects we'll need. I'll expand from here for:

  • Cross-project auth
  • Cross-project Sentry
  • Cross-project Posthog
  • Connecting projects (i.e. marketing app needs to link to web app, etc.)
  • Prefilling dummy content
  • Setting up the boilerplate auth guards (i.e. nobody should know our admin url / have access to it unless it's us (should get bounced to web app)
  • Setting up boilerplate content (might be fun to throw a few dashboards in our admin app)

Test plan

  • CI workflow runs on PR
  • Preview deployment creates Neon branch
  • Cleanup runs on PR close

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • New Admin dashboard app and separate Marketing app added
    • Preview deployments now publish consolidated per-service statuses and automated cleanup comments
  • Infrastructure

    • CI and deployment workflows reorganized for multi-service builds and clearer steps
    • Improved per-service deployment status persistence and final PR summary
    • Environment handling and setup scripts simplified and parameterized
  • Removed

    • Blog application and related UI/components removed
    • Some third-party integrations pruned

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Dec 12, 2025

Walkthrough

Restructures the monorepo: adds admin/api/web/marketing apps with TRPC and env configs, replaces single deploy with multi-job GitHub Actions (per-service deployments, status artifacts, templated PR comments), parameterizes Neon scripts, removes the blog and website app artifacts, and updates TRPC user/router and global envs.

Changes

Cohort / File(s) Summary
GitHub Workflows
.github/workflows/ci.yml, .github/workflows/deploy-preview.yml, .github/workflows/cleanup-preview.yml, .github/workflows/deploy-production.yml
CI triggers expanded and step renames; preview deploy split into per-service jobs (database, api, web, marketing, admin, docs) with per-service status artifacts and final templated PR comment; cleanup workflow generates templated cleanup comment; production deploy restructured to multi-service flow.
GitHub Templates
.github/templates/preview-comment.md, .github/templates/cleanup-comment.md
New PR templates for preview deployment status and cleanup confirmation with service-level placeholders and links.
Monorepo / Tooling
turbo.jsonc, .gitignore, .neon
turbo.jsonc globalEnv updated (adds MOCK_USER_ID and new NEXT_PUBLIC_* URLs, removes several secrets); .gitignore adjusted (adds .envrc, Next.js ignores); .neon file deleted.
Neon Setup/Teardown
.superset/setup.sh, .superset/teardown.sh
Scripts parameterized to use NEON_PROJECT_ID, split pooled/unpooled URLs (DIRECT_URL/POOLED_URL), write DATABASE_URL_UNPOOLED, and validate required envs.
Docs
AGENTS.md
Reworked apps listing (api, web, marketing, admin), replaced hardcoded Neon IDs with env guidance, expanded Desktop App section.
Admin App (new)
apps/admin/... (next.config.ts, package.json, postcss.config.mjs, src/app/globals.css, src/app/layout.tsx, src/app/page.tsx, src/app/providers.tsx, src/env.ts, src/trpc/react.tsx, src/trpc/server.tsx)
New Next.js admin app with config, Tailwind/PostCSS, global CSS, root layout, TRPC client/server integrations, Providers, and a simple users dashboard; exports env/config/trpc modules.
API App (new)
apps/api/... (next-env.d.ts, next.config.ts, package.json, src/app/api/trpc/[trpc]/route.ts, src/env.ts)
New API Next.js app exposing TRPC route via fetchRequestHandler, CORS headers produced via headers() in config, and env validation.
Web App (new)
apps/web/... (next-env.d.ts, next.config.ts, package.json, postcss.config.mjs, src/app/globals.css, src/app/layout.tsx, src/app/page.tsx, src/app/providers.tsx, src/env.ts, src/trpc/query-client.ts, src/trpc/react.tsx, src/trpc/server.tsx, tsconfig.json)
New Web Next.js app with TRPC client/server factories, query client utility, env validation, layout/providers, globals, and page using TRPC queries.
Marketing App (refactor/new)
apps/marketing/... (next-env.d.ts, next.config.ts, package.json, postcss.config.mjs, src/app/layout.tsx, src/env.ts, tsconfig.json)
Marketing app added/renamed with Next config, removed TRPC deps, dev port set to 3002, env changes, and PostCSS.
Docs App
apps/docs/package.json
Development port changed from 3001 to 3004.
Blog App Removal
apps/blog/... (many files)
Entire blog application removed: package.json, next config, README, MDX pages, global CSS, MDX components, motion/three components, Header/Footer and related UI.
Website App Removal / Migration
apps/website/... (.gitignore, next.config.ts, src/app/api/trpc/[trpc]/route.ts, src/trpc/server.tsx)
Website app config and server TRPC route removed; functionality migrated into api/web/marketing/admin apps.
TRPC Package Changes
packages/trpc/src/env.ts, packages/trpc/src/router/user.ts
MOCK_USER_ID validation made required; user router gains a protected me procedure returning current user by session id.

Sequence Diagram(s)

sequenceDiagram
    participant GH as GitHub Actions
    participant DB as Neon Database
    participant VAPI as Vercel (API)
    participant VWEB as Vercel (Web)
    participant VMKT as Vercel (Marketing)
    participant VADM as Vercel (Admin)
    participant VDOC as Vercel (Docs)
    participant PR as Pull Request

    GH->>DB: deploy-database job (create branch, run migrations)
    DB-->>GH: upload artifact (database-status.env)

    par parallel deployments
        GH->>VAPI: deploy-api (needs database)
        VAPI-->>GH: upload artifact (api-status.env)

        GH->>VWEB: deploy-web (needs database)
        VWEB-->>GH: upload artifact (web-status.env)

        GH->>VMKT: deploy-marketing (needs database)
        VMKT-->>GH: upload artifact (marketing-status.env)

        GH->>VADM: deploy-admin (needs database)
        VADM-->>GH: upload artifact (admin-status.env)

        GH->>VDOC: deploy-docs (needs database)
        VDOC-->>GH: upload artifact (docs-status.env)
    end

    GH->>GH: post-final-comment job (download artifacts, render `preview-comment.md`)
    GH->>PR: post combined preview status comment
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

  • Pay special attention to:
    • .github/workflows/deploy-preview.yml and .github/workflows/deploy-production.yml (job dependencies, artifact handling, env propagation)
    • TRPC server/client factories across apps (apps/*/src/trpc/*) to ensure headers/env consistency
    • Neon setup/teardown scripts (.superset/setup.sh, .superset/teardown.sh) for safe branch deletion and env writing
    • Removed blog/website files to ensure no remaining imports or build references to deleted components

Possibly related PRs

Poem

🐰 I hopped through branches, tidy and neat,
Built halls for api, web, and admin to meet.
The old blog burrow tucked away with care,
Neon lights now sparkle everywhere.
Six deployments dance — a burrow reborn! 🌱

Pre-merge checks and finishing touches

❌ Failed checks (2 warnings)
Check name Status Explanation Resolution
Description check ⚠️ Warning The PR description is largely incomplete. While it includes a Summary section and a Test plan, it is missing all required template sections including Description (placeholder only), Related Issues, Type of Change, Testing details, and screenshots. Provide a comprehensive description covering all template sections: expand the Summary with detailed changes, link related issues, mark the Type of Change checkbox, add actual Testing steps, and include any relevant Screenshots or Additional Notes.
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 (1 passed)
Check name Status Explanation
Title check ✅ Passed The title 'ci: add CI/CD workflows and environment setup' accurately describes the main change: adding CI/CD workflows and environment configuration as shown by the workflow files and environment setup changes.
✨ Finishing touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch ci-env-setup

📜 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 8744819 and 65a1418.

📒 Files selected for processing (1)
  • .github/workflows/ci.yml (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • .github/workflows/ci.yml

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.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Dec 12, 2025

🧹 Preview Cleanup Complete

The following preview resources have been cleaned up:

Service Status
Database (Neon)

Thank you for your contribution! 🎉


Preview resources have been processed for cleanup

Copy link
Copy Markdown
Contributor

@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: 20

Caution

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

⚠️ Outside diff range comments (2)
apps/marketing/src/app/layout.tsx (1)

25-29: Fix missing React type import (React.ReactNode).
React.ReactNode (Line 28) will fail typechecking unless React is in scope; prefer import type { ReactNode } from "react" and use children: ReactNode.

 import type { Metadata } from "next";
 import { IBM_Plex_Mono, Inter } from "next/font/google";
 import Script from "next/script";
 import { ThemeProvider } from "next-themes";
+import type { ReactNode } from "react";
 import "./globals.css";
@@
 export default function RootLayout({
 	children,
 }: Readonly<{
-	children: React.ReactNode;
+	children: ReactNode;
 }>) {
apps/web/src/trpc/react.tsx (1)

31-55: Return a plain object from headers() to match tRPC's type expectations.

The httpBatchStreamLink.headers() callback must return HTTPHeaders (a plain object), not a Headers instance. Your server-side implementation already uses the correct pattern. Update the headers callback to:

 				headers() {
-					const headers = new Headers();
-					headers.set("x-trpc-source", "nextjs-react");
-					return headers;
+					return { "x-trpc-source": "nextjs-react" };
 				},
🧹 Nitpick comments (9)
.gitignore (1)

50-52: Appropriate Next.js build output ignores.

The new Next.js section correctly excludes .next and out, which are standard build and static export directories. These additions align well with the introduction of four new Next.js applications (API, Admin, Web, Marketing) in this restructuring.

Consider also ignoring .vercel if any of these Next.js apps deploy to Vercel, though this can be deferred if not currently in use.

turbo.jsonc (2)

7-7: Clarify whether these environment variables should be global or app-specific.

The additions to globalEnv make MOCK_USER_ID and cross-app URLs available to all packages in the monorepo. While appropriate for shared variables, this approach means each app receives URLs for every other app—e.g., the admin app gets NEXT_PUBLIC_MARKETING_URL and vice versa. Consider whether this is necessary or if app-specific environment configuration would be more aligned with least-privilege principles.

Additionally, verify that these variables are guaranteed to be set in all CI/CD environments; otherwise, builds could fail with undefined globals.

Also applies to: 10-12


7-7: Document the purpose and usage of MOCK_USER_ID.

MOCK_USER_ID has been added to globalEnv but there is no context about its intended use (testing, development mocking, etc.) or expected value. Add a comment or documentation clarifying this variable's purpose so contributors understand when and how to set it.

Would you like me to help add inline documentation or open a task to document all environment variables in the project's README or .env.example?

.superset/setup.sh (1)

54-58: Make .env writes idempotent (avoid duplicate keys on repeated setup runs).

Right now repeated runs will append new DATABASE_URL*/NEON_BRANCH_ID lines. Consider rewriting existing keys (e.g., use a temp file + replace) or generate a dedicated .env.local that you overwrite safely.

apps/admin/src/app/page.tsx (1)

3-22: Consider a minimal failure state for the server query
Right now any failure in user.all will hard-error the route. If this is intended as a smoke-test page, OK; otherwise consider a small try/catch and render an error message.

apps/api/src/env.ts (1)

5-12: Align/confirm DB env validation strategy across apps
apps/api uses z.string() for DB URLs (Line 5-8) while web/admin use z.string().url(). Either standardize (prefer .url() if you always expect postgres://...) or document why API is looser.

apps/admin/src/trpc/server.tsx (1)

3-7: Confirm httpBatchLink (server) vs httpBatchStreamLink (client) is intentional
Client-side code uses httpBatchStreamLink in this PR; server-side uses httpBatchLink. If you want consistent streaming semantics in RSC/server calls too, consider aligning—but only if supported by your tRPC/Next setup.

Also applies to: 15-25

apps/admin/src/app/layout.tsx (1)

11-22: Layout metadata/viewport wiring looks good.

Optional: consider using explicit hex values (e.g. #fff / #000) if you want to avoid any ambiguity with named colors.

apps/web/package.json (1)

13-44: Consider moving React Query Devtools to devDependencies (if not used in prod).

If @tanstack/react-query-devtools is only conditionally imported in development, it’s typically better as a dev dependency to avoid unnecessary prod install surface area.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 0b066f9 and 8744819.

⛔ Files ignored due to path filters (17)
  • apps/admin/public/favicon.ico is excluded by !**/*.ico
  • apps/api/public/favicon.ico is excluded by !**/*.ico
  • apps/blog/public/file.svg is excluded by !**/*.svg
  • apps/blog/public/globe.svg is excluded by !**/*.svg
  • apps/blog/public/next.svg is excluded by !**/*.svg
  • apps/blog/public/vercel.svg is excluded by !**/*.svg
  • apps/blog/public/window.svg is excluded by !**/*.svg
  • apps/blog/src/app/favicon.ico is excluded by !**/*.ico
  • apps/docs/public/favicon.ico is excluded by !**/*.ico
  • apps/marketing/public/favicon.ico is excluded by !**/*.ico
  • apps/marketing/public/hero/change-themes.gif is excluded by !**/*.gif
  • apps/marketing/public/hero/manage-terminals.gif is excluded by !**/*.gif
  • apps/marketing/public/hero/open-worktrees.gif is excluded by !**/*.gif
  • apps/marketing/public/hero/use-agents.gif is excluded by !**/*.gif
  • apps/marketing/public/title.svg is excluded by !**/*.svg
  • apps/web/public/favicon.ico is excluded by !**/*.ico
  • bun.lock is excluded by !**/*.lock
📒 Files selected for processing (72)
  • .github/templates/cleanup-comment.md (1 hunks)
  • .github/templates/preview-comment.md (1 hunks)
  • .github/workflows/ci.yml (1 hunks)
  • .github/workflows/cleanup-preview.yml (1 hunks)
  • .github/workflows/deploy-preview.yml (2 hunks)
  • .github/workflows/deploy-production.yml (1 hunks)
  • .gitignore (2 hunks)
  • .neon (0 hunks)
  • .superset/setup.sh (2 hunks)
  • .superset/teardown.sh (2 hunks)
  • AGENTS.md (2 hunks)
  • apps/admin/next.config.ts (1 hunks)
  • apps/admin/package.json (1 hunks)
  • apps/admin/postcss.config.mjs (1 hunks)
  • apps/admin/src/app/globals.css (1 hunks)
  • apps/admin/src/app/layout.tsx (1 hunks)
  • apps/admin/src/app/page.tsx (1 hunks)
  • apps/admin/src/app/providers.tsx (1 hunks)
  • apps/admin/src/env.ts (1 hunks)
  • apps/admin/src/trpc/react.tsx (1 hunks)
  • apps/admin/src/trpc/server.tsx (1 hunks)
  • apps/api/next-env.d.ts (1 hunks)
  • apps/api/next.config.ts (1 hunks)
  • apps/api/package.json (1 hunks)
  • apps/api/src/app/api/trpc/[trpc]/route.ts (1 hunks)
  • apps/api/src/env.ts (1 hunks)
  • apps/blog/.gitignore (0 hunks)
  • apps/blog/README.md (0 hunks)
  • apps/blog/mdx-components.tsx (0 hunks)
  • apps/blog/next.config.ts (0 hunks)
  • apps/blog/package.json (0 hunks)
  • apps/blog/src/app/building-with-nextra.mdx (0 hunks)
  • apps/blog/src/app/globals.css (0 hunks)
  • apps/blog/src/app/hello-world.mdx (0 hunks)
  • apps/blog/src/app/layout.tsx (0 hunks)
  • apps/blog/src/app/page.mdx (0 hunks)
  • apps/blog/src/components/Footer.tsx (0 hunks)
  • apps/blog/src/components/Header.tsx (0 hunks)
  • apps/blog/src/components/motion/FadeUp.tsx (0 hunks)
  • apps/blog/src/components/motion/HeroParallax.tsx (0 hunks)
  • apps/blog/src/components/motion/TiltCard.tsx (0 hunks)
  • apps/blog/src/components/motion/index.ts (0 hunks)
  • apps/blog/src/components/three/HeroCanvas.tsx (0 hunks)
  • apps/blog/src/components/three/index.ts (0 hunks)
  • apps/docs/package.json (1 hunks)
  • apps/marketing/next-env.d.ts (1 hunks)
  • apps/marketing/next.config.ts (1 hunks)
  • apps/marketing/package.json (2 hunks)
  • apps/marketing/postcss.config.mjs (1 hunks)
  • apps/marketing/src/app/layout.tsx (1 hunks)
  • apps/marketing/src/env.ts (1 hunks)
  • apps/marketing/tsconfig.json (1 hunks)
  • apps/web/next-env.d.ts (1 hunks)
  • apps/web/next.config.ts (1 hunks)
  • apps/web/package.json (1 hunks)
  • apps/web/postcss.config.mjs (1 hunks)
  • apps/web/src/app/globals.css (1 hunks)
  • apps/web/src/app/layout.tsx (1 hunks)
  • apps/web/src/app/page.tsx (1 hunks)
  • apps/web/src/app/providers.tsx (1 hunks)
  • apps/web/src/env.ts (1 hunks)
  • apps/web/src/trpc/query-client.ts (1 hunks)
  • apps/web/src/trpc/react.tsx (3 hunks)
  • apps/web/src/trpc/server.tsx (1 hunks)
  • apps/web/tsconfig.json (1 hunks)
  • apps/website/.gitignore (0 hunks)
  • apps/website/next.config.ts (0 hunks)
  • apps/website/src/app/api/trpc/[trpc]/route.ts (0 hunks)
  • apps/website/src/trpc/server.tsx (0 hunks)
  • packages/trpc/src/env.ts (1 hunks)
  • packages/trpc/src/router/user.ts (1 hunks)
  • turbo.jsonc (1 hunks)
💤 Files with no reviewable changes (23)
  • apps/blog/README.md
  • apps/blog/src/components/three/index.ts
  • apps/blog/src/app/building-with-nextra.mdx
  • apps/blog/mdx-components.tsx
  • apps/blog/src/components/Footer.tsx
  • apps/blog/src/components/motion/index.ts
  • .neon
  • apps/blog/package.json
  • apps/blog/src/components/motion/HeroParallax.tsx
  • apps/blog/src/app/hello-world.mdx
  • apps/website/src/trpc/server.tsx
  • apps/website/next.config.ts
  • apps/blog/src/app/globals.css
  • apps/blog/src/components/motion/TiltCard.tsx
  • apps/website/.gitignore
  • apps/blog/src/components/motion/FadeUp.tsx
  • apps/blog/src/components/three/HeroCanvas.tsx
  • apps/blog/.gitignore
  • apps/blog/src/components/Header.tsx
  • apps/blog/next.config.ts
  • apps/blog/src/app/layout.tsx
  • apps/website/src/app/api/trpc/[trpc]/route.ts
  • apps/blog/src/app/page.mdx
🧰 Additional context used
📓 Path-based instructions (2)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Maintain type safety and avoid using any unless absolutely necessary in TypeScript code

Files:

  • apps/web/src/app/providers.tsx
  • apps/admin/src/app/layout.tsx
  • apps/web/src/app/page.tsx
  • apps/admin/next.config.ts
  • apps/admin/src/app/page.tsx
  • apps/web/next.config.ts
  • apps/admin/src/trpc/react.tsx
  • apps/marketing/next.config.ts
  • apps/admin/src/trpc/server.tsx
  • apps/web/next-env.d.ts
  • apps/marketing/src/app/layout.tsx
  • apps/api/src/app/api/trpc/[trpc]/route.ts
  • apps/web/src/env.ts
  • apps/web/src/app/layout.tsx
  • apps/web/src/trpc/query-client.ts
  • packages/trpc/src/env.ts
  • apps/api/src/env.ts
  • apps/api/next-env.d.ts
  • apps/admin/src/app/providers.tsx
  • apps/marketing/next-env.d.ts
  • apps/admin/src/env.ts
  • apps/web/src/trpc/react.tsx
  • apps/api/next.config.ts
  • packages/trpc/src/router/user.ts
  • apps/web/src/trpc/server.tsx
  • apps/marketing/src/env.ts
AGENTS.md

📄 CodeRabbit inference engine (CLAUDE.md)

Document agent responsibilities and interactions in AGENTS.md

Files:

  • AGENTS.md
🧠 Learnings (13)
📚 Learning: 2025-12-08T23:32:32.232Z
Learnt from: CR
Repo: superset-sh/superset PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-08T23:32:32.232Z
Learning: Use React + TailwindCSS v4 + shadcn/ui for UI components

Applied to files:

  • apps/admin/src/app/layout.tsx
  • apps/admin/src/app/providers.tsx
  • apps/marketing/package.json
  • apps/admin/src/app/globals.css
  • apps/web/src/app/globals.css
📚 Learning: 2025-11-24T21:33:13.267Z
Learnt from: CR
Repo: superset-sh/superset PR: 0
File: apps/desktop/AGENTS.md:0-0
Timestamp: 2025-11-24T21:33:13.267Z
Learning: Applies to apps/desktop/**/*.{ts,tsx} : Please use alias as defined in `tsconfig.json` when possible

Applied to files:

  • apps/admin/next.config.ts
  • apps/web/next-env.d.ts
  • apps/api/next-env.d.ts
  • apps/web/tsconfig.json
  • apps/marketing/next-env.d.ts
  • apps/marketing/tsconfig.json
📚 Learning: 2025-11-24T21:33:13.267Z
Learnt from: CR
Repo: superset-sh/superset PR: 0
File: apps/desktop/AGENTS.md:0-0
Timestamp: 2025-11-24T21:33:13.267Z
Learning: Applies to apps/desktop/**/*.{ts,tsx,js,jsx} : For Electron interprocess communication, ALWAYS use tRPC as defined in `src/lib/trpc`

Applied to files:

  • apps/admin/src/trpc/react.tsx
  • apps/admin/src/trpc/server.tsx
  • apps/api/src/app/api/trpc/[trpc]/route.ts
  • apps/web/src/trpc/react.tsx
  • apps/web/src/trpc/server.tsx
📚 Learning: 2025-12-08T23:32:32.232Z
Learnt from: CR
Repo: superset-sh/superset PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-08T23:32:32.232Z
Learning: Applies to apps/desktop/src/renderer/**/*.{ts,tsx} : Never import Node.js modules in renderer process or shared code - only in src/main/

Applied to files:

  • apps/web/next-env.d.ts
  • apps/api/next-env.d.ts
  • apps/marketing/next-env.d.ts
📚 Learning: 2025-12-08T23:32:32.232Z
Learnt from: CR
Repo: superset-sh/superset PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-08T23:32:32.232Z
Learning: Applies to **/*.{ts,tsx} : Maintain type safety and avoid using `any` unless absolutely necessary in TypeScript code

Applied to files:

  • apps/web/next-env.d.ts
  • apps/api/next-env.d.ts
  • apps/web/tsconfig.json
  • apps/marketing/next-env.d.ts
  • apps/marketing/tsconfig.json
📚 Learning: 2025-12-08T23:32:32.232Z
Learnt from: CR
Repo: superset-sh/superset PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-08T23:32:32.232Z
Learning: Applies to apps/desktop/src/lib/**/*.{ts,tsx} : Never import Node.js modules like node:fs, node:path, node:os in src/lib/electron-router-dom.ts or similar shared code

Applied to files:

  • apps/web/next-env.d.ts
  • apps/api/next-env.d.ts
  • apps/marketing/next-env.d.ts
📚 Learning: 2025-12-08T23:32:32.232Z
Learnt from: CR
Repo: superset-sh/superset PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-08T23:32:32.232Z
Learning: Applies to apps/desktop/src/main/index.ts : Load environment variables from monorepo root .env file in src/main/index.ts with override: true

Applied to files:

  • apps/web/src/env.ts
  • turbo.jsonc
  • apps/api/src/env.ts
  • apps/admin/src/env.ts
  • .gitignore
📚 Learning: 2025-11-24T21:32:21.725Z
Learnt from: CR
Repo: superset-sh/superset PR: 0
File: apps/desktop/CLAUDE.md:0-0
Timestamp: 2025-11-24T21:32:21.725Z
Learning: Applies to apps/desktop/**/AGENTS.md : Document agent responsibilities, capabilities, and interaction patterns in AGENTS.md

Applied to files:

  • AGENTS.md
📚 Learning: 2025-11-24T21:32:17.800Z
Learnt from: CR
Repo: superset-sh/superset PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-24T21:32:17.800Z
Learning: Applies to AGENTS.md : Document agent responsibilities and interactions in AGENTS.md

Applied to files:

  • AGENTS.md
📚 Learning: 2025-12-08T23:32:32.232Z
Learnt from: CR
Repo: superset-sh/superset PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-08T23:32:32.232Z
Learning: Use Turborepo for the build system in this Bun monorepo

Applied to files:

  • AGENTS.md
  • .gitignore
📚 Learning: 2025-12-08T23:32:32.232Z
Learnt from: CR
Repo: superset-sh/superset PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-08T23:32:32.232Z
Learning: Create database migrations by modifying Drizzle schema in packages/db/src/ then running drizzle-kit generate

Applied to files:

  • AGENTS.md
📚 Learning: 2025-12-08T23:32:32.232Z
Learnt from: CR
Repo: superset-sh/superset PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-08T23:32:32.232Z
Learning: Applies to src/components/{ui,ai-elements,react-flow}/**/*.tsx : Use kebab-case single files for shadcn/ui components in src/components/ui/, src/components/ai-elements, and src/components/react-flow/

Applied to files:

  • apps/marketing/tsconfig.json
📚 Learning: 2025-12-08T23:32:32.232Z
Learnt from: CR
Repo: superset-sh/superset PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-08T23:32:32.232Z
Learning: Applies to apps/desktop/src/main/lib/*{workspace,worktree}-*.ts : Use git worktree-based workspace management in the desktop app through workspace-manager.ts and worktree-manager.ts

Applied to files:

  • apps/web/package.json
🧬 Code graph analysis (14)
apps/web/src/app/page.tsx (3)
apps/admin/src/trpc/server.tsx (1)
  • api (11-26)
apps/web/src/trpc/server.tsx (1)
  • api (11-26)
packages/db/src/schema/schema.ts (1)
  • users (15-29)
.superset/teardown.sh (1)
.superset/setup.sh (1)
  • error (8-8)
apps/admin/src/app/page.tsx (4)
apps/web/src/app/page.tsx (1)
  • Home (3-58)
packages/db/src/schema/schema.ts (1)
  • users (15-29)
apps/admin/src/trpc/server.tsx (1)
  • api (11-26)
apps/web/src/trpc/server.tsx (1)
  • api (11-26)
apps/web/src/env.ts (4)
apps/admin/src/env.ts (1)
  • env (5-32)
apps/api/src/env.ts (1)
  • env (4-19)
apps/marketing/src/env.ts (1)
  • env (5-21)
packages/trpc/src/env.ts (1)
  • env (4-12)
apps/web/src/app/layout.tsx (3)
apps/admin/src/app/layout.tsx (1)
  • RootLayout (23-44)
packages/ui/src/lib/utils.ts (1)
  • cn (4-6)
apps/web/src/app/providers.tsx (1)
  • Providers (8-22)
apps/web/src/trpc/query-client.ts (1)
apps/admin/src/trpc/query-client.ts (1)
  • createQueryClient (7-24)
.superset/setup.sh (1)
.superset/teardown.sh (1)
  • error (8-8)
apps/api/src/env.ts (3)
apps/admin/src/env.ts (1)
  • env (5-32)
apps/marketing/src/env.ts (1)
  • env (5-21)
apps/web/src/env.ts (1)
  • env (5-34)
apps/admin/src/app/providers.tsx (3)
apps/web/src/app/providers.tsx (1)
  • Providers (8-22)
apps/admin/src/trpc/react.tsx (1)
  • TRPCReactProvider (33-64)
apps/web/src/trpc/react.tsx (1)
  • TRPCReactProvider (35-66)
apps/admin/src/env.ts (3)
apps/api/src/env.ts (1)
  • env (4-19)
apps/marketing/src/env.ts (1)
  • env (5-21)
apps/web/src/env.ts (1)
  • env (5-34)
apps/web/src/trpc/react.tsx (2)
apps/admin/src/trpc/react.tsx (1)
  • context (30-30)
apps/web/src/env.ts (1)
  • env (5-34)
apps/api/next.config.ts (1)
apps/api/src/env.ts (1)
  • env (4-19)
packages/trpc/src/router/user.ts (1)
packages/db/src/schema/schema.ts (1)
  • users (15-29)
apps/web/src/trpc/server.tsx (3)
apps/admin/src/trpc/server.tsx (2)
  • api (11-26)
  • headers (20-22)
apps/api/src/env.ts (1)
  • env (4-19)
apps/web/src/env.ts (1)
  • env (5-34)
🪛 actionlint (1.7.9)
.github/workflows/deploy-production.yml

74-74: shellcheck reported issue in this script: SC2086:info:1:52: Double quote to prevent globbing and word splitting

(shellcheck)


74-74: shellcheck reported issue in this script: SC2086:info:2:29: Double quote to prevent globbing and word splitting

(shellcheck)


74-74: shellcheck reported issue in this script: SC2086:info:3:41: Double quote to prevent globbing and word splitting

(shellcheck)


117-117: shellcheck reported issue in this script: SC2086:info:1:52: Double quote to prevent globbing and word splitting

(shellcheck)


117-117: shellcheck reported issue in this script: SC2086:info:2:29: Double quote to prevent globbing and word splitting

(shellcheck)


117-117: shellcheck reported issue in this script: SC2086:info:3:41: Double quote to prevent globbing and word splitting

(shellcheck)


155-155: shellcheck reported issue in this script: SC2086:info:1:52: Double quote to prevent globbing and word splitting

(shellcheck)


155-155: shellcheck reported issue in this script: SC2086:info:2:29: Double quote to prevent globbing and word splitting

(shellcheck)


155-155: shellcheck reported issue in this script: SC2086:info:3:41: Double quote to prevent globbing and word splitting

(shellcheck)


197-197: shellcheck reported issue in this script: SC2086:info:1:52: Double quote to prevent globbing and word splitting

(shellcheck)


197-197: shellcheck reported issue in this script: SC2086:info:2:29: Double quote to prevent globbing and word splitting

(shellcheck)


197-197: shellcheck reported issue in this script: SC2086:info:3:41: Double quote to prevent globbing and word splitting

(shellcheck)


237-237: shellcheck reported issue in this script: SC2086:info:1:52: Double quote to prevent globbing and word splitting

(shellcheck)


237-237: shellcheck reported issue in this script: SC2086:info:2:29: Double quote to prevent globbing and word splitting

(shellcheck)


237-237: shellcheck reported issue in this script: SC2086:info:3:41: Double quote to prevent globbing and word splitting

(shellcheck)

.github/workflows/deploy-preview.yml

96-96: shellcheck reported issue in this script: SC2086:info:2:38: Double quote to prevent globbing and word splitting

(shellcheck)


96-96: shellcheck reported issue in this script: SC2086:info:3:56: Double quote to prevent globbing and word splitting

(shellcheck)


124-124: shellcheck reported issue in this script: SC2086:info:1:49: Double quote to prevent globbing and word splitting

(shellcheck)


124-124: shellcheck reported issue in this script: SC2086:info:2:22: Double quote to prevent globbing and word splitting

(shellcheck)


124-124: shellcheck reported issue in this script: SC2086:info:3:47: Double quote to prevent globbing and word splitting

(shellcheck)


124-124: shellcheck reported issue in this script: SC2086:info:4:14: Double quote to prevent globbing and word splitting

(shellcheck)


124-124: shellcheck reported issue in this script: SC2086:info:4:55: Double quote to prevent globbing and word splitting

(shellcheck)


124-124: shellcheck reported issue in this script: SC2086:info:4:78: Double quote to prevent globbing and word splitting

(shellcheck)


124-124: shellcheck reported issue in this script: SC2086:info:5:34: Double quote to prevent globbing and word splitting

(shellcheck)


172-172: shellcheck reported issue in this script: SC2086:info:2:38: Double quote to prevent globbing and word splitting

(shellcheck)


172-172: shellcheck reported issue in this script: SC2086:info:3:56: Double quote to prevent globbing and word splitting

(shellcheck)


195-195: shellcheck reported issue in this script: SC2086:info:1:49: Double quote to prevent globbing and word splitting

(shellcheck)


195-195: shellcheck reported issue in this script: SC2086:info:2:22: Double quote to prevent globbing and word splitting

(shellcheck)


195-195: shellcheck reported issue in this script: SC2086:info:3:47: Double quote to prevent globbing and word splitting

(shellcheck)


195-195: shellcheck reported issue in this script: SC2086:info:4:14: Double quote to prevent globbing and word splitting

(shellcheck)


195-195: shellcheck reported issue in this script: SC2086:info:4:55: Double quote to prevent globbing and word splitting

(shellcheck)


195-195: shellcheck reported issue in this script: SC2086:info:4:78: Double quote to prevent globbing and word splitting

(shellcheck)


195-195: shellcheck reported issue in this script: SC2086:info:5:34: Double quote to prevent globbing and word splitting

(shellcheck)


249-249: shellcheck reported issue in this script: SC2086:info:1:49: Double quote to prevent globbing and word splitting

(shellcheck)


249-249: shellcheck reported issue in this script: SC2086:info:2:22: Double quote to prevent globbing and word splitting

(shellcheck)


249-249: shellcheck reported issue in this script: SC2086:info:3:47: Double quote to prevent globbing and word splitting

(shellcheck)


249-249: shellcheck reported issue in this script: SC2086:info:4:14: Double quote to prevent globbing and word splitting

(shellcheck)


249-249: shellcheck reported issue in this script: SC2086:info:4:61: Double quote to prevent globbing and word splitting

(shellcheck)


249-249: shellcheck reported issue in this script: SC2086:info:4:84: Double quote to prevent globbing and word splitting

(shellcheck)


249-249: shellcheck reported issue in this script: SC2086:info:5:34: Double quote to prevent globbing and word splitting

(shellcheck)


290-290: shellcheck reported issue in this script: SC2086:info:2:38: Double quote to prevent globbing and word splitting

(shellcheck)


290-290: shellcheck reported issue in this script: SC2086:info:3:56: Double quote to prevent globbing and word splitting

(shellcheck)


318-318: shellcheck reported issue in this script: SC2086:info:1:49: Double quote to prevent globbing and word splitting

(shellcheck)


318-318: shellcheck reported issue in this script: SC2086:info:2:22: Double quote to prevent globbing and word splitting

(shellcheck)


318-318: shellcheck reported issue in this script: SC2086:info:3:47: Double quote to prevent globbing and word splitting

(shellcheck)


318-318: shellcheck reported issue in this script: SC2086:info:4:14: Double quote to prevent globbing and word splitting

(shellcheck)


318-318: shellcheck reported issue in this script: SC2086:info:4:57: Double quote to prevent globbing and word splitting

(shellcheck)


318-318: shellcheck reported issue in this script: SC2086:info:4:80: Double quote to prevent globbing and word splitting

(shellcheck)


318-318: shellcheck reported issue in this script: SC2086:info:5:34: Double quote to prevent globbing and word splitting

(shellcheck)


374-374: shellcheck reported issue in this script: SC2086:info:1:49: Double quote to prevent globbing and word splitting

(shellcheck)


374-374: shellcheck reported issue in this script: SC2086:info:2:22: Double quote to prevent globbing and word splitting

(shellcheck)


374-374: shellcheck reported issue in this script: SC2086:info:3:47: Double quote to prevent globbing and word splitting

(shellcheck)


374-374: shellcheck reported issue in this script: SC2086:info:4:14: Double quote to prevent globbing and word splitting

(shellcheck)


374-374: shellcheck reported issue in this script: SC2086:info:4:56: Double quote to prevent globbing and word splitting

(shellcheck)


374-374: shellcheck reported issue in this script: SC2086:info:4:79: Double quote to prevent globbing and word splitting

(shellcheck)


374-374: shellcheck reported issue in this script: SC2086:info:5:34: Double quote to prevent globbing and word splitting

(shellcheck)

🪛 markdownlint-cli2 (0.18.1)
.github/templates/preview-comment.md

12-12: Images should have alternate text (alt text)

(MD045, no-alt-text)


17-17: Images should have alternate text (alt text)

(MD045, no-alt-text)


22-22: Images should have alternate text (alt text)

(MD045, no-alt-text)


27-27: Images should have alternate text (alt text)

(MD045, no-alt-text)


32-32: Images should have alternate text (alt text)

(MD045, no-alt-text)


37-37: Images should have alternate text (alt text)

(MD045, no-alt-text)


45-45: Emphasis used instead of a heading

(MD036, no-emphasis-as-heading)

.github/templates/cleanup-comment.md

11-11: Images should have alternate text (alt text)

(MD045, no-alt-text)


19-19: Emphasis used instead of a heading

(MD036, no-emphasis-as-heading)

⏰ 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). (5)
  • GitHub Check: Deploy Admin
  • GitHub Check: Deploy Marketing
  • GitHub Check: Deploy Docs
  • GitHub Check: Deploy API
  • GitHub Check: Deploy Web
🔇 Additional comments (28)
.gitignore (1)

36-40: Well-organized environment configuration ignores.

Moving .envrc from the Turbo section to the dedicated "Env variables" section is semantically correct and better reflects its purpose. This aligns with the monorepo's shift toward centralized environment setup per the PR objectives.

apps/docs/package.json (1)

12-35: Dependency versions align with documented library support.

The pinned versions for React 19.1.1, Next.js 15.5.7, Tailwind CSS 4.0.9, and TypeScript 5.9.3 are consistent with the documented support for these libraries, and the type packages match React 19's TypeScript requirements.

.superset/teardown.sh (1)

16-19: Good: require NEON_PROJECT_ID and pass it explicitly to neonctl.

Also applies to: 32-32

.github/workflows/cleanup-preview.yml (1)

16-39: LGTM: templated cleanup comment + artifactless status computation is clean.

.github/workflows/ci.yml (1)

6-80: CI structure is sound. Bun 1.3.3 is compatible with setup-bun@v2, and ~/.bun/install/cache is the correct default cache path on ubuntu-latest. The workflow configuration is correct.

apps/web/postcss.config.mjs (1)

1-5: Config looks fine; verify it matches your Tailwind v4 setup.
Given Tailwind v4’s split packages, confirm Next builds pick up this PostCSS config as expected for the web app.

apps/web/tsconfig.json (1)

1-11: LGTM: @/* alias + shared base config are sensible.
Encourage using @/… imports in this app to match the alias and repo learnings.

apps/api/next-env.d.ts (1)

1-6: Looks standard; verify the .next/types/routes.d.ts reference is valid in your build.
If typed routes aren’t enabled/produced for apps/api, this reference can break editor/tsc in clean checkouts.

apps/marketing/tsconfig.json (1)

1-11: LGTM: consistent TS config + path alias.
Same note: prefer @/… imports where possible.

apps/web/next-env.d.ts (1)

1-6: Standard Next next-env.d.ts; verify typed routes reference path.
Make sure apps/web actually generates .next/types/routes.d.ts under your Next.js + typed routes settings.

apps/web/next.config.ts (1)

3-8: Consider the architectural rationale before changing typescript.ignoreBuildErrors: true.

The codebase intentionally decouples Next.js build-time TypeScript handling from type safety enforcement. A separate typecheck job in CI (.github/workflows/ci.yml) runs tsc --noEmit and catches TypeScript errors as a parallel gate. This pattern is consistent across all Next.js apps (apps/web, apps/admin, apps/api, apps/marketing), indicating it's a deliberate monorepo decision.

If the typecheck CI job is enforced as a required status check for merges, the current setup is safe and intentional. If it is not enforced, then the concern is valid and this should be addressed by making typecheck a required merge gate rather than changing the Next.js config.

apps/marketing/next-env.d.ts (1)

1-6: LGTM - Standard Next.js type declarations.

This is the standard auto-generated Next.js environment declaration file. The references and structure are correct.

apps/admin/postcss.config.mjs (1)

1-5: LGTM - Cleaner inline export.

The inline export is functionally equivalent to the previous pattern and slightly more concise. This change is consistent with the pattern applied across other PostCSS configs in this PR.

AGENTS.md (3)

9-12: LGTM - Accurate app structure documentation.

The updated apps list correctly reflects the new monorepo structure introduced in this PR (web, marketing, admin, api).


156-157: LGTM - Improved Neon configuration guidance.

Using environment variables for Neon org/project IDs is more secure than hardcoding them in documentation. This aligns with the environment configuration patterns established across the apps in this PR.


159-261: LGTM - Comprehensive desktop app documentation.

The desktop app section provides clear guidance on:

  • Architecture and IPC communication
  • Node.js module import restrictions
  • Type-safe IPC system usage
  • Environment variable loading

This documentation follows the learning pattern to document agent responsibilities and interactions in AGENTS.md.

Based on learnings, comprehensive documentation of agent responsibilities and interaction patterns is maintained.

apps/admin/next.config.ts (1)

4-6: LGTM - React Compiler experiment enabled.

Enabling the experimental React Compiler is appropriate for testing Next.js 15's new compilation features.

apps/admin/package.json (1)

1-45: LGTM - Standard Next.js app configuration.

The package.json follows monorepo best practices:

  • Proper workspace dependencies via workspace:*
  • Correct Next.js 15.5.7, React 19.1.1, and Zod 4.1.13 versions matching the documented library versions
  • Dev server on port 3003 avoids conflicts with other apps
  • Standard lifecycle scripts for build, dev, and typecheck
apps/marketing/postcss.config.mjs (1)

1-5: LGTM - Consistent inline export pattern.

This matches the inline export pattern applied in apps/admin/postcss.config.mjs, maintaining consistency across the monorepo PostCSS configurations.

apps/admin/src/app/globals.css (1)

1-4: LGTM - Consistent with web app globals.

This file follows the same pattern as apps/web/src/app/globals.css:

  • Tailwind v4 import syntax
  • Shared UI globals from workspace package
  • @source directive for content detection with correct relative path

The consistency across apps ensures a unified styling baseline.

apps/web/src/app/globals.css (1)

1-4: Tailwind v4 @source directive syntax is correct.

The @source directive syntax and path resolution are verified as correct per Tailwind v4 documentation:

  • @source "../../../../packages/ui/src/**/*.{ts,tsx}"; follows the documented syntax
  • The relative path correctly resolves from apps/web/src/app/ to the UI package source directory
  • The glob pattern with file extensions is valid and supported in Tailwind v4
  • All imports and directives are properly ordered
apps/web/src/app/providers.tsx (1)

11-16: Confirm intended theme persistence behavior across apps on the same origin
storageKey="superset-theme" (Line 15): if apps/web and apps/admin ever share an origin, decide whether you want a shared theme key across apps or intentionally separate keys (admin currently uses a different key).

apps/web/src/app/layout.tsx (1)

1-44: LGTM! Clean Next.js 15 App Router layout implementation.

The layout follows Next.js 15 and React 19 best practices with proper metadata exports, viewport configuration, font integration, and provider wrapping. The structure is consistent with other app layouts in the monorepo.

apps/admin/src/trpc/react.tsx (2)

18-27: LGTM! Correct QueryClient singleton pattern.

The singleton pattern correctly creates a new QueryClient per request on the server (preventing cross-request state pollution) while maintaining a singleton on the client for performance.


33-64: LGTM! Well-configured tRPC React provider.

The provider implementation follows tRPC best practices:

  • Correct use of useState to prevent client recreation
  • Appropriate logger configuration (dev + errors)
  • SuperJSON transformer for complex types
  • Proper environment variable usage for API URL
  • Correct provider nesting order
apps/marketing/package.json (2)

38-38: React Compiler is properly configured.

The babel-plugin-react-compiler addition to devDependencies aligns with the configuration in apps/marketing/next.config.ts, where experimental.reactCompiler is explicitly set to true. No conflicting Babel configuration files exist in the marketing app directory, and Next.js 15 will automatically handle the React Compiler plugin without requiring separate Babel setup.


13-28: Remove unused NEXT_PUBLIC_API_URL from env.ts.

tRPC dependencies have been correctly removed, but apps/marketing/src/env.ts still requires NEXT_PUBLIC_API_URL in the client schema. This variable is not used anywhere in the marketing app codebase—there are no API calls, fetch patterns, or references to it. Remove the NEXT_PUBLIC_API_URL requirement from the client schema in env.ts (lines 14 and 18).

⛔ Skipped due to learnings
Learnt from: CR
Repo: superset-sh/superset PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-08T23:32:32.232Z
Learning: Use React + TailwindCSS v4 + shadcn/ui for UI components
apps/marketing/src/env.ts (1)

12-20: Deployment configuration verified for NEXT_PUBLIC_API_URL.

The environment schema requires NEXT_PUBLIC_API_URL as a client-side variable. This is already properly configured in all deployment workflows:

  • Production: NEXT_PUBLIC_API_URL is set via GitHub secrets in deploy-production.yml
  • Preview: NEXT_PUBLIC_API_URL is constructed from API_ALIAS in deploy-preview.yml

No action needed—deployment configuration is complete.

Comment on lines +5 to +14
<table>
<tr>
<th align="left">Service</th>
<th align="center">Status</th>
</tr>
<tr>
<td><img src="https://neon.com/favicon.ico" width="20" height="20"> <strong>Database (Neon)</strong></td>
<td align="center">$NEON_STATUS</td>
</tr>
</table>
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Add alt text to <img> and avoid MD036 emphasis-as-heading.

-<td><img src="https://neon.com/favicon.ico" width="20" height="20"> <strong>Database (Neon)</strong></td>
+<td><img alt="Neon" src="https://neon.com/favicon.ico" width="20" height="20"> <strong>Database (Neon)</strong></td>

-*Preview resources have been processed for cleanup*
+Preview resources have been processed for cleanup.

Also applies to: 19-19

🧰 Tools
🪛 markdownlint-cli2 (0.18.1)

11-11: Images should have alternate text (alt text)

(MD045, no-alt-text)

🤖 Prompt for AI Agents
In .github/templates/cleanup-comment.md around lines 5-14 (also applies to line
19), the <img> tag lacks an alt attribute and the bold text is triggering MD036
emphasis-as-heading; add a meaningful alt attribute to the image (e.g.,
alt="Neon logo") and replace the bold heading markup with plain text or a proper
heading syntax to avoid emphasis-as-heading (or remove unnecessary emphasis),
ensuring the table cell content remains valid markdown without using bold as a
heading.

Comment on lines +5 to +41
<table>
<tr>
<th align="left">Service</th>
<th align="center">Status</th>
<th align="left">Link</th>
</tr>
<tr>
<td><img src="https://neon.com/favicon.ico" width="20" height="20"> <strong>Database (Neon)</strong></td>
<td align="center">$DATABASE_STATUS</td>
<td>$DATABASE_LINK</td>
</tr>
<tr>
<td><img src="https://vercel.com/favicon.ico" width="20" height="20"> <strong>API (Vercel)</strong></td>
<td align="center">$API_STATUS</td>
<td>$API_LINK</td>
</tr>
<tr>
<td><img src="https://vercel.com/favicon.ico" width="20" height="20"> <strong>Web (Vercel)</strong></td>
<td align="center">$WEB_STATUS</td>
<td>$WEB_LINK</td>
</tr>
<tr>
<td><img src="https://vercel.com/favicon.ico" width="20" height="20"> <strong>Marketing (Vercel)</strong></td>
<td align="center">$MARKETING_STATUS</td>
<td>$MARKETING_LINK</td>
</tr>
<tr>
<td><img src="https://vercel.com/favicon.ico" width="20" height="20"> <strong>Admin (Vercel)</strong></td>
<td align="center">$ADMIN_STATUS</td>
<td>$ADMIN_LINK</td>
</tr>
<tr>
<td><img src="https://vercel.com/favicon.ico" width="20" height="20"> <strong>Docs (Vercel)</strong></td>
<td align="center">$DOCS_STATUS</td>
<td>$DOCS_LINK</td>
</tr>
</table>
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Add alt text to <img> and avoid MD036 emphasis-as-heading.
markdownlint will keep failing on MD045/MD036 as written.

-<td><img src="https://neon.com/favicon.ico" width="20" height="20"> <strong>Database (Neon)</strong></td>
+<td><img alt="Neon" src="https://neon.com/favicon.ico" width="20" height="20"> <strong>Database (Neon)</strong></td>

-<td><img src="https://vercel.com/favicon.ico" width="20" height="20"> <strong>API (Vercel)</strong></td>
+<td><img alt="Vercel" src="https://vercel.com/favicon.ico" width="20" height="20"> <strong>API (Vercel)</strong></td>
...
-*Preview updates automatically with new commits*
+Preview updates automatically with new commits.

Also applies to: 45-45

🧰 Tools
🪛 markdownlint-cli2 (0.18.1)

12-12: Images should have alternate text (alt text)

(MD045, no-alt-text)


17-17: Images should have alternate text (alt text)

(MD045, no-alt-text)


22-22: Images should have alternate text (alt text)

(MD045, no-alt-text)


27-27: Images should have alternate text (alt text)

(MD045, no-alt-text)


32-32: Images should have alternate text (alt text)

(MD045, no-alt-text)


37-37: Images should have alternate text (alt text)

(MD045, no-alt-text)

🤖 Prompt for AI Agents
.github/templates/preview-comment.md lines 5-41 (and also line 45): the <img>
tags in the service table are missing alt attributes and some bolded text is
being treated as emphasis-as-heading (MD036) causing markdownlint failures; add
meaningful alt text to each <img> (e.g., alt="Neon favicon", alt="Vercel
favicon") and remove/avoid emphasis-as-heading by not using leading emphasis for
headings—use plain text or proper heading markup with a blank line before it so
MD036/MD045 no longer trigger; apply the same fixes at line 45.

Comment on lines +113 to +130
- name: Build and Deploy API
id: deploy
env:
VERCEL_TOKEN: ${{ secrets.VERCEL_TOKEN }}
VERCEL_ORG_ID: ${{ secrets.VERCEL_ORG_ID }}
VERCEL_PROJECT_ID: ${{ secrets.VERCEL_API_PROJECT_ID }}
DATABASE_URL: ${{ env.DATABASE_URL }}
DATABASE_URL_UNPOOLED: ${{ env.DATABASE_URL_UNPOOLED }}
NEXT_PUBLIC_WEB_URL: https://${{ env.WEB_ALIAS }}
NEXT_PUBLIC_ADMIN_URL: https://${{ env.ADMIN_ALIAS }}
MOCK_USER_ID: ${{ secrets.MOCK_USER_ID }}
run: |
vercel pull --yes --environment=preview --token=$VERCEL_TOKEN
vercel build --token=$VERCEL_TOKEN
VERCEL_URL=$(vercel deploy --prebuilt --token=$VERCEL_TOKEN)
vercel alias $VERCEL_URL ${{ env.API_ALIAS }} --scope=$VERCEL_ORG_ID --token=$VERCEL_TOKEN
echo "vercel_url=$VERCEL_URL" >> $GITHUB_OUTPUT

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

git ls-files .github/workflows/ | head -20

Repository: superset-sh/superset

Length of output: 241


🏁 Script executed:

if [ -f ".github/workflows/deploy-preview.yml" ]; then
  echo "File exists"
  wc -l .github/workflows/deploy-preview.yml
fi

Repository: superset-sh/superset

Length of output: 116


🏁 Script executed:

sed -n '113,130p' .github/workflows/deploy-preview.yml

Repository: superset-sh/superset

Length of output: 955


🏁 Script executed:

sed -n '183,201p' .github/workflows/deploy-preview.yml

Repository: superset-sh/superset

Length of output: 1025


🌐 Web query:

GitHub Actions secrets available pull_request event fork security best practices

💡 Result:

Short summary — what happens and recommended best practices:

What GitHub does

  • pull_request (normal): workflows triggered by PRs from forks run in the contributor’s context and do NOT receive repository/organization/environment secrets; GITHUB_TOKEN is scoped read-only. [1][2][3].
  • pull_request_target: runs in the base-repository context and CAN access repo secrets and full token permissions — but it runs using the base branch workflow and therefore is dangerous if you check out or run PR code without strong controls (risk: secret exfiltration / pwn requests). [1][2][4].

Practical best practices

  1. Default: keep fork PRs on pull_request (no secrets). Treat PR code as untrusted. [1][3].
  2. If you MUST use secrets for PRs from forks, prefer one of:
    • Use pull_request_target but do NOT check out or run untrusted PR code in the same job that has secrets; separate the secret-using job and only operate on vetted content. Enforce minimal permissions. [1][2][4].
    • Use a secondary workflow triggered after CI (workflow_run) that runs in the repo context and uses secrets only after the PR has passed automated checks or been approved. [3][7].
    • Use protected Environments with required reviewers/approvals for jobs that expose secrets. [1][4].
  3. Minimize scope of credentials: use least-privilege tokens, short-lived credentials, GitHub Apps or deploy keys instead of personal tokens. Limit secrets to exactly what’s needed. [1][5].
  4. Avoid printing secrets, use automatic redaction, and audit logs for suspicious runs. Do not write secrets into artifacts accessible to PR authors. [1][5].
  5. For high-risk operations (publishing, deploy keys, package registry credentials), keep those workflows completely out of automatic PRs from forks — require maintainer approval or run them in CI after merge. [4][5].
  6. Consider an isolated self-hosted runner or dedicated integration job that has limited network access and runs only after human review for sensitive tests. [4].

References (key sources)

  • GitHub Docs — Secrets for Actions (how secrets are provided and redaction). [1]
  • GitHub Security blog / “preventing pwn requests” guidance (explain pull_request vs pull_request_target risks). [2]
  • Community answers / StackOverflow on pull_request_target vs pull_request and workflow_run alternatives. [3]
  • Practical write-ups and OSS guidance warning about secret exfiltration and use of Environments. [4][7]

If you want, I can: (A) show a safe example workflow pattern (separate jobs, checkout logic, environment/approval settings), or (B) draft an approval + environment policy for your repo. Which do you prefer?


🏁 Script executed:

head -50 .github/workflows/deploy-preview.yml

Repository: superset-sh/superset

Length of output: 1560


🏁 Script executed:

grep -n "^on:" .github/workflows/deploy-preview.yml -A 20

Repository: superset-sh/superset

Length of output: 844


Quote shell variables (SC2086) throughout the workflow and address secrets unavailability on fork PRs.

The workflow uses the pull_request event to deploy on every PR, but GitHub Actions does NOT provide repository secrets (VERCEL_TOKEN, VERCEL_ORG_ID, NEON_API_KEY, MOCK_USER_ID) to workflows triggered by pull requests from forks. This causes deploy steps to fail on fork contributions with unset secret variables.

Quoting fix (lines 113-130, and also 183-201, 242-255, 307-324, 365-380, 413-454):

-          vercel pull --yes --environment=preview --token=$VERCEL_TOKEN
-          vercel build --token=$VERCEL_TOKEN
-          VERCEL_URL=$(vercel deploy --prebuilt --token=$VERCEL_TOKEN)
-          vercel alias $VERCEL_URL ${{ env.API_ALIAS }} --scope=$VERCEL_ORG_ID --token=$VERCEL_TOKEN
+          vercel pull --yes --environment=preview --token="$VERCEL_TOKEN"
+          vercel build --token="$VERCEL_TOKEN"
+          VERCEL_URL="$(vercel deploy --prebuilt --token="$VERCEL_TOKEN")"
+          vercel alias "$VERCEL_URL" "${{ env.API_ALIAS }}" --scope="$VERCEL_ORG_ID" --token="$VERCEL_TOKEN"

For fork PR support, consider one of:

  • Switch to pull_request_target (if you can isolate secret-using jobs and avoid checking out untrusted PR code in the same job)
  • Use Environment protections with required approvals for preview deploys
  • Restrict this workflow to same-repository PRs only and skip silently on forks
  • Use a workflow_run trigger to deploy only after PR passes CI (runs in repo context with secrets available)
🧰 Tools
🪛 actionlint (1.7.9)

124-124: shellcheck reported issue in this script: SC2086:info:1:49: Double quote to prevent globbing and word splitting

(shellcheck)


124-124: shellcheck reported issue in this script: SC2086:info:2:22: Double quote to prevent globbing and word splitting

(shellcheck)


124-124: shellcheck reported issue in this script: SC2086:info:3:47: Double quote to prevent globbing and word splitting

(shellcheck)


124-124: shellcheck reported issue in this script: SC2086:info:4:14: Double quote to prevent globbing and word splitting

(shellcheck)


124-124: shellcheck reported issue in this script: SC2086:info:4:55: Double quote to prevent globbing and word splitting

(shellcheck)


124-124: shellcheck reported issue in this script: SC2086:info:4:78: Double quote to prevent globbing and word splitting

(shellcheck)


124-124: shellcheck reported issue in this script: SC2086:info:5:34: Double quote to prevent globbing and word splitting

(shellcheck)

🤖 Prompt for AI Agents
.github/workflows/deploy-preview.yml lines 113-130: the workflow uses unquoted
shell variables and assumes secrets are available for fork PRs causing failures;
quote all shell variable expansions (e.g. "$VERCEL_TOKEN", "$VERCEL_URL",
"$GITHUB_OUTPUT", env vars) to avoid word-splitting (SC2086) and update the job
to handle secrets-unavailable on forked PRs by choosing one mitigation: switch
the trigger to pull_request_target (ensuring you do not check out untrusted PR
code in the same job), or gate the deploy step with an environment
protection/required approval, or detect fork PRs and skip the deploy silently,
or move deploy to a workflow_run that runs in repo context; implement the chosen
approach across the other referenced blocks (lines 183-201, 242-255, 307-324,
365-380, 413-454).

Comment on lines +63 to +78
- name: Install Vercel CLI
run: npm install --global vercel@latest

- name: Build and Deploy API
env:
VERCEL_TOKEN: ${{ secrets.VERCEL_TOKEN }}
VERCEL_ORG_ID: ${{ secrets.VERCEL_ORG_ID }}
VERCEL_PROJECT_ID: ${{ secrets.VERCEL_API_PROJECT_ID }}
NEXT_PUBLIC_WEB_URL: ${{ secrets.NEXT_PUBLIC_WEB_URL }}
NEXT_PUBLIC_ADMIN_URL: ${{ secrets.NEXT_PUBLIC_ADMIN_URL }}
MOCK_USER_ID: ${{ secrets.MOCK_USER_ID }}
run: |
vercel pull --yes --environment=production --token=$VERCEL_TOKEN
vercel build --prod --token=$VERCEL_TOKEN
vercel deploy --prod --prebuilt --token=$VERCEL_TOKEN

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🌐 Web query:

Vercel CLI stable version LTS production deployment best practices

💡 Result:

Summary — stable/LTS production deployments with Vercel CLI (concise best practices)

  1. Install & pin a stable CLI release
  • Install via npm/pnpm/yarn and pin a tested version in CI (npm i -g vercel@ or add to CI image) so CLI behaviour is reproducible. Validate with vercel --version. [1]
  1. Use tokens for CI (no interactive login)
  • Create a Vercel token and pass --token in CI jobs or use VERCEL_TOKEN env var to authenticate non-interactively. [1]
  1. Prefer Git-based CI + preview → promote workflow
  • Use Git deployments for automated previews and only promote a tested preview to production. For manual CLI deploys, deploy staged production (--prod --skip-domain) and then vercel promote when ready. This avoids immediately routing traffic to an unvetted build. [2][4]
  1. Use prebuilt/local build when required
  • Use vercel build locally and vercel deploy --prebuilt when you must inspect or produce builds outside Vercel (keeps source private and ensures parity). [2]
  1. Pin runtime (Node) and build environment
  • Set engines/node in package.json or choose Project Settings Node.js version to a supported LTS major (Vercel maps semver ranges to available majors). Pining avoids unexpected runtime upgrades. Check Vercel’s supported Node versions. [6][8]
  1. CI validation: run builds & tests before deploy
  • Run full tests, linting, and a production build in CI; fail fast before vercel deploy --prod. Use the same Node version and build command as Vercel’s settings. [2][6]
  1. Environment variables & secrets management
  • Store production secrets in Vercel’s Environment Variables / Secrets and load only the required vars into production builds/deploys. Avoid committing secrets to repo. [3]
  1. Deploy flags & domain handling
  • Use --prod only after CI validation. For staged deployments: vercel --prod --skip-domain then vercel promote when ready. Use deploy hooks or the REST API to trigger controlled deploys where appropriate. [2][4]
  1. Traffic control (canary / rolling releases)
  • For progressive rollouts use Rolling Releases (Pro/Enterprise) or manual promote/rollback to limit blast radius. Monitor canary metrics before full promotion. [5][4]
  1. Rollback & instant recovery
  • Use instant rollback (reassign domain to previous deployment) or promote a known-good deployment. Keep runbook and CI artifact references for quick recovery. [4]
  1. Observability & health checks
  • Integrate logs, APM, uptime checks and use Vercel’s logs/edge analytics. Add health endpoints for automated monitoring and alerting. [3]
  1. Optimize build surface & caching
  • Use .vercelignore, build caches, and incremental/static rendering (ISR/SSG) where appropriate to speed builds and reduce errors. Prefer minimal serverless function bundles. [3]
  1. Secrets of reproducibility
  • Commit lockfiles, declare exact build commands, and keep a .vercel/project/org linkage in repo (.vercel) to reproduce deployments reliably. [1][2]
  1. Security and least privilege
  • Limit token scope, rotate tokens, use scoped team/org tokens for CI, and review role permissions for users who can promote/alias deployments. [1][3]

References

  • Vercel CLI overview & install/update/CI auth. [1]
  • Deploying from CLI, prebuilt, staged production and promote workflow. [2][4]
  • Deployments, environment handling, logs and build advice. [3]
  • Rolling Releases (canary/gradual rollout). [5]
  • Supported Node.js versions / runtime pinning and Node 22 LTS notice. [6][8]

If you want, I can: 1) produce a ready-to-drop CI job (GitHub Actions/GitLab) that pins CLI, builds, tests and runs vercel deploy --prod safely; or 2) audit a specific project’s settings for gaps. Which would you like?


🌐 Web query:

Vercel CLI version pinning CI/CD recommended

💡 Result:

Short answer: Yes — pin the Vercel CLI in CI for reproducible, stable builds; use an exact published version and review/update on a schedule.

How to pin (recommended options):

  • Install a specific npm release in CI: npm i -g vercel@ or npx vercel@ (or add vercel as a devDependency and run npx vercel). (npmjs.com)
  • Alternatively some workflows use the VERCEL_CLI_VERSION env var (note: using it may opt you out of new fixes/features — test before locking). (community.vercel.com)

Best practices:

  • Pin to an exact patch/minor (e.g., vercel@47.0.5) for reproducibility; avoid floating tags like @latest in CI. (npmjs.com)
  • Run CI jobs that print vercel --version to verify which CLI ran. (vercel.com)
  • Schedule periodic reviews/updates (e.g., monthly/quarterly) and test releases in a staging pipeline before promoting to production. (community.vercel.com)

If you want, I can produce example CI snippets (GitHub Actions, GitLab CI, or GitHub Actions using npx) pinned to a specific version.

Citations:


🏁 Script executed:

# Check if there's any documentation or version hints in the repository
find . -type f \( -name "*.md" -o -name "*.txt" -o -name ".nvmrc" -o -name ".tool-versions" \) | head -20

Repository: superset-sh/superset

Length of output: 673


🏁 Script executed:

# Look for any existing version references in other workflows or config files
rg "vercel@" --type yaml --type json

Repository: superset-sh/superset

Length of output: 46


🌐 Web query:

Vercel CLI current version 2024 2025

💡 Result:

If you mean which major Vercel CLI versions were current across 2024–2025:

  • 2024: v34.x was the stable/common release series. [1]
  • 2025: the CLI moved through v41.x into the v44.x series (reports of v41.2.2 and v44.* in 2025). [2][3]

For the absolute latest release right now (Dec 12, 2025) run vercel --version or npm view vercel version; Vercel’s docs also point to installing/updating with npm i -g vercel@latest. [1][4]

Sources:
[1] Vercel CLI docs (install/version).
[2] Vercel Community deployment logs showing Vercel CLI v41.2.2.
[3] vercel/vercel GitHub (issues referencing v44.*).
[4] npm package listings / install instructions.


🏁 Script executed:

# Check for shellcheck or actionlint configuration in the repo
find . -type f \( -name ".shellcheckrc" -o -name "actionlint.yaml" -o -name ".actionlintrc" \)

Repository: superset-sh/superset

Length of output: 46


🏁 Script executed:

# Look at the actual workflow file to understand context better
cat -n .github/workflows/deploy-production.yml | head -80

Repository: superset-sh/superset

Length of output: 2818


🌐 Web query:

GitHub Actions shell variable quoting best practices SC2086

💡 Result:

Short best-practices for GitHub Actions shell steps to avoid ShellCheck SC2086 (double‑quote to prevent globbing/word‑splitting):

  • Always double‑quote expansions: use "${var}" (and prefer braces) to prevent word‑splitting and globbing. [1]
  • When you intentionally want word‑splitting into multiple arguments, do it explicitly (read -a / mapfile / arrays) rather than leaving unquoted expansions. [1][2]
  • Pass workflow outputs into run scripts via environment variables (env:) instead of embedding ${{ … }} directly in the script; then reference the env var as "${MY_VAR}". This avoids injection/quoting issues. Also ensure shell: bash if using POSIX shell syntax. [3]
  • Quote environment file redirections and special GitHub vars: >> "${GITHUB_OUTPUT}" (use braces + quotes). [2]
  • If ShellCheck flags are noisy for a known-safe pattern, either fix by quoting or document/disable the specific rule in .shellcheckrc or with an inline directive — but prefer fixing. Run ShellCheck in CI to catch regressions. [4][5]

References:
[1] ShellCheck SC2086 documentation.
[2] GH‑lint guidance: quote GITHUB_OUTPUT and use braces.
[3] GitHub discussion: prefer env variables over inserting ${{ }} into run scripts.
[4] ShellCheck action / integration for CI.


🏁 Script executed:

# Check the other deploy jobs mentioned in "Also applies to"
sed -n '103,121p' .github/workflows/deploy-production.yml

Repository: superset-sh/superset

Length of output: 958


🏁 Script executed:

# Check another range
sed -n '146,159p' .github/workflows/deploy-production.yml

Repository: superset-sh/superset

Length of output: 650


🏁 Script executed:

# Check more locations
sed -n '184,201p' .github/workflows/deploy-production.yml

Repository: superset-sh/superset

Length of output: 882


🏁 Script executed:

# Check final location
sed -n '226,240p' .github/workflows/deploy-production.yml

Repository: superset-sh/superset

Length of output: 783


🌐 Web query:

npm Vercel CLI latest stable version December 2025

💡 Result:

The latest stable npm package version of Vercel CLI (as of December 12, 2025) is 47.0.5. [1][2]

Sources:

  • npm package page for vercel (latest version listed). [1]
  • Vercel CLI docs (install/update instructions). [2]

Pin Vercel CLI to v47.0.5 and quote shell variables to address SC2086 and ensure deterministic production deployments.

      - name: Install Vercel CLI
-        run: npm install --global vercel@latest
+        run: npm install --global vercel@47.0.5

       - name: Build and Deploy API
         env:
           VERCEL_TOKEN: ${{ secrets.VERCEL_TOKEN }}
@@
         run: |
-          vercel pull --yes --environment=production --token=$VERCEL_TOKEN
-          vercel build --prod --token=$VERCEL_TOKEN
-          vercel deploy --prod --prebuilt --token=$VERCEL_TOKEN
+          vercel pull --yes --environment=production --token="${VERCEL_TOKEN}"
+          vercel build --prod --token="${VERCEL_TOKEN}"
+          vercel deploy --prod --prebuilt --token="${VERCEL_TOKEN}"

Using @latest in production CI is non-deterministic and can cause unexpected failures. Pin to v47.0.5 (current stable as of Dec 2025) and review quarterly for updates. Quoting $VERCEL_TOKEN follows GitHub Actions shell best practices and avoids SC2086 warnings.

Also applies to: 103-121, 146-159, 184-201, 226-240

🧰 Tools
🪛 actionlint (1.7.9)

74-74: shellcheck reported issue in this script: SC2086:info:1:52: Double quote to prevent globbing and word splitting

(shellcheck)


74-74: shellcheck reported issue in this script: SC2086:info:2:29: Double quote to prevent globbing and word splitting

(shellcheck)


74-74: shellcheck reported issue in this script: SC2086:info:3:41: Double quote to prevent globbing and word splitting

(shellcheck)

Comment thread apps/admin/next.config.ts
experimental: {
reactCompiler: true,
},
typescript: { ignoreBuildErrors: true },
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

cat -n apps/admin/next.config.ts

Repository: superset-sh/superset

Length of output: 316


🏁 Script executed:

rg -i "ignoreBuildErrors|typescript.*error" apps/admin/ -A 2 -B 2

Repository: superset-sh/superset

Length of output: 266


🏁 Script executed:

rg -i "TODO.*typescript|TODO.*type" apps/admin/ | head -20

Repository: superset-sh/superset

Length of output: 46


🏁 Script executed:

git log --oneline -n 20 -- apps/admin/next.config.ts

Repository: superset-sh/superset

Length of output: 114


🏁 Script executed:

rg "ignoreBuildErrors" --type ts --type tsx

Repository: superset-sh/superset

Length of output: 91


Remove ignoreBuildErrors or provide strong justification.

The typescript: { ignoreBuildErrors: true } setting on line 7 bypasses TypeScript's type checking during builds, which can hide critical type safety issues and bugs. This directly contradicts the coding guideline to maintain type safety in TypeScript code.

If this is temporary for migration purposes, add a TODO comment with a target removal date and document which specific errors are being suppressed. Otherwise, remove this flag and fix the underlying TypeScript errors.

🤖 Prompt for AI Agents
In apps/admin/next.config.ts around line 7, the TypeScript build config uses
typescript: { ignoreBuildErrors: true } which disables type checking during
builds; either remove this flag and fix the TypeScript errors causing build
failures, or if temporary, replace it with a clear TODO comment including a
target removal date, a link/ticket reference, and an explicit list of the
suppressed errors (or files) being bypassed; update project docs or the linked
ticket with steps to resolve those errors and ensure CI fails if the flag is
still present after the target date.

Comment thread apps/web/src/env.ts
Comment on lines +13 to +17
server: {
// Database (needed by @superset/trpc dependency)
DATABASE_URL: z.string().url(),
DATABASE_URL_UNPOOLED: z.string().url(),
},
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Verify whether apps/web should require DB env vars at all
DATABASE_URL / DATABASE_URL_UNPOOLED (Line 13-17) being required can break web-only deployments if the web app doesn’t directly touch the DB. If this is only to satisfy @superset/trpc import-time validation, consider making those optional in web/admin or moving DB validation into the API/db package boundary.

🤖 Prompt for AI Agents
In apps/web/src/env.ts around lines 13 to 17 the server schema currently
requires DATABASE_URL and DATABASE_URL_UNPOOLED which forces web-only
deployments to provide DB env vars; make these optional or remove them from the
web package and instead validate DB connection vars at the API/db package
boundary. Update the env schema in apps/web to mark DATABASE_URL and
DATABASE_URL_UNPOOLED as optional (or remove those keys entirely), and move any
strict DB validation/creation logic into the server/api package where the
database is actually used so import-time validation in @superset/trpc doesn’t
break web-only deployments.

Comment on lines +15 to +27
dehydrate: {
serializeData: SuperJSON.serialize,
shouldDehydrateQuery: (query) =>
defaultShouldDehydrateQuery(query) ||
query.state.status === "pending",
shouldRedactErrors: () => {
// We should not catch Next.js server errors
// as that's how Next.js detects dynamic pages
// so we cannot redact them.
// Next.js also automatically redacts errors for us
// with better digests.
return false;
},
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Error redaction disabled: potential sensitive data leak via dehydration
shouldRedactErrors: () => false (Line 20-27) can expose server error details to the client through dehydrated state. Make this environment-dependent (at least redact in production).

 			dehydrate: {
 				serializeData: SuperJSON.serialize,
 				shouldDehydrateQuery: (query) =>
 					defaultShouldDehydrateQuery(query) ||
 					query.state.status === "pending",
-				shouldRedactErrors: () => {
-					// We should not catch Next.js server errors
-					// as that's how Next.js detects dynamic pages
-					// so we cannot redact them.
-					// Next.js also automatically redacts errors for us
-					// with better digests.
-					return false;
-				},
+				shouldRedactErrors: () => process.env.NODE_ENV === "production",
 			},
📝 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
dehydrate: {
serializeData: SuperJSON.serialize,
shouldDehydrateQuery: (query) =>
defaultShouldDehydrateQuery(query) ||
query.state.status === "pending",
shouldRedactErrors: () => {
// We should not catch Next.js server errors
// as that's how Next.js detects dynamic pages
// so we cannot redact them.
// Next.js also automatically redacts errors for us
// with better digests.
return false;
},
dehydrate: {
serializeData: SuperJSON.serialize,
shouldDehydrateQuery: (query) =>
defaultShouldDehydrateQuery(query) ||
query.state.status === "pending",
shouldRedactErrors: () => process.env.NODE_ENV === "production",
🤖 Prompt for AI Agents
In apps/web/src/trpc/query-client.ts around lines 15 to 27, the current
shouldRedactErrors: () => false leaves errors unredacted for all environments;
change it to be environment-dependent so errors are redacted in production.
Replace the always-false with a conditional that returns false only in
development and true in production (e.g., check process.env.NODE_ENV or your
runtime config), so server error details are not exposed when running in
production; ensure the logic preserves the existing development behavior and add
a brief unit or smoke check if you have env-specific test runs.

Comment on lines +11 to +26
export const api = cache(async () => {
const heads = new Headers(await headers());
heads.set("x-trpc-source", "rsc");

return createTRPCClient<AppRouter>({
links: [
httpBatchLink({
transformer: SuperJSON,
url: `${env.NEXT_PUBLIC_API_URL}/api/trpc`,
headers() {
return Object.fromEntries(heads.entries());
},
}),
],
});
});
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🌐 Web query:

Next.js 15 cache() react request scoping headers()

💡 Result:

Short answer: Next.js 15 separates component-level caching ("'use cache'"/Cache Components) from per-request memoization (React's cache() and request-scoped APIs like headers()/cookies()). You cannot read request-scoped data (headers(), cookies(), etc.) from a build-time or globally cached scope; cache keys only include serializable inputs and closed-over values become request-time references. Use request-scoped code outside 'use cache' (or use 'use cache: private' for user-specific cached content), and use React.cache() for memoization within the request lifetime. See Next.js docs for details. [1][2][3]

Quick pointers

  • "'use cache' (Next 15) = cache components/functions across requests; keys include build ID, function ID, and serializable args; cannot access request-time APIs when used for prerendering." [1]
  • "React's cache() memoizes during a request/render pass (request-scoped memoization) and is appropriate for DB/GraphQL clients when fetch isn't suitable." [2]
  • "Next.js Data Cache / fetch: server fetches are memoized/cached with fetch options; request-scoped APIs (headers(), cookies()) opt the route out of prerendering / global caching." [3]

If you want, tell me which code snippet you have and I’ll show where to move headers()/React.cache()/ 'use cache' so caching behaves correctly.


🌐 Web query:

Next.js react cache request boundary scope RSC

💡 Result:

Short answer — they are different caches with different scopes and purposes:

  • React cache() (React.cache) — per-request / per-render memoization used by RSCs: entries live for the lifetime of the current server render (can dedupe work across components in the same request). Use cacheSignal to cancel in-flight work when rendering finishes. (stevekinney.com)

  • Next.js Cache Components / "use cache" — a Next.js-level, opt-in feature that can persist results beyond a single request (prerender/static-shell caching, revalidation via tags, cacheLife, updateTag/revalidateTag). It’s intended for partial-prerendering and sharing cached results across requests (or including them in the static shell), not for transient per-request memoization. (nextjs.org)

Practical guidance

  • Use React.cache for short-lived dedupe within a single RSC render (request-scoped). (stevekinney.com)
  • Use "use cache" (Next.js cache components + tags/revalidation) when you want cached output that can be reused across requests or included in the prerendered shell. (nextjs.org)
  • If you need to cancel long fetches inside a cached render, pass React’s cacheSignal to fetch. (react.dev)

If you want, tell me which concrete pattern/code you’re implementing and I’ll show a small example converting between request-scoped React.cache usage and Next.js "use cache" with revalidation.

Citations:


🌐 Web query:

Next.js tRPC client cache headers security

💡 Result:

Short summary + key risks and recommendations:

  • Risk: don’t cache responses that contain user-specific or sensitive data (auth tokens, PII). Browser/edge caches can leak that to other users or later requests. Use private/no-store for per-user responses. [1][2]

  • How to set cache headers with tRPC: set them server-side (responseMeta / res.setHeader) on your tRPC handler or Next API route (e.g. s-maxage, stale-while-revalidate). But remember Next may override certain asset headers; set API response headers where supported. [2][1]

  • Streaming/batching caveat: tRPC’s streamed http-batch links can prevent headers (and revalidation) from behaving as expected because response headers may be sent before streaming completes. If you rely on cache-related headers or revalidateTag() from inside tRPC routes, use a non-streamed httpBatchLink or split public/private links. Reddit reports revalidation failing when using the streamed batch link; switching to non-streamed fixed it. [4]

  • SSR and cookies: when doing SSR with tRPC, forward cookies/headers explicitly in the client link only when needed (so you don’t accidentally make cached responses include auth). For public queries use links that omit cookies; for authenticated/user data forward cookies and set private/no-store. [5]

  • Practical rules to follow:

    1. Treat any endpoint that depends on request headers/cookies as private: Cache-Control: private, no-store, or omit cache headers. [2][5]
    2. For public read-only data, use s-maxage + stale-while-revalidate and set them via tRPC responseMeta or res.setHeader. Validate behavior on your host (Vercel, Cloudflare). [2][1]
    3. Use splitLink or separate endpoints for cached public data vs. private/authenticated requests. [2]
    4. If you need revalidateTag()/Next revalidation from a tRPC route and it’s not working, check if you’re using streamed httpBatchLink — switch to non-streamed batching or call a plain Next revalidation route. [4]
    5. Test in production deployment (edge/CDN) because Next.js/Vercel may change header handling compared to local. [1]

Sources: Next.js headers/cache docs; tRPC response-caching & SSR docs; community report on streaming/batching header/revalidation behavior. [1][2][5][4][3]

References
[1] Next.js headers / cache-control docs. (nextjs.org)
[2] tRPC response caching (responseMeta guidance, warning about caching auth data). (trpc.io)
[3] tRPC Next.js SSR & forwarding headers (cookie forwarding example). (trpc.io)
[4] Community thread: streamed httpBatchLink prevents expected header/revalidation behavior (report + resolution). (reddit.com)
[5] tRPC server-side helpers / server call notes. (trpc.io)

Citations:


🏁 Script executed:

cat -n apps/web/src/trpc/server.tsx | head -35

Repository: superset-sh/superset

Length of output: 877


🌐 Web query:

Next.js 15 tRPC client factory cache() pattern recommended

💡 Result:

Short answer — prefer creating the tRPC client via the official Next.js integration (createTRPCNext / server-side helpers) and only memoize the factory with React's cache (or Next's "use cache" at the appropriate server-level) when you must reuse a single instance within the same server-render request. Do NOT create a global, long-lived tRPC client that persists across user requests.

Why / how (concise):

  • Use createTRPCNext / tRPC server-side helpers for Next.js integration and server prefetching — these are the supported patterns for SSR/SSG and client hooks. [3][4]
  • For server-only memoization within a request, use React.cache (or Next's "use cache" directive on a component/function) to memoize non-fetch clients (DB/GraphQL clients and client-factory functions) so you avoid re-instantiating them inside the same render. This matches Next/React guidance. [2][1]
  • Avoid caching a client across requests (no permanent singletons) because Next.js app/server caching semantics changed in v14/15 and persistent in-memory singletons can cause stale context, invalidation and revalidation issues. Use React.cache / "use cache" for per-request memoization and rely on tRPC's cache/React-Query invalidation APIs on the client for data freshness. [1][2][3][4]

Practical pattern (one-line):

  • export a factory that builds the tRPC client via createTRPCNext (or server-side helper) and, if you need intra-request reuse, wrap the factory with React.cache; call it from server components or server actions, and use tRPC/tanstack-react-query on the client for caching/invalidation. [3][4][2]

Sources:

  • Next.js directives / caching docs (use cache, cache guidance). [1][2]
  • tRPC Next.js client & server-side helpers docs (createTRPCNext, server-side prefetching). [3][4]

🌐 Web query:

React cache() request scoped safe headers() memoization

💡 Result:

Short summary and practical guidance:

  • What cache() does: React’s cache() memoizes a function’s return values for the lifetime of a single server-render request (a render pass). Use it to deduplicate non-fetch data calls (DB, GraphQL, custom clients). Fetch GET requests are also request-memoized automatically during a render pass. [1][2]

  • headers()/cookies(): calling headers() or cookies() in a Server Component gives you the incoming request values, but the framework treats components that read request headers/cookies as “dynamic” (private/no-store), preventing full-page public caching and CDN-friendly Vary behavior by default. If you only depend on public-safe header variants (e.g. Accept-Language) you must explicitly design for safe forwarding/variant caching (allow-list headers, set Vary, or use other APIs). [3][2]

  • Common safe patterns / memoization strategies

    1. Keep request-scoped values in a small request-only cached getter and pass derived non-sensitive keys into cached functions. Example pattern:
      • create a request-scoped helper that reads headers() and normalizes an allowed header value, memoized with React cache().
      • call cache()d data fetchers with that normalized value as an argument so memoization keys include only safe values.
    2. Don’t forward all incoming headers to downstream/response — build an allow-list and drop Authorization/Cookie/x-* headers. Use NextResponse/Headers guidance when proxying. [2]
    3. For user-specific private data, keep cache scoped to request or use per-user tags/force-cache + revalidation (Next’s data cache) — don’t expose private tokens to shared caches. [1][2]
    4. If you need public HTML variants (Vary), avoid reading arbitrary headers directly in Server Components; instead read only explicitly allow-listed headers and implement variant-aware caching at the CDN or route-handler level (or follow Next.js evolving APIs/discussions). [3]
  • Minimal example (concept):

    • requestHeaders.ts
      const { cache } = require('react')
      export const getSafeVariant = cache(() => {
      const h = headers()
      return (h.get('accept-language') ?? 'en').split(',')[0]
      })
    • data.ts
      export const getItems = cache(async (lang) => fetch(...?lang=lang))
    • page.tsx
      const lang = getSafeVariant()
      const items = await getItems(lang)

References:

  • Next.js caching & request memoization docs. [1]
  • Next.js headers/NextResponse guidance (allow-list headers, avoid forwarding sensitive headers). [2]
  • Next.js community discussion about headers() making pages dynamic and Vary/cache implications. [3]

If you want, I can produce a concrete code example tailored to your stack (Next.js version and whether you use cacheComponents).


🏁 Script executed:

# Check if there are any other files in the same directory that might provide context
ls -la apps/web/src/trpc/

Repository: superset-sh/superset

Length of output: 359


🏁 Script executed:

# Check if headers() forwarding with Object.fromEntries() is intentional
# Look for any security policies or comments around this
rg -A 5 -B 5 "x-trpc-source" apps/web/src/

Repository: superset-sh/superset

Length of output: 1202


🏁 Script executed:

# Check Next.js and tRPC documentation patterns for server-side client factories
# Look for any comments or documentation in the codebase about security
rg "headers\(\)" apps/web/src/ -A 2 -B 2 | head -40

Repository: superset-sh/superset

Length of output: 953


🌐 Web query:

Next.js RSC headers() forwarding security best practices allow-list

💡 Result:

Concise best-practices checklist for forwarding headers from Next.js RSCs (headers()) — use an allow-list and harden trust boundaries

Key principles

  • Treat all incoming headers as untrusted. Never assume a header value is authentic unless the request passed through a trusted boundary you control. [1][2]
  • Minimize: only read/forward the exact headers your upstream service truly needs. Default to “deny all” (allow-list) and add headers only with a clear justification. [1][5]
  • Don’t leak secrets: never forward Authorization, Cookie, set-cookie, proxy/forwarding, or internal-trace headers unless explicitly required and proven safe. Strip hop-by-hop headers (Connection, Keep-Alive, Proxy-Authenticate, Transfer-Encoding, TE, Trailer, Upgrade). [1][8]

Concrete rules to implement

  1. Allow-list per-destination:
    • Maintain a mapping of allowed headers for each upstream (e.g., api.example.com → [content-type, x-correlation-id]). Only include those when proxying. Log and alert on attempts to forward disallowed headers. [1][5]
  2. Canonicalize and validate values:
    • Normalize header names, validate allowed character sets/lengths, and reject unexpected formats (e.g., numeric IDs, UUID regex for x-request-id). This prevents header injection and header-splitting attacks. [1]
  3. Authenticate/trust at the edge:
    • If headers must be trusted (e.g., preservation of user identity), only accept them from a trusted reverse proxy or internal network and verify provenance (mutual TLS, signed headers, or a header added by your proxy). Don’t accept those headers from public clients. [1][2]
  4. Use Next.js security features:
    • Read headers with next/headers() in server components, but re-verify any sensitive data against your backend (don’t pass raw header-derived auth into data access without server-side checks). Use serverActions.allowedOrigins for Server Actions when dealing with cross-host setups. [6][2][5]
  5. Strip or rewrite sensitive headers when proxying:
    • Remove Authorization, Cookie, Set-Cookie, and any internal-only headers unless the upstream explicitly requires them and the request is coming from a trusted flow. Replace user-supplied trace IDs with sanitized/generated ones if you need canonical tracing. [1][8]
  6. Enforce transport & response protections:
    • Require HTTPS and HSTS. Set secure response headers (CSP, X-Frame-Options, X-Content-Type-Options, Referrer-Policy) and use nonces where needed. [3][4]
  7. Audit & testing:
    • Add unit/integration tests for header allow-lists, and runtime logging/monitoring for header forwarding decisions. Periodically review the allow-list and scan for accidental forwarding of sensitive headers. [1]

Example minimal pattern (pseudo)

  • Incoming headers = await headers()
  • Build forwardHeaders = {}
  • For each header in allowListForTarget:
    if headers.get(name) && passesValidation(headers.get(name)) then forwardHeaders[name] = headers.get(name)
  • Remove hop-by-hop and known sensitive headers before calling fetch to upstream.

Useful references

  • Next.js security guidance (Server Components & Actions). [2]
  • next/headers() API reference. [6]
  • Next.js data-security guide (serverActions.allowedOrigins and advice to re-verify headers/cookies). [5]
  • CSP and secure-response-headers guidance. [3][4]
  • Known issues / behavior notes (header handling, middleware interactions) — audit your Next.js version. [8]

If you want, I can:

  • produce a ready-to-drop allow-list middleware + helper for header canonicalization for your Next.js app, or
  • review a specific header list you’re currently forwarding and flag risky entries.

Consider using an allow-list for headers instead of forwarding all incoming headers.

The cache() wrapper is correct and recommended for request-scoped memoization in Next.js RSCs. However, forwarding all request headers via Object.fromEntries(heads.entries()) could expose sensitive headers (Authorization, Cookie, etc.) to your backend. Follow the pattern used in react.tsx: explicitly construct a Headers object and only include necessary headers.

export const api = cache(async () => {
	const heads = new Headers(await headers());
	heads.set("x-trpc-source", "rsc");

	return createTRPCClient<AppRouter>({
		links: [
			httpBatchLink({
				transformer: SuperJSON,
				url: `${env.NEXT_PUBLIC_API_URL}/api/trpc`,
				headers() {
-					return Object.fromEntries(heads.entries());
+					return { "x-trpc-source": "rsc" };
				},
			}),
		],
	});
});
📝 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
export const api = cache(async () => {
const heads = new Headers(await headers());
heads.set("x-trpc-source", "rsc");
return createTRPCClient<AppRouter>({
links: [
httpBatchLink({
transformer: SuperJSON,
url: `${env.NEXT_PUBLIC_API_URL}/api/trpc`,
headers() {
return Object.fromEntries(heads.entries());
},
}),
],
});
});
export const api = cache(async () => {
const heads = new Headers(await headers());
heads.set("x-trpc-source", "rsc");
return createTRPCClient<AppRouter>({
links: [
httpBatchLink({
transformer: SuperJSON,
url: `${env.NEXT_PUBLIC_API_URL}/api/trpc`,
headers() {
return { "x-trpc-source": "rsc" };
},
}),
],
});
});
🤖 Prompt for AI Agents
In apps/web/src/trpc/server.tsx around lines 11 to 26, the code currently
forwards all incoming request headers via Object.fromEntries(heads.entries()),
which risks leaking sensitive headers; instead, construct a new Headers (or
plain object) and explicitly copy only an allow-list of safe headers (for
example x-trpc-source, accept-language, user-agent, and any other app-specific
non-sensitive headers used by your backend), do not copy Authorization, Cookie,
or other sensitive headers, and return
Object.fromEntries(allowedHeaders.entries()) or the plain object; follow the
same explicit header-building pattern used in react.tsx.

Comment thread packages/trpc/src/env.ts
export const env = createEnv({
server: {
MOCK_USER_ID: z.string().uuid().optional(),
MOCK_USER_ID: z.string().uuid(),
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Reconsider requiring MOCK_USER_ID in all environments.

Making MOCK_USER_ID required (removing .optional()) forces all environments, including production, to provide a mock user ID. The variable name suggests this is intended for testing or development purposes, but requiring it universally may lead to:

  1. Production environments needing to set dummy/placeholder values
  2. Confusion about whether this is a real requirement or a test fixture
  3. Potential security concerns if mock authentication is inadvertently used in production

Consider one of the following approaches:

Option 1: Keep it optional and handle runtime checks

-MOCK_USER_ID: z.string().uuid(),
+MOCK_USER_ID: z.string().uuid().optional(),

Option 2: Use environment-specific configuration

MOCK_USER_ID: process.env.NODE_ENV === 'production' 
  ? z.string().uuid().optional() 
  : z.string().uuid(),

Option 3: If this is actually a required auth mechanism, rename it

-MOCK_USER_ID: z.string().uuid(),
+DEFAULT_USER_ID: z.string().uuid(),

Please clarify whether this variable is truly needed in production environments or if it should remain optional for non-production use.

🤖 Prompt for AI Agents
In packages/trpc/src/env.ts around line 6 the MOCK_USER_ID schema was made
required (z.string().uuid()) which forces all environments including production
to supply a mock ID; change this to an environment-appropriate config: either
revert to optional by using z.string().uuid().optional() so non-tests aren’t
forced to provide it, or implement the conditional check using
process.env.NODE_ENV (required in non-production, optional in production) so
only dev/test require a mock ID; if MOCK_USER_ID is actually part of real auth,
rename it to a clear production name and keep it required. Ensure the chosen
approach is clearly commented in the file.

Comment on lines +9 to +13
me: protectedProcedure.query(async ({ ctx }) => {
return db.query.users.findFirst({
where: eq(users.id, ctx.session.user.id),
});
}),
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Handle the case where the user might not exist in the database.

The findFirst query can return undefined if the user doesn't exist in the database, even though the session contains a valid user.id. This mismatch could occur if the user was deleted after the session was created, or due to database synchronization issues.

Consider explicitly handling this case to prevent downstream null reference errors:

 me: protectedProcedure.query(async ({ ctx }) => {
-	return db.query.users.findFirst({
+	const user = await db.query.users.findFirst({
 		where: eq(users.id, ctx.session.user.id),
 	});
+	if (!user) {
+		throw new Error("User not found");
+	}
+	return user;
 }),

Alternatively, if returning undefined is acceptable, ensure the return type is explicitly typed as User | undefined and that all calling code handles the null case appropriately.

🤖 Prompt for AI Agents
In packages/trpc/src/router/user.ts around lines 9 to 13, the
protectedProcedure.query uses findFirst which can return undefined if the DB
record was removed; update the handler to explicitly handle that case by
checking the result after the query and either (a) throw a trpc/TRPCError with
code "NOT_FOUND" (or another appropriate error) and a clear message when no user
is found, or (b) explicitly type the return as User | undefined and ensure
callers handle undefined; implement one of these approaches and adjust
types/imports accordingly.

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