HY @hoangyell/gallery
v1.0 on npm

The friendly Astro image gallery

Lightbox. Pyramid layout. Dark mode. Accessible. Zero config. Drop it into any .astro or .mdx file and ship.

$ npm install @hoangyell/gallery
See it live

MIT licensed · No tracking · No ads · No build-time magic

↑ Click any image. Use arrow keys or swipe.

Three layouts. Infinite combinations.

One rows prop is all it takes.

Trio · 1 row

Six-pack · 2 rows

Pyramid · 3 rows

Built for real content

Born from years of running an image-heavy travel blog. Every default is the one I wanted on production day one.

Pyramid multi-row layout

Pass any number of images, declare `rows`, get a perfectly balanced grid that pyramids the extras to the bottom.

Accessible lightbox

Click, tap, keyboard arrows, swipe, ESC. Focus is restored. `inert` locks the page behind. `prefers-reduced-motion` is honored.

Dark mode that just works

Follows OS preference by default. Respects `<html class="dark">` and `[data-theme]` so it slots into any theming setup.

Zero config

Plain CSS, no Tailwind required in the host project. Drop it in an `.astro` or `.mdx` file and ship.

Themeable

Five CSS custom properties cover gaps, radii, colors, and accents. Bring your own brand.

Tiny

One component, ~8 KB gzipped. No runtime dependencies. Tree-shakeable. Ships nothing you don't use.

Looks like Astro, behaves like magic

One import. One component. Works the same way in .astro and .mdx.

Astro page

---
import { Gallery } from "@hoangyell/gallery";

const photos = [
  "/img/japan-1.webp",
  "/img/japan-2.webp",
  "/img/japan-3.webp",
  "/img/japan-4.webp",
];
---

<Gallery items={photos} rows={2} />

Inside MDX

import { Gallery } from "@hoangyell/gallery";

# Our honeymoon in Japan

<Gallery
  items={[
    "/japan/temple.webp",
    { src: "/japan/sushi.webp", alt: "Toyosu sushi" },
    "/japan/fuji.webp",
  ]}
  rows={2}
/>
Vibe coding

Let an AI agent install it for you

Paste any prompt below into Claude, ChatGPT, Cursor, Copilot, or Windsurf. The agent will read the repo, install the package, and wire up your imports.

  1. 1 Copy a prompt below.
  2. 2 Edit the bracketed parts to fit your project.
  3. 3 Paste into your AI tool. Done.

Install and wire it up

Refer to https://github.com/HoangYell/hoangyell-gallery as the
complete reference for the @hoangyell/gallery package, then in
my current project:

1. Install it with pnpm (or detect my package manager).
2. Pick one MDX or .astro file that already has an image grid
   or a stack of <img> tags.
3. Replace that grid with <Gallery items={[...]} rows={2} />,
   preserving every existing src and alt.
4. Show me a small diff of what changed.

Migrate from Hugo or another gallery

Refer to https://github.com/HoangYell/hoangyell-gallery for the
@hoangyell/gallery API. Find every Hugo {{< gallery >}} shortcode
(or my existing gallery component) across src/content/**/*.{md,mdx}
and rewrite each one as <Gallery items={[...]} rows={N}> with
the same images. Keep alt text. Add the import at the top of
each file that needs it.

Theme to match my brand

Refer to https://github.com/HoangYell/hoangyell-gallery for the
CSS custom properties exposed by .hy-gallery. Add an override
block in src/styles/global.css that sets:

- --hy-gallery-accent to my brand color
- --hy-gallery-radius to 1.25rem
- --hy-gallery-gap to 6px

Scope it under .prose .hy-gallery so it only applies inside
blog content.

Works with any AI that reads URLs · Claude · ChatGPT · Cursor · GitHub Copilot · Windsurf

Ready to ship galleries that don't suck?

One install. One import. Beautiful images on every screen.

$ npm install @hoangyell/gallery
$ pnpm add @hoangyell/gallery