Skip to content

Coming Soon Mode#243

Open
sawinez wants to merge 2 commits intodevfrom
coming-soon-mode
Open

Coming Soon Mode#243
sawinez wants to merge 2 commits intodevfrom
coming-soon-mode

Conversation

@sawinez
Copy link
Copy Markdown

@sawinez sawinez commented Apr 2, 2026

Why

  • Prevent access to unfinished routes without breaking navigation
  • Avoid sending users to sign-in for pages that are not ready yet
  • Provide a consistent, branded placeholder experience

What

  • Added middleware-based route rewriting for "coming soon" pages
  • Introduced a centralized coming-soon route and reusable UI component
  • Implemented a simple feature flag (isComingSoonRoute) to control which routes are gated
  • Ensured /coming-soon bypasses auth while preserving existing middleware behavior
  • Updated navigation to use local routes so middleware can handle rewrites correctly

Satisfies

https://linear.app/acmutsa/issue/HK-218/coming-soon-mode
#211

Notes

  • Feature
    • Added global coming soon mode with route-level control

Summary by CodeRabbit

  • New Features

    • Introduced a "Coming Soon" page with customizable title and description text.
    • Added coming-soon mode that automatically redirects configured routes to the coming-soon page.
    • Implemented feature flag system to manage coming-soon mode state and route-specific behavior.
  • Chores

    • Updated environment configuration and middleware routing logic to support coming-soon mode.

sawinez added 2 commits April 2, 2026 11:34
Added global coming soon mode with route-level control
@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Apr 2, 2026

📝 Walkthrough

Walkthrough

This pull request introduces a "coming soon" mode feature that allows conditional display of a coming-soon page for specific routes. It adds a new React component, creates feature flag infrastructure, updates environment validation to support the feature, and modifies middleware routing to redirect flagged routes to the coming-soon page.

Changes

Cohort / File(s) Summary
Coming Soon Component & Page
apps/web/src/components/comingSoon.tsx, apps/web/src/app/coming-soon/page.tsx
New ComingSoon component with customizable title/description, layered background effects, logo display, and "Back to Home" link. New page route exports and renders the component with default props.
Feature Flags & Configuration
apps/web/src/lib/feature_flags.ts, apps/web/src/env.ts
New feature flag module exports featureFlags, comingSoonRoutes array ("/faq", "/register"), and isComingSoonRoute() matcher. Environment validation updated with COMING_SOON_MODE flag and conditional requirement for multiple server/client secrets based on mode.
Middleware Routing
apps/web/src/middleware.ts
Middleware modified to check and rewrite coming-soon routes before auth protection; extracts isComingSoonRoute() check and adds pathname caching; refactors auth query to avoid inline duplicate calls when checking banned users.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~22 minutes

Poem

🐰 A coming-soon page hops into place,
With flags and features setting the pace,
Routes rewritten by middleware's embrace,
Pretty UI and config keep up the race—
Soon visitors will see our special space! 🌟

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'Coming Soon Mode' directly corresponds to the main feature implemented across all changes, which introduces a coming soon mode with route rewriting, environment configuration, and a dedicated UI component.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch coming-soon-mode

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

❤️ Share

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

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 8

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@apps/web/src/app/coming-soon/page.tsx`:
- Around line 1-10: The file defining the ComingSoonPage component (export
default function ComingSoonPage) is missing a trailing newline which causes
Prettier/style pipeline failures; fix by adding a single newline at the end of
the file (ensure the file ends with a newline character after the closing
brace/JSX) so the ComingSoonPage export and its JSX are followed by a trailing
newline.

In `@apps/web/src/components/comingSoon.tsx`:
- Around line 34-40: The Link JSX block in the ComingSoon component uses spaces
for indentation while the rest of the file uses tabs, causing Prettier warnings;
update the indentation for the Link element and its nested content (the Back to
Home text and surrounding tags) to use tabs consistent with the file's existing
formatting (locate the Link component in apps/web/src/components/comingSoon.tsx
and adjust the indentation around the Link, its props, and closing tag to tabs).

In `@apps/web/src/env.ts`:
- Line 11: The COMING_SOON_MODE env var is validated in env.ts but feature
gating still hardcodes comingSoonMode: true in feature_flags.ts; change the
feature_flags.ts to read the validated value (e.g., use the COMING_SOON_MODE
export from env.ts and coerce it to a boolean like env.COMING_SOON_MODE ===
"true" or a Boolean conversion) and replace the hardcoded true so routes and
flags honor the env setting; keep existing relaxation for secrets as-is.
- Around line 41-42: The file ends with the object property
"emptyStringAsUndefined: true," but is missing a trailing newline; update
apps/web/src/env.ts by adding a final newline character at the end of the file
(ensure the file ends with a single trailing newline) and re-run
Prettier/formatting so the file passes the pipeline.

In `@apps/web/src/lib/feature_flags.ts`:
- Around line 10-17: The file ends without a trailing newline which causes the
Prettier pipeline to fail; open the file containing the isComingSoonRoute
function and add a single newline character at the end of the file (ensure the
file ends with a blank line) so the file terminates with a trailing newline and
satisfies formatting checks.
- Around line 1-3: featureFlags currently hardcodes comingSoonMode: true which
ignores the validated COMING_SOON_MODE from env.ts; update the featureFlags
export to derive comingSoonMode from the COMING_SOON_MODE env export (or, if you
prefer to remove the feature flag, delete the env var in env.ts to avoid
confusion) — specifically, import COMING_SOON_MODE from env.ts and set
featureFlags.comingSoonMode = COMING_SOON_MODE (or remove the unused
COMING_SOON_MODE symbol and its validation if you choose the removal route) so
route gating for /faq and /register reflects the environment configuration.

In `@apps/web/src/middleware.ts`:
- Around line 52-54: The exported config block (export const config) in
middleware.ts fails Prettier checks; reformat the file to match project Prettier
rules (run your repo's Prettier or eslint --fix) so the matcher array and
surrounding whitespace/commas/quotes follow the code style; save the file after
formatting and ensure the export const config block is the only change.
- Around line 38-42: authData.userId is being non-null asserted before querying
bannedUsers which can be unsafe; update the middleware to guard against a
null/undefined userId from auth() before calling db.query.bannedUsers.findFirst
(e.g., check if authData.userId is present and handle the missing-case early or
skip the DB lookup), and replace the current unsafe expression that uses
authData.userId! with a safe access (use authData.userId or optional chaining)
so references like authData, auth(), db.query.bannedUsers.findFirst and
bannedUsers.userID no longer rely on a non-null assertion.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 330710a5-efaa-41ca-b90c-67dc3cae5e96

📥 Commits

Reviewing files that changed from the base of the PR and between 1427c56 and c12cdba.

📒 Files selected for processing (5)
  • apps/web/src/app/coming-soon/page.tsx
  • apps/web/src/components/comingSoon.tsx
  • apps/web/src/env.ts
  • apps/web/src/lib/feature_flags.ts
  • apps/web/src/middleware.ts

Comment on lines +1 to +10
import ComingSoon from "@/components/comingSoon";

export default function ComingSoonPage() {
return (
<ComingSoon
title="Coming Soon"
description="We’re still building this page. Check back soon."
/>
);
} No newline at end of file
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Fix Prettier formatting issues.

The pipeline reports code style issues. Based on the summary, this file is missing a trailing newline.

🔧 Proposed fix
 export default function ComingSoonPage() {
 	return (
 		<ComingSoon
 			title="Coming Soon"
 			description="We're still building this page. Check back soon."
 		/>
 	);
 }
+
📝 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
import ComingSoon from "@/components/comingSoon";
export default function ComingSoonPage() {
return (
<ComingSoon
title="Coming Soon"
description="Were still building this page. Check back soon."
/>
);
}
import ComingSoon from "@/components/comingSoon";
export default function ComingSoonPage() {
return (
<ComingSoon
title="Coming Soon"
description="We're still building this page. Check back soon."
/>
);
}
🧰 Tools
🪛 GitHub Actions: Prettier Check

[warning] 1-1: Prettier formatting warning: code style issues found in this file.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/web/src/app/coming-soon/page.tsx` around lines 1 - 10, The file defining
the ComingSoonPage component (export default function ComingSoonPage) is missing
a trailing newline which causes Prettier/style pipeline failures; fix by adding
a single newline at the end of the file (ensure the file ends with a newline
character after the closing brace/JSX) so the ComingSoonPage export and its JSX
are followed by a trailing newline.

Comment on lines +34 to +40
<Link
href="/"
className="group inline-flex items-center gap-2 rounded-xl border border-white/15 bg-white/5 px-6 py-3 text-sm font-medium text-white backdrop-blur transition-all hover:border-white/25 hover:bg-white/10"
>
Back to Home
</Link>
</div>
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Fix inconsistent indentation.

Lines 35-39 use spaces while the rest of the file uses tabs. This is likely causing the Prettier formatting warning.

🔧 Proposed fix for indentation
 							<div className="mt-8">
 								<Link
-                                    href="/"
-                                    className="group inline-flex items-center gap-2 rounded-xl border border-white/15 bg-white/5 px-6 py-3 text-sm font-medium text-white backdrop-blur transition-all hover:border-white/25 hover:bg-white/10"
-                                >
-                                    Back to Home
-                                </Link>
+									href="/"
+									className="group inline-flex items-center gap-2 rounded-xl border border-white/15 bg-white/5 px-6 py-3 text-sm font-medium text-white backdrop-blur transition-all hover:border-white/25 hover:bg-white/10"
+								>
+									Back to Home
+								</Link>
 							</div>
📝 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
<Link
href="/"
className="group inline-flex items-center gap-2 rounded-xl border border-white/15 bg-white/5 px-6 py-3 text-sm font-medium text-white backdrop-blur transition-all hover:border-white/25 hover:bg-white/10"
>
Back to Home
</Link>
</div>
<div className="mt-8">
<Link
href="/"
className="group inline-flex items-center gap-2 rounded-xl border border-white/15 bg-white/5 px-6 py-3 text-sm font-medium text-white backdrop-blur transition-all hover:border-white/25 hover:bg-white/10"
>
Back to Home
</Link>
</div>
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/web/src/components/comingSoon.tsx` around lines 34 - 40, The Link JSX
block in the ComingSoon component uses spaces for indentation while the rest of
the file uses tabs, causing Prettier warnings; update the indentation for the
Link element and its nested content (the Back to Home text and surrounding tags)
to use tabs consistent with the file's existing formatting (locate the Link
component in apps/web/src/components/comingSoon.tsx and adjust the indentation
around the Link, its props, and closing tag to tabs).

message: "INTERNAL_AUTH_KEY must be at least 64 characters",
}),
BOT_API_URL: z.string(),
COMING_SOON_MODE: z.enum(["true", "false"]).default("false"),
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

COMING_SOON_MODE is defined but not wired to feature flags.

This env var is properly validated here but feature_flags.ts hardcodes comingSoonMode: true instead of reading from this value. The validation relaxation for secrets works correctly, but actual route gating ignores this setting.

See the related comment in feature_flags.ts for the fix.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/web/src/env.ts` at line 11, The COMING_SOON_MODE env var is validated in
env.ts but feature gating still hardcodes comingSoonMode: true in
feature_flags.ts; change the feature_flags.ts to read the validated value (e.g.,
use the COMING_SOON_MODE export from env.ts and coerce it to a boolean like
env.COMING_SOON_MODE === "true" or a Boolean conversion) and replace the
hardcoded true so routes and flags honor the env setting; keep existing
relaxation for secrets as-is.

Comment on lines 41 to +42
emptyStringAsUndefined: true,
});
}); No newline at end of file
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Fix Prettier formatting.

The pipeline reports code style issues. The file appears to be missing a trailing newline.

🔧 Proposed fix
 	emptyStringAsUndefined: true,
 });
+
📝 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
emptyStringAsUndefined: true,
});
});
emptyStringAsUndefined: true,
});
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/web/src/env.ts` around lines 41 - 42, The file ends with the object
property "emptyStringAsUndefined: true," but is missing a trailing newline;
update apps/web/src/env.ts by adding a final newline character at the end of the
file (ensure the file ends with a single trailing newline) and re-run
Prettier/formatting so the file passes the pipeline.

Comment on lines +1 to +3
export const featureFlags = {
comingSoonMode: true
};
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

comingSoonMode is hardcoded and ignores COMING_SOON_MODE env var.

env.ts defines a COMING_SOON_MODE environment variable with validation and conditional logic, but this module hardcodes comingSoonMode: true. The env var has no effect on actual route gating—routes /faq and /register are permanently gated regardless of the environment configuration.

Either wire this to the env var or remove the env var definition to avoid confusion.

🔧 Proposed fix to use the env var
+import { env } from "@/env";
+
 export const featureFlags = {
-	comingSoonMode: true
+	comingSoonMode: env.COMING_SOON_MODE === "true",
 };
📝 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 featureFlags = {
comingSoonMode: true
};
import { env } from "@/env";
export const featureFlags = {
comingSoonMode: env.COMING_SOON_MODE === "true"
};
🧰 Tools
🪛 GitHub Actions: Prettier Check

[warning] 1-1: Prettier formatting warning: code style issues found in this file.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/web/src/lib/feature_flags.ts` around lines 1 - 3, featureFlags currently
hardcodes comingSoonMode: true which ignores the validated COMING_SOON_MODE from
env.ts; update the featureFlags export to derive comingSoonMode from the
COMING_SOON_MODE env export (or, if you prefer to remove the feature flag,
delete the env var in env.ts to avoid confusion) — specifically, import
COMING_SOON_MODE from env.ts and set featureFlags.comingSoonMode =
COMING_SOON_MODE (or remove the unused COMING_SOON_MODE symbol and its
validation if you choose the removal route) so route gating for /faq and
/register reflects the environment configuration.

Comment on lines +10 to +17
export function isComingSoonRoute(pathname: string) {
return (
featureFlags.comingSoonMode &&
comingSoonRoutes.some(
(route) => pathname === route || pathname.startsWith(`${route}/`),
)
);
} No newline at end of file
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Route matching logic and Prettier formatting.

The isComingSoonRoute function correctly handles both exact matches and nested routes. However, the file is missing a trailing newline per the Prettier pipeline failure.

🔧 Proposed fix for trailing newline
 export function isComingSoonRoute(pathname: string) {
 	return (
 		featureFlags.comingSoonMode &&
 		comingSoonRoutes.some(
 			(route) => pathname === route || pathname.startsWith(`${route}/`),
 		)
 	);
 }
+
📝 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 function isComingSoonRoute(pathname: string) {
return (
featureFlags.comingSoonMode &&
comingSoonRoutes.some(
(route) => pathname === route || pathname.startsWith(`${route}/`),
)
);
}
export function isComingSoonRoute(pathname: string) {
return (
featureFlags.comingSoonMode &&
comingSoonRoutes.some(
(route) => pathname === route || pathname.startsWith(`${route}/`),
)
);
}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/web/src/lib/feature_flags.ts` around lines 10 - 17, The file ends
without a trailing newline which causes the Prettier pipeline to fail; open the
file containing the isComingSoonRoute function and add a single newline
character at the end of the file (ensure the file ends with a blank line) so the
file terminates with a trailing newline and satisfies formatting checks.

Comment on lines +38 to 42
const authData = await auth();

const isBanned = !!(await db.query.bannedUsers.findFirst({
where: eq(bannedUsers.userID, (await auth()).userId!),
where: eq(bannedUsers.userID, authData.userId!),
}));
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Non-null assertion on userId may be unsafe.

After auth.protect(), the user is authenticated, but userId could still theoretically be null in edge cases. Consider adding a guard or using optional chaining with a fallback.

🛡️ Proposed defensive fix
 		const authData = await auth();
+		if (!authData.userId) {
+			return NextResponse.next();
+		}
 
 		const isBanned = !!(await db.query.bannedUsers.findFirst({
-			where: eq(bannedUsers.userID, authData.userId!),
+			where: eq(bannedUsers.userID, authData.userId),
 		}));
📝 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
const authData = await auth();
const isBanned = !!(await db.query.bannedUsers.findFirst({
where: eq(bannedUsers.userID, (await auth()).userId!),
where: eq(bannedUsers.userID, authData.userId!),
}));
const authData = await auth();
if (!authData.userId) {
return NextResponse.next();
}
const isBanned = !!(await db.query.bannedUsers.findFirst({
where: eq(bannedUsers.userID, authData.userId),
}));
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/web/src/middleware.ts` around lines 38 - 42, authData.userId is being
non-null asserted before querying bannedUsers which can be unsafe; update the
middleware to guard against a null/undefined userId from auth() before calling
db.query.bannedUsers.findFirst (e.g., check if authData.userId is present and
handle the missing-case early or skip the DB lookup), and replace the current
unsafe expression that uses authData.userId! with a safe access (use
authData.userId or optional chaining) so references like authData, auth(),
db.query.bannedUsers.findFirst and bannedUsers.userID no longer rely on a
non-null assertion.

Comment on lines 52 to +54
export const config = {
matcher: ["/((?!.*\\..*|_next).*)", "/", "/(api)(.*)"],
};
}; No newline at end of file
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Fix Prettier formatting.

The pipeline reports code style issues in this file.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/web/src/middleware.ts` around lines 52 - 54, The exported config block
(export const config) in middleware.ts fails Prettier checks; reformat the file
to match project Prettier rules (run your repo's Prettier or eslint --fix) so
the matcher array and surrounding whitespace/commas/quotes follow the code
style; save the file after formatting and ensure the export const config block
is the only change.

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