Skip to content

site: version-control the landing page + FAQ#35

Merged
FiscalMindset merged 1 commit into
mainfrom
site/version-control-landing
Jul 15, 2026
Merged

site: version-control the landing page + FAQ#35
FiscalMindset merged 1 commit into
mainfrom
site/version-control-landing

Conversation

@FiscalMindset

@FiscalMindset FiscalMindset commented Jul 15, 2026

Copy link
Copy Markdown
Owner

Adds the production website to the repo so it's version-controlled alongside Blindfold (it was previously untracked — living only on a local machine + the Vercel deployment).

What's added

  • site/index.html — the production landing page (hero, nested architecture + wire animation, responsive system-design flow diagram, three-paths, providers, live proof, 8-dimension comparison table with heatmap + copy, interactive command reference, pricing with testnet overlay, FAQ)
  • site/faq.html — the full FAQ page (25 Q&A, live search, comparison table)
  • site/og.png + site/og.svg — the share card (1200×630) + its source
  • vercel.json + .vercelignore — serve site/ statically; upload only the landing page, never the rest of the monorepo

Live at https://blindfold-rho.vercel.app. No secrets in site/ (verified).


Summary by cubic

Version-controls the production marketing site and serves it statically from site/ on Vercel. Only the site is deployed; the rest of the monorepo stays out of uploads.

  • New Features
    • site/index.html — production landing page (hero, architecture, diagrams, providers, comparison table, commands, pricing, FAQ link).
    • site/faq.html — full FAQ (25 Q&A) with live search and comparison table.
    • site/og.png and site/og.svg — share card and source.
    • vercel.json — static deploy of site/, clean URLs, cache header for og.png.
    • .vercelignore — upload only site/ and vercel.json.

Written for commit 8593730. Summary will update on new commits.

Review in cubic

- add site/ — the production landing page (index.html), FAQ (faq.html), and
  share card (og.png + og.svg source). Live at https://blindfold-rho.vercel.app
- add vercel.json + .vercelignore so a deploy serves site/ statically and uploads
  only the landing page — never the rest of the monorepo

Co-authored-by: algsoch <algsoch@gmail.com>
@FiscalMindset
FiscalMindset merged commit 7cdf849 into main Jul 15, 2026
3 of 5 checks passed
@FiscalMindset
FiscalMindset deleted the site/version-control-landing branch July 15, 2026 11:55
@gitar-bot

gitar-bot Bot commented Jul 15, 2026

Copy link
Copy Markdown

Important

You are using the Gitar free plan. Upgrade to unlock code review, CI analysis, auto-apply, custom automations, and more.

Gitar

@qodo-code-review

Copy link
Copy Markdown

PR Summary by Qodo

Version-control static landing page + FAQ for Vercel deployment

✨ Enhancement ⚙️ Configuration changes 🕐 20-40 Minutes

Grey Divider

AI Description

• Add version-controlled static landing + FAQ pages under site/ for production hosting.
• Configure Vercel to deploy only site/ and exclude the rest of the monorepo.
• Implement lightweight interactivity (search, copy buttons, responsive diagrams) in plain
 HTML/CSS/JS.
Diagram

graph TD
  R["Repo"] --> I[".vercelignore"] --> V["Vercel deploy"]
  R --> C["vercel.json"] --> V --> O["Static output (site/)"] --> H["site/index.html"]
  O --> F["site/faq.html"]
  O --> G["site/og.png"]
Loading
High-Level Assessment

The following are alternative approaches to this PR:

1. Separate website repository
  • ➕ Hard isolation from monorepo contents without relying on ignore rules
  • ➕ Cleaner ownership boundaries and CI/deploy config
  • ➖ Extra repo overhead (versioning, issues, PRs, coordination)
  • ➖ Harder to keep website copy in sync with product changes
2. Vercel project configured with Root Directory = site/
  • ➕ Reduces reliance on .vercelignore for monorepo privacy
  • ➕ Simplifies deployment intent (deploy only site/ by configuration)
  • ➖ Requires Vercel project settings changes (less self-contained in-repo)
  • ➖ Still may need guarding if other outputs/assets are added later

Recommendation: The PR’s approach (in-repo static site + vercel.json + restrictive .vercelignore) is the best default for a monorepo: it keeps deployment configuration versioned and reviewable while explicitly preventing non-site uploads. Consider additionally setting the Vercel Root Directory to site/ as a defense-in-depth measure, but the current setup is already clear and effective.

Files changed (4) +1548 / -0

Enhancement (2) +1530 / -0
index.htmlAdd production landing page as a self-contained static HTML site +1277/-0

Add production landing page as a self-contained static HTML site

• Introduces the full landing page with inline styles and scripts, including responsive sections, interactive copy-to-clipboard elements, animated architecture/system-design visuals, pricing/testnet overlay, and an embedded FAQ preview linking to /faq.

site/index.html

faq.htmlAdd standalone FAQ page with live search and comparison table +253/-0

Add standalone FAQ page with live search and comparison table

• Adds a dedicated FAQ page with inline CSS/JS, a searchable Q&A list with category hiding, mobile nav behavior, and a copyable comparison table exported as Markdown.

site/faq.html

Other (2) +18 / -0
.vercelignoreRestrict Vercel uploads to site/ and vercel.json only +4/-0

Restrict Vercel uploads to site/ and vercel.json only

• Adds ignore rules that exclude the entire repo by default while explicitly allowing site/ and vercel.json. This is intended to prevent accidental upload of the private monorepo into Vercel deployments.

.vercelignore

vercel.jsonConfigure Vercel to serve site/ as static output with clean URLs +14/-0

Configure Vercel to serve site/ as static output with clean URLs

• Defines a no-framework Vercel deployment that serves the site/ directory as the output, enables clean URLs, and sets cache headers for /og.png.

vercel.json

@qodo-code-review

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (3) 📘 Rule violations (0) 📜 Skill insights (0)

Context used
✅ Compliance rules (platform): 5 rules
✅ Skills: blindfold

Grey Divider


Action required

1. Duplicate arch IDs 🐞 Bug ≡ Correctness
Description
site/index.html defines id="arch" on both the <section> and the inner diagram <div>, so
document.getElementById('arch') used by the wire/packet animation can select the wrong element. This
can misplace the SVG overlay (appended to the <section> instead of the positioned .arch container)
and break the animation layout.
Code

site/index.html[R553-560]

+<section id="arch">
+  <div class="wrap">
+    <div class="center reveal">
+      <span class="eyebrow">Architecture</span>
+      <h2>The real stack — nested, not flat</h2>
+      <p class="lead">Your machine is untrusted. The key lives inside an enclave, inside an Intel TDX trust domain, inside the Terminal 3 network. Each boundary is real hardware/crypto isolation.</p>
+    </div>
+    <div class="arch reveal" id="arch">
Evidence
The markup shows two elements with the same id, and the animation code selects by that id and
appends an absolutely positioned SVG to it—making correct element selection critical for
layout/positioning.

site/index.html[553-561]
site/index.html[1195-1202]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
`site/index.html` uses `id="arch"` twice: on the `<section>` and on the inner `.arch` diagram container. The animation code calls `document.getElementById('arch')` and appends an absolutely-positioned SVG (`svg.wires`) to that element; if it resolves to the `<section>`, the SVG is appended outside the intended positioned container and can render misaligned.

### Issue Context
The packet/wire animation expects the selected `arch` element to be the positioned diagram container (`.arch{position:relative}`), since it appends an absolutely positioned SVG and computes coordinates relative to that container.

### Fix Focus Areas
- site/index.html[553-561]
- site/index.html[1195-1202]

### Suggested fix
1. Keep `id="arch"` only on the `<section>` (so `href="#arch"` continues to work).
2. Rename the inner diagram container to something unique (e.g. `id="archDiagram"`).
3. Update the animation code to select that inner container (e.g. `document.getElementById('archDiagram')`).

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Remediation recommended

2. Observer APIs unguarded 🐞 Bug ☼ Reliability
Description
site/index.html constructs IntersectionObserver and ResizeObserver without feature detection, which
will throw ReferenceError in older browsers/webviews and prevent animations (and any later script
initialization) from running. The file already uses a ResizeObserver guard elsewhere, but not
consistently.
Code

site/index.html[R1087-1088]

+  const io=new IntersectionObserver(es=>es.forEach(e=>{if(e.isIntersecting){e.target.classList.add('in');io.unobserve(e.target);}}),{threshold:.1});
+  document.querySelectorAll('.reveal').forEach(el=>io.observe(el));
Evidence
The code constructs IntersectionObserver unconditionally, and also constructs ResizeObserver
unconditionally in the packet animation; in contrast, a separate block shows the intended guarded
pattern for ResizeObserver.

site/index.html[1087-1089]
site/index.html[1114-1116]
site/index.html[1269-1273]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
`site/index.html` uses `new IntersectionObserver(...)` and later `new ResizeObserver(...)` without checking for API availability. In environments lacking these APIs, the script throws and stops subsequent initialization.

### Issue Context
There is already a guarded use of `ResizeObserver` for the system-design diagram, but the packet animation uses an unguarded `ResizeObserver`, and `IntersectionObserver` is also unguarded.

### Fix Focus Areas
- site/index.html[1087-1089]
- site/index.html[1114-1116]
- site/index.html[1269-1273]

### Suggested fix
- Wrap `IntersectionObserver` usage:
 - `if ('IntersectionObserver' in window) { ... } else { /* fall back: add .in immediately / start animations */ }`
- Wrap `ResizeObserver` usage similarly:
 - `if ('ResizeObserver' in window) { ... }` else rely on existing `resize` event listeners.
- Ensure fallbacks still render the page correctly (even if animations are disabled).

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


3. Animations never pause 🐞 Bug ➹ Performance
Description
The hero terminal demo starts an infinite async loop (for(;;)) the first time it becomes visible and
never stops when the element scrolls out of view. This keeps doing timed DOM work in the background,
increasing CPU/battery usage on long-lived tabs (especially on mobile).
Code

site/index.html[R1179-1192]

+    let running=false;
+    async function play(){
+      running=true;
+      for(;;){
+        b1.innerHTML=''; b2.innerHTML=''; w2.classList.add('idle');
+        await runScript(b1, s1);
+        await wait(450); w2.classList.remove('idle'); await wait(350);
+        await runScript(b2, s2);
+        await wait(3400);
+      }
+    }
+    const vo=new IntersectionObserver(es=>es.forEach(e=>{ if(e.isIntersecting && !running){ play(); } }),{threshold:.15});
+    vo.observe(document.getElementById('term1'));
+  })();
Evidence
The code shows an explicit infinite loop in play(), and the observer only triggers start when
intersecting without any stop/pause path when not intersecting.

site/index.html[1179-1192]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
The hero terminal animation runs forever once started (`for(;;)`), and the IntersectionObserver only starts it—there is no mechanism to pause/cancel when the hero is no longer visible.

### Issue Context
This is a marketing page; background CPU/battery drain is avoidable and can be noticeable on mobile.

### Fix Focus Areas
- site/index.html[1179-1192]

### Suggested fix
- Track `active` state from IntersectionObserver (`active = entry.isIntersecting`).
- In `play()`:
 - Replace `for(;;)` with `while (active)` and/or periodically check `active` between steps.
 - When `active` becomes false, exit the loop and allow restart when visible again.
- Optionally honor `prefers-reduced-motion` by skipping the animation entirely when users request reduced motion.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Qodo Logo

Comment thread site/index.html
Comment on lines +553 to +560
<section id="arch">
<div class="wrap">
<div class="center reveal">
<span class="eyebrow">Architecture</span>
<h2>The real stack — nested, not flat</h2>
<p class="lead">Your machine is untrusted. The key lives inside an enclave, inside an Intel TDX trust domain, inside the Terminal 3 network. Each boundary is real hardware/crypto isolation.</p>
</div>
<div class="arch reveal" id="arch">

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Action required

1. Duplicate arch ids 🐞 Bug ≡ Correctness

site/index.html defines id="arch" on both the <section> and the inner diagram <div>, so
document.getElementById('arch') used by the wire/packet animation can select the wrong element. This
can misplace the SVG overlay (appended to the <section> instead of the positioned .arch container)
and break the animation layout.
Agent Prompt
### Issue description
`site/index.html` uses `id="arch"` twice: on the `<section>` and on the inner `.arch` diagram container. The animation code calls `document.getElementById('arch')` and appends an absolutely-positioned SVG (`svg.wires`) to that element; if it resolves to the `<section>`, the SVG is appended outside the intended positioned container and can render misaligned.

### Issue Context
The packet/wire animation expects the selected `arch` element to be the positioned diagram container (`.arch{position:relative}`), since it appends an absolutely positioned SVG and computes coordinates relative to that container.

### Fix Focus Areas
- site/index.html[553-561]
- site/index.html[1195-1202]

### Suggested fix
1. Keep `id="arch"` only on the `<section>` (so `href="#arch"` continues to work).
2. Rename the inner diagram container to something unique (e.g. `id="archDiagram"`).
3. Update the animation code to select that inner container (e.g. `document.getElementById('archDiagram')`).

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Comment thread site/index.html
Comment on lines +1087 to +1088
const io=new IntersectionObserver(es=>es.forEach(e=>{if(e.isIntersecting){e.target.classList.add('in');io.unobserve(e.target);}}),{threshold:.1});
document.querySelectorAll('.reveal').forEach(el=>io.observe(el));

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Remediation recommended

2. Observer apis unguarded 🐞 Bug ☼ Reliability

site/index.html constructs IntersectionObserver and ResizeObserver without feature detection, which
will throw ReferenceError in older browsers/webviews and prevent animations (and any later script
initialization) from running. The file already uses a ResizeObserver guard elsewhere, but not
consistently.
Agent Prompt
### Issue description
`site/index.html` uses `new IntersectionObserver(...)` and later `new ResizeObserver(...)` without checking for API availability. In environments lacking these APIs, the script throws and stops subsequent initialization.

### Issue Context
There is already a guarded use of `ResizeObserver` for the system-design diagram, but the packet animation uses an unguarded `ResizeObserver`, and `IntersectionObserver` is also unguarded.

### Fix Focus Areas
- site/index.html[1087-1089]
- site/index.html[1114-1116]
- site/index.html[1269-1273]

### Suggested fix
- Wrap `IntersectionObserver` usage:
  - `if ('IntersectionObserver' in window) { ... } else { /* fall back: add .in immediately / start animations */ }`
- Wrap `ResizeObserver` usage similarly:
  - `if ('ResizeObserver' in window) { ... }` else rely on existing `resize` event listeners.
- Ensure fallbacks still render the page correctly (even if animations are disabled).

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Comment thread site/index.html
Comment on lines +1179 to +1192
let running=false;
async function play(){
running=true;
for(;;){
b1.innerHTML=''; b2.innerHTML=''; w2.classList.add('idle');
await runScript(b1, s1);
await wait(450); w2.classList.remove('idle'); await wait(350);
await runScript(b2, s2);
await wait(3400);
}
}
const vo=new IntersectionObserver(es=>es.forEach(e=>{ if(e.isIntersecting && !running){ play(); } }),{threshold:.15});
vo.observe(document.getElementById('term1'));
})();

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Remediation recommended

3. Animations never pause 🐞 Bug ➹ Performance

The hero terminal demo starts an infinite async loop (for(;;)) the first time it becomes visible and
never stops when the element scrolls out of view. This keeps doing timed DOM work in the background,
increasing CPU/battery usage on long-lived tabs (especially on mobile).
Agent Prompt
### Issue description
The hero terminal animation runs forever once started (`for(;;)`), and the IntersectionObserver only starts it—there is no mechanism to pause/cancel when the hero is no longer visible.

### Issue Context
This is a marketing page; background CPU/battery drain is avoidable and can be noticeable on mobile.

### Fix Focus Areas
- site/index.html[1179-1192]

### Suggested fix
- Track `active` state from IntersectionObserver (`active = entry.isIntersecting`).
- In `play()`:
  - Replace `for(;;)` with `while (active)` and/or periodically check `active` between steps.
  - When `active` becomes false, exit the loop and allow restart when visible again.
- Optionally honor `prefers-reduced-motion` by skipping the animation entirely when users request reduced motion.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

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