REFERENCE
- Gallery page: https://magpui.com/en/i/paper-plane-postcard-globe-922b53
- First frame (image): https://dnioievkvxejjbxgwvko.supabase.co/storage/v1/object/public/media/paper-plane-postcard-globe-922b53/shot.jpg
- Clip (mp4): https://dnioievkvxejjbxgwvko.supabase.co/storage/v1/object/public/media/paper-plane-postcard-globe-922b53/clip.mp4
- Original post: https://x.com/mannupaaji/status/2115451904667042099 by @mannupaaji
Before building, download the first frame and look at it. If ffmpeg is available, download the clip and extract frames (ffmpeg -i clip.mp4 -vf fps=2 frame-%02d.png), then study the motion frame by frame. Match what you see; the text below describes it, the frames are the truth.
BUILD: Build a postcard composer micro-interaction. A compact dark compose card sits in front of the top half of a slowly rotating 3D Earth. As the user types, the text is printed live in a monospace face on a white postcard that peeks out from behind the composer, above the globe. On Send, the postcard rises out of the globe, folds into a white paper plane, the plane circles the globe once along a thin glowing blue orbit trail, dives to the destination, and a small pill pops up over the landing point (avatar + "Landed in <city>") on a thin pin line. It should feel tactile, calm and a little magical, like mailing a real card.
DESIGN SYSTEM: Page background near black #0A0A0B. Globe: about 260px diameter, realistic night-blue oceans #0B1E3F, earthy continents, white cloud wisps, a soft blue rim light; only the top ~60% is visible above the composer. Composer card: ~360px wide, radius 16px, surface #18181B with a 1px border #27272A, inner padding 12px. Row 1: muted label "To", three overlapping 20px avatars, a location chip (pin icon + "Mia · Lisbon", bg #27272A, radius 999px, 12px text). Row 2: textarea, 14px sans, placeholder "Write a postcard..." in #71717A. Footer row: three small ghost icons (attach, image, location) left, status text 12px #71717A, and a primary pill button right (bg #2563EB, white 13px medium label + paper-plane icon, radius 10px, height 30px). Postcard: ~150x110px white #FAFAFA, 1px #E4E4E7 border, faint dashed inner frame, a tiny date line top left in 8px gray mono, a blue stamp top right (#2563EB square with a white plane glyph and a postmark circle overlapping it), body text 10px dark mono #18181B. Landing pill: white, radius 999px, 18px avatar + 12px text, with a 1px blue line down to a 6px blue dot on the globe.
MOTION: Idle globe spins 360deg in 60s linear on its Y axis. Typing: each keystroke appends the character to the postcard with a 60ms fade-up (translateY 2px to 0, opacity 0 to 1). Send press: button scale 0.97 for 120ms, label swaps to "Sending" with a spinner, status text "On its way to Lisbon". Postcard lift: translateY -40px and scale 1 to 1.35 over 500ms cubic-bezier(0.22, 1, 0.36, 1), the textarea clears at the same time. Fold: the card folds along its diagonals into a paper plane in 700ms (two hinge rotations of 90deg and 160deg, cubic-bezier(0.65, 0, 0.35, 1)), shading darkens on the folded faces. Flight: the plane follows a tilted elliptical orbit around the globe (about 1.5x globe width, tilted 15deg) for one lap in 2200ms cubic-bezier(0.45, 0, 0.55, 1); a 2px blue #60A5FA trail with additive glow draws behind it and fades out over 600ms; the plane passes behind the globe (depth sorted) on the far side. Landing: the globe eases its rotation so the destination faces the camera (800ms ease-out), the plane shrinks to a dot at the target, the pin line grows from 0 to 40px in 240ms, then the pill pops in with scale 0.8 to 1 and opacity, spring (stiffness 400, damping 26). Button turns into "Sent" with a check icon, footer shows "Landed in Lisbon" then "Write another" as a text button.
SECTIONS: Parts: globe, postcard, composer (recipient row, textarea, footer actions), paper plane, orbit trail, landing pin. States: idle (empty textarea, postcard hidden behind the composer), typing (postcard shows live text), sending (lift, fold, flight), landed (pin and pill visible, button "Sent"), reset ("Write another" clears the pin, globe resumes spin, postcard slides back down). Dragging the globe rotates it with inertia in any state except during the flight.
IMPLEMENTATION: React Three Fiber (or plain Three.js) for the globe, plane and trail inside one canvas behind the HTML composer. Globe: sphere with a day or night earth texture, a cloud layer sphere slightly larger with alpha, and a fresnel rim shader. Postcard and plane: a single planar mesh with the postcard drawn into a CanvasTexture so typed text updates live; build the fold with a few hinged sub-meshes animated with Motion or GSAP timelines. Orbit: a CatmullRomCurve3 or parametric ellipse; trail as a fading line ribbon of the last 40 positions. HTML parts (composer, pill) in React with Motion; project the landing lat/lon to screen space each frame to place the pill. prefers-reduced-motion: skip the fold and flight, crossfade the postcard out and show the pin directly. Keyboard: Cmd/Ctrl+Enter sends, visible focus rings on the textarea and buttons, aria-live status for "Sending" and "Landed". Keep the canvas DPR at 1.5 max and pause rendering when offscreen.
ADAPT TO THE PROJECT: Reuse the project's existing design tokens, button, input and avatar components and its fonts; map the colors above to the closest existing tokens. Do not copy logos, brand names, photos or illustrations from the original; use placeholder avatars, a placeholder recipient and a public-domain earth texture.
SUCCESS CHECK:
- Typing updates the postcard text live, and Send runs lift, fold, one orbit lap with a glowing trail, and a landing pin in under 5 seconds.
- The plane is correctly hidden behind the globe on the far side of the orbit, and the globe can be dragged to rotate.
- With prefers-reduced-motion enabled the message still sends and the pin appears without the flight animation.