Skip to content

One-time DebateOwl welcome with Ollie and the rename notice - #237

Merged
Programcode merged 7 commits into
design/debateowl-restylefrom
design/debateowl-intro
Oct 26, 2026
Merged

Programcode merged 7 commits into
design/debateowl-restylefrom
design/debateowl-intro

Conversation

@Programcode

Copy link
Copy Markdown
Owner

Adds a one-time welcome that ships with the DebateOwl restyle (#228). It targets design/debateowl-restyle, not main.

What it does

The first time someone opens the signed-in app after this ships, they see one dialog. It holds the owl's introduction and the rename notice together and has one dismiss button.

The owl sits on a sky disc and says four lines into a speech bubble, changing pose for each one. The sequence takes about 6.6 seconds:

  1. Surprised, then waving: "Hi, I'm Ollie, the DebateOwl owl!"
  2. Finger up: "DebateLab has a new look."
  3. Thinking and bobbing, as the app's loader does, beside thinking dots: "I'll keep you company while things load."
  4. Thumbs up, beside the mint check (the only mint in the dialog): "Same tools as before, in the same spots."

Under the bubble, the notice is visible from the start: "DebateLab is slowly becoming DebateOwl. Same app, same account, same saved work, with a new look and name. We're moving to help more people find us on Google." It names no domain or URL and claims no new features.

Got it is the only button that closes the dialog, and it has focus when the dialog opens. Esc and the backdrop also close it. Skip animation jumps to the last frame without closing. With prefers-reduced-motion the dialog opens on that last frame and starts no timers. Radix keeps focus inside the dialog. The bubble's lines hold their space before they appear, so nothing jumps. The owl stacks over the bubble on phones and sits beside it from 640 px up.

The animation uses Framer Motion, which the app already depends on, and the existing owl poses. No new dependencies.

Show once

  • Closing the dialog in any way writes debateowl_intro_seen_v1 to localStorage. Any stored value counts as seen.
  • The flag lives in localStorage only. Profiles have no column for UI flags, the onboarding tour already keeps its state in localStorage, and a column would mean a migration for a one-off dialog.
  • If storage can't be read, the dialog stays closed. Otherwise it would reopen on every load.
  • It mounts inside RequireAuth, so public, SEO and prerendered guide pages never load it. It opens after the app layout has loaded.
  • A brand-new account sees the welcome first and the onboarding tour after it. Without the welcome, the tour mounts exactly as before.

Owl name

The owl is Ollie. OWL_NAME in src/lib/debateowl-intro.ts is the only place the name lives, so changing it later is a one-line edit. It is the same in every language, so it is a constant rather than a locale key. The owl introduces itself as "Hi, I'm Ollie, the DebateOwl owl!", "¡Hola, soy Ollie, el búho de DebateOwl!" and "Szia, Ollie vagyok, a DebateOwl baglya!". Setting OWL_NAME to an empty string falls back to "Hi, I'm DebateOwl!".

Tests and test runs

  • Playwright builds (VITE_E2E=1) and the verify stack, agentic tests and db-gate browser runs (VITE_LOCAL_PREVIEW=true) never open it. ?intro=show forces it open in any build and ?intro=skip keeps it closed.
  • Two runners drive production builds, so they seed the flag instead: the production canary and the service worker offline test (npm run test:sw). The first verify run caught the welcome covering the Tools page that test:sw clicks.
  • src/test/onboarding/debateowl-intro.test.tsx covers the show-once logic. It checks the stored flag, the test-mode and query overrides, and unreadable storage. It checks that Got it and Esc mark the dialog seen while Skip animation does not, and it checks that Ollie introduces itself by name and that an empty name falls back to DebateOwl.
  • The verify skill, docs/testing.md and docs/architecture.md each note the welcome and ?intro=show.

Restyle branch

This branch includes design/debateowl-restyle after it was brought up to date with main (#233 to #236) by a normal merge (715b2e5). That merge had four conflicts. Each one keeps both sides:

  • src/locales/en.json: main's {{proMonthly}} price parameter with the restyle's sentence-case "Start trial" and "View pricing".
  • ToolPageLayout.tsx: the restyle's owl mark and Fredoka wordmark with main's localized home link and site.product name.
  • public/seo-pages.css and the stylesheet in scripts/generate_seo_content.py: the restyle's palette and buttons plus main's new .table styles for desktop and mobile. Rerunning the generator reproduces the committed guide pages byte for byte.

npm run verify passed on the restyle merge before it was pushed.

Screenshots

These are on the image-only branch intro-screenshots, not on this PR. They cover phone 390, iPad 768 and 1024, and desktop 1440 in light, plus desktop 1440 in dark. Each size has six animation frames (the owl landing, then each line, then the settled notice), the app after closing, and a reduced-motion frame and a Skip animation frame. They come from the Playwright stub session at /app?intro=show, so they show rendering only, not an authenticated backend. The same run checked that the dialog fits each viewport, that Got it and Esc store the flag, and that a reload does not reopen it.

Verification

Local only. GitHub Actions jobs on this repo fail in 2 to 6 seconds with no logs, which is the out-of-minutes billing state, so there is no CI result.

  • npm run verify on this branch at c1fe62f passed: docs check, lint, typecheck, 663 unit tests in 91 files, 30 collaboration tests, 482 edge tests, build, the service worker offline test and 47 desktop Chromium smoke tests.
  • npm run verify on design/debateowl-restyle at 715b2e5 (the merge with main) passed with the same steps.
  • The screenshot run at c1fe62f passed 37 checks. It covered every frame at five sizes. It checked that the dialog fits each viewport and that Got it and Esc store the flag so a reload does not reopen it. It checked reduced motion (no Skip animation button, focus on Got it and kept inside the dialog) and that Skip animation does not close the dialog or store the flag.

Not checked: a real signed-in account on the verify stack (it suppresses the dialog by design, and ?intro=show there renders the same component), WebKit, and staging.

🤖 Generated with Claude Code

Programcode and others added 7 commits October 26, 2026 20:27
The owl says hello and introduces DebateOwl as the new look of
DebateLab. Two more steps follow: what changed (the look, the owl
guide, everything still where it was) and the slow move to the
DebateOwl name. The hello takes about 3 seconds. Under reduced
motion it shows its last frame and starts no timers.

It opens once per browser inside the signed-in app, after the
layout loads, and runs before the onboarding tour. Closing it any
way (Skip, Got it, Esc, the X, the backdrop) writes
debateowl_intro_seen_v1 to localStorage. There is no profile column
for UI flags, so localStorage is the only store, as with the tour.

Playwright (VITE_E2E) and the verify stack (VITE_LOCAL_PREVIEW)
never open it. ?intro=show forces it and ?intro=skip suppresses it.
The production canary seeds the flag. The owl's personal name is the
empty owlName key; while it stays empty the owl says "Hi there!".

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The owl's introduction and the rename notice now share one dialog, so
nobody sees two popups. Over about 6.6 seconds the owl says its lines
into a speech bubble, one beat per pose: it introduces itself as
DebateOwl, says DebateLab has a new look, bobs over thinking dots as it
promises company while things load, and gives a thumbs-up beside the
mint check for the same tools as before. The notice ("DebateLab is
slowly becoming DebateOwl") sits under the bubble from the start.

Got it is the one way out; Esc and the backdrop still close it and
mark it seen. Skip animation jumps to the last frame without closing.
Reduced motion shows that frame at once.

The owl's name moves to OWL_NAME in src/lib/debateowl-intro.ts, a
constant rather than a locale key, since it is the same in every
language. While it is empty the owl calls itself DebateOwl.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
No name has been chosen, so the owl introduces itself as DebateOwl in
every language and OWL_NAME stays empty. The test for a set name uses
an obvious placeholder instead of a made-up name.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
OWL_NAME is now "Ollie", still the one place the name lives. The owl
introduces itself as "Hi, I'm Ollie, the DebateOwl owl!", in Spanish
"¡Hola, soy Ollie, el búho de DebateOwl!" and in Hungarian "Szia, Ollie
vagyok, a DebateOwl baglya!". The product name stays DebateOwl.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
test:sw drives a production build, where the one-time DebateOwl
welcome opens and covered the Tools page the test clicks. It now seeds
debateowl_intro_seen_v1 next to the tour flag, as the canary does.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
At 390 px the greeting left "owl!" alone on its second line. It now
balances across both lines.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Oct 26, 2026 •

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

Run configuration

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Note

🎁 Summarized by CodeRabbit Free

Your organization is on the Free plan. CodeRabbit will generate a high-level summary and a walkthrough for each pull request. For a comprehensive line-by-line review, please upgrade your subscription to CodeRabbit Essentials by visiting https://app.coderabbit.ai/settings/billing.

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

@Programcode
Programcode marked this pull request as ready for review October 26, 2026 21:04
Copilot AI balanced review requested due to automatic review settings October 26, 2026 21:04
@Programcode
Programcode merged commit e5c6efc into design/debateowl-restyle Oct 26, 2026
3 of 10 checks passed

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Copilot was unable to review this pull request because the user who requested the review has insufficient remaining quota.

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.

2 participants