Join the Agent Deck Discord Server!
Discord에서 Agent Deck 커뮤니티 확인, 357명과 자유 음성·텍스트 채팅 이용
아직 감지된 업데이트가 없습니다. GitHub 릴리스가 나오면 여기에 보입니다.
개인 계정의 공개 저장소 소유자는 GitHub로 로그인해 운영자를 확인하고 소개를 직접 관리할 수 있습니다. 관리자 승인은 필요하지 않습니다.
로그인한 뒤 확인 파일을 만들어 이 저장소의 기본 브랜치에 30분 안에 커밋해 주세요. 다른 브랜치나 포크의 파일은 인정하지 않습니다. 파일을 올린 뒤 아래에서 확인하면 관리자 승인 없이 관리할 수 있습니다. 자격을 유지하려면 파일을 남겨 두세요.
로그인이 필요하면 로그인 화면으로 이동합니다. 로그인 후 이곳으로 돌아와 원하는 확인 버튼을 다시 눌러 주세요.
프로젝트 폴더에서 /nomorevibe verify를 실행하면 소유권을 확인하고 소개를 직접 관리할 수 있습니다.
1분 만에 확인하기Moment Share Square is a responsive, TypeScript-driven web application for sharing short text and image moments in a square-style social feed. Built with modern component patterns and CSS for styling, it’s designed for fast front-end development, easy backend integration (authentication, media storage), and extensibility for features like reactions
저장소 README에서 가져옴
README 전체를 불러오는 중입니다. 아래는 저장된 발췌입니다.
Paste this whole document into Lovable as the initial prompt. It is written for Lovable to read directly.
Meanwhile is a prototype for a two-person app. Two friends who live far apart share one rectangle. The rectangle is split into two squares: the left square is one person's moment, the right square is the other's. A moment is a photo taken right now, or a single large emoji.
The whole point is that there is no obligation to reply. Sending is already complete on its own. The second square is an invitation, never a debt.README 전문 보기 ↗Meanwhile — Lovable Build Spec
Paste this whole document into Lovable as the initial prompt. It is written for Lovable to read directly.
Meanwhile is a prototype for a two-person app. Two friends who live far apart share one rectangle. The rectangle is split into two squares: the left square is one person's moment, the right square is the other's. A moment is a photo taken right now, or a single large emoji.
The whole point is that there is no obligation to reply. Sending is already complete on its own. The second square is an invitation, never a debt.
Build this as a front-end prototype with local state and seed data. No backend, no auth, no database, no real push notifications. It must run entirely in the browser and be demo-able on a phone screen.
This is a deliberate, austere black-and-white system. Follow it exactly — do not add color, softness, or decoration.
Color
Token Value Use --ink #000000 All borders, all text --paper #FFFFFF All backgrounds, empty cells
Two colors only. No greys, no tinted blacks (#111, #0B0B0B are forbidden), no accent color, no gradients, no shadows.
Borders
Every square and rectangle is outlined with 2px solid var(--ink).
The divider between the two squares is also 2px solid var(--ink).
border-radius: 0 everywhere, with no exceptions.
Borders are the only structural device in this UI. There are no cards, no panels, no elevation.
Type
One typeface throughout: General Sans (Fontshare). Fallback: Archivo from Google Fonts, then system-ui, sans-serif.
Weights: 400 for everything, 500 only for the logotype.
Sentence case everywhere. Do not use all-caps labels.
Do not use a monospace font anywhere.
Timestamps are set in the same family as everything else, at 13px, letter-spacing 0.01em.
Layout
Mobile-first, max content width 420px, centered on larger screens.
Page margin: 20px left and right.
The rectangle is always 2:1 — width 100% of the content column, height exactly half that width. Each square inside is 1:1.
Generous vertical whitespace. Nothing is crowded. Let the frames sit in empty space.
Motion
One motion moment only: the pairing animation (spec'd in §6). Do not add fade-and-slide-up entrances, hover transitions on every element, or page-load sequences. Respect prefers-reduced-motion by snapping instantly to the paired state.
Logo
Top-left of the header. It is the product mark itself: a 2:1 rectangle, 28px wide × 14px tall, 2px solid #000 outline, with a 2px vertical divider at the midpoint. The left square is filled solid black; the right square is white. Beside it, the wordmark meanwhile in lowercase, 15px, weight 500, 10px to the right of the mark.
type Person = { id: string; // "you" | "friend" name: string; // "You" | "Mei" city: string; // "Stockholm" | "Guangzhou" }
type Cell = { kind: "photo" | "emoji"; photoUrl?: string; // object URL or seed image emoji?: string; // single emoji character timestamp: string; // ISO datetime, LOCAL to that person city: string; }
type Moment = { id: string; initiator: "you" | "friend"; // who opened this rectangle initiatorCell: Cell; // always present responderCell: Cell | null; // null = not yet paired }
Ordering rule: the timeline is sorted by initiatorCell.timestamp, newest first. The rectangle's canonical date is always the initiator's timestamp — a response that lands six hours later does not move the rectangle.
This is the heart of the product. Get these exactly right.
State A — Sent, viewed by the sender
The initiator's photo fills the entire 2:1 rectangle, edge to edge, object-fit: cover.
No divider. No empty cell. No plus icon. No placeholder.
One timestamp, bottom-left.
Nothing in this view may suggest something is missing or pending. For the sender, this moment is finished.
┌──────────────────────────────────┐ │ │ │ my photo, full bleed │ │ 15:04 Stockholm │ └──────────────────────────────────┘
State B — Sent, viewed by the receiver
Split 50 / 50. Left square = the sender's photo. Right square = empty white with a centered plus.
The plus is a plain + glyph drawn as two 2px black strokes, 20px long, centered. No circle around it, no icon library, no button chrome.
The empty cell has the same 2px black border as everything else.
The empty cell breathes: opacity oscillates between 1 and 0.45 over 2.4s, ease-in-out, infinite. This is the one ambient motion allowed, and only here, and only on the newest moment.
┌────────────────┬─────────────────┐ │ │ │ │ their photo │ + │ │ 21:37 Guangzhou│ │ └────────────────┴─────────────────┘
State C — Paired
Split 50 / 50. Both squares filled with photos. Each square carries its own timestamp and city, bottom-left of that square.
┌────────────────┬─────────────────┐ │ │ │ │ my photo │ their photo │ │ 15:04 Stockholm│ 21:37 Guangzhou │ └────────────────┴─────────────────┘
State D — Paired with an emoji
Identical to State C, except the responder's square is pure white with a single large emoji centered, font-size = 46% of the square's height. The timestamp still appears bottom-left of that square, in black.
An emoji reply fills its square as completely as a photo does. It must never look like less.
Timestamp rendering
Format: 15:04 Stockholm — 24-hour time, then a space, then the city. No date on the rectangle itself.
Position: 10px from the left edge, 10px from the bottom edge, of its own square (or of the whole rectangle in State A).
Rendering: color: #FFF; mix-blend-mode: difference; so it stays legible over any photo while keeping the palette strictly black and white. Over the white emoji cell this makes it read as black — correct.
The full date (2026.09.15) appears above the rectangle in the timeline, not on the image.
5.1 Header (persistent, all screens)
Left: the logo mark + meanwhile wordmark.
Right: a perspective toggle — two text labels, You and Mei, separated by a 2px black vertical rule, the active one at full opacity and the inactive at 0.35. Tapping switches whose eyes you are seeing through.
This toggle is a demo affordance, not a real product feature. Keep it, it is needed to show both sides of the rectangle live.
Below the header, a 2px full-bleed black rule.
5.2 Now (home, default route /)
The most recent moment, rendered large at the top, in whichever of States A–D applies to the currently selected perspective.
The date sits above it, left-aligned: 2026.09.15.
Below it, 32px down, a single line of plain text: Take one — tapping it opens the Add sheet. If the current perspective already has a filled cell in this moment, this line reads Start a new one instead.
Below that, the top ~20% of the next timeline rectangle peeks above the fold, to signal scrollability. Scrolling down navigates to Timeline.
5.3 Add sheet (bottom sheet over Now)
Opens when the user taps the empty + cell, or taps Take one.
Three options, stacked as full-width rows separated by 2px black rules:
Take a photo — opens the device camera via
Choose a photo — plain file input (for demo convenience on desktop)
Send an emoji — reveals a row of 8 emoji: 🙂 🥲 😂 🫶 👀 🌙 ☕️ 🚶
Tapping any option immediately commits the moment and closes the sheet. There is no confirm step, no caption field, no preview-and-edit screen. Friction here defeats the product.
5.4 Timeline (route /timeline)
Vertical scroll, one rectangle centered at a time, using CSS scroll-snap-type: y mandatory on the container and scroll-snap-align: center on each item.
Each item: the date above it, then the rectangle. 64px of empty space between items.
Unpaired moments appear here in State A regardless of perspective — full-bleed single photo, no plus, no empty cell, no divider. Same visual weight as a paired rectangle.
The + appears only on the single newest moment, and only when the current perspective has not filled their cell. Historical unpaired moments never show a plus. The timeline is a record, not a to-do list.
No counters, no "3 months since you last paired", no streaks, no activity score, no sorting controls, no filters.
5.5 Moment detail (optional, route /m/:id)
Tapping a rectangle opens it full-screen on a white background, same 2:1 proportion, with both timestamps shown larger. Tap anywhere to dismiss. Build this only after everything above works.
When the responder commits their cell, animate the transition from State B to State C/D on screen:
The sender's photo scales from 100% to 50% of the rectangle's width, anchored left.
Simultaneously, the responder's cell slides in from the right edge.
Duration 280ms, easing cubic-bezier(0.22, 1, 0.36, 1), with a 4px overshoot that settles — the two squares should feel like they click into place, not fade.
The 2px divider appears at the end of the motion, not during it.
This is the single memorable moment of the prototype. It should be smooth at 60fps on a phone.
Preload 8 moments so the timeline is full on first open. Use placeholder images — quiet, ordinary, unstaged scenes (a street, a table, a window, a bus). Avoid glossy stock photography.
Two unpaired moments are intentional. They stay in the record, unannotated.
Lovable tends to add these by default. None of them belong here.
Interaction
Read receipts, "seen" indicators, typing indicators, delivery status
Streaks, daily counters, "you haven't paired in N days"
Unread badges, red dots, notification counts
Like counts, reaction counts, comment threads
Any copy that frames an empty cell as waiting, pending, overdue, or missed
Infinite scroll without snap
A plus on any moment other than the newest
Confirm/preview steps between choosing a photo and committing it
Visual
Rounded corners, drop shadows, gradients, blurs, glassmorphism
Any color other than pure black and pure white
Icon libraries (lucide, heroicons, etc.) — the only glyph is the +, drawn as two strokes
All-caps labels, eyebrow labels above headings, → appended to link text
Middle-dot meta strings (A · B · C)
Skeleton loaders, spinners, toasts
Scope
Login, signup, accounts, invites, onboarding flow
Backend, database, real-time sync
Music links, video, WhatsApp/FaceTime integration
Settings, profile pages, dark mode
Design tokens, header, logo mark
The component with all four states, driven by props
Now screen with the perspective toggle, wired to seed data
Add sheet with camera + emoji, committing to local state
Pairing animation
Timeline with scroll-snap
Moment detail (only if time remains)
Ship each step working before starting the next.
Name: Beside
This project was built with Lovable.
Live app: https://moment-share-square.lovable.app
Continue developing this project in the Lovable editor.
main on GitHub and your changes sync back into Lovable, ready for your next prompt.Prefer working locally? You need Node.js and npm — install with nvm.
git clone <this-repository-url>
cd <repository-name>
npm i
npm run dev