From 03f3c00d22117924f33bd086cf4e78bfb023fb89 Mon Sep 17 00:00:00 2001 From: Elliot Hopkins <160373706+elliothco@users.noreply.github.com> Date: Sun, 12 Apr 2026 12:46:37 -0700 Subject: [PATCH] Landing: plainer copy, optional install detail, bolder editorial styling --- public/extension-demo/popup-demo.js | 14 +- src/components/SiteFooter.astro | 2 +- src/components/SiteHeader.astro | 4 +- src/components/sections/EditorialValue.astro | 6 +- src/components/sections/FAQCompact.astro | 33 +++- src/components/sections/HeroWithProof.astro | 14 +- src/components/sections/InstallJourney.astro | 83 +++++----- src/components/sections/PrivacyBand.astro | 17 +- src/components/sections/UsageMicro.astro | 4 +- src/pages/index.astro | 2 +- src/styles/global.css | 163 ++++++++++++++----- 11 files changed, 215 insertions(+), 127 deletions(-) diff --git a/public/extension-demo/popup-demo.js b/public/extension-demo/popup-demo.js index 2bcc306..c83a293 100644 --- a/public/extension-demo/popup-demo.js +++ b/public/extension-demo/popup-demo.js @@ -12,16 +12,16 @@ const SAMPLE_SUMMARY = `## The lede -This is the **same chrome** as the Lede extension: summarize the active tab, then chat with answers grounded in that text. +This is what the **Lede** popup looks like: one tap for a short summary, then chat about the page. -- **Quick Summary** is real in the build you install—here it’s sample copy. -- **Chat** uses placeholder replies so you can try the layout without an API key. -- Use **Regenerate** after a summary to replay the flow.`; +- **Quick Summary** uses sample text here; after you install it reads the tab you’re on. +- **Chat** shows placeholder answers on this site so you can try the layout at your own pace. +- Tap **Regenerate** to replay the sample summary.`; const ASSISTANT_REPLIES = [ - "In the installed extension I read the tab’s extracted text and answer from that. Here you’re seeing canned replies so the marketing site stays fast and private.", - "After you install, open **Settings** (this demo’s gear only shows a hint) to point at **Ollama** or your own API and model.", - "Try **Regenerate** on the summary card to replay the streamed summary—useful when a page updates underneath you.", + "Once Lede is installed, answers come from the article open in your browser. Here the replies are samples so this page stays quick and private.", + "When you’re ready, open **Settings** in the real extension to choose a model on your computer or one you already use.", + "**Regenerate** on the summary is handy if the page changed and you want a fresh take.", ]; let currentTheme = "system"; diff --git a/src/components/SiteFooter.astro b/src/components/SiteFooter.astro index da7d27d..1f5bb89 100644 --- a/src/components/SiteFooter.astro +++ b/src/components/SiteFooter.astro @@ -10,7 +10,7 @@ const { tangled } = Astro.props; - + diff --git a/src/components/sections/EditorialValue.astro b/src/components/sections/EditorialValue.astro index ab7f982..5e760b1 100644 --- a/src/components/sections/EditorialValue.astro +++ b/src/components/sections/EditorialValue.astro @@ -14,11 +14,11 @@

Questions stay grounded

-

Follow-ups reference the page and the summary you already generated—no free-floating chat pretending it read for you.

+

Follow-ups stick to the page and the summary you already made—no vague answers from something that never read the article.

-

Your stack

-

Ollama native, OpenAI-compatible hosts, Groq, LM Studio—pick the model and base URL in settings instead of a locked vendor.

+

Your choice of AI

+

Use a model on your machine or one you already pay for—set it once in settings instead of being locked to a single vendor.

diff --git a/src/components/sections/FAQCompact.astro b/src/components/sections/FAQCompact.astro index b9eb87b..eef120f 100644 --- a/src/components/sections/FAQCompact.astro +++ b/src/components/sections/FAQCompact.astro @@ -1,25 +1,42 @@ +--- +interface Props { + tangled: string; +} + +const { tangled } = Astro.props; +--- +

FAQ

-

When something blocks install

+

Quick answers

- Cannot connect to localhost:11434 + Why isn't Lede in the store yet?

- Run ollama serve, confirm models with ollama list, and keep - Native mode on http://localhost:11434 without /v1. + We're still in beta and iterating quickly. Installing from the project page keeps early testers close to + the latest fixes while we work toward a store listing.

- HTTP 403 or 405 + Does Lede watch everything I read?

- Wrong API mode for the URL: Native → no /v1. OpenAI-compatible → include - /v1 (for example http://localhost:11434/v1 for Ollama - compatibility mode). + No. Lede only looks at the active tab when you open it and run a summary or a question. There isn't a + background feed of your browsing. +

+
+
+
+ Setup or connection errors +
+

+ If something won't connect or the README mentions a setting you don't recognize, the + project page has the latest step-by-step + notes—we keep them with the extension itself.

diff --git a/src/components/sections/HeroWithProof.astro b/src/components/sections/HeroWithProof.astro index b88c486..be87eaf 100644 --- a/src/components/sections/HeroWithProof.astro +++ b/src/components/sections/HeroWithProof.astro @@ -9,21 +9,21 @@ const { tangled } = Astro.props;
-

Page summarizer and chat · Chrome and Firefox

+

Summarize any page · Chrome and Firefox

Don't bury the lede

- Summarize and ask about this tab before you spend twenty minutes on noise. + Get the gist of this tab in a few seconds—then ask follow-ups if you want more.

- Answers trace the page you have open—not a blank assistant waiting for a prompt. + Lede reads what you're looking at, not a blank chat box that guesses what you meant.

-

Keyboard

+

Shortcut

@@ -48,7 +48,7 @@ const { tangled } = Astro.props;

Beta - Interactive demo uses the same popup layout as the extension—mocked summary and chat only. + Play with the real layout here; after you install, summaries use your page and your settings.
diff --git a/src/components/sections/InstallJourney.astro b/src/components/sections/InstallJourney.astro index 3525deb..ea4d24f 100644 --- a/src/components/sections/InstallJourney.astro +++ b/src/components/sections/InstallJourney.astro @@ -10,74 +10,67 @@ const { tangled } = Astro.props;

Install

-

From repo to toolbar

+

Try the beta

- Clone webai-summarizer on Tangled—not this marketing repo. You need a folder that contains - manifest.json. lede-website is only this page. + Lede isn't in the Chrome or Firefox stores yet. Download the extension folder from the project page, then + add it to your browser—full click-by-click steps are there too.

-

Get the code

-

Download or clone the extension repo so the project lives on disk.

- Open Tangled repo +

Grab the build

+

Open the project page and download the extension files to your computer.

+ Open project page
-

Choose a browser

-

Chrome uses unpacked load; Firefox uses a temporary add-on.

+

Add it in the browser

+

Chrome and Firefox each have a simple “load from folder” flow for betas.

-

Load and configure

-

Point settings at Ollama native or an OpenAI-compatible endpoint, then try a tab.

+

Pick how Lede thinks

+

In settings, choose a local model or another provider you already use.

-
-
-
-

Chrome

-
    -
  1. Open chrome://extensions/
  2. -
  3. Enable Developer mode
  4. -
  5. Click Load unpacked
  6. -
  7. Select the webai-summarizer folder that contains manifest.json
  8. -
  9. Optional: shortcuts at chrome://extensions/shortcuts
  10. -
+
+ Step-by-step for Chrome or Firefox +
+
+
+

Chrome

+
    +
  1. Open chrome://extensions/
  2. +
  3. Enable Developer mode
  4. +
  5. Click Load unpacked
  6. +
  7. Select the extension folder that contains manifest.json
  8. +
  9. Optional: shortcuts at chrome://extensions/shortcuts
  10. +
+
+
+

Firefox

+
    +
  1. Open about:debugging#/runtime/this-firefox
  2. +
  3. Click Load Temporary Add-on
  4. +
  5. Select manifest.json inside the extension folder
  6. +
  7. Add-ons → gear → Manage Extension Shortcuts for the hotkey
  8. +
+

+ Temporary add-ons clear when you fully quit Firefox—reload during active dev sessions. +

+
-
-

Firefox

-
    -
  1. Open about:debugging#/runtime/this-firefox
  2. -
  3. Click Load Temporary Add-on
  4. -
  5. Select manifest.json inside webai-summarizer
  6. -
  7. Add-ons → gear → Manage Extension Shortcuts for the hotkey
  8. -
-

- Temporary add-ons clear when you fully quit Firefox—reload during active dev sessions. -

-
-
-
- -
- Advanced: build scripts per browser -
-

- If you already use split manifests, ./build.sh chrome or - ./build.sh firefox from the extension repo targets a specific build. -

-

- Source: +

+ Project: {tangled}

diff --git a/src/components/sections/PrivacyBand.astro b/src/components/sections/PrivacyBand.astro index 9164785..8243e0c 100644 --- a/src/components/sections/PrivacyBand.astro +++ b/src/components/sections/PrivacyBand.astro @@ -1,24 +1,25 @@
-

Privacy and APIs

-

Where text goes

+

Privacy

+

Your reading stays yours

-

Ollama native

+

On your computer

- /api/generate on your machine. Base URL omits /v1. + Point Lede at a local model and page text stays on your machine. Nothing is uploaded in the background while + you browse.

-

OpenAI-compatible

+

When you use a cloud model

- /v1/chat/completions to the endpoint you configure. Content leaves the browser only when - you summarize or chat—not via a script on every site. + If you connect to a hosted service you trust, text is sent only when you summarize or chat—not on every site + you visit.

-

Extraction is on-demand when you ask.

+

Lede only reads a tab when you ask it to.

diff --git a/src/components/sections/UsageMicro.astro b/src/components/sections/UsageMicro.astro index 72b6841..89cd8c3 100644 --- a/src/components/sections/UsageMicro.astro +++ b/src/components/sections/UsageMicro.astro @@ -28,7 +28,7 @@

- The hero above is a live shell of the extension popup—try theme, Quick Summary, and chat there; - install from source for the real pipeline (page extraction, your model, settings). + The preview above matches the real popup—try the theme, Quick Summary, and chat. After you install, + those same controls work on whatever page you have open.

diff --git a/src/pages/index.astro b/src/pages/index.astro index 571478f..daf0da3 100644 --- a/src/pages/index.astro +++ b/src/pages/index.astro @@ -35,7 +35,7 @@ const ogImage = existsSync(path.join(imagesDir, "hero.webp")) - +
diff --git a/src/styles/global.css b/src/styles/global.css index ad3af94..e26e643 100644 --- a/src/styles/global.css +++ b/src/styles/global.css @@ -17,9 +17,10 @@ --color-ink-muted: oklch(72% 0.02 var(--hue-ink)); --color-surface: oklch(99.4% 0.004 var(--hue-brand)); - --color-brand: oklch(63.5% 0.196 38); - --color-brand-hover: oklch(57% 0.18 38); - --color-brand-active: oklch(50% 0.165 38); + --color-brand: oklch(64.5% 0.205 38); + --color-brand-hover: oklch(58% 0.19 38); + --color-brand-active: oklch(51% 0.175 38); + --color-brand-soft: color-mix(in oklch, var(--color-brand) 14%, var(--color-canvas)); --color-on-brand: oklch(99% 0.01 95); --color-link: oklch(38% 0.02 var(--hue-ink)); @@ -38,8 +39,8 @@ --font-mono: ui-monospace, "SF Mono", "Cascadia Code", monospace; /* Fluid display scale (≥1.25 ratio between steps) */ - --text-hero: clamp(2.25rem, 4vw + 1.5rem, 3.75rem); - --text-xl: clamp(1.75rem, 2.2vw + 1.1rem, 2.4rem); + --text-hero: clamp(2.85rem, 5.5vw + 1.15rem, 4.85rem); + --text-xl: clamp(1.9rem, 2.6vw + 1.05rem, 2.75rem); --text-lg: clamp(1.35rem, 1.2vw + 1rem, 1.75rem); --text-md: clamp(1.0625rem, 0.5vw + 0.95rem, 1.25rem); --text-sm: 0.875rem; @@ -80,7 +81,9 @@ --shadow-card-edge: oklch(0% 0 0 / 0.07); --shadow-card-soft: oklch(0% 0 0 / 0.11); --shadow-popup: - 0 0 0 1px oklch(0% 0 0 / 0.07), 0 10px 24px oklch(0% 0 0 / 0.07), 0 28px 70px oklch(0% 0 0 / 0.11); + 0 0 0 1px color-mix(in oklch, var(--color-brand) 18%, oklch(0% 0 0 / 0.06)), + 0 12px 28px oklch(0% 0 0 / 0.08), + 0 32px 80px oklch(0% 0 0 / 0.12); } @media (prefers-color-scheme: dark) { @@ -94,9 +97,10 @@ --color-ink-muted: oklch(56% 0.022 70); --color-surface: oklch(21.2% 0.014 var(--hue-brand)); - --color-brand: oklch(69% 0.19 38); - --color-brand-hover: oklch(75% 0.195 40); - --color-brand-active: oklch(61% 0.17 38); + --color-brand: oklch(70% 0.2 38); + --color-brand-hover: oklch(76% 0.2 40); + --color-brand-active: oklch(62% 0.175 38); + --color-brand-soft: color-mix(in oklch, var(--color-brand) 18%, var(--color-canvas)); --color-on-brand: oklch(14% 0.02 42); --color-link: oklch(78% 0.04 72); @@ -112,13 +116,29 @@ --shadow-card-edge: oklch(100% 0 0 / 0.08); --shadow-card-soft: oklch(0% 0 0 / 0.42); --shadow-popup: - 0 0 0 1px oklch(100% 0 0 / 0.1), 0 12px 28px oklch(0% 0 0 / 0.42), - 0 28px 72px oklch(0% 0 0 / 0.52); + 0 0 0 1px color-mix(in oklch, var(--color-brand) 28%, oklch(100% 0 0 / 0.12)), + 0 14px 32px oklch(0% 0 0 / 0.45), + 0 36px 88px oklch(0% 0 0 / 0.55); } .section--dark .eyebrow { color: oklch(76% 0.055 55); } + + .hero-mast { + background: + radial-gradient(ellipse 78% 58% at 0% 0%, color-mix(in oklch, var(--color-brand) 24%, transparent), transparent 55%), + linear-gradient( + 172deg, + color-mix(in oklch, var(--color-subtle) 92%, #000) 0%, + var(--color-canvas) 48%, + oklch(14.5% 0.016 var(--hue-brand)) 100% + ); + } + + .hero-mast .eyebrow { + color: color-mix(in oklch, var(--color-brand) 48%, var(--color-ink-muted)); + } } *, @@ -236,10 +256,11 @@ a:focus-visible { font-family: var(--font-display); font-size: var(--text-hero); font-weight: 700; - line-height: var(--leading-tight); - letter-spacing: var(--tracking-display); + line-height: 1.02; + letter-spacing: -0.028em; color: var(--color-ink); margin: 0 0 var(--space-sm); + text-wrap: balance; } .heading-xl { @@ -293,9 +314,24 @@ a:focus-visible { position: sticky; top: 0; z-index: 50; - background: color-mix(in oklch, var(--color-canvas) 92%, transparent); - backdrop-filter: blur(10px); + isolation: isolate; + background: color-mix(in oklch, var(--color-canvas) 96%, transparent); + backdrop-filter: blur(6px); border-bottom: 1px solid var(--color-border); + box-shadow: 0 1px 0 color-mix(in oklch, var(--color-brand) 8%, transparent); +} + +.site-header::before { + content: ""; + position: absolute; + inset: 0 0 auto 0; + height: 3px; + background: linear-gradient( + 90deg, + color-mix(in oklch, var(--color-brand) 88%, transparent), + color-mix(in oklch, var(--color-brand) 35%, var(--color-canvas)) + ); + pointer-events: none; } .site-header__inner { @@ -481,23 +517,31 @@ a:focus-visible { } .btn--primary { - color: var(--color-brand); - background: transparent; - border-color: var(--color-brand); + color: var(--color-on-brand); + background: var(--color-brand); + border-color: color-mix(in oklch, var(--color-brand) 78%, var(--color-ink)); + box-shadow: + 0 1px 0 color-mix(in oklch, var(--color-on-brand) 22%, transparent), + 0 3px 0 color-mix(in oklch, var(--color-brand-active) 55%, var(--color-ink)); } .btn--primary:hover { - background: var(--color-brand); + background: var(--color-brand-hover); + border-color: var(--color-brand-hover); color: var(--color-on-brand); - border-color: var(--color-brand); - transform: translateY(-1px); + transform: translateY(-2px); + box-shadow: + 0 1px 0 color-mix(in oklch, var(--color-on-brand) 28%, transparent), + 0 5px 0 color-mix(in oklch, var(--color-brand-active) 45%, var(--color-ink)), + 0 14px 28px color-mix(in oklch, var(--color-brand) 22%, transparent); } .btn--primary:active { background: var(--color-brand-active); border-color: var(--color-brand-active); color: var(--color-on-brand); - transform: translateY(0); + transform: translateY(1px); + box-shadow: 0 1px 0 color-mix(in oklch, var(--color-on-brand) 15%, transparent); } .btn--secondary { @@ -527,9 +571,12 @@ a:focus-visible { /* Privacy dark band */ .section--dark { - background: var(--color-dark-canvas); + background-color: var(--color-dark-canvas); + background-image: + radial-gradient(ellipse 120% 70% at 100% 0%, oklch(38% 0.06 48 / 0.4), transparent 52%), + radial-gradient(ellipse 90% 55% at 0% 100%, oklch(32% 0.07 38 / 0.35), transparent 48%); color: var(--color-dark-ink); - padding-block: var(--space-3xl); + padding-block: calc(var(--space-3xl) + var(--space-md)); border-block: 1px solid var(--color-dark-border); } @@ -643,7 +690,7 @@ a:focus-visible { .reveal-item { opacity: 0; - transform: translateY(12px); + transform: translateY(18px); animation: reveal-in var(--duration-enter) var(--ease-out) forwards; animation-delay: calc(var(--i, 0) * var(--stagger)); } @@ -687,10 +734,10 @@ a:focus-visible { .deck { font-family: var(--font-display); - font-size: clamp(1.125rem, 1.5vw + 0.75rem, 1.45rem); + font-size: clamp(1.2rem, 1.85vw + 0.7rem, 1.6rem); font-weight: 600; line-height: var(--leading-ui); - letter-spacing: -0.015em; + letter-spacing: -0.018em; color: var(--color-ink); max-width: 28em; margin: 0 0 var(--space-sm); @@ -702,8 +749,22 @@ a:focus-visible { } .hero-mast { - padding-block: var(--space-2xl) var(--space-3xl); + position: relative; + isolation: isolate; + padding-block: calc(var(--space-2xl) + var(--space-sm)) calc(var(--space-3xl) + var(--space-md)); border-bottom: 1px solid var(--color-border); + background: + radial-gradient(ellipse 85% 65% at 0% 0%, var(--color-brand-soft), transparent 58%), + linear-gradient( + 168deg, + color-mix(in oklch, var(--color-surface) 55%, var(--color-canvas)) 0%, + var(--color-canvas) 42%, + color-mix(in oklch, var(--color-subtle) 88%, var(--color-canvas)) 100% + ); +} + +.hero-mast .eyebrow { + color: color-mix(in oklch, var(--color-brand) 42%, var(--color-ink-muted)); } .hero-mast__grid { @@ -714,8 +775,8 @@ a:focus-visible { @media (min-width: 960px) { .hero-mast__grid { - grid-template-columns: minmax(0, 1fr) minmax(320px, 1.05fr); - gap: var(--space-2xl); + grid-template-columns: minmax(0, 1.02fr) minmax(320px, 1.12fr); + gap: clamp(var(--space-2xl), 4vw, var(--space-3xl)); align-items: center; } } @@ -850,7 +911,12 @@ a:focus-visible { } .journey-band--callout { - background: color-mix(in oklch, var(--color-subtle) 65%, var(--color-canvas)); + background: linear-gradient( + 135deg, + color-mix(in oklch, var(--color-brand-soft) 80%, var(--color-subtle)) 0%, + color-mix(in oklch, var(--color-subtle) 72%, var(--color-canvas)) 100% + ); + border-color: color-mix(in oklch, var(--color-brand) 22%, var(--color-border)); } .journey-band__text { @@ -891,9 +957,10 @@ a:focus-visible { .journey-strip__num { font-family: var(--font-display); font-weight: 700; - font-size: var(--text-xl); + font-size: clamp(2.25rem, 4.5vw + 1rem, 3.35rem); color: var(--color-brand); - line-height: 1; + line-height: 0.95; + letter-spacing: -0.03em; } .journey-strip__title { @@ -930,23 +997,30 @@ a:focus-visible { @media (min-width: 800px) { .editorial-grid { - grid-template-columns: repeat(3, 1fr); - gap: var(--space-lg); + grid-template-columns: 1.18fr 0.92fr 0.92fr; + gap: clamp(var(--space-lg), 3vw, var(--space-xl)); + align-items: start; } } .editorial-block { - padding-top: var(--space-md); - border-top: 2px solid color-mix(in oklch, var(--color-brand) 35%, var(--color-border)); + padding-top: var(--space-lg); + border-top: 3px solid color-mix(in oklch, var(--color-brand) 52%, var(--color-border)); } .editorial-block p { - margin: var(--space-xs) 0 0; - font-size: var(--text-sm); + margin: var(--space-sm) 0 0; + font-size: clamp(0.9375rem, 0.35vw + 0.88rem, 1.0625rem); line-height: var(--leading-prose); color: var(--color-ink-secondary); } +@media (min-width: 800px) { + .editorial-block:first-child .heading-md { + font-size: clamp(1.2rem, 0.9vw + 1rem, 1.45rem); + } +} + .usage-flow { list-style: none; margin: 0; @@ -1000,10 +1074,13 @@ a:focus-visible { } .privacy-kicker { - margin: var(--space-lg) 0 0; - font-weight: 600; - font-size: var(--text-sm); - max-width: 42ch; + margin: var(--space-xl) 0 0; + font-family: var(--font-display); + font-weight: 700; + font-size: var(--text-md); + letter-spacing: -0.02em; + max-width: 40ch; + color: var(--color-dark-ink); } .faq-stack { -- 2.51.2