Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion site/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ python3 -m http.server 4321 --directory site # then open http://localhost:4321
- `styles.css`: everything visual. Colors are the app's: ink `#0A0A0A`, highlighter `#E9FF3B`, paper white.
- `main.js`: the illustrated scenes (hero cards, badge, thread) keep their designed size and scale down to fit smaller screens. Below 1180 px the fit is content-aware (it crops a scene's empty margins, so the scene draws larger), and on phones `styles.css` recomposes the hero and the thread into a narrower layout of the same parts. From 1180 px up the page renders exactly as before.
- `lanyard.js`: the badge in "Hire a bot" drops onto its lanyard (with a little wind) the first time it scrolls into view, then swings when you hover, drag or tap it (a few springs and a CSS 3D transform). At rest, with reduced motion or without JavaScript it is exactly the static design.
- `notes.js`: music notes drift out of the hero Boppy's headphones; clicking or tapping it makes a burst of them. It sings along (its mouth, a flat line as it listens, opens with the notes), its eyes follow the pointer and blink, and it squints happily in a burst. Off with reduced motion.
- `notes.js`: music notes drift out of the hero Boppy's headphones. Boppy listens like someone into the music: now and then it shuts its eyes for a moment, hums, or sings a short phrase on its own; its eyes follow the pointer and blink; pointing at it makes it smile and blush. Clicking or tapping it makes a burst of notes and a song of its own length each time (its mouth, a flat line as it listens, sings each syllable), ending in a big smile. Off with reduced motion.
- `download.js`: the three Download for Mac buttons go to `/download/Bops.dmg`. On a Mac they open Get First Access first: leave an email (it goes to PostHog) or skip, and either way the download starts and the card says so. At the card's foot, What's new in the newest release: its version and lines from `/download/latest.json` (written with each release by Orgo's `scripts/download-publish.sh`, in its private OrgoAI/bops-secrets), left out when that can't be read. Anywhere else (iPhone, iPad, Android, Windows, Linux) they open a short note to get Bops on a Mac instead, with Send to my Mac (the share sheet, so AirDrop or Messages) and Copy link. An Intel Mac in Chrome gets the note's Apple silicon version. Without JS the buttons simply download. Test it with `node scripts/test-site.mjs`.
- Pricing (`#pricing`, linked from the nav): Free, Pro and Max in exactly the app's words (`PLAN_CARDS` in `lib/plan-includes.ts`, which the app's Settings shows); `scripts/test-site.mjs` fails when the two differ. Change the plans there and here together.
- PostHog: the snippet in `index.html` sends to Orgo's production project, with `site: bops.bot` on every event. The card's events are `bops_download_click` (with which button: nav, hero or footer), `bops_download_email` (and an identify by the email), `bops_download_skip_email` and `bops_download_note` (the non-Mac or Intel note). Every call is guarded, so a blocker can't break the buttons.
Expand Down
6 changes: 3 additions & 3 deletions site/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link href="https://fonts.googleapis.com/css2?family=Geist:wght@400;500;600;700;800;900&family=Geist+Mono:wght@500;600&display=swap" rel="stylesheet" />
<link rel="stylesheet" href="styles.css?v=10" />
<link rel="stylesheet" href="styles.css?v=11" />
<!-- PostHog (the Orgo project), for the download card's events (download.js). -->
<script>
!function(t,e){var o,n,p,r;e.__SV||(window.posthog=e,e._i=[],e.init=function(i,s,a){function g(t,e){var o=e.split(".");2==o.length&&(t=t[o[0]],e=o[1]),t[e]=function(){t.push([e].concat(Array.prototype.slice.call(arguments,0)))}}(p=t.createElement("script")).type="text/javascript",p.crossOrigin="anonymous",p.async=!0,p.src=s.api_host.replace(".i.posthog.com","-assets.i.posthog.com")+"/static/array.js",(r=t.getElementsByTagName("script")[0]).parentNode.insertBefore(p,r);var u=e;for(void 0!==a?u=e[a]=[]:a="posthog",u.people=u.people||[],Object.defineProperty(u,"toString",{configurable:!0,enumerable:!0,writable:!0,value:function(t){var e="posthog";return"posthog"!==a&&(e+="."+a),t||(e+=" (stub)"),e}}),Object.defineProperty(u.people,"toString",{configurable:!0,enumerable:!0,writable:!0,value:function(){return u.toString(1)+".people (stub)"}}),o="init capture register register_once register_for_session unregister unregister_for_session getFeatureFlag getFeatureFlagResult isFeatureEnabled reloadFeatureFlags updateEarlyAccessFeatureEnrollment getEarlyAccessFeatures on onFeatureFlags onSessionId getSurveys getActiveMatchingSurveys renderSurvey canRenderSurvey getNextSurveyStep identify setPersonProperties group resetGroups setPersonPropertiesForFlags resetPersonPropertiesForFlags setGroupPropertiesForFlags resetGroupPropertiesForFlags reset get_distinct_id getGroups get_session_id get_session_replay_url alias set_config startSessionRecording stopSessionRecording sessionRecordingStarted captureException loadToolbar get_property getSessionProperty createPersonProfile opt_in_capturing opt_out_capturing has_opted_in_capturing has_opted_out_capturing clear_opt_in_out_capturing debug".split(" "),n=0;n<o.length;n++)g(u,o[n]);e._i.push([i,s,a])},e.__SV=1)}(document,window.posthog||[]);
Expand Down Expand Up @@ -106,7 +106,7 @@ <h1 class="hero-title">Bops<br />dot<br />bot.</h1>
<div class="fit" data-w="800" data-h="790">
<div class="stage" style="width:800px;height:790px">
<div class="spot" style="left:90px;top:40px;width:640px;height:640px"></div>
<svg class="boppy-float" style="position:absolute;left:270px;top:92px" width="280" height="280" viewBox="0 0 40 40" role="img" aria-label="Boppy"><g transform="translate(20 21) scale(.9) translate(-20 -20)"><g transform="rotate(-9 20 20)"><path d="M5.3 17.6C4.4 8.4 11.1 2 20 2s15.6 6.4 14.7 15.6" fill="none" stroke="#0A0A0A" stroke-width="2.8" stroke-linecap="round"/><path d="M20 6c8.5 0 14 6 14 13.5S28.5 34 20 34 6 27 6 19.5 11.5 6 20 6z" fill="#0A0A0A"/><g transform="translate(.6 -1.5)"><g class="hero-eyes"><ellipse cx="15.6" cy="20" rx="2.4" ry="3.15" fill="#fff"/><ellipse cx="24.4" cy="20" rx="2.4" ry="3.15" fill="#fff"/></g></g><ellipse class="hero-mouth" cx="20.78" cy="26.9" rx="1.4" ry="1.7" fill="#fff"/><rect x="4" y="16" width="7" height="11" rx="3.5" fill="#E9FF3B" stroke="#0A0A0A" stroke-width="2"/><rect x="29" y="16" width="7" height="11" rx="3.5" fill="#E9FF3B" stroke="#0A0A0A" stroke-width="2"/></g></g></svg>
<svg class="boppy-float" style="position:absolute;left:270px;top:92px" width="280" height="280" viewBox="0 0 40 40" role="img" aria-label="Boppy"><g transform="translate(20 21) scale(.9) translate(-20 -20)"><g transform="rotate(-9 20 20)"><path d="M5.3 17.6C4.4 8.4 11.1 2 20 2s15.6 6.4 14.7 15.6" fill="none" stroke="#0A0A0A" stroke-width="2.8" stroke-linecap="round"/><path d="M20 6c8.5 0 14 6 14 13.5S28.5 34 20 34 6 27 6 19.5 11.5 6 20 6z" fill="#0A0A0A"/><g transform="translate(.6 -1.5)"><g class="hero-eyes"><ellipse cx="15.6" cy="20" rx="2.4" ry="3.15" fill="#fff"/><ellipse cx="24.4" cy="20" rx="2.4" ry="3.15" fill="#fff"/><path class="hero-closed" d="M13.4 20.3q2.2 2.2 4.4 0M22.2 20.3q2.2 2.2 4.4 0" fill="none" stroke="#fff" stroke-width="1.4" stroke-linecap="round" opacity="0"/></g></g><path class="hero-mouth" d="M19.28 26.9h3" fill="#fff" stroke="#fff" stroke-width=".62" stroke-linecap="round" stroke-linejoin="round"/><g class="hero-cheeks" fill="#FF8FB8"><ellipse cx="14.6" cy="24.3" rx="1.8" ry="1.1"/><ellipse cx="26.4" cy="24.3" rx="1.8" ry="1.1"/></g><rect x="4" y="16" width="7" height="11" rx="3.5" fill="#E9FF3B" stroke="#0A0A0A" stroke-width="2"/><rect x="29" y="16" width="7" height="11" rx="3.5" fill="#E9FF3B" stroke="#0A0A0A" stroke-width="2"/></g></g></svg>

<div class="card needs" style="left:476px;top:34px;width:268px">
<div class="needs-head"><span class="dot-amber"></span><span class="mono-label ink">NEEDS YOU</span></div>
Expand Down Expand Up @@ -301,6 +301,6 @@ <h2 class="h2-final">Hire your first Bop.</h2>
<script src="main.js?v=5"></script>
<script src="lanyard.js?v=6" defer></script>
<script src="download.js?v=8" defer></script>
<script src="notes.js?v=6" defer></script>
<script src="notes.js?v=7" defer></script>
</body>
</html>
Loading
Loading