Serein
Rust로 만든 가볍고 성능 좋은 Discord 전용 네이티브 클라이언트
아직 감지된 업데이트가 없습니다. GitHub 릴리스가 나오면 여기에 보입니다.
개인 계정의 공개 저장소 소유자는 GitHub로 로그인해 운영자를 확인하고 소개를 직접 관리할 수 있습니다. 관리자 승인은 필요하지 않습니다.
로그인한 뒤 확인 파일을 만들어 이 저장소의 기본 브랜치에 30분 안에 커밋해 주세요. 다른 브랜치나 포크의 파일은 인정하지 않습니다. 파일을 올린 뒤 아래에서 확인하면 관리자 승인 없이 관리할 수 있습니다. 자격을 유지하려면 파일을 남겨 두세요.
로그인이 필요하면 로그인 화면으로 이동합니다. 로그인 후 이곳으로 돌아와 원하는 확인 버튼을 다시 눌러 주세요.
프로젝트 폴더에서 /nomorevibe verify를 실행하면 소유권을 확인하고 소개를 직접 관리할 수 있습니다.
1분 만에 확인하기메이커가 쓴 소개는 위의 한 줄이 전부입니다. 더 자세한 내용은 저장소 README에서 읽을 수 있습니다. 저장소 README ↗
README 전체를 불러오는 중입니다.
README 전문 보기 ↗Turn empty tables into thriving communities.
ALongTable is a marketplace that connects restaurants with unused seating to people who want to organize or attend social events. Restaurants publish spaces, any user can book a space and create an event, and other users join by reserving a seat.
Source of truth: V0 PRD (Google Doc)
Database contract: data-model/README.md
Live app: https://alongtable.vercel.app (every push to main deploys automatically)
Lucy defined the product the build followed. Dhwani's design is what both screens implement. Amar stood up the database and the deploy, Lucas extended that database for the restaurant side, and Kemet and Lucas built the APIs on top of it. The map and the AI sit on those same flows.
npm install
cp .env.example .env.local # then fill in SUPABASE_URL and SUPABASE_SERVICE_ROLE_KEY (ask the team),
# plus ANTHROPIC_API_KEY for the AI workflows
npm run dev
npm test # unit tests for lib/ (node --test, no extra dependencies)
Database scripts (run in the Supabase SQL Editor):
supabase/seed.sql: add three restaurants plus sample spaces, events and reservations (Il Nido is left empty for the live demo). Safe to re-run.supabase/seed-history.sql (optional): give Harbor & Pine 8 weeks of past Tuesday and Thursday dinners with reservations, so /restaurant/insights shows real numbers instead of the sample. Run after seed.sql. Safe to re-run.supabase/reset.sql: wipe spaces, events and reservations before a demo run. Keeps restaurants. Run seed.sql afterwards to restore the sample data.supabase/drop.sql, then schema.sql, then seed.sql: rebuild from scratch after a schema change. Deletes all data.supabase/add-photos.sql (restaurant and event photos), then supabase/add-coordinates.sql (map pins on /events). Both are safe to re-run and keep your data; a fresh schema.sql already includes them.Two features use Claude (claude-sonnet-5-5) through the Anthropic SDK. Both need ANTHROPIC_API_KEY in .env.local (and on Vercel, where it's already set). Both follow the same rules:
components/ui/ai-tag.tsx) with a note on what the person still decides, so it's clear where the human is in the loop. Numbers worked out by code, like insights, are not tagged.Where: Host an event → Plan with AI tab (/spaces?tab=plan).
An organizer describes the gathering in plain language, e.g. "Philosophy meetup for about 8 people, Wednesday evening, somewhere quiet, under $30 each."
search_spaces tool (date range, minimum seats, max price per person, time of day) that filters listAvailableSpaces(). It searches again with looser filters if nothing matches.submit_plan with up to 3 spaces (best first, each with a one-line reason) and a drafted title, description and number of spots./spaces/[id]/create-event?title=…&description=…&capacity=…, which opens the normal create-event form prefilled. Publishing still goes through createEventForSpace().Guardrails: recommendations are dropped unless the space came back from a search; spots are capped at each space's capacity; if nothing fits (e.g. 30 people when the largest space seats 16), it recommends nothing and explains why.
| File | Purpose |
|---|---|
lib/planner.ts | Tool definitions, the tool-use loop, plan validation |
app/api/plan/route.ts | POST { request } → streamed steps, then { type: "plan" } |
app/spaces/planner.tsx, app/spaces/sample-plan.ts | The tab UI and the offline sample |
app/spaces/[id]/create-event/page.tsx | Reads title, description, capacity from the URL as starting values |
Typical run: 5–13 seconds. Estimated cost: a few cents (2–3 Claude calls of a few thousand tokens each; not measured).
Where: /restaurant/signup → Your Google Maps link. The page follows the design prototype's steps: Find your restaurant, Confirm details, Pick dates, House rules, Review and publish, then a Live screen.
maps.app.goo.gl/…) are expanded by following redirects on Google Maps hosts only. The place name and pin come from the URL itself; Maps page content is never fetched (google.com is blocked for web fetch).submit_profile tool: neighborhood, address, cuisine, price range, opening hours, seating areas, sources, and what it couldn't confirm.AREAS, SLOTS, CAPACITIES, PRICES, FEATURES). Code drops any that fall outside opening hours, in the past, or duplicate a space the restaurant already has. If hours weren't found, the suggestions are labelled as estimates.restaurants.house_rules and shown on the space and event pages.If the lookup fails, the owner can Enter my details myself (name and neighborhood; suggestions are then labelled as estimates) or Try with a sample restaurant. Both continue through the same steps. If the suggestion call fails, Pick dates still lists the open days so the owner can choose.
House rules need supabase/add-house-rules.sql on an existing database; until then sign-up skips saving them.
Only name and location are saved; cuisine, hours and the rest are used for suggestions and not stored, so the data model is unchanged. Google's busy-hours ("Popular times") data isn't available, so "quiet" times are based on opening hours and typical restaurant patterns, and the copy says so.
| File | Purpose |
|---|---|
lib/onboarding.ts | Link parsing, web research loop, spot suggestions and validation |
app/api/onboard/route.ts | POST { link } → streamed steps, then { type: "profile" } |
app/restaurant/signup/onboard-actions.ts | Server actions: register, get suggestions, publish a suggestion |
app/restaurant/signup/maps-setup.tsx, sample-profile.ts | The setup UI and the offline sample restaurant |
app/restaurant/new/page.tsx | Reads area, date, slot, capacity, price, features from the URL |
Typical run: about 25–35 seconds for research plus 5–10 for suggestions. Estimated cost: roughly 5–15 cents per sign-up, mostly from the web pages Claude reads (not measured).
/spaces?tab=plan and click an example prompt. It needs available spaces, so run supabase/seed.sql first.https://www.google.com/maps/place/The+Pink+Door/@47.6103,-122.3425,17z. Registering creates a real restaurant row, so use a test name (e.g. prefix ZZ Test) and delete it afterwards.V0 is one web app with two interfaces that demonstrates the complete booking journey. No payments and no auth: users identify themselves by name and email.
| UI | Who | Screens |
|---|---|---|
Restaurant Owner (/restaurant) | Restaurant owners | Sign up, Publish space, View spaces + booking status, Insights preview |
Landing (/) | Everyone | Landing page |
Regular User (/events, /spaces) | Anyone | Discover events, Event details, Join event, Booking confirmation, Browse spaces, Space details, Create event, Event created confirmation |
Why a real database instead of mock JSON: the PRD requires that bookings persist after a refresh, that a booked space disappears for everyone, and that a full event stops taking reservations. These checks need shared, transactional state.
main deploys).supabase/schema.sql implements the data model and is live in Supabase./restaurant/signup): register once by name and location, or sign back in with the same details. The restaurant id is kept in a cookie; /restaurant/new doesn't ask for name and location again./restaurant/new) with tile choices for area, day, time slot, seats, features and minimum spend./restaurant): only that restaurant's spaces, stat tiles, a guests chart, a calendar, a booked/open filter, and cancelling events or deleting spaces with confirmation./restaurant when signed out; step-by-step signup matching the design prototype (find, confirm, pick dates, house rules, review and publish, live); a Your next move card (lib/next-move.ts, unit-tested) and open-space days on the calendar./restaurant/insights, linked from the dashboard as See insights): fill rate, estimated sales, returning guests, a weekly chart with a simple 4-week forecast, and weekday patterns, all worked out from the restaurant's past events (lib/insights.ts, no AI). It shows clearly labelled sample data until the restaurant has hosted 8 events across 4 weeks; run supabase/seed-history.sql to demo real numbers.npm run dev write real rows; run supabase/reset.sql to clear them././spaces): listAvailableSpaces(), each with restaurant, location, date, time and capacity. Now shown on a map with the list on the right./spaces/[id]): full details and a "Book this space & create event" button./spaces/[id]/create-event): a form with title, description, number of spots (1 up to the space's capacity), and organizer name and email. It calls createEventForSpace()./events/[id]/created): a success screen with a link to the public event page.message (e.g. when someone else just booked the space) and link back to /spaces.✅ Done when: after an event is created, its space no longer appears in /spaces, the second space still does, and /restaurant shows the space as Booked.
/events): listUpcomingEvents(), each with title, description excerpt, date, time, location and "X spots left" (or a Sold out badge). Now shown on a map with the list on the right./events/[id]): full details, spots left, and a Join button that is disabled when the event is sold out./events/[id]/join): a name and email form that calls reserveSeat(). Disable the button while submitting./reservations/[code]): confirmation code, event details, and "No payment collected."message for EVENT_FULL and ALREADY_RESERVED.✅ Done when: joining moves the event from 10 to 9 spots left on the list, detail and restaurant pages, and the count is unchanged after a refresh.
The landing page (/) is the first thing judges see. It should explain the product in five seconds and send each type of visitor to the right flow.
/events (primary)/spaces/restaurantlistUpcomingEvents({ limit: 3 }), shown as cards with spots left. Each card links to /events/[id]. If there are no events yet, show "Be the first to host" linking to /spaces. This proves the page reads live data.✅ Done when: from /, a first-time visitor reaches each of the three flows in one click, and a newly created event appears in "Upcoming events" after a refresh.
Partly done: the new screens (maps, AI planner, Google Maps setup) were checked at phone width, but not every page has been reviewed, and there's no one-click reset yet.
/admin/reset page)Not run yet. Every feature it needs is built; run it end to end on the live site before the demo.
Done. Two workflows are live: the event planner for organizers and restaurant setup from Google Maps for owners. See AI workflows for how they work.
lib/)Pages call these from Server Components or server actions. They are server-only. Read functions belong inside <Suspense>.
| Page | Function |
|---|---|
/restaurant | listSpaces() (lib/spaces.ts) |
/restaurant/new | createSpace(input) (lib/spaces.ts) |
/spaces | listAvailableSpaces() (lib/spaces.ts) |
/spaces/[id] | getSpace(id) (lib/spaces.ts). Returns null if not found. Check status === "available" before showing the book button |
/spaces/[id]/create-event | createEventForSpace(input) (lib/events.ts) |
/events, landing | listUpcomingEvents() and listUpcomingEvents({ limit: 3 }) (lib/events.ts). Sold-out events are included with seatsLeft: 0 |
/events/[id], /events/[id]/created | getEvent(id) (lib/events.ts). Returns null if not found |
/events/[id]/join | reserveSeat({ eventId, name, email }) (lib/events.ts) |
/reservations/[code] | getReservation(code) (lib/events.ts). Returns { reservation, event } or null |
createEventForSpace and reserveSeat return { ok: true, data } or { ok: false, code, message }. Show message to the user. code is one of SPACE_NOT_FOUND, SPACE_NOT_AVAILABLE, CAPACITY_INVALID, EVENT_NOT_FOUND, EVENT_FULL or ALREADY_RESERVED. Unexpected database errors throw. Validate form fields (non-empty, email format) in the server action before calling.
supabase/reset.sql, then seed.sql).Payments, revenue sharing, reviews, chat, waitlists, recurring availability, guest cancellations, and auth (PRD §7). Restaurants can cancel events and delete spaces from their dashboard.
/events) and Host an event → Browse spaces (/spaces) show a map of Seattle with the list on the right (below it on phones). Tapping a pin narrows the list to that restaurant. Pins come from the Google Maps setup or from geocoding the restaurant's location (OpenStreetMap). Needs supabase/add-coordinates.sql on an existing database.