Petal Pro is the full SaaS app this is built for

Auth, billing, admin, and Claude Code integration included. One purchase, unlimited projects.

Meteors

Meteors renders a shower of meteors streaking across its parent container. Positions, delays and durations are generated server-side, so the whole effect is pure CSS and ships zero JavaScript. Drop it behind a dark hero or card to add motion without touching your bundle.
Basic Meteors

The component fills its nearest relative ancestor, so give the container relative and overflow-hidden. Content inside the same container needs relative too, otherwise it sits underneath the meteor layer. The layer is decorative: it renders with aria-hidden and meteors are hidden for users who opt out of animation via prefers-reduced-motion.

Ship faster with Petal

<div class="relative overflow-hidden rounded-xl bg-gray-950 px-8 py-16">
<.meteors count={20} />
<div class="relative text-center">
<h3 class="text-2xl font-bold text-white">Ship faster with Petal</h3>
</div>
</div>
Density and Seed

count controls how many meteors render. Positions are deterministic for a given seed, so LiveView re-renders never make the meteors jump. When rendering several meteor fields on one page, give each a different seed so they don't share the same scatter pattern.

count: 10, seed: 1

count: 40, seed: 2

<div class="grid grid-cols-1 gap-8 sm:grid-cols-2">
<div class="relative overflow-hidden rounded-xl bg-gray-950 px-8 py-16">
<.meteors count={10} seed={1} />
<div class="relative text-center">
<p class="font-mono text-sm text-gray-400">count: 10, seed: 1</p>
</div>
</div>
<div class="relative overflow-hidden rounded-xl bg-gray-950 px-8 py-16">
<.meteors count={40} seed={2} />
<div class="relative text-center">
<p class="font-mono text-sm text-gray-400">count: 40, seed: 2</p>
</div>
</div>
</div>
Direction and Colour

New in 4.4.0: angle points the shower anywhere (the default streaks down-left), color tints the meteors and their trails, and reverse mirrors the whole field so meteors stream the other way.

color: sky

reverse

<div class="grid grid-cols-1 gap-8 sm:grid-cols-2">
<div class="relative overflow-hidden rounded-xl bg-gray-950 px-8 py-16">
<.meteors count={20} color="#38bdf8" seed={3} />
<div class="relative text-center">
<p class="font-mono text-sm text-gray-400">color: sky</p>
</div>
</div>
<div class="relative overflow-hidden rounded-xl bg-gray-950 px-8 py-16">
<.meteors count={20} reverse seed={4} />
<div class="relative text-center">
<p class="font-mono text-sm text-gray-400">reverse</p>
</div>
</div>
</div>
Hero Example

Meteors read best on near-black panels. Here's a fuller hero: heading, subtitle and a call to action sitting on a relative wrapper above the shower.

Build your next SaaS with Petal

Phoenix, LiveView and Tailwind, wired together so you can get straight to shipping the actual product.

<div class="relative overflow-hidden rounded-xl bg-gray-950 px-8 py-24">
<.meteors count={30} />
<div class="relative mx-auto flex max-w-xl flex-col items-center text-center">
<h2 class="text-3xl font-bold text-white">Build your next SaaS with Petal</h2>
<p class="mt-4 text-gray-300">
Phoenix, LiveView and Tailwind, wired together so you can get straight to shipping
the actual product.
</p>
<.button color="primary" label="Get started" class="mt-8" />
</div>
</div>
Properties
Attribute Type Default Description
angle string "215deg" direction the meteors travel, as a CSS angle (default streaks down and to the left)
class any nil extra classes for the container
color string "#64748b" meteor and trail colour. Any CSS colour; the default slate suits dark panels
count integer 20 number of meteors
rest global
reverse boolean false mirror the shower horizontally, so meteors stream the opposite way
seed integer 0 vary this when rendering several meteor fields on one page so each gets a different scatter pattern