Claude Code से तेज इमेज गैलरी बनाना
Claude Code से responsive image gallery बनाएं: React कोड, srcset, lightbox, pitfalls और checks.
इमेज गैलरी सिर्फ सुंदर layout नहीं है
Claude Code से image gallery बनाते समय अगर prompt सिर्फ “एक सुंदर masonry gallery बना दो” कहता है, तो demo जल्दी मिल सकता है, लेकिन production quality नहीं मिलती। असली समस्या image size, alt text, layout shift, mobile width, keyboard से lightbox बंद करना, CMS से आने वाला broken data और image देखने के बाद user को अगला step दिखाना है। Portfolio, ecommerce page, workshop report और technical article में gallery सीधे भरोसा और conversion से जुड़ती है।
इस guide में हम gallery को एक publishable feature की तरह बनाएंगे। पहले Claude Code को constraints देंगे, फिर typed React component लिखेंगे, फिर srcset, sizes, lazy loading, lightbox और verification checklist जोड़ेंगे। Related topics के लिए Claude Code image processing, performance optimization और accessibility implementation देखें। Official references के लिए Claude Code docs, MDN की responsive images guide, Lazy loading guide और WCAG 2.2 उपयोग करें।
मेरी practical rule है: visual style से पहले data contract तय करें। हर image में id, category, width, height और meaningful alt होना चाहिए। इसके बाद आप raw img, Next.js Image, Astro image या CDN component में से कोई भी चुन सकते हैं।
Claude Code को देने वाला prompt
यह prompt सीधे इस्तेमाल किया जा सकता है। इसमें code, failure states और review तीनों मांगे गए हैं।
React में image gallery implement करें।
Goal है articles, case studies, product screenshots और workshop photos के लिए fast UI.
Conditions:
- Existing routing और design system conventions न तोड़ें.
- Image type define करें जिसमें id, src, alt, width, height और category required हों.
- Responsive layout के लिए CSS Grid use करें.
- srcset, sizes, loading और fetchPriority को जानबूझकर use करें.
- Click पर lightbox खुले और Escape से बंद हो.
- Empty array, image load failure, long alt और mobile width handle करें.
- Implementation के बाद changed files, tests और remaining risks explain करें.
Pseudocode नहीं, copy-paste-ready React/TypeScript और CSS दें.
इस prompt से Claude Code एक छोटा और reviewable patch देता है। width और height layout shift कम करते हैं। Required alt field “image 1” जैसे कमजोर text को रोकता है। Risk explanation Claude Code को generation के बाद review mode में ले जाता है।
Suggested architecture
Code से पहले यह flow दिखाना उपयोगी है। इससे Claude Code data, UI और verification को अलग रखता है।
flowchart LR
A["Original images"] --> B["Size variants"]
B --> C["GalleryImage array"]
C --> D["Category filter"]
D --> E["CSS Grid cards"]
E --> F["Lightbox"]
E --> G["Lighthouse and manual checks"]
| Decision | Safe default | कब फिर सोचें |
|---|---|---|
| Layout | CSS Grid | Images की height बहुत अलग हो |
| Lazy loading | Fold के नीचे वाली images | First image देर से दिखे |
| Variants | 480/960/1440px के आसपास | Large screens बहुत हों |
| Lightbox | Minimal accessible behavior | Gallery purchase decision बदलती हो |
शुरुआत में masonry library जोड़ना जरूरी नहीं। कई pages में stable cards, fast thumbnails और clear preview काफी होते हैं। Dependencies कम होने से Claude Code का diff भी छोटा रहता है।
Copy-paste React implementation
यह component framework-light है। Vite में चल सकता है, Next.js client component में जा सकता है, और बाद में existing image abstraction से replace किया जा सकता है।
import { useEffect, useMemo, useState } from "react";
import "./image-gallery.css";
export type GalleryImage = {
id: string;
src: string;
alt: string;
width: number;
height: number;
category: string;
sources?: Array<{ width: number; src: string }>;
};
function buildSrcSet(image: GalleryImage) {
if (!image.sources?.length) return undefined;
return [...image.sources]
.sort((a, b) => a.width - b.width)
.map((source) => `${source.src} ${source.width}w`)
.join(", ");
}
export function ImageGallery({ images }: { images: GalleryImage[] }) {
const [category, setCategory] = useState("all");
const [activeId, setActiveId] = useState<string | null>(null);
const [brokenIds, setBrokenIds] = useState<Set<string>>(() => new Set());
const categories = useMemo(() => {
return ["all", ...Array.from(new Set(images.map((image) => image.category)))];
}, [images]);
const visibleImages = useMemo(() => {
if (category === "all") return images;
return images.filter((image) => image.category === category);
}, [category, images]);
const activeImage = visibleImages.find((image) => image.id === activeId);
useEffect(() => {
if (!activeImage) return;
const handleKeyDown = (event: KeyboardEvent) => {
if (event.key === "Escape") setActiveId(null);
};
window.addEventListener("keydown", handleKeyDown);
return () => window.removeEventListener("keydown", handleKeyDown);
}, [activeImage]);
function markBroken(id: string) {
setBrokenIds((current) => new Set(current).add(id));
}
if (images.length === 0) {
return <p className="gallery-empty">No images are available yet.</p>;
}
return (
<section className="gallery" aria-label="Image gallery">
<div className="gallery-toolbar" aria-label="Filter images by category">
{categories.map((item) => (
<button
className={item === category ? "is-active" : ""}
key={item}
onClick={() => setCategory(item)}
type="button"
>
{item === "all" ? "All" : item}
</button>
))}
</div>
<div className="gallery-grid">
{visibleImages.map((image, index) => {
const isBroken = brokenIds.has(image.id);
return (
<button
className="gallery-card"
key={image.id}
onClick={() => setActiveId(image.id)}
type="button"
>
{isBroken ? (
<span className="gallery-fallback">Image unavailable</span>
) : (
<img
alt={image.alt}
width={image.width}
height={image.height}
src={image.src}
srcSet={buildSrcSet(image)}
sizes="(min-width: 960px) 33vw, (min-width: 640px) 50vw, 100vw"
loading={index < 2 ? "eager" : "lazy"}
fetchPriority={index === 0 ? "high" : "auto"}
style={{ aspectRatio: `${image.width} / ${image.height}` }}
onError={() => markBroken(image.id)}
/>
)}
<span>{image.alt}</span>
</button>
);
})}
</div>
{activeImage && (
<div
className="gallery-lightbox"
role="dialog"
aria-modal="true"
aria-label={activeImage.alt}
tabIndex={-1}
onClick={() => setActiveId(null)}
>
<button className="gallery-close" onClick={() => setActiveId(null)} type="button">
Close
</button>
<img
alt={activeImage.alt}
width={activeImage.width}
height={activeImage.height}
src={activeImage.src}
onClick={(event) => event.stopPropagation()}
/>
</div>
)}
</section>
);
}
.gallery {
display: grid;
gap: 1rem;
}
.gallery-toolbar {
display: flex;
flex-wrap: wrap;
gap: 0.5rem;
}
.gallery-toolbar button,
.gallery-card,
.gallery-close {
border: 1px solid #d4d4d8;
background: #ffffff;
color: #18181b;
cursor: pointer;
}
.gallery-toolbar button {
border-radius: 999px;
padding: 0.45rem 0.8rem;
}
.gallery-toolbar .is-active {
background: #18181b;
color: #ffffff;
}
.gallery-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
gap: 1rem;
}
.gallery-card {
display: grid;
gap: 0.5rem;
padding: 0;
overflow: hidden;
border-radius: 8px;
text-align: left;
}
.gallery-card img {
width: 100%;
object-fit: cover;
background: #f4f4f5;
}
.gallery-fallback {
display: grid;
min-height: 180px;
place-items: center;
background: #f4f4f5;
color: #71717a;
}
.gallery-card span {
padding: 0 0.75rem 0.75rem;
font-size: 0.875rem;
}
.gallery-lightbox {
position: fixed;
inset: 0;
z-index: 50;
display: grid;
place-items: center;
padding: 2rem;
background: rgb(0 0 0 / 0.86);
}
.gallery-lightbox img {
max-width: min(100%, 1100px);
max-height: 82vh;
object-fit: contain;
}
.gallery-close {
position: absolute;
top: 1rem;
right: 1rem;
border-radius: 6px;
padding: 0.5rem 0.75rem;
}
.gallery-empty {
color: #71717a;
}
Real app में raw img को project के standard image component से replace किया जा सकता है। लेकिन alt, width, height और sizes data contract में रहने चाहिए।
Data model और use cases
Data component के बाहर रखें। CMS से आने पर भी पहले normalize करें।
import type { GalleryImage } from "./ImageGallery";
export const galleryImages: GalleryImage[] = [
{
id: "case-study-dashboard",
src: "/images/gallery/dashboard-960.webp",
alt: "Analytics dashboard after Claude Code refactoring",
width: 960,
height: 640,
category: "Case study",
sources: [
{ width: 480, src: "/images/gallery/dashboard-480.webp" },
{ width: 960, src: "/images/gallery/dashboard-960.webp" },
{ width: 1440, src: "/images/gallery/dashboard-1440.webp" },
],
},
{
id: "workshop-room",
src: "/images/gallery/workshop-960.webp",
alt: "Team workshop board with Claude Code review checklist",
width: 960,
height: 720,
category: "Training",
},
{
id: "product-shot",
src: "/images/gallery/template-pack-960.webp",
alt: "Claude Code template pack product preview",
width: 960,
height: 540,
category: "Product",
},
];
पहला use case portfolio या case study page है। Images reader को result compare करने में मदद करती हैं और फिर full case study या consultation page की तरफ ले जाती हैं।
दूसरा use case ecommerce या digital product page है। Screenshots, use scenes, comparison और post-purchase preview hesitation कम करते हैं। लेकिन सभी high-resolution images शुरुआत में load करना conversion से पहले page slow कर देता है।
तीसरा use case training, event और internal knowledge है। Whiteboard photos, step screenshots, before/after और error screens reusable learning material बन जाते हैं। Internal content में customer name, email, token और personal data जरूर जांचें।
चौथा use case technical article है। अगर article में कई code examples हैं, तो concept diagram और verification screenshots reader को context में रखते हैं।
Common pitfalls
पहली गलती है first viewport image को lazy-load करना। यह image LCP को affect कर सकती है, इसलिए पहली image पर eager और fetchPriority="high" सोचें। दूसरी तरफ, सभी images को eager करना भी initial load खराब करता है।
दूसरी गलती है width और height छोड़ देना। Images load होते समय card height बदलती है और page unstable लगता है। Claude Code से CLS risk review करवाएं।
तीसरी गलती है alt को SEO keywords की list बना देना। Alt का काम image न दिखने पर image का meaning बताना है।
चौथी गलती mouse-only lightbox है। Close button का label, Escape support, visible focus और mobile behavior minimum requirements हैं। Strict focus trap चाहिए तो Radix UI या React Aria पर विचार करें।
पांचवीं गलती image operations तय न करना है। CMS में 6 MB PNG upload होते ही performance गिर सकती है। Maximum size, allowed formats, naming rules और review checklist को CLAUDE.md में रखें।
Verification
Publish से पहले filter, lightbox, keyboard, empty data, broken image और 375px mobile width check करें। Playwright हो तो शुरुआत ऐसी test से करें:
import { expect, test } from "@playwright/test";
test("image gallery filters and opens a lightbox", async ({ page }) => {
await page.goto("/gallery");
await expect(page.getByRole("region", { name: "Image gallery" })).toBeVisible();
await page.getByRole("button", { name: "Training" }).click();
await expect(page.getByRole("button", { name: /workshop/i })).toBeVisible();
await page.getByRole("button", { name: /workshop/i }).click();
await expect(page.getByRole("dialog")).toBeVisible();
await page.keyboard.press("Escape");
await expect(page.getByRole("dialog")).toBeHidden();
});
Review prompt में fixed criteria दें: initial requests, srcset और sizes का actual layout से match, alt quality, button/link roles, mobile overflow, broken CMS data और private information leakage.
CTA और practical result
Gallery को business path support करना चाहिए। Case image case article पर ले जाए, product image purchase details पर, और workshop photo Claude Code training और consultation पर। Technical deep dive के लिए lazy loading images और React development with Claude Code देखें।
इस workflow को test करने पर data type, component, CSS और review criteria को अलग रखना बहुत उपयोगी लगा। Required width, height और alt ने weak image entries जल्दी पकड़ीं। Final check में DevTools Network, Lighthouse और mobile manual operation शामिल था।
मुफ़्त PDF: Claude Code cheatsheet
Email डालें और commands, review habits तथा safe workflow वाली एक-page PDF पाएँ.
हम आपका data सुरक्षित रखते हैं और spam नहीं भेजते.
लेखक के बारे में
Masa
Claude Code workflow और team adoption पर काम करने वाला engineer.
संबंधित लेख
Claude Code Obsidian to CLAUDE.md workflow: context बार-बार न समझाएं
Obsidian notes को CLAUDE.md operating notes में बदलकर Claude Code sessions को resume करना आसान बनाएं.
Claude Code Revenue CTA Routing: article से PDF, Gumroad और consultation तक
Reader intent के आधार पर free PDF, Gumroad products और consultation तक CTA route करने वाला workflow.
Claude Code टीम हैंडऑफ नियम: review proof, permissions, rollback और revenue path
Claude Code टीम काम के लिए evidence, permission rules, rollback, free PDF, Gumroad और consultation path वाला handoff.