Skip to content

fix(site): add reCAPTCHA v3, main landmark, and docs sitemap#469

Merged
Aureliolo merged 5 commits intomainfrom
fix/site-recaptcha-and-pagespeed
Mar 15, 2026
Merged

fix(site): add reCAPTCHA v3, main landmark, and docs sitemap#469
Aureliolo merged 5 commits intomainfrom
fix/site-recaptcha-and-pagespeed

Conversation

@Aureliolo
Copy link
Copy Markdown
Owner

Summary

  • reCAPTCHA v3: Add invisible reCAPTCHA integration to contact form — hidden g-recaptcha-response field + fresh token generated before each submission. Fixes Formcarry "Google reCAPTCHA Validation Failed" error.
  • <main> landmark: Wrap page content in <main> tag — fixes PageSpeed "Document does not have a main landmark" accessibility warning.
  • Docs sitemap: Add https://synthorg.io/docs/sitemap.xml to robots.txt so Google discovers the 35 documentation pages built by Zensical.
  • Block /_assets/: Prevent indexing of Astro's hashed CSS/JS build artifacts.

Test plan

  • Submit contact form — no reCAPTCHA validation error
  • Form submission reaches email
  • No visible CAPTCHA widget (v3 is invisible)
  • PageSpeed: "Document does not have a main landmark" warning gone
  • Google Search Console: docs sitemap discovered via robots.txt

- Add reCAPTCHA v3 integration to contact form (hidden token before
  each submission) — fixes Formcarry validation error
- Wrap page content in <main> landmark (PageSpeed accessibility fix)
- Add docs sitemap to robots.txt for Google discovery
- Block /_assets/ from indexing (hashed build artifacts)
@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Mar 15, 2026

Dependency Review

✅ No vulnerabilities or license issues or OpenSSF Scorecard issues found.

OpenSSF Scorecard

PackageVersionScoreDetails
npm/@types/grecaptcha 3.0.9 🟢 6.5
Details
CheckScoreReason
Maintained🟢 1030 commit(s) and 1 issue activity found in the last 90 days -- score normalized to 10
Code-Review🟢 8Found 23/28 approved changesets -- score normalized to 8
Packaging⚠️ -1packaging workflow not detected
CII-Best-Practices⚠️ 0no effort to earn an OpenSSF best practices badge detected
Dangerous-Workflow🟢 10no dangerous workflow patterns detected
Security-Policy🟢 10security policy file detected
Token-Permissions⚠️ 0detected GitHub workflow tokens with excessive permissions
License🟢 9license file detected
Branch-Protection⚠️ -1internal error: error during branchesHandler.setup: internal error: some github tokens can't read classic branch protection rules: https://github.com/ossf/scorecard-action/blob/main/docs/authentication/fine-grained-auth-token.md
Signed-Releases⚠️ -1no releases found
Binary-Artifacts🟢 10no binaries found in the repo
Pinned-Dependencies🟢 8dependency not pinned by hash detected -- score normalized to 8
SAST⚠️ 0SAST tool is not run on all commits -- score normalized to 0
Fuzzing⚠️ 0project is not fuzzed

Scanned Files

  • site/package-lock.json

@gemini-code-assist
Copy link
Copy Markdown
Contributor

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request significantly enhances the site's robustness and user experience by integrating reCAPTCHA v3 for improved spam protection on the contact form, boosting accessibility by adding a

landmark to page content, and optimizing search engine discoverability of documentation through sitemap inclusion in robots.txt. Additionally, it prevents unnecessary indexing of build assets.

Highlights

  • reCAPTCHA v3 Integration: Added invisible reCAPTCHA v3 to the contact form, generating a fresh token before each submission to resolve 'Google reCAPTCHA Validation Failed' errors.
  • Main Landmark for Accessibility: Wrapped the main page content in a HTML tag to address PageSpeed's 'Document does not have a main landmark' accessibility warning.
  • Docs Sitemap for SEO: Included the documentation sitemap (https://synthorg.io/docs/sitemap.xml) in robots.txt to enhance Google's discovery of documentation pages.
  • Asset Indexing Prevention: Blocked the /_assets/ directory in robots.txt to prevent search engines from indexing Astro's hashed CSS/JS build artifacts.
Changelog
  • site/public/robots.txt
    • Added a 'Disallow' rule for the '/_assets/' directory to prevent indexing of build artifacts.
    • Included the documentation sitemap (https://synthorg.io/docs/sitemap.xml) for improved discoverability.
  • site/src/components/ContactForm.astro
    • Introduced a hidden input field ('g-recaptcha-response') to store the reCAPTCHA token.
    • Implemented JavaScript logic to fetch a fresh reCAPTCHA v3 token before form submission and populate the hidden input.
  • site/src/layouts/Base.astro
    • Wrapped the main content slot with a HTML landmark for improved accessibility.
    • Added the Google reCAPTCHA v3 script to the base layout for site-wide availability.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Mar 15, 2026

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: c918782d-d251-477b-92e1-6e74deaa1c38

📥 Commits

Reviewing files that changed from the base of the PR and between 778c465 and 4d6e317.

📒 Files selected for processing (1)
  • site/src/components/ContactForm.astro

📝 Walkthrough

Summary by CodeRabbit

  • New Features

    • Added reCAPTCHA v3 protection to the contact form.
    • Footer moved into the main layout for consistent site rendering; individual pages updated accordingly.
  • Chores

    • robots.txt updated to disallow /_assets/ and include an additional sitemap entry.
    • Development tooling updated with reCAPTCHA TypeScript typings.

Walkthrough

Adds Disallow and sitemap entries to robots.txt, integrates Google reCAPTCHA v3 into the contact form (client-side token fetch), exposes an enableRecaptcha prop and script injection in Base layout, moves slot into

, renders Footer from Base, and removes Footer usage from two pages.

Changes

Cohort / File(s) Summary
SEO Configuration
site/public/robots.txt
Added Disallow: /_assets/ and an additional Sitemap: https://synthorg.io/docs/sitemap.xml.
reCAPTCHA & Layout
site/src/components/ContactForm.astro, site/src/layouts/Base.astro, site/package.json
ContactForm: added module-scope recaptchaSiteKey, data-recaptcha-key on the form, hidden g-recaptcha-response input, and client-side pre-submit logic to call grecaptcha.execute (action "contact") and populate the token before submission; error handling when grecaptcha unavailable. Base: added enableRecaptcha?: boolean prop (default false), declares recaptchaSiteKey, wraps content in <main>, imports/renders <Footer />, and conditionally injects the reCAPTCHA v3 script when enableRecaptcha is true. package.json: added devDependency @types/grecaptcha.
Page Footer removals & Base usage
site/src/pages/get/index.astro, site/src/pages/index.astro
Removed Footer import and <Footer /> usage from these pages; index.astro updated to pass enableRecaptcha={true} to Base.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant Browser as Site (contact page)
    participant Recaptcha as Google reCAPTCHA
    participant Server as Site backend

    User->>Browser: Click submit on contact form
    Browser->>Recaptcha: grecaptcha.ready -> grecaptcha.execute(action:"contact", site_key)
    Recaptcha-->>Browser: returns token (g-recaptcha-response)
    Browser->>Browser: insert token into hidden input
    Browser->>Server: POST form data (includes g-recaptcha-response)
    Server->>Recaptcha: verify token with reCAPTCHA API
    Recaptcha-->>Server: verification result
    Server-->>Browser: respond with success/error
    Browser-->>User: display result
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately and concisely summarizes the three main changes: reCAPTCHA v3 integration, main landmark addition, and docs sitemap inclusion.
Description check ✅ Passed The description is directly related to the changeset, providing clear context for each of the four main changes with a detailed test plan.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix/site-recaptcha-and-pagespeed
✨ Simplify code
  • Create PR with simplified code
  • Commit simplified code in branch fix/site-recaptcha-and-pagespeed
📝 Coding Plan
  • Generate coding plan for human review comments

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

@Aureliolo Aureliolo temporarily deployed to cloudflare-preview March 15, 2026 21:44 — with GitHub Actions Inactive
Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request introduces several useful features, including reCAPTCHA v3 integration, accessibility improvements with a <main> landmark, and SEO enhancements through robots.txt and sitemap additions. The changes are well-intentioned, but I've identified a critical issue regarding the hardcoding of the reCAPTCHA site key in two separate files. This poses a security and maintainability risk. My review comments provide specific code suggestions to refactor this using environment variables, which is the standard and recommended practice for managing such keys in Astro applications.

try {
// Get fresh reCAPTCHA v3 token before submission
if (typeof grecaptcha !== "undefined") {
const token = await grecaptcha.execute("6LdQkossAAAAADwxZo5bt8p6az7P3M6I_8k4_ypu", { action: "contact" });
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.

high

This reCAPTCHA site key is hardcoded. To improve security and maintainability, it's best to avoid hardcoding keys. Instead, you should load it from an environment variable and pass it to this client-side script.

A common pattern in Astro is to:

  1. Read the environment variable in the component's frontmatter (e.g., const recaptchaSiteKey = import.meta.env.PUBLIC_RECAPTCHA_SITE_KEY;).
  2. Pass it to the template via a data attribute on the form: <form data-recaptcha-key={recaptchaSiteKey} ...>.
  3. Access it in the script via form.dataset.recaptchaKey.

Remember to also add a check to ensure form.dataset.recaptchaKey is available before using it.

          const token = await grecaptcha.execute(form.dataset.recaptchaKey, { action: "contact" });

<!-- GitHub buttons (https://buttons.github.io/) -->
<script async defer src="https://buttons.github.io/buttons.js"></script>
<!-- Google reCAPTCHA v3 (contact form spam protection) -->
<script async defer src="https://www.google.com/recaptcha/api.js?render=6LdQkossAAAAADwxZo5bt8p6az7P3M6I_8k4_ypu"></script>
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.

high

Hardcoding API keys, even public ones like a reCAPTCHA site key, is not recommended. It makes managing keys across different environments (e.g., development, production) difficult and error-prone. Please store this key in an environment variable and access it using Astro's import.meta.env feature. Remember that public client-side environment variables must be prefixed with PUBLIC_.

    <script async defer src={`https://www.google.com/recaptcha/api.js?render=${import.meta.env.PUBLIC_RECAPTCHA_SITE_KEY}`}></script>

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 4

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

Inline comments:
In `@site/src/components/ContactForm.astro`:
- Around line 111-116: The submission currently proceeds when grecaptcha is
undefined, so update the submit handler in ContactForm.astro to detect when
typeof grecaptcha === "undefined" and stop the submission flow: prevent the form
submit/return early, set a visible error message (reuse the component's existing
form error state/UI) informing the user that reCAPTCHA failed to load and they
should retry or disable blockers, and do not call
form.querySelector("#captchaResponse") or proceed to send data; ensure the check
occurs before the grecaptcha.execute call and references grecaptcha,
captchaInput and the form submit handler to locate where to add this
early-return and UI error display.
- Around line 112-113: The TypeScript compiler complains about the global
grecaptcha used in ContactForm.astro; add a proper type declaration for
grecaptcha to satisfy strict TS. Either install the `@types/grecaptcha` dev
package (npm install --save-dev `@types/grecaptcha`) or add a local declaration
file (e.g., env.d.ts) that declares the global grecaptcha with ready and execute
signatures so the call to grecaptcha.execute(...) in ContactForm.astro is typed
and the build error is resolved.

In `@site/src/layouts/Base.astro`:
- Around line 72-73: Extract the hard-coded reCAPTCHA site key into a single
shared constant (for example PUBLIC_RECAPTCHA_SITE_KEY) and reference that
constant in both Base.astro and ContactForm.astro; implement it by placing the
key in an environment variable exposed to the client (e.g., via
import.meta.env.PUBLIC_RECAPTCHA_SITE_KEY) or a shared config module, then
replace the inline literal in Base.astro's script src and the literal used in
ContactForm.astro (line ~113) with the shared variable (e.g., use
?render=${PUBLIC_RECAPTCHA_SITE_KEY}) so updates happen in one place.
- Around line 67-69: The Base.astro layout currently wraps the page slot in
<main> causing any slotted <footer> (Footer component) to be nested inside
<main>; update Base.astro so <main> contains only the primary <slot /> and
render the Footer component as a sibling after </main> in Base.astro, then
remove Footer usage from individual pages that currently slot it (so pages only
provide main content to the slot). Ensure you reference the layout's <main> and
the Footer component when making the change so the Footer is no longer nested
inside <main>.
🪄 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: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: eb11854a-85e9-4813-bc39-8d514df72328

📥 Commits

Reviewing files that changed from the base of the PR and between 11b645e and 8998642.

📒 Files selected for processing (3)
  • site/public/robots.txt
  • site/src/components/ContactForm.astro
  • site/src/layouts/Base.astro
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Analyze (python)
🔇 Additional comments (2)
site/public/robots.txt (1)

3-6: LGTM!

The Disallow: /_assets/ directive correctly prevents indexing of Astro's hashed build artifacts, and the additional sitemap entry enables search engine discovery of the documentation pages.

site/src/components/ContactForm.astro (1)

63-63: LGTM!

The hidden input for the reCAPTCHA token is correctly placed with appropriate id and name attributes for Formcarry integration.

Comment on lines +72 to +73
<!-- Google reCAPTCHA v3 (contact form spam protection) -->
<script async defer src="https://www.google.com/recaptcha/api.js?render=6LdQkossAAAAADwxZo5bt8p6az7P3M6I_8k4_ypu"></script>
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial

Consider extracting the reCAPTCHA site key to a shared constant.

The site key 6LdQkossAAAAADwxZo5bt8p6az7P3M6I_8k4_ypu is duplicated here and in ContactForm.astro (line 113). If the key ever changes, both locations need updating.

Consider defining it once (e.g., in an environment variable or a shared config) and referencing it in both places.

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

In `@site/src/layouts/Base.astro` around lines 72 - 73, Extract the hard-coded
reCAPTCHA site key into a single shared constant (for example
PUBLIC_RECAPTCHA_SITE_KEY) and reference that constant in both Base.astro and
ContactForm.astro; implement it by placing the key in an environment variable
exposed to the client (e.g., via import.meta.env.PUBLIC_RECAPTCHA_SITE_KEY) or a
shared config module, then replace the inline literal in Base.astro's script src
and the literal used in ContactForm.astro (line ~113) with the shared variable
(e.g., use ?render=${PUBLIC_RECAPTCHA_SITE_KEY}) so updates happen in one place.

- Extract reCAPTCHA site key to env var (PUBLIC_RECAPTCHA_SITE_KEY)
  with fallback, passed via data attribute — no more hardcoded duplication
- Install @types/grecaptcha for TypeScript compilation
- Block form submission when reCAPTCHA unavailable (ad-blocker, network)
  with user-friendly error message
- Move Footer to Base layout outside <main> — fixes semantic HTML nesting
- Remove Footer import/usage from individual pages (now in layout)
@socket-security
Copy link
Copy Markdown

socket-security bot commented Mar 15, 2026

Review the following changes in direct dependencies. Learn more about Socket for GitHub.

Diff Package Supply Chain
Security
Vulnerability Quality Maintenance License
Addednpm/​@​types/​grecaptcha@​3.0.91001007180100

View full report

@Aureliolo Aureliolo temporarily deployed to cloudflare-preview March 15, 2026 21:53 — with GitHub Actions Inactive
Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

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

Inline comments:
In `@site/src/components/ContactForm.astro`:
- Around line 116-127: The current reCAPTCHA logic calls grecaptcha.execute
without waiting for grecaptcha.ready and proceeds if the `#captchaResponse` input
is missing; change it to call grecaptcha.ready() first (use
grecaptcha.ready(async () => { ... })) before calling
grecaptcha.execute(siteKey, { action: "contact" }), ensure you immediately
error/return if form.dataset.recaptchaKey is falsy or if
form.querySelector("#captchaResponse") returns null (do not continue
submission), and keep the existing errorMsg update/focus when
readiness/token/getting the captcha input fails so submission fails closed;
reference grecaptcha.ready, grecaptcha.execute, form.dataset.recaptchaKey, and
captchaInput/#captchaResponse to find the code to modify.

In `@site/src/layouts/Base.astro`:
- Around line 75-76: Add an optional prop to Base.astro's Props interface named
enableRecaptcha?: boolean, wrap the existing reCAPTCHA script element in a
conditional that only renders when enableRecaptcha is true (e.g.,
{enableRecaptcha && <script ...>}), and update index.astro to pass
enableRecaptcha={true} when rendering Base so only the page that contains
ContactForm loads the third‑party reCAPTCHA script; leave other pages unchanged
(do not pass the prop or pass false).
🪄 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: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 40da3d9b-2387-49b6-abe7-e6d3b719f082

📥 Commits

Reviewing files that changed from the base of the PR and between 8998642 and 70b3d0b.

⛔ Files ignored due to path filters (1)
  • site/package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (5)
  • site/package.json
  • site/src/components/ContactForm.astro
  • site/src/layouts/Base.astro
  • site/src/pages/get/index.astro
  • site/src/pages/index.astro
💤 Files with no reviewable changes (2)
  • site/src/pages/get/index.astro
  • site/src/pages/index.astro
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Analyze (python)
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2026-03-15T11:48:14.867Z
Learnt from: CR
Repo: Aureliolo/synthorg PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-15T11:48:14.867Z
Learning: Applies to web/** : Web dashboard: Node.js 20+, dependencies in web/package.json (Vue 3, PrimeVue, Tailwind CSS, Pinia, VueFlow, ECharts, Axios, vue-draggable-plus, Vitest, fast-check, ESLint, vue-tsc).

Applied to files:

  • site/package.json
🔇 Additional comments (2)
site/package.json (1)

17-20: Looks good.

No issues found in this manifest change.

site/src/layouts/Base.astro (1)

69-72: Good semantic landmark structure.

<main> now contains primary content and <Footer /> is correctly outside it.

Comment on lines +75 to +76
<!-- Google reCAPTCHA v3 (contact form spam protection) -->
<script async defer src={`https://www.google.com/recaptcha/api.js?render=${recaptchaSiteKey}`}></script>
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

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Verify current reCAPTCHA script scope and layout usage.
rg -n --type=astro 'recaptcha/api.js|enableRecaptcha' site/src/layouts/Base.astro
rg -n --type=astro '<ContactForm' site/src/pages site/src/components
rg -n --type=astro '<Base' site/src/pages

Repository: Aureliolo/synthorg

Length of output: 151


🏁 Script executed:

#!/bin/bash
# Verify reCAPTCHA script and layout usage in Astro files
# First, check if the Base.astro file exists and view the relevant lines
echo "=== Checking Base.astro content around lines 75-76 ==="
if [ -f "site/src/layouts/Base.astro" ]; then
  sed -n '70,80p' "site/src/layouts/Base.astro"
else
  echo "Base.astro not found"
fi

echo ""
echo "=== Searching for recaptcha/api.js references ==="
rg 'recaptcha/api.js' site/

echo ""
echo "=== Searching for enableRecaptcha ==="
rg 'enableRecaptcha' site/

echo ""
echo "=== Searching for ContactForm component usage ==="
rg '<ContactForm' site/src/pages site/src/components 2>/dev/null || rg 'ContactForm' site/src/pages site/src/components

echo ""
echo "=== Searching for Base layout usage ==="
rg '<Base\s' site/src/pages 2>/dev/null || rg 'Base layout\|import.*Base' site/src/pages

Repository: Aureliolo/synthorg

Length of output: 1223


🏁 Script executed:

#!/bin/bash
# Check Base.astro Props interface and search all pages
echo "=== Base.astro Props interface (first 30 lines) ==="
head -30 site/src/layouts/Base.astro

echo ""
echo "=== All pages using Base layout ==="
rg -l 'Base' site/src/pages

echo ""
echo "=== All ContactForm usages ==="
rg -l 'ContactForm' site/src/pages site/src/components

echo ""
echo "=== Count of .astro files in site/src/pages ==="
find site/src/pages -name "*.astro" -type f | wc -l

Repository: Aureliolo/synthorg

Length of output: 1282


Scope reCAPTCHA loading to pages that actually need it.

Currently, reCAPTCHA loads on all 4 pages using Base.astro, but ContactForm only exists on index.astro. This means 3 pages (install-sh.astro, install-ps1.astro, get/index.astro) unnecessarily load a third-party script, adding avoidable performance and privacy overhead.

Move the reCAPTCHA script to only load when needed by:

  1. Adding enableRecaptcha?: boolean prop to the Props interface
  2. Wrapping the script in a conditional: {enableRecaptcha && <script ...>}
  3. Setting enableRecaptcha={true} only in index.astro
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@site/src/layouts/Base.astro` around lines 75 - 76, Add an optional prop to
Base.astro's Props interface named enableRecaptcha?: boolean, wrap the existing
reCAPTCHA script element in a conditional that only renders when enableRecaptcha
is true (e.g., {enableRecaptcha && <script ...>}), and update index.astro to
pass enableRecaptcha={true} when rendering Base so only the page that contains
ContactForm loads the third‑party reCAPTCHA script; leave other pages unchanged
(do not pass the prop or pass false).

…A loading

- Wrap grecaptcha.execute in grecaptcha.ready() to ensure library is
  initialized before use
- Fail-closed: block submission if siteKey or captchaInput is missing
- Add enableRecaptcha prop to Base layout — reCAPTCHA script only loads
  on pages that need it (index.astro), not /get/ or view pages
@Aureliolo Aureliolo temporarily deployed to cloudflare-preview March 15, 2026 22:01 — with GitHub Actions Inactive
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: 1

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

Inline comments:
In `@site/src/components/ContactForm.astro`:
- Line 125: The grecaptcha.ready() await can hang indefinitely; wrap the
existing await new Promise<void>((resolve) => grecaptcha.ready(() =>
resolve())); in a timeout guard (e.g., Promise.race between the grecaptcha.ready
promise and a setTimeout that resolves/rejects after a short interval) so the
wait fails fast if reCAPTCHA never becomes ready, then handle the timeout path
in the ContactForm.astro submit flow (stop the "Sending..." state and surface an
error message). Ensure you reference the grecaptcha.ready wrapper and the submit
handler in ContactForm.astro when adding the timeout and the error handling.
🪄 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: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 318db28a-1e20-4279-899c-7d61fda3399e

📥 Commits

Reviewing files that changed from the base of the PR and between 70b3d0b and 8bea55a.

📒 Files selected for processing (3)
  • site/src/components/ContactForm.astro
  • site/src/layouts/Base.astro
  • site/src/pages/index.astro
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Analyze (python)
🔇 Additional comments (6)
site/src/layouts/Base.astro (3)

71-74: LGTM! Semantic HTML structure is now correct.

The <Footer /> is properly rendered as a sibling of <main>, not nested within it. This correctly addresses the HTML landmark semantics where <footer> should be at the page level.


77-80: LGTM! Conditional reCAPTCHA loading is well-implemented.

The script only loads when enableRecaptcha is true, avoiding unnecessary third-party script loading on pages that don't need it. This addresses both performance and privacy concerns.


23-23: Site key duplication still exists between Base.astro and ContactForm.astro.

The recaptchaSiteKey constant with the same fallback value is defined in both files. While both now use the environment variable, the hardcoded fallback is duplicated.

This was already flagged in a past review. Consider extracting to a shared config module if this becomes a maintenance concern.

site/src/pages/index.astro (1)

8-8: LGTM! reCAPTCHA correctly enabled for the contact form page.

Passing enableRecaptcha={true} ensures the reCAPTCHA script loads only on this page where ContactForm is used, optimizing performance for other pages.

site/src/components/ContactForm.astro (2)

116-127: LGTM! Fail-closed reCAPTCHA integration is well-implemented.

The implementation correctly:

  • Validates all required elements (grecaptcha, siteKey, captchaInput) before proceeding
  • Uses grecaptcha.ready() before execute() per the official API contract
  • Blocks submission with a user-friendly error if security verification is unavailable

68-68: LGTM! Hidden input correctly configured for reCAPTCHA v3.

The hidden input with name="g-recaptcha-response" follows the standard field name that form processors like Formcarry expect for reCAPTCHA token validation.

Prevents form hanging on "Sending..." if reCAPTCHA never becomes
ready (partial script load, network stall). Falls through to the
existing catch block which resets the button and shows the error.
@Aureliolo Aureliolo temporarily deployed to cloudflare-preview March 15, 2026 22:06 — with GitHub Actions Inactive
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: 1

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

Inline comments:
In `@site/src/components/ContactForm.astro`:
- Around line 125-128: The Promise.race timer created with setTimeout should be
cleared when grecaptcha.ready resolves to avoid a lingering timeout; modify the
block around grecaptcha.ready()/Promise.race to assign the timeout to a variable
(e.g., const timer = setTimeout(...)) and call clearTimeout(timer) inside the
grecaptcha.ready resolve path (the resolver passed to new Promise that calls
grecaptcha.ready), ensuring the timeout is cancelled when grecaptcha.ready wins;
keep the existing reject path for the timeout so it still rejects if
grecaptcha.ready doesn't fire.
🪄 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: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 602d9e58-632a-413d-a7ed-88e0d80fc175

📥 Commits

Reviewing files that changed from the base of the PR and between 8bea55a and 778c465.

📒 Files selected for processing (1)
  • site/src/components/ContactForm.astro
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Analyze (python)
🔇 Additional comments (2)
site/src/components/ContactForm.astro (2)

2-3: Good reCAPTCHA key wiring to form dataset.

Line 2 + Line 10 cleanly expose the site key to the submit handler without changing the component API.

Also applies to: 10-10


68-68: Correct hidden field name for Formcarry reCAPTCHA token.

Line 68 uses name="g-recaptcha-response", which is the expected payload field for reCAPTCHA verification handoff.

@Aureliolo Aureliolo merged commit fa6d35c into main Mar 15, 2026
11 of 13 checks passed
@Aureliolo Aureliolo deleted the fix/site-recaptcha-and-pagespeed branch March 15, 2026 22:11
@Aureliolo Aureliolo temporarily deployed to cloudflare-preview March 15, 2026 22:11 — with GitHub Actions Inactive
Aureliolo added a commit that referenced this pull request Mar 15, 2026
🤖 I have created a release *beep* *boop*
---


##
[0.2.6](v0.2.5...v0.2.6)
(2026-03-15)


### Features

* add intra-loop stagnation detector
([#415](#415))
([#458](#458))
([8e9f34f](8e9f34f))
* add RFC 9457 structured error responses (Phase 1)
([#457](#457))
([6612a99](6612a99)),
closes [#419](#419)
* implement AgentStateRepository for runtime state persistence
([#459](#459))
([5009da7](5009da7))
* **site:** add SEO essentials, contact form, early-access banner
([#467](#467))
([11b645e](11b645e)),
closes [#466](#466)


### Bug Fixes

* CLI improvements — config show, completion install, enhanced doctor,
Sigstore verification
([#465](#465))
([9e08cec](9e08cec))
* **site:** add reCAPTCHA v3, main landmark, and docs sitemap
([#469](#469))
([fa6d35c](fa6d35c))
* use force-tag-creation instead of manual tag creation hack
([#462](#462))
([2338004](2338004))

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).
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