Skip to content

kwrkb/visual-echo

Folders and files

NameName
Last commit message
Last commit date

Latest commit

ย 

History

34 Commits
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 

Repository files navigation

๐ŸŽจ Visual Echo

Visual Echoใฏใ€็”ŸๆˆAIใ‚’ๆดป็”จใ—ใŸ้žๅŒๆœŸใƒปๅˆ†ๅฒๅž‹ใฎ็”ปๅƒ้€ฃๆƒณใ‚ฒใƒผใƒ ใงใ™ใ€‚

็”ปๅƒใ‚’่จ€่‘‰ใง่กจ็พใ—ใ€AIใŒใใฎ่จ€่‘‰ใ‹ใ‚‰ๆ–ฐใ—ใ„็”ปๅƒใ‚’็”Ÿๆˆใ€‚ใ“ใฎ้€ฃ้Ž–ใซใ‚ˆใฃใฆใ€ๅฝ“ๅˆใฎๆ„ๅ›ณใ‹ใ‚‰้›ขใ‚Œใฆใ„ใ๏ผˆใ‚ใ‚‹ใ„ใฏๅฅ‡่ทก็š„ใซ็ถญๆŒใ•ใ‚Œใ‚‹๏ผ‰่ฆ–่ฆš็š„ใชๅค‰้ทใ‚’ๆฅฝใ—ใ‚€ใ“ใจใŒใงใใพใ™ใ€‚

Next.js TypeScript Supabase Google Gemini

โœจ ็‰นๅพด

  • ๐ŸŒณ ใƒ„ใƒชใƒผๆง‹้€ : Gitใฎใƒ–ใƒฉใƒณใƒใฎใ‚ˆใ†ใซใ€1ใคใฎ็”ปๅƒใ‹ใ‚‰่ค‡ๆ•ฐใฎ่งฃ้‡ˆใŒๅˆ†ๅฒ
  • ๐Ÿ”„ ้žๅŒๆœŸๅ‡ฆ็†: ใƒชใ‚ขใƒซใ‚ฟใ‚คใƒ ๆ€งใ‚’ๅฟ…่ฆใจใ›ใšใ€่‡ชๅˆ†ใฎใƒšใƒผใ‚นใงใƒ—ใƒฌใ‚คๅฏ่ƒฝ
  • ๐ŸŽฏ ่ฆ–่ฆšๅŒ–: ใ‚คใƒณใ‚ฟใƒฉใ‚ฏใƒ†ใ‚ฃใƒ–ใชใƒ„ใƒชใƒผใƒ“ใƒฅใƒผใงๅ…จไฝ“ใฎ้€ฃ้Ž–ใ‚’ไฟฏ็žฐ
  • ๐ŸŽจ AI็”Ÿๆˆ: Google Gemini 2.5 Flash Imageใซใ‚ˆใ‚‹้ซ˜ๅ“่ณชใช็”ปๅƒ็”Ÿๆˆ
  • ๐Ÿ“Š ็ณป่ญœ่ฟฝ่ทก: ็”ปๅƒใฎ่ช•็”Ÿใ‹ใ‚‰็พๅœจใพใงใ€ใ™ในใฆใฎๅค‰้ทใ‚’่ฟฝ่ทกๅฏ่ƒฝ

๐Ÿ–ผ๏ธ ใ‚นใ‚ฏใƒชใƒผใƒณใ‚ทใƒงใƒƒใƒˆ

ใ‚ฎใƒฃใƒฉใƒชใƒผใƒ“ใƒฅใƒผ

ใƒฉใƒณใƒ€ใƒ ใซ้ธใฐใ‚ŒใŸ3ๆžšใฎ็”ปๅƒใ‚’่กจ็คบใ€‚ๅ„็”ปๅƒใ‹ใ‚‰ๆ–ฐใ—ใ„้€ฃ้Ž–ใ‚’้–‹ๅง‹ใงใใพใ™ใ€‚

ใƒ„ใƒชใƒผใƒ“ใƒฅใƒผ

ใ™ในใฆใฎ็”ปๅƒใฎ้€ฃ้Ž–ใ‚’ๆœจๆง‹้€ ใงๅฏ่ฆ–ๅŒ–ใ€‚ใ‚บใƒผใƒ ใƒปใƒ‘ใƒณๆ“ไฝœใซๅฏพๅฟœใ€‚

็”ปๅƒ่ฉณ็ดฐ

็”ปๅƒใฎ็ณป่ญœ๏ผˆใƒซใƒผใƒˆใ‹ใ‚‰็พๅœจใพใง๏ผ‰ใ‚’่ฆ–่ฆš็š„ใซ่กจ็คบใ—ใ€ๆ–ฐใ—ใ„่งฃ้‡ˆใ‚’่ฟฝๅŠ ใงใใพใ™ใ€‚

๐Ÿ›  ๆŠ€่ก“ใ‚นใ‚ฟใƒƒใ‚ฏ

ใ‚ซใƒ†ใ‚ดใƒช ๆŠ€่ก“ ็”จ้€”
Frontend Next.js 15 (App Router) React 19ใƒ™ใƒผใ‚นใฎใƒ•ใƒซใ‚นใ‚ฟใƒƒใ‚ฏใƒ•ใƒฌใƒผใƒ ใƒฏใƒผใ‚ฏ
Language TypeScript 5 ๅž‹ๅฎ‰ๅ…จใช้–‹็™บ็’ฐๅขƒ
Database Supabase (PostgreSQL) ใƒชใ‚ขใƒซใ‚ฟใ‚คใƒ ใƒ‡ใƒผใ‚ฟใƒ™ใƒผใ‚น
AI Model Google Gemini 2.5 Flash Image Text-to-Image็”Ÿๆˆ
Styling Tailwind CSS ใƒฆใƒผใƒ†ใ‚ฃใƒชใƒ†ใ‚ฃใƒ•ใ‚กใƒผใ‚นใƒˆCSS
Storage Local Filesystem ็”Ÿๆˆ็”ปๅƒใฎไฟๅญ˜ (public/images/generated/)

๐Ÿ“ ใ‚ขใƒผใ‚ญใƒ†ใ‚ฏใƒใƒฃ

ใƒ‡ใƒผใ‚ฟใƒ•ใƒญใƒผ

sequenceDiagram
    participant User
    participant ServerAction as Next.js Server Action
    participant DB as Supabase DB
    participant Background as Background Process
    participant Gemini as Google Gemini API
    participant LocalFS as Local Filesystem

    User->>ServerAction: 1. ่ชฌๆ˜Žใƒ†ใ‚ญใ‚นใƒˆ้€ไฟก
    ServerAction->>DB: 2. Pending็”Ÿๆˆใƒฌใ‚ณใƒผใƒ‰ไฝœๆˆ
    ServerAction->>Background: 3. ้žๅŒๆœŸใง็”ปๅƒ็”Ÿๆˆ้–‹ๅง‹
    Background->>Gemini: 4. Prompt้€ไฟก
    Gemini->>Background: 5. ็”ปๅƒใƒ‡ใƒผใ‚ฟ่ฟ”ๅด (Base64)
    Background->>LocalFS: 6. ็”ปๅƒไฟๅญ˜
    Background->>DB: 7. ใƒกใ‚ฟใƒ‡ใƒผใ‚ฟๆ›ดๆ–ฐ (completed)
    User->>DB: 8. ใƒใƒผใƒชใƒณใ‚ฐใง็Šถๆ…‹็ขบ่ช
    DB->>User: 9. ๅฎŒๆˆ็”ปๅƒใจใƒกใ‚ฟใƒ‡ใƒผใ‚ฟ่ฟ”ๅด
Loading

ใƒ‡ใƒผใ‚ฟใƒ™ใƒผใ‚น่จญ่จˆ

generations ใƒ†ใƒผใƒ–ใƒซ - ่‡ชๅทฑๅ‚็…งใซใ‚ˆใ‚‹ใƒ„ใƒชใƒผๆง‹้€ ๏ผˆAdjacency List ใƒ‘ใ‚ฟใƒผใƒณ๏ผ‰

ใ‚ซใƒฉใƒ ๅ ๅž‹ ่ชฌๆ˜Ž
id UUID ไธปใ‚ญใƒผ๏ผˆ่‡ชๅ‹•็”Ÿๆˆ๏ผ‰
parent_id UUID ่ฆช็”ปๅƒใฎID๏ผˆใƒซใƒผใƒˆใฎๅ ดๅˆใฏNULL๏ผ‰
image_url TEXT ็”Ÿๆˆ็”ปๅƒใฎใƒญใƒผใ‚ซใƒซใƒ‘ใ‚น
prompt TEXT ใƒฆใƒผใ‚ถใƒผๅ…ฅๅŠ›ใฎ่ชฌๆ˜Žๆ–‡
created_at TIMESTAMPTZ ไฝœๆˆๆ—ฅๆ™‚
status generation_status ็”Ÿๆˆใ‚นใƒ†ใƒผใ‚ฟใ‚น๏ผˆpending/completed/failed๏ผ‰

RPC้–ขๆ•ฐ: get_tree_structure(root_id UUID) - ๅ†ๅธฐ็š„CTEใซใ‚ˆใ‚‹ๅŠน็އ็š„ใชใƒ„ใƒชใƒผๅ–ๅพ—

๐Ÿš€ ใ‚ปใƒƒใƒˆใ‚ขใƒƒใƒ—

ๅ‰ๆๆกไปถ

  • Node.js 20ไปฅไธŠ
  • Supabaseใ‚ขใ‚ซใ‚ฆใƒณใƒˆ
  • Google Gemini APIใ‚ญใƒผ

ใ‚คใƒณใ‚นใƒˆใƒผใƒซๆ‰‹้ †

  1. ใƒชใƒใ‚ธใƒˆใƒชใฎใ‚ฏใƒญใƒผใƒณ
git clone https://github.com/kwrkb/visual-echo.git
cd visual-echo
  1. ไพๅญ˜้–ขไฟ‚ใฎใ‚คใƒณใ‚นใƒˆใƒผใƒซ
npm install
  1. ็’ฐๅขƒๅค‰ๆ•ฐใฎ่จญๅฎš
cp .env.local.example .env.local

.env.localใ‚’็ทจ้›†ใ—ใฆใ€ไปฅไธ‹ใ‚’่จญๅฎš:

# Supabase่จญๅฎš๏ผˆProject Settings โ†’ API ใ‹ใ‚‰ๅ–ๅพ—๏ผ‰
NEXT_PUBLIC_SUPABASE_URL=your-project-url.supabase.co
NEXT_PUBLIC_SUPABASE_ANON_KEY=your-anon-key

# Google Gemini API่จญๅฎš๏ผˆhttps://makersuite.google.com/app/apikey ใ‹ใ‚‰ๅ–ๅพ—๏ผ‰
GEMINI_API_KEY=your-gemini-api-key

# ใ‚ชใƒ—ใ‚ทใƒงใƒณ: ใƒขใƒ‡ใƒซๆŒ‡ๅฎš๏ผˆใƒ‡ใƒ•ใ‚ฉใƒซใƒˆ: gemini-2.5-flash-image๏ผ‰
GEMINI_MODEL=gemini-2.5-flash-image
  1. ใƒ‡ใƒผใ‚ฟใƒ™ใƒผใ‚นใฎใ‚ปใƒƒใƒˆใ‚ขใƒƒใƒ—

Supabase DashboardใฎSQL Editorใงไปฅไธ‹ใ‚’้ †็•ชใซๅฎŸ่กŒ:

-- 1. ใ‚นใ‚ญใƒผใƒžใจใƒ†ใƒผใƒ–ใƒซไฝœๆˆ
-- supabase/schema.sql ใฎๅ†…ๅฎนใ‚’ๅฎŸ่กŒ

-- 2. RPC้–ขๆ•ฐไฝœๆˆ๏ผˆๆ—ขๅญ˜DBใฎๅ ดๅˆใฏไปฅไธ‹ใฎใƒžใ‚คใ‚ฐใƒฌใƒผใ‚ทใƒงใƒณใ‚’ๅฎŸ่กŒ๏ผ‰
-- supabase/migrations/add_generation_status_enum.sql
-- supabase/migrations/update_tree_rpc_enum.sql

ๆ–ฐ่ฆใ‚ปใƒƒใƒˆใ‚ขใƒƒใƒ—ใฎๅ ดๅˆใฏsupabase/schema.sqlใฎใฟใงOKใงใ™ใ€‚

  1. ้–‹็™บใ‚ตใƒผใƒใƒผใฎ่ตทๅ‹•
npm run dev

http://localhost:3000 ใงใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใŒ่ตทๅ‹•ใ—ใพใ™ใ€‚

๐Ÿ“ฑ ไฝฟใ„ๆ–น

1. ใ‚ฎใƒฃใƒฉใƒชใƒผใง็”ปๅƒใ‚’้ธใถ

/gallery ใซใ‚ขใ‚ฏใ‚ปใ‚นใ—ใฆใ€ใƒฉใƒณใƒ€ใƒ ใซ่กจ็คบใ•ใ‚Œใ‚‹3ๆžšใฎ็”ปๅƒใ‹ใ‚‰ๅฅฝใใชใ‚‚ใฎใ‚’้ธๆŠžใ€‚

2. ็”ปๅƒใ‚’่จ€่‘‰ใง่ชฌๆ˜Ž

้ธๆŠžใ—ใŸ็”ปๅƒใ‚’่ฆ‹ใฆใ€ใใฎๅ†…ๅฎนใ‚’่‡ชๅˆ†ใฎ่จ€่‘‰ใง่ชฌๆ˜Žใ—ใพใ™ใ€‚

3. AIใŒๆ–ฐใ—ใ„็”ปๅƒใ‚’็”Ÿๆˆ

ใ‚ใชใŸใฎ่ชฌๆ˜Žใ‚’ใ‚‚ใจใซใ€AIใŒๆ–ฐใ—ใ„็”ปๅƒใ‚’็”Ÿๆˆใ—ใพใ™๏ผˆ็ด„10ใ€œ30็ง’๏ผ‰ใ€‚

4. ้€ฃ้Ž–ใ‚’็ขบ่ช

็”Ÿๆˆใ•ใ‚ŒใŸ็”ปๅƒใจๅ…ƒใฎ็”ปๅƒใ‚’ๆฏ”่ผƒใ€‚็ณป่ญœใƒ“ใƒฅใƒผใงใ€ใƒซใƒผใƒˆใ‹ใ‚‰ใฎๅค‰้ทใ‚’็ขบ่ชใงใใพใ™ใ€‚

5. ใƒ„ใƒชใƒผใƒ“ใƒฅใƒผใงๅ…จไฝ“ใ‚’ไฟฏ็žฐ

/tree ใซใ‚ขใ‚ฏใ‚ปใ‚นใ—ใฆใ€ใ™ในใฆใฎ็”ปๅƒใฎ้€ฃ้Ž–ใ‚’ใ‚คใƒณใ‚ฟใƒฉใ‚ฏใƒ†ใ‚ฃใƒ–ใชใƒ„ใƒชใƒผใงๆŽข็ดขใ€‚

๐ŸŽฏ ไธป่ฆๆฉŸ่ƒฝ

ใ‚ฎใƒฃใƒฉใƒชใƒผ (/gallery)

  • ใƒฉใƒณใƒ€ใƒ ใซ3ๆžšใฎ็”ปๅƒใ‚’่กจ็คบ
  • ใ€Œๅ…จใฆ่กจ็คบใ€ใƒœใ‚ฟใƒณใงๅ…จ็”ปๅƒไธ€่ฆงใซ้ท็งป

ใƒ„ใƒชใƒผใƒ“ใƒฅใƒผ (/tree)

  • ๅ…จ็”ปๅƒใฎ้€ฃ้Ž–ใ‚’ๆœจๆง‹้€ ใงๅฏ่ฆ–ๅŒ–
  • ใ‚บใƒผใƒ ใƒปใƒ‘ใƒณๆ“ไฝœใซๅฏพๅฟœ
  • ๅ„ใƒŽใƒผใƒ‰ใ‚’ใ‚ฏใƒชใƒƒใ‚ฏใ—ใฆ่ฉณ็ดฐใธ้ท็งป

็”ปๅƒ่ฉณ็ดฐ (/gallery/[id])

  • ็”ปๅƒใฎ็ณป่ญœ๏ผˆใƒซใƒผใƒˆใ‹ใ‚‰็พๅœจใพใง๏ผ‰ใ‚’่กจ็คบ
  • ใƒ—ใƒญใƒณใƒ—ใƒˆๅ…ฅๅŠ›ใƒ•ใ‚ฉใƒผใƒ ใงๆ–ฐใ—ใ„ๅˆ†ๅฒใ‚’ไฝœๆˆ
  • ๅญ็”ปๅƒไธ€่ฆงใ‚’่กจ็คบ

ๆ–ฐ่ฆไฝœๆˆ (/create)

  • ใƒซใƒผใƒˆ็”ปๅƒ๏ผˆใƒ„ใƒชใƒผใฎ่ตท็‚น๏ผ‰ใ‚’็”Ÿๆˆ

๐Ÿ”ง ้–‹็™บใ‚ณใƒžใƒณใƒ‰

# ้–‹็™บใ‚ตใƒผใƒใƒผ่ตทๅ‹•
npm run dev

# ๆœฌ็•ชใƒ“ใƒซใƒ‰
npm run build

# ๆœฌ็•ชใ‚ตใƒผใƒใƒผ่ตทๅ‹•
npm start

# Lintใƒใ‚งใƒƒใ‚ฏ
npm run lint

๐Ÿ“Š ใƒ—ใƒญใ‚ธใ‚งใ‚ฏใƒˆๆง‹ๆˆ

visual-echo/
โ”œโ”€โ”€ app/                      # Next.js App Router
โ”‚   โ”œโ”€โ”€ actions/             # Server Actions
โ”‚   โ”œโ”€โ”€ gallery/             # ใ‚ฎใƒฃใƒฉใƒชใƒผใƒšใƒผใ‚ธ็พค
โ”‚   โ”œโ”€โ”€ tree/                # ใƒ„ใƒชใƒผใƒ“ใƒฅใƒผ
โ”‚   โ””โ”€โ”€ create/              # ๆ–ฐ่ฆไฝœๆˆใƒšใƒผใ‚ธ
โ”œโ”€โ”€ components/              # Reactใ‚ณใƒณใƒใƒผใƒใƒณใƒˆ
โ”œโ”€โ”€ lib/                     # ใƒฉใ‚คใƒ–ใƒฉใƒชใƒปใƒฆใƒผใƒ†ใ‚ฃใƒชใƒ†ใ‚ฃ
โ”‚   โ”œโ”€โ”€ supabase/           # Supabaseใ‚ฏใƒฉใ‚คใ‚ขใƒณใƒˆ
โ”‚   โ”œโ”€โ”€ gemini/             # Gemini APIใ‚ฏใƒฉใ‚คใ‚ขใƒณใƒˆ
โ”‚   โ””โ”€โ”€ queries/            # ใƒ‡ใƒผใ‚ฟใƒ™ใƒผใ‚นใ‚ฏใ‚จใƒช
โ”œโ”€โ”€ types/                   # TypeScriptๅž‹ๅฎš็พฉ
โ”œโ”€โ”€ supabase/               # ใƒ‡ใƒผใ‚ฟใƒ™ใƒผใ‚น้–ข้€ฃ
โ”‚   โ”œโ”€โ”€ schema.sql          # ใ‚นใ‚ญใƒผใƒžๅฎš็พฉ
โ”‚   โ””โ”€โ”€ migrations/         # ใƒžใ‚คใ‚ฐใƒฌใƒผใ‚ทใƒงใƒณใ‚นใ‚ฏใƒชใƒ—ใƒˆ
โ””โ”€โ”€ public/                 # ้™็š„ใƒ•ใ‚กใ‚คใƒซ
    โ””โ”€โ”€ images/
        โ””โ”€โ”€ generated/      # AI็”Ÿๆˆ็”ปๅƒ๏ผˆgitignoreๅฏพ่ฑก๏ผ‰

โš ๏ธ ๆณจๆ„ไบ‹้ …

ใƒญใƒผใ‚ซใƒซ็’ฐๅขƒใงใฎๅ‹•ไฝœใ‚’ๆƒณๅฎš

ๆœฌใ‚ขใƒ—ใƒชใ‚ฑใƒผใ‚ทใƒงใƒณใฏ็”Ÿๆˆใ•ใ‚ŒใŸ็”ปๅƒใ‚’ใƒญใƒผใ‚ซใƒซใƒ•ใ‚กใ‚คใƒซใ‚ทใ‚นใƒ†ใƒ ใซไฟๅญ˜ใ—ใพใ™ใ€‚ๆœฌ็•ช็’ฐๅขƒใซใƒ‡ใƒ—ใƒญใ‚คใ™ใ‚‹ๅ ดๅˆใฏใ€Supabase Storageใ‚„Cloudinaryใชใฉใฎใ‚ฏใƒฉใ‚ฆใƒ‰ใ‚นใƒˆใƒฌใƒผใ‚ธใธใฎ็งป่กŒใŒๅฟ…่ฆใงใ™ใ€‚

APIๅˆฉ็”จๆ–™้‡‘

Google Gemini APIใฎไฝฟ็”จใซใ‚ˆใ‚Šๆ–™้‡‘ใŒ็™บ็”Ÿใ™ใ‚‹ๅฏ่ƒฝๆ€งใŒใ‚ใ‚Šใพใ™ใ€‚่ฉณ็ดฐใฏGemini API Pricingใ‚’ใ”็ขบ่ชใใ ใ•ใ„ใ€‚

ใƒ‡ใƒผใ‚ฟใƒ™ใƒผใ‚นใƒใƒชใ‚ทใƒผ

้–‹็™บ็”จใซๅ…จใƒฆใƒผใ‚ถใƒผใŒ่ชญใฟๆ›ธใๅฏ่ƒฝใชRLSใƒใƒชใ‚ทใƒผใŒ่จญๅฎšใ•ใ‚Œใฆใ„ใพใ™ใ€‚ๆœฌ็•ช็’ฐๅขƒใงใฏ้ฉๅˆ‡ใช่ช่จผใƒป่ชๅฏใƒใƒชใ‚ทใƒผใ‚’่จญๅฎšใ—ใฆใใ ใ•ใ„ใ€‚

๐Ÿ“ ใƒฉใ‚คใ‚ปใƒณใ‚น

MIT License

๐Ÿค ใ‚ณใƒณใƒˆใƒชใƒ“ใƒฅใƒผใ‚ทใƒงใƒณ

IssueใƒปPull Requestใ‚’ๆญ“่ฟŽใ—ใพใ™๏ผ

๐Ÿ“ฎ ใŠๅ•ใ„ๅˆใ‚ใ›

่ณชๅ•ใ‚„ๆๆกˆใŒใ‚ใ‚‹ๅ ดๅˆใฏใ€IssuesใงใŠ็Ÿฅใ‚‰ใ›ใใ ใ•ใ„ใ€‚


Made with โค๏ธ using Next.js, Supabase, and Google Gemini AI


๐Ÿ‡ฌ๐Ÿ‡ง Visual Echo (English)

Visual Echo is an asynchronous, branching image association game powered by generative AI.

Describe an image in words, and AI will generate a new image based on your description. Through this chain, you can enjoy the visual evolution that departs from (or miraculously maintains) the original intention.

Next.js TypeScript Supabase Google Gemini

โœจ Features

  • ๐ŸŒณ Tree Structure: Just like Git branches, multiple interpretations branch out from a single image.
  • ๐Ÿ”„ Asynchronous Processing: No real-time requirement; play at your own pace.
  • ๐ŸŽฏ Visualization: Overview the entire chain with an interactive tree view.
  • ๐ŸŽจ AI Generation: High-quality image generation using Google Gemini 2.5 Flash Image.
  • ๐Ÿ“Š Genealogy Tracking: Track every transition from the image's birth to the present.

๐Ÿ–ผ๏ธ Screenshots

Gallery View

Displays 3 randomly selected images. You can start a new chain from each image.

Tree View

Visualizes the chain of all images in a tree structure. Supports zoom and pan operations.

Image Details

Visually displays the genealogy of an image (from root to current) and allows adding new interpretations.

๐Ÿ›  Tech Stack

Category Technology Usage
Frontend Next.js 15 (App Router) React 19-based full-stack framework
Language TypeScript 5 Type-safe development environment
Database Supabase (PostgreSQL) Real-time database
AI Model Google Gemini 2.5 Flash Image Text-to-Image generation
Styling Tailwind CSS Utility-first CSS
Storage Local Filesystem Saving generated images (public/images/generated/)

๐Ÿ“ Architecture

Data Flow

sequenceDiagram
    participant User
    participant ServerAction as Next.js Server Action
    participant DB as Supabase DB
    participant Background as Background Process
    participant Gemini as Google Gemini API
    participant LocalFS as Local Filesystem

    User->>ServerAction: 1. Send description text
    ServerAction->>DB: 2. Create Pending generation record
    ServerAction->>Background: 3. Start image generation asynchronously
    Background->>Gemini: 4. Send Prompt
    Gemini->>Background: 5. Return image data (Base64)
    Background->>LocalFS: 6. Save image
    Background->>DB: 7. Update metadata (completed)
    User->>DB: 8. Check status via polling
    DB->>User: 9. Return completed image and metadata
Loading

Database Design

generations table - Tree structure via self-reference (Adjacency List Pattern)

Column Name Type Description
id UUID Primary Key (Auto-generated)
parent_id UUID Parent Image ID (NULL if root)
image_url TEXT Local path of the generated image
prompt TEXT Description entered by the user
created_at TIMESTAMPTZ Creation timestamp
status generation_status Generation status (pending/completed/failed)

RPC Function: get_tree_structure(root_id UUID) - Efficient tree retrieval using Recursive CTE

๐Ÿš€ Setup

Prerequisites

  • Node.js 20 or higher
  • Supabase Account
  • Google Gemini API Key

Installation Steps

  1. Clone the repository
git clone https://github.com/kwrkb/visual-echo.git
cd visual-echo
  1. Install dependencies
npm install
  1. Set up environment variables
cp .env.local.example .env.local

Edit .env.local and set the following:

# Supabase Configuration (Get from Project Settings โ†’ API)
NEXT_PUBLIC_SUPABASE_URL=your-project-url.supabase.co
NEXT_PUBLIC_SUPABASE_ANON_KEY=your-anon-key

# Google Gemini API Configuration (Get from https://makersuite.google.com/app/apikey)
GEMINI_API_KEY=your-gemini-api-key

# Optional: Model specification (Default: gemini-2.5-flash-image)
GEMINI_MODEL=gemini-2.5-flash-image
  1. Database Setup

Run the following in order in the Supabase Dashboard SQL Editor:

-- 1. Create schema and tables
-- Execute content of supabase/schema.sql

-- 2. Create RPC functions (Run the following migrations if using an existing DB)
-- supabase/migrations/add_generation_status_enum.sql
-- supabase/migrations/update_tree_rpc_enum.sql

For a new setup, just supabase/schema.sql is sufficient.

  1. Start Development Server
npm run dev

The application will start at http://localhost:3000.

๐Ÿ“ฑ Usage

1. Choose an image in the Gallery

Access /gallery and select your favorite from 3 randomly displayed images.

2. Describe the image

Look at the selected image and describe its content in your own words.

3. AI generates a new image

Based on your description, AI generates a new image (approx. 10-30 seconds).

4. Check the chain

Compare the generated image with the original. You can see the transition from the root in the genealogy view.

5. Overview with Tree View

Access /tree to explore the chains of all images in an interactive tree.

๐ŸŽฏ Key Features

Gallery (/gallery)

  • Displays 3 random images
  • "View All" button to transition to the full image list

Tree View (/tree)

  • Visualizes the chain of all images in a tree structure
  • Supports zoom and pan operations
  • Click each node to transition to details

Image Details (/gallery/[id])

  • Displays image genealogy (from root to current)
  • Prompt input form to create a new branch
  • Displays list of child images

Create New (/create)

  • Generates a root image (starting point of a tree)

๐Ÿ”ง Development Commands

# Start development server
npm run dev

# Production build
npm run build

# Start production server
npm start

# Lint check
npm run lint

๐Ÿ“Š Project Structure

visual-echo/
โ”œโ”€โ”€ app/                      # Next.js App Router
โ”‚   โ”œโ”€โ”€ actions/             # Server Actions
โ”‚   โ”œโ”€โ”€ gallery/             # Gallery pages
โ”‚   โ”œโ”€โ”€ tree/                # Tree view
โ”‚   โ””โ”€โ”€ create/              # Creation page
โ”œโ”€โ”€ components/              # React components
โ”œโ”€โ”€ lib/                     # Libraries & Utilities
โ”‚   โ”œโ”€โ”€ supabase/           # Supabase client
โ”‚   โ”œโ”€โ”€ gemini/             # Gemini API client
โ”‚   โ””โ”€โ”€ queries/            # Database queries
โ”œโ”€โ”€ types/                   # TypeScript type definitions
โ”œโ”€โ”€ supabase/               # Database related
โ”‚   โ”œโ”€โ”€ schema.sql          # Schema definition
โ”‚   โ””โ”€โ”€ migrations/         # Migration scripts
โ””โ”€โ”€ public/                 # Static files
    โ””โ”€โ”€ images/
        โ””โ”€โ”€ generated/      # AI generated images (gitignored)

โš ๏ธ Notes

Assumes local environment operation

This application saves generated images to the local filesystem. To deploy to a production environment, migration to cloud storage such as Supabase Storage or Cloudinary is required.

API Usage Costs

Charges may apply for using the Google Gemini API. Please check Gemini API Pricing for details.

Database Policy

For development, an RLS policy allowing read/write for all users is set. Please set appropriate authentication/authorization policies for production.

๐Ÿ“ License

MIT License

๐Ÿค Contribution

Issues and Pull Requests are welcome!

๐Ÿ“ฎ Contact

If you have questions or suggestions, please let us know in Issues.

About

Visual Echo - AI-powered image telephone game

Topics

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors