Skip to content

feat(public): gate public pages with explicit flags#3566

Open
PlaneInABottle wants to merge 7 commits intosimstudioai:stagingfrom
PlaneInABottle:feat/public-page-flags
Open

feat(public): gate public pages with explicit flags#3566
PlaneInABottle wants to merge 7 commits intosimstudioai:stagingfrom
PlaneInABottle:feat/public-page-flags

Conversation

@PlaneInABottle
Copy link

Summary

  • add explicit public-surface flags for landing, studio, changelog, legal pages, templates, and careers so self-hosted deployments can disable each surface independently
  • make public discovery outputs and shared UI respect the same helpers, including auth legal-link fallbacks and careers redirect/link gating
  • add focused regression coverage for route guards, nav/footer visibility, auth legal links, discovery outputs, template metadata visibility, and careers redirect behavior

@vercel
Copy link

vercel bot commented Mar 13, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
docs Skipped Skipped Mar 14, 2026 7:52pm

Request Review

@cursor
Copy link

cursor bot commented Mar 13, 2026

PR Summary

Medium Risk
Adds new env-driven gating that can return notFound/404 or change redirects and SEO/discovery outputs across multiple public routes; misconfiguration could unintentionally hide pages from users and crawlers. Changes are mostly conditional rendering/metadata with good test coverage, reducing runtime risk.

Overview
Introduces explicit env flags (default-on unless set false) to independently disable public surfaces: landing (/), studio (/studio* + feeds), changelog, legal pages, templates, and careers links/redirect.

Updates route handlers and UI to respect these flags: pages now call notFound() (or return 404 for RSS/sitemaps) when disabled; nav/footer/logo stop linking to disabled routes; auth forms resolve Terms/Privacy links via new helpers with external-URL fallback or per-link hiding.

Aligns SEO/discovery outputs with visibility: sitemap.ts, robots.ts, llms.txt, and llms-full.txt omit disabled routes/links; templates metadata returns noindex when public templates are disabled or template is not approved. Adds targeted Vitest coverage for the new gating, link visibility, discovery outputs, and conditional /careers redirect.

Written by Cursor Bugbot for commit 84e0540. This will update automatically on new commits. Configure here.

@greptile-apps
Copy link
Contributor

greptile-apps bot commented Mar 13, 2026

Greptile Summary

This PR introduces six explicit opt-out feature flags (NEXT_PUBLIC_ENABLE_*) that let self-hosted deployments independently disable the landing page, studio pages, changelog, legal pages, templates, and careers link. When unset, every surface defaults to enabled, so existing deployments are unaffected.

Key changes:

  • feature-flags.ts — adds isPublicPageEnabled (defaults-to-enabled helper), six flag constants, and getAuthLegalLinkConfig / getAuthTermsLinkConfig / getAuthPrivacyLinkConfig for auth-surface legal links with external-URL fallback support.
  • Route guards — each public page/layout now calls notFound() (server-side) when its flag is off, replacing the previous client-side useEffect redirects on legal pages.
  • Discovery outputssitemap.ts, robots.ts, llms.txt, and llms-full.txt all respect the same flags, omitting disabled routes from crawlable output and adding them to the robots.txt disallow list.
  • UI gating — nav and footer links are conditionally rendered; the logo link wrapper is removed when the landing page is disabled.
  • next.config.ts/careers redirect is conditionally included via the exported getCareersRedirect helper.
  • Tests — broad regression coverage across route guards, nav/footer link visibility, auth legal-link fallback logic, discovery metadata, template metadata visibility, and the careers redirect.

Confidence Score: 4/5

  • Safe to merge — all flag gates default to enabled so no existing behavior changes. Minor formatting issues in LLM discovery documents when flags are disabled.
  • The implementation is well-structured, thoroughly tested, and defaults-to-enabled so no regressions are introduced. The only issues found are cosmetic: empty section headers in llms.txt and a stray blank line in llms-full.txt when all flags are off. These do not affect production users of the hosted deployment.
  • apps/sim/app/llms.txt/route.ts and apps/sim/app/llms-full.txt/route.ts — empty section headers / stray blank lines when flags are disabled.

Important Files Changed

Filename Overview
apps/sim/lib/core/config/feature-flags.ts Core flag implementation — adds isPublicPageEnabled helper, six flag constants, and getAuthLegalLinkConfig/getAuthTermsLinkConfig/getAuthPrivacyLinkConfig helpers. All flags correctly default to enabled when unset. isFalsy accepts `string
apps/sim/app/llms.txt/route.ts Conditionally omits disabled pages from the LLM discovery document. When all flags are off, corePages and optionalLinks become empty strings, leaving orphaned ## Core Pages and ## Optional section headers with no content.
apps/sim/app/llms-full.txt/route.ts Gates website and legal links behind flags. When isPublicLandingPageEnabled is false, websiteLink is an empty string that introduces a stray blank line before - **Documentation** in the ## Links section.
apps/sim/next.config.ts Adds getCareersRedirect helper that conditionally includes the /careers → Ashby redirect based on the NEXT_PUBLIC_ENABLE_CAREERS_LINK flag. Implementation is clean and well-tested.
apps/sim/app/robots.ts Adds disabled public routes to the robots disallow list. Landing page root / is intentionally excluded from the disallow list (adding it would block all pages). Correct behavior; confirmed by test.
apps/sim/app/sitemap.ts Wraps each static sitemap entry group behind its corresponding feature flag. Blog pages are also gated behind isPublicStudioPagesEnabled. Correct and well-tested.
apps/sim/app/(landing)/privacy/page.tsx Converts from a client component (useEffect-based redirect) to a server component with synchronous notFound() / redirect(). Cleaner and more SEO-friendly approach.
apps/sim/app/(landing)/terms/page.tsx Same as privacy page — converts from client to server component with proper notFound() / redirect() gates. Correct implementation.
apps/sim/app/templates/[id]/page.tsx Adds notFound() guard and extracts getPublicTemplateMetadataRecord helper that hides metadata (returns getUnavailableTemplateMetadata) for both disabled flag and non-approved templates.
apps/sim/app/(auth)/login/login-form.tsx Replaces hard-coded /terms and /privacy links with dynamic config from getAuthTermsLinkConfig / getAuthPrivacyLinkConfig. Correctly handles all combinations (both, one, or neither link present).
apps/sim/app/(landing)/components/footer/footer.tsx Wraps Pricing, Sim Studio, Changelog, Careers, Privacy, and Terms footer links behind their respective flags. Clean implementation.
apps/sim/app/(landing)/components/nav/nav.tsx Extracts homeContent to avoid duplication and gates the logo's Link wrapper behind isPublicLandingPageEnabled. Falls back to a non-clickable div when the landing page is disabled.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    subgraph EnvVars["Environment Variables (NEXT_PUBLIC_ENABLE_*)"]
        E1[LANDING_PAGE]
        E2[STUDIO_PAGES]
        E3[CHANGELOG_PAGE]
        E4[LEGAL_PAGES]
        E5[TEMPLATES_PAGES]
        E6[CAREERS_LINK]
    end

    subgraph Flags["feature-flags.ts — isPublicPageEnabled()"]
        F1[isPublicLandingPageEnabled]
        F2[isPublicStudioPagesEnabled]
        F3[isPublicChangelogPageEnabled]
        F4[isPublicLegalPagesEnabled]
        F5[isPublicTemplatesPagesEnabled]
        F6[isPublicCareersLinkEnabled]
    end

    E1 --> F1
    E2 --> F2
    E3 --> F3
    E4 --> F4
    E5 --> F5
    E6 --> F6

    F1 -->|false| LP_404["/  →  notFound()"]
    F1 -->|true| LP_OK["/  →  Landing page"]

    F2 -->|false| SP_404["/studio* layout → notFound()\nRSS & image-sitemap → 404"]
    F2 -->|true| SP_OK["/studio* served normally"]

    F3 -->|false| CL_404["/changelog → notFound()"]
    F3 -->|true| CL_OK["/changelog served normally"]

    F4 -->|false| LEG_404["/terms & /privacy → notFound()\nAuth forms: use TERMS_URL / PRIVACY_URL or hide"]
    F4 -->|true| LEG_OK["/terms & /privacy served\nAuth forms: internal links"]

    F5 -->|false| T_404["/templates & /templates/[id] → notFound()"]
    F5 -->|true| T_OK["/templates served normally"]

    F6 -->|false| C_NO["Nav/Footer Careers link hidden\n/careers redirect removed from next.config"]
    F6 -->|true| C_OK["Nav/Footer Careers link shown\n/careers → jobs.ashbyhq.com/sim"]

    F1 & F2 & F3 & F4 & F5 --> SITEMAP[sitemap.ts — omits disabled URLs]
    F2 & F3 & F4 & F5 --> ROBOTS[robots.ts — disallows disabled paths]
    F1 & F2 & F3 & F4 & F5 & F6 --> LLMS[llms.txt / llms-full.txt — omits disabled links]
Loading

Last reviewed commit: c65dfae

@PlaneInABottle
Copy link
Author

I opened this pr since I am using the project as my backend, had to remove the public pages manually. I think most people who self host the project would do the same.

@PlaneInABottle PlaneInABottle force-pushed the feat/public-page-flags branch from 4e6c7f8 to 7b8c38e Compare March 14, 2026 17:09
@vercel
Copy link

vercel bot commented Mar 14, 2026

@PlaneInABottle is attempting to deploy a commit to the Sim Team on Vercel.

A member of the Team first needs to authorize it.

@icecrasher321
Copy link
Collaborator

bugbot run

Copy link

@cursor cursor bot left a comment

Choose a reason for hiding this comment

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

✅ Bugbot reviewed your changes and found no new issues!

Comment @cursor review or bugbot run to trigger another review on this PR

@icecrasher321
Copy link
Collaborator

icecrasher321 commented Mar 14, 2026

@PlaneInABottle Is it possible to consolidate these env vars into one -- or just behind isHosted? We'd rather not update the helm charts, docs with these

@PlaneInABottle
Copy link
Author

@icecrasher321 fixed

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.

3 participants