piruicy
The collection

Glass hello

after Apple

A cursive hello in liquid glass that writes itself, hands over from language to language, and opens with a swipe up.

Swipe up to open · ← → change the wallpaper

Make it yours

Paste this brief into your coding agent. You make four images; it does the rest, step by step, and checks each one.

HANDOFF.md
# Glass hello: agent handoff

Paste this whole brief into your coding agent (Claude Code, Cursor, Codex, or another) in the project where you want the effect. You draw the words and choose the wallpapers. The agent does everything else and checks each step before moving on.

---

## For the agent: your job

You are guiding a person through putting **Glass hello** into their project with **their own words and wallpapers**. The effect is a cursive word in liquid glass that writes itself, then hands over to the next word with a sweep from left to right, and waits for a swipe up. It's after Apple's iOS 26 Setup screen, measured frame by frame.

It ships with placeholder words (Hershey Script, public domain) and six painted wallpapers, so it already works. The person's own words are what make it theirs.

**The person only draws and chooses.** You do everything else: install, convert, measure, wire up, verify. Do not hand them technical steps.

**How to work:**
- Go **one step at a time**. Say in a sentence what's happening and what you need.
- **Check every word with numbers before moving on** (Step 3). A badly drawn word looks wrong in glass in ways that are hard to see in a vector editor.
- When a word fails a check, say plainly what's wrong and how to fix the drawing.

**What's installed:**
- The component: `components/piruicy/glass-hello.tsx`, with its CSS module and the placeholder words, `glass-hello-words.ts`.
- `scripts/glass-hello/strokes.mjs`: turns an SVG of single-line paths into the component's stroke data.
- This brief: `scripts/glass-hello/HANDOFF.md`.

---

## Step 0: Set up (you, quietly)

1. If the files aren't there yet, install with `npx shadcn@latest add @piruicy/glass-hello` (it needs the piruicy pass and token), or copy them in. There are no dependencies; it needs WebGL2.
2. Check Node 18+.
3. Render `<GlassHello />` on a test page inside a tall box (for example 390×844) and confirm it plays: a drop, then "hello" written in glass, then "hola".

## Step 1: Choose the words (ask the person)

Ask them:
- **Which words, in which order?** The first one is written slowly after the intro drop; each after it arrives every 3.8 seconds.
- **The caption under each** (the placeholder says "Swipe up to open" in each language).
- **Do they have a mark**, a simple solid logo, that should melt into the first stroke? It must be their own: a single filled SVG path. Without one, a drop swells from nothing.

## Step 2: Draw the words (the person)

Tell them how to draw so the glass reads well:
- **Single lines, not outlines.** Use the pen or pencil tool with a stroke and no fill, as if writing with a pen. Never convert text to outlines: a font's letters are filled shapes, and they come out as hollow double tubes.
- **Join the letters**, like handwriting. Each continuous line becomes one stroke the pen writes without lifting; lift only where a hand would (the cross of a t, the second stroke of a k).
- **Draw in writing order and direction**: left to right, top of a stroke to its bottom, as a hand would. The pen follows the path's direction, and later lines pass over earlier ones where they cross.
- **Dots and accents** are tiny closed shapes or short marks; they become dabs.
- **Keep the line smooth.** Fewer, longer curves read better than many short ones.
- **Draw every word at the same size**, on a guide line for the baseline. Note the font size they're drawing at, for example 100px.
- Export each word as its own SVG (in Figma: select it, Export, SVG, with "Outline stroke" off).

## Step 3: Convert and check each word (you)

1. Convert, with the em (the size they drew at) and the baseline's y in the SVG:
   `node scripts/glass-hello/strokes.mjs --em 100 --baseline 160 word.svg > public/glass-hello/word.json`
2. Check it, in a small script over the JSON, and fix with the person if any fail:
   - **Size.** The word's height above the baseline should be about 600–800 units (the reference's "h" is 737). If it's far off, the `--em` is wrong.
   - **Width.** Words wider than about 3,900 units are scaled down to fit 85% of the screen, so their tube gets thinner. Fine for one long word; if most are, draw them narrower.
   - **Strokes.** Count them. A cursive word should be one to five. Dozens mean it was outlined or drawn in short pieces.
   - **Dots.** They're stored last, as one-curve strokes whose start and end are the same point.
3. Show each word in the component, alone, with `time` frozen at about 4.5 to see it written, and at 0.3s steps through 1.2–3.7 to see it drawn. Look for: the pen doubling back over itself, joins that don't meet, and dots in the wrong place.

## Step 4: Wallpapers (ask, then you)

- Ask for their wallpapers, or offer the six painted ones (Mint, Dawn, Lagoon, Dune, Bloom, Graphite).
- A wallpaper works best with **soft, large shapes and an edge or a change of colour behind the middle of the screen**, where the word sits. Glass over a flat colour all but disappears.
- For each, a tall image (about 1290×2796) and, if it will ever be wide, a wide one (about 2400×1500). Pass `{ tall, wide }` or one URL.
- Fine grain is good; the frost catches it. Strong detail behind the word fights it.
- ← and → cycle them with a cross-fade, while the pointer is over the component or it has focus.

## Step 5: Wire it up (you)

```tsx
import { GlassHello } from '@/components/piruicy/glass-hello';

<div style={{ height: 844, aspectRatio: '1082 / 2340' }}>
  <GlassHello
    words={[{ strokes: '/glass-hello/hello.json', caption: 'Swipe up to open' }, ...]}
    wallpapers={[{ tall: '/glass-hello/wall-tall.jpg', wide: '/glass-hello/wall-wide.jpg' }]}
    mark={MARK_PATH} // optional: one filled path in a 24-unit box
    onOpen={() => { /* the sheet was swiped away */ }}
  >
    {/* what's under the sheet */}
  </GlassHello>
</div>
```

- `words` and `mark` are read once: pass stable values (a module constant, or `useMemo`).
- `dark` switches the glass and the painted wallpapers to the dark appearance.
- With reduced motion, each word simply shows, settled, for its turn.

## Step 6: Verify (you)

- The first word lands from the drop as one tube, not two.
- Each hand-over: the old word dissolves just ahead of the sweep; the new one fades in behind it with no ball at the pen's tip.
- Swipe up: the sheet's rounded bottom edge follows the finger; let go past about a fifth of the height and it goes; what's under fades in.
- ← and → change the wallpaper.
- Show the person a recording of one full cycle.

 

Details

  • Two WebGL2 passes at twice the screen's resolution: every stroke segment is a 3D capsule writing its height and edge distance, then a glass pass looks through that height field at the wallpaper, with refraction, frost, colour fringes, a dark rim and a specular glint.
  • The first word lands from a drop as one tube, oversized and thick, shrinking onto its true start; its progress, thickness and landing were read off every frame.
  • After it, nothing is timed per word: one front sweeps left to right at 738px a second on a 1082px screen, every 3.795s. The old word dissolves just ahead of it; the new one's pen runs behind its own front at 850px a second, and its ink fades in over 0.24s, so the pen's tip never shows.
  • A long word is scaled down until its path is 85% of the screen's width, as Apple's 안녕하세요 is.
  • Swipe up and the sheet is clipped from below by a rounded edge that follows the finger, with the wallpaper blurred and tinted under it; past a fifth of the height, or flung, it goes.
  • ← and → cycle the wallpapers with a cross-fade; six are painted in code, in light and dark. With reduced motion, each word simply shows for its turn.
  • Draw your own words as single lines and the agent handoff below turns them into stroke data and checks them.

© 2026 Dhaval Khandhadia. Use it in anything you build; don’t resell it. MIT with the Commons Clause.