Skip to content

Commit 4364399

Browse files
wimpywarlordclaude
andcommitted
Add global gallery viewer with scale animation for all images and videos
- Created GalleryProvider context with scale/translate animation - Implemented GalleryImage and GalleryVideo wrapper components - Added Notion-style toolbar with close and download buttons - Videos autoplay/loop/muted as thumbnails, full controls when expanded - Videos play at 80% volume in expanded mode - Applied gallery functionality across all blog posts - Added trailer_4.mp4 to taste blog assets 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
1 parent 46cf56c commit 4364399

File tree

13 files changed

+432
-165
lines changed

13 files changed

+432
-165
lines changed

public/blog/taste/trailer_4.mp4

39.2 MB
Binary file not shown.

src/app/layout.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import type { Metadata } from "next";
22
import { Geist, Geist_Mono } from "next/font/google";
33
import "./globals.css";
4+
import { GalleryProvider } from "@/components/gallery";
45

56
const geistSans = Geist({
67
variable: "--font-geist-sans",
@@ -80,7 +81,9 @@ export default function RootLayout({
8081
<body
8182
className={`${geistSans.variable} ${geistMono.variable} antialiased`}
8283
>
83-
{children}
84+
<GalleryProvider>
85+
{children}
86+
</GalleryProvider>
8487
</body>
8588
</html>
8689
);

src/components/blog-posts/cracked-dev.tsx

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
import Link from "next/link";
55
import { Card } from "@/components/ui/card";
6+
import { GalleryVideo } from "@/components/gallery";
67

78
// Helper component for text highlighting
89
const Highlight = ({ children }: { children: React.ReactNode }) => {
@@ -253,6 +254,16 @@ export function CrackedReactDev() {
253254
</Link>
254255
{" - Beautiful & consistent icon toolkit"}
255256
</li>
257+
<li>
258+
<Link
259+
href="https://iconicsets.com/"
260+
target="_blank"
261+
className="text-primary hover:text-primary/80 underline underline-offset-2"
262+
>
263+
Iconic Sets
264+
</Link>
265+
{" - Curated collection of premium icon sets"}
266+
</li>
256267
</ul>
257268

258269
<p>was looking for brand icons today</p>
@@ -517,13 +528,13 @@ export function CrackedReactDev() {
517528
</p>
518529

519530
<div className="my-6">
520-
<video controls className="w-full max-w-2xl rounded-lg mx-auto">
531+
<GalleryVideo className="w-full max-w-2xl rounded-lg mx-auto">
521532
<source
522533
src="/blog/cracked_react_dev/devtools-inspect-disappearing-elements.mp4"
523534
type="video/mp4"
524535
/>
525536
Your browser does not support the video tag.
526-
</video>
537+
</GalleryVideo>
527538
</div>
528539

529540
<p>

src/components/blog-posts/cs-guide-for-autistic-nerds.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
/* eslint-disable react/no-unescaped-entities */
33

44
import Link from "next/link";
5-
import Image from "next/image";
5+
import { GalleryImage } from "@/components/gallery";
66

77
// Helper component for text highlighting
88
const Highlight = ({ children }: { children: React.ReactNode }) => {
@@ -1209,7 +1209,7 @@ export function CsGuideForAutisticNerds() {
12091209
</h2>
12101210

12111211
<p>To start with - solve these questions:</p>
1212-
<Image
1212+
<GalleryImage
12131213
src="/blog/cs_study_plan/assets/CleanShot_2025-07-09_at_11.08.472x.png"
12141214
alt="DSA Starting Problems"
12151215
width={1200}
@@ -1293,7 +1293,7 @@ export function CsGuideForAutisticNerds() {
12931293
</Link>
12941294
</p>
12951295

1296-
<Image
1296+
<GalleryImage
12971297
src="/blog/cs_study_plan/assets/Screenshot_at_Aug_06_21-42-45.png"
12981298
alt="Time Complexity Chart"
12991299
width={1200}

src/components/blog-posts/llm-video-games.tsx

Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
/* eslint-disable react/no-unescaped-entities */
33

44
import Link from "next/link";
5-
import Image from "next/image";
5+
import { GalleryImage, GalleryVideo } from "@/components/gallery";
66

77
// Helper component for text highlighting
88
const Highlight = ({
@@ -19,40 +19,40 @@ export function LlmWukong() {
1919
<h2 className="text-primary">What did I build?</h2>
2020

2121
<div className="my-4 sm:my-6">
22-
<video controls className="w-full rounded-lg mb-2">
22+
<GalleryVideo className="w-full rounded-lg mb-2">
2323
<source src="/blog/llm_wukong/assets/smash.mp4" type="video/mp4" />
2424
Your browser does not support the video tag.
25-
</video>
25+
</GalleryVideo>
2626
<p className="text-xs sm:text-sm text-muted-foreground m-0">
2727
New input paradigm - controlling 3D embodied characters through natural speech.
2828
</p>
2929
</div>
3030

3131
<div className="grid grid-cols-1 sm:grid-cols-2 gap-3 sm:gap-6 my-4 sm:my-6">
3232
<div>
33-
<video controls className="w-full rounded-lg mb-2">
33+
<GalleryVideo className="w-full rounded-lg mb-2">
3434
<source src="/blog/llm_wukong/assets/dodge.mp4" type="video/mp4" />
3535
Your browser does not support the video tag.
36-
</video>
36+
</GalleryVideo>
3737
<p className="text-xs sm:text-sm text-muted-foreground m-0">
3838
Context awareness - control input (space-bar press for dodging) is fed into the system context - the robot responds accordingly.
3939
</p>
4040
</div>
4141

4242
<div>
43-
<video controls className="w-full rounded-lg mb-2">
43+
<GalleryVideo className="w-full rounded-lg mb-2">
4444
<source src="/blog/llm_wukong/assets/time.mp4" type="video/mp4" />
4545
Your browser does not support the video tag.
46-
</video>
46+
</GalleryVideo>
4747
<p className="text-xs sm:text-sm text-muted-foreground m-0">
4848
Spatial + Vision + Time awareness - human like immersion.
4949
</p>
5050
</div>
5151
</div>
5252

5353
<div className="flex flex-col sm:flex-row gap-3 sm:gap-4 my-4 sm:my-6 mb-2">
54-
<Image src="/blog/llm_wukong/assets/personality_config.png" alt="Personality Configuration" width={800} height={600} className="flex-1 w-full object-contain rounded-lg" />
55-
<Image src="/blog/llm_wukong/assets/dashboard.png" alt="Dashboard" width={800} height={600} className="flex-1 w-full object-contain rounded-lg" />
54+
<GalleryImage src="/blog/llm_wukong/assets/personality_config.png" alt="Personality Configuration" width={800} height={600} className="flex-1 w-full object-contain rounded-lg" />
55+
<GalleryImage src="/blog/llm_wukong/assets/dashboard.png" alt="Dashboard" width={800} height={600} className="flex-1 w-full object-contain rounded-lg" />
5656
</div>
5757

5858
<p className="text-xs sm:text-sm text-muted-foreground m-0 mb-4">
@@ -78,21 +78,21 @@ export function LlmWukong() {
7878

7979
<p>
8080
The number 1 problem you will run into while building something like this is - Latency. Ideal total latency for video games: 20–60 ms (that pretty FAST{" "}
81-
<Image src="/blog/llm_wukong/assets/sonic-running.gif" alt="Sonic Running" width={24} height={24} className="inline h-5 sm:h-6 align-middle" unoptimized />
81+
<GalleryImage src="/blog/llm_wukong/assets/sonic-running.gif" alt="Sonic Running" width={24} height={24} className="inline h-5 sm:h-6 align-middle" unoptimized />
8282
). However average latency for LLMs is 6 seconds (anecdotally{" "}
83-
<Image src="/blog/llm_wukong/assets/slow_parrot.gif" alt="Slow Parrot" width={16} height={16} className="inline h-4 align-middle" unoptimized />
83+
<GalleryImage src="/blog/llm_wukong/assets/slow_parrot.gif" alt="Slow Parrot" width={16} height={16} className="inline h-4 align-middle" unoptimized />
8484
).
8585
</p>
8686

87-
<Image src="/blog/llm_wukong/assets/latency_chart.png" alt="Latency Chart" width={1200} height={800} className="w-full rounded-lg my-4 sm:my-6" />
87+
<GalleryImage src="/blog/llm_wukong/assets/latency_chart.png" alt="Latency Chart" width={1200} height={800} className="w-full rounded-lg my-4 sm:my-6" />
8888

8989
<p>
9090
No one wants to see an autistic alien use the joystick at turtle speeds{" "}
91-
<Image src="/blog/llm_wukong/assets/this_is_fine.gif" alt="This is Fine" width={24} height={24} className="inline h-5 sm:h-6 align-middle" unoptimized />.
91+
<GalleryImage src="/blog/llm_wukong/assets/this_is_fine.gif" alt="This is Fine" width={24} height={24} className="inline h-5 sm:h-6 align-middle" unoptimized />.
9292
</p>
9393

9494
<div className="flex justify-center my-4 sm:my-6">
95-
<Image src="/blog/llm_wukong/assets/no_brain.jpg" alt="No Brain" width={600} height={400} className="max-w-full rounded-lg" />
95+
<GalleryImage src="/blog/llm_wukong/assets/no_brain.jpg" alt="No Brain" width={600} height={400} className="max-w-full rounded-lg" />
9696
</div>
9797

9898
<p>
@@ -109,14 +109,14 @@ export function LlmWukong() {
109109
Short answer <Highlight>Yes</Highlight>. Here is how:
110110
</p>
111111

112-
<Image src="/blog/llm_wukong/assets/flowchart.png" alt="Flowchart" width={1200} height={800} className="w-full rounded-lg my-4 sm:my-6" />
112+
<GalleryImage src="/blog/llm_wukong/assets/flowchart.png" alt="Flowchart" width={1200} height={800} className="w-full rounded-lg my-4 sm:my-6" />
113113

114114
<p>
115115
The <Highlight>fundamental difference</Highlight> in my approach here is to write game scripts (pre-meditated or generated by LLM on the fly) for controlling the agent input.
116116
</p>
117117

118118
<p>
119-
<Image src="/blog/llm_wukong/assets/catjam.gif" alt="Cat Jam" width={20} height={20} className="inline h-5 align-middle" unoptimized /> LLMs never controls the control input directly. LLM only decides what game script to run. The scripts are then injected in the game engine and executed in realtime.
119+
<GalleryImage src="/blog/llm_wukong/assets/catjam.gif" alt="Cat Jam" width={20} height={20} className="inline h-5 align-middle" unoptimized /> LLMs never controls the control input directly. LLM only decides what game script to run. The scripts are then injected in the game engine and executed in realtime.
120120
</p>
121121

122122
<p>
@@ -167,7 +167,7 @@ You must respond with 'action_type' field with one of these values.
167167
</p>
168168

169169
<div className="flex justify-center my-4 sm:my-6">
170-
<Image src="/blog/llm_wukong/assets/actually.png" alt="Actually" width={600} height={400} className="max-w-full rounded-lg" />
170+
<GalleryImage src="/blog/llm_wukong/assets/actually.png" alt="Actually" width={600} height={400} className="max-w-full rounded-lg" />
171171
</div>
172172

173173
<p>
@@ -188,15 +188,15 @@ You must respond with 'action_type' field with one of these values.
188188
Well that is where having the LLM generate game scripts on the fly comes into play. Voyager has achieved great success at that with Minecraft.
189189
</p>
190190

191-
<video controls className="w-full rounded-lg my-4 sm:my-6">
191+
<GalleryVideo className="w-full rounded-lg my-4 sm:my-6">
192192
<source src="/blog/llm_wukong/assets/voyager.mp4" type="video/mp4" />
193193
Your browser does not support the video tag.
194-
</video>
194+
</GalleryVideo>
195195

196196
<h3>Optimizations</h3>
197197

198198
<div className="flex justify-center my-4 sm:my-6">
199-
<Image src="/blog/llm_wukong/assets/optimization.jpg" alt="Yo Dawg Optimization Meme" width={600} height={400} className="max-w-full rounded-lg" />
199+
<GalleryImage src="/blog/llm_wukong/assets/optimization.jpg" alt="Yo Dawg Optimization Meme" width={600} height={400} className="max-w-full rounded-lg" />
200200
</div>
201201

202202
<p>

src/components/blog-posts/macos-setup-guide.tsx

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
/* eslint-disable react/no-unescaped-entities */
33

44
import Link from "next/link";
5-
import Image from "next/image";
5+
import { GalleryImage } from "@/components/gallery";
66

77
// Helper component for text highlighting
88
const Highlight = ({ children }: { children: React.ReactNode }) => {
@@ -140,21 +140,21 @@ export function MacosOnSteroids() {
140140
<h3 className="text-base sm:text-lg">Desktop Wallpapers</h3>
141141
<p>My collection of desktop wallpapers:</p>
142142

143-
<Image
143+
<GalleryImage
144144
src="/blog/mac_os_setup/assets/dracula_mac_wallpaper.png"
145145
alt="Dracula Mac Wallpaper"
146146
width={1200}
147147
height={800}
148148
className="w-full rounded-lg my-3 sm:my-4"
149149
/>
150-
<Image
150+
<GalleryImage
151151
src="/blog/mac_os_setup/assets/Wallpaper.jpg"
152152
alt="Main Wallpaper"
153153
width={1200}
154154
height={800}
155155
className="w-full rounded-lg my-3 sm:my-4"
156156
/>
157-
<Image
157+
<GalleryImage
158158
src="/blog/mac_os_setup/assets/satoru-gojo-suguru-3840x2160-16373.png"
159159
alt="Gojo Suguru Wallpaper"
160160
width={1200}
@@ -166,28 +166,28 @@ export function MacosOnSteroids() {
166166
<p>For your Twitter account banners and social media:</p>
167167

168168
<div className="grid grid-cols-1 sm:grid-cols-2 gap-3 sm:gap-4">
169-
<Image
169+
<GalleryImage
170170
src="/blog/mac_os_setup/assets/GwUsUFvXsAEZf83.jpg"
171171
alt="Twitter Banner"
172172
width={800}
173173
height={600}
174174
className="w-full rounded-lg"
175175
/>
176-
<Image
176+
<GalleryImage
177177
src="/blog/mac_os_setup/assets/IMG_1514.jpeg"
178178
alt="Social Media Banner"
179179
width={800}
180180
height={600}
181181
className="w-full rounded-lg"
182182
/>
183-
<Image
183+
<GalleryImage
184184
src="/blog/mac_os_setup/assets/IMG_1515.png"
185185
alt="Alternative Banner"
186186
width={800}
187187
height={600}
188188
className="w-full rounded-lg"
189189
/>
190-
<Image
190+
<GalleryImage
191191
src="/blog/mac_os_setup/assets/IMG_1680.jpeg"
192192
alt="Banner Option"
193193
width={800}
@@ -200,21 +200,21 @@ export function MacosOnSteroids() {
200200
<p>For consistency across all your accounts:</p>
201201

202202
<div className="flex flex-col sm:flex-row justify-center gap-3 sm:gap-4 my-4">
203-
<Image
203+
<GalleryImage
204204
src="/blog/mac_os_setup/assets/Group_2.png"
205205
alt="Profile Picture"
206206
width={400}
207207
height={400}
208208
className="max-w-[200px] mx-auto sm:mx-0 rounded-lg"
209209
/>
210-
<Image
210+
<GalleryImage
211211
src="/blog/mac_os_setup/assets/1689993698983_1.png"
212212
alt="Alternative Profile Picture"
213213
width={400}
214214
height={400}
215215
className="max-w-[200px] mx-auto sm:mx-0 rounded-lg"
216216
/>
217-
<Image
217+
<GalleryImage
218218
src="/blog/mac_os_setup/assets/profile.png"
219219
alt="Main Profile Picture"
220220
width={400}
@@ -1603,7 +1603,7 @@ esac
16031603
</CommandBox>
16041604

16051605
<div className="text-center my-4 sm:my-6">
1606-
<Image
1606+
<GalleryImage
16071607
src="/blog/mac_os_setup/assets/CleanShot_2025-08-02_at_16.32.482x.png"
16081608
alt="Paste without formatting setup"
16091609
width={1200}

src/components/blog-posts/realized-man.tsx

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
"use client";
22
/* eslint-disable react/no-unescaped-entities */
33

4-
import Image from "next/image";
4+
import { GalleryImage, GalleryVideo } from "@/components/gallery";
55

66
export function RealizedMan() {
77
return (
@@ -89,7 +89,7 @@ export function RealizedMan() {
8989

9090
<div className="my-8 sm:my-12 flex justify-center">
9191
<div className="w-full max-w-3xl">
92-
<Image
92+
<GalleryImage
9393
src="/blog/realized_man/father.jpeg"
9494
alt="Father and son"
9595
width={1200}
@@ -98,15 +98,15 @@ export function RealizedMan() {
9898
/>
9999

100100
<div className="grid grid-cols-1 sm:grid-cols-2 gap-3 sm:gap-4">
101-
<video controls className="w-full rounded-lg">
101+
<GalleryVideo className="w-full rounded-lg">
102102
<source src="/blog/realized_man/video1.mp4" type="video/mp4" />
103103
Your browser does not support the video tag.
104-
</video>
104+
</GalleryVideo>
105105

106-
<video controls className="w-full rounded-lg">
106+
<GalleryVideo className="w-full rounded-lg">
107107
<source src="/blog/realized_man/video2.mp4" type="video/mp4" />
108108
Your browser does not support the video tag.
109-
</video>
109+
</GalleryVideo>
110110
</div>
111111
</div>
112112
</div>

0 commit comments

Comments
 (0)