TreeMap
무료 오픈소스 디스크 사용량 시각화 도구로, 사각형 트리맵·중복 파일 탐색·디스크 가득 예측·정리 시 파일을 휴지통으로만 이동한다
아직 감지된 업데이트가 없습니다. GitHub 릴리스가 나오면 여기에 보입니다.
개인 계정의 공개 저장소 소유자는 GitHub로 로그인해 운영자를 확인하고 소개를 직접 관리할 수 있습니다. 관리자 승인은 필요하지 않습니다.
로그인한 뒤 확인 파일을 만들어 이 저장소의 기본 브랜치에 30분 안에 커밋해 주세요. 다른 브랜치나 포크의 파일은 인정하지 않습니다. 파일을 올린 뒤 아래에서 확인하면 관리자 승인 없이 관리할 수 있습니다. 자격을 유지하려면 파일을 남겨 두세요.
로그인이 필요하면 로그인 화면으로 이동합니다. 로그인 후 이곳으로 돌아와 원하는 확인 버튼을 다시 눌러 주세요.
프로젝트 폴더에서 /nomorevibe verify를 실행하면 소유권을 확인하고 소개를 직접 관리할 수 있습니다.
1분 만에 확인하기README 전체를 불러오는 중입니다. 아래는 저장된 발췌입니다.
Find the time everyone is actually free, then fill it with something worth doing.
Waddle is a small web app with no build step. A group shares one link; each
person marks when they're busy — by hand or by importing a calendar — and the
planner shows the windows where everybody is free, ranked longest first. The
group collects ideas, votes on them, and pencils in a plan with its own time
votes and RSVPs. Around that: friends, a "free now" status, per-friend control
over what of your calendar they see, and a public booking link.README 전문 보기 ↗Find the time everyone is actually free, then fill it with something worth doing.
Project context and running to-do list: PROJECT.md. For the full feature inventory, see BLUEPRINT.md; for public launch requirements, see LAUNCH_READINESS.md.
Waddle is a small web app with no build step. A group shares one link; each person marks when they're busy — by hand or by importing a calendar — and the planner shows the windows where everybody is free, ranked longest first. The group collects ideas, votes on them, and pencils in a plan with its own time votes and RSVPs. Around that: friends, a "free now" status, per-friend control over what of your calendar they see, and a public booking link.
No build step and no frontend framework. The browser code has no dependencies; the server uses one npm package (@vercel/og draws link-preview cards), so run npm install once before the tests.
npm install # once: the server's npm package
npm run dev # http://localhost:4173
npm test # unit and API tests
npm run test:e2e # browser tests in headless Chromium (see below)
npm test && npm run test:e2e # everything, before calling a change done
npm run dev serves the static files and the /api handlers, so the app
behaves the same locally as it does deployed. Without database credentials it
runs in demo mode: a sample workspace, with your changes kept in this browser.
npm run test:e2e runs test/e2e/app.e2e.mjs, a Playwright suite that starts
its own dev server on a free port, drives headless Chromium through the main
flows and stops the server afterwards: the group view, proposing and voting on
a plan and RSVPing, painting My availability, connecting and disconnecting
Google Calendar (browser token and server sync), making an event private in
Who sees what, the Free now strip, booking and cancelling on a public booking
page, cancelling as the owner, the activity bell, a friend's calendar, each
Who sees what level as the friend sees it (Nothing, Busy, Picked, Everything, a
per-friend override, the group level, and sharing more for a while), sharing
choices following you to another device, sending and accepting a friend
request, Settings (lock, export, reset), the phone day strip, saving a usual
week, creating, renaming and switching groups, the getting-started checklist,
inviting and removing people, repeating plans, adding a plan to a calendar
(the .ics file and the Google link; Google itself is never opened), ideas with
photos, your profile, adding an ICS link, best-time cards, setting up a
booking link, the sign-in gate, the offline shell and install, the Friends
page with a request by phone number, signing in with a texted code, a 1-on-1
with a friend, organization groups, always-busy hours, a few layout checks,
and phone and dark-theme smoke tests. Any page error fails the test.
It adds no dependency: it uses Playwright from PLAYWRIGHT_PATH
(default /opt/node22/lib/node_modules/playwright/index.mjs) or an installed
playwright package, and skips every test with a message when neither is
there. Nothing reaches the network: sign-in is fake-supabase.js, and Google
and /api/book are stubbed. The setup is shared with the agent driver in
.claude/skills/run-hangout-planner/ (session.mjs).
| File | What it does |
|---|---|
index.html | The whole UI. Every dynamic region is an empty container the app renders into. |
app.js | State, rendering and interactions. Loaded as an ES module. |
booking-owner.js | Your side of a booking link: set it up, share it, see and cancel bookings. |
book.html, book.js | The public booking page at /book/<handle>, for guests without an account. |
sw.js, manifest.webmanifest | The home-screen app: installable, and opens offline from its cached shell. |
lib/planner.js | Dates, overlap detection and state validation — shared by the browser and the API. |
lib/ics.js | A small iCalendar reader (recurrence rules, exceptions, all-day events). |
lib/membership.js | Decides which member row is you, so nobody ends up in a group twice. |
lib/friends.js | Friend requests: what belongs in each list, and the database calls. |
lib/calendar-export.js | Turns a pencilled-in plan into an .ics file or a Google Calendar link. |
lib/hangout.js | A plan's time votes, repeats and RSVPs. |
lib/groups.js | The "Your groups" list, and unguessable links for new groups. |
lib/sharing.js | Who sees what of your calendar: levels, picked and private events, time-limited shares, and the filtered copies friends get. |
lib/booking.js | Booking links: working hours across time zones, open slots, and the calendar files guests and owners get. |
lib/presence.js | "Free now": how long a status lasts. |
lib/sync.js | When a saved calendar is due for a refresh, and whether a refresh changed anything. |
lib/checklist.js, lib/appearance.js, lib/palettes.js, lib/avatar.js, lib/pwa.js | The getting-started steps, theme and colour choices, profile photos, and install prompts. |
Each member carries two kinds of availability:
Mondays 9–12). It applies to every
week you haven't touched, so a workspace stays useful without constant upkeep.A member who has shared neither is unknown for that week rather than free, so "everyone is free" never quietly includes somebody who simply hasn't answered. The group grid shows three states: everyone free, some free, and busy.
There are three ways, and none of them can put the same person in a group twice:
If a friend you add is already in the group under a name somebody typed by
hand, Waddle offers to link that row to their account instead of adding
a duplicate. The rules for all of this live in lib/membership.js and are
covered by tests.
Each group lives at its own link (/?w=book-club-7fq2x). Your groups (in
the sidebar, or tap the group name at the top) lists every group you've opened
on this device and, when you're signed in, every group your account belongs
to on any device. Start a new group there: the link gets a random code on
the end, so nobody can find your group by guessing its name.
Set a tentative plan (or Plan this on an idea) pencils something in without locking anyone into a date. The plan card lists the group's best free times; people vote on them with the heart, and anyone can pick one. Once a time is picked, everyone answers Going, Maybe or Can't make it. A plan can repeat every week, every 2 weeks or every month: after each date it rolls on to the next by itself, keeping its wall-clock time across daylight-saving changes, and each date gets its own RSVPs.
.ics address under Calendar
links — for Google, that's Settings → your calendar → Secret address in
iCal format. Saved links refresh by themselves every time you open
Waddle, or come back to the tab, if the last refresh is over 30 minutes
old. A refresh that finds nothing new saves nothing.My calendar shows your own week with every event name, from all the calendars you've connected. Only you see it: the names are kept in this browser, and only what the choices below allow ever leaves it.
Who sees what decides what leaves, per audience:
| Level | What they get |
|---|---|
| Nothing | Can't open your calendar at all |
| Busy / free only | When you're busy, never what |
| Only events I pick | Names of the events you tapped in My calendar; the rest read "Busy" |
| Everything | Every event name |
calendar_shares, one row per
friend), which row level security lets only them read. Open a friend's
calendar from Friends → Calendar.sharing_settings) and
follow you to every device; whichever device changed them last wins.Friends don't need a group. Friends in the sidebar sends requests by email or phone number (someone without an account sees it when they first sign in with that address or number), lists your friends, opens their calendar (as much as they chose to show you) with the hours you're both free, and adds them to the current group in one tap. 1-on-1 opens a two-person space with that friend for plans, time votes and RSVPs. Both of you land in the same space: its link is made from your friendship's id, which only the two of you can read, and it is locked to the two of you. I'm free tells your friends you're free for an hour, 2 hours or the rest of today; friends who are free show in the Free now strip on the home screen.
When you start a group you pick Friends or Organization or business (a club, team or workplace). An organization group only ever shows free and busy: event details can't be switched on, and names and places are stripped every time the group is saved, by the server too. Settings → Group type changes it later.
Always busy in the sidebar blocks the same hours every week in one go: quick adds for work (Mon–Fri 9–5), school and sleep (11 pm–7 am, overnight), or your own days and times. Groups, friends and your booking link see those hours as busy, never the label. The rules are saved with your sharing choices, so they follow you to your other devices and every group you open.
Google, or your phone number: Waddle texts a one-time code (Supabase Auth
signInWithOtp). Phone sign-in needs the Phone provider turned on in Supabase
with an SMS provider such as Twilio; until then the app says it isn't
switched on yet.
Booking link in the sidebar gives you one public page (/book/<handle>)
for anyone outside your groups. Guests need no account and only ever see open
times. You choose the days and hours (or only the times you pick), meeting
length, gap between meetings, notice and how far ahead. When Keep my
calendar's busy times blocked is on, open times skip:
Bookings show in the same dialog, where you can cancel them, and a private calendar feed puts them in your own calendar app. Guests get a calendar file and a cancel link on screen. When the server has email set up (DEPLOY.md step 5), guests also get a confirmation email with that link, you get a notice for each new booking, and both of you hear about cancellations. The booking page tells guests which of the two they'll get.
/?w=<slug>. Opening one needs a Google sign-in: without a
valid token the API answers 401 and returns nothing about the group, and the
app shows a sign-in screen instead. Anyone signed in with the link can join.
The demo group (weekend-crew) stays open so people can try the app./book/<handle>) never need an account on the booker's side.Every change renders immediately, then saves. A save carries the revision it
read; if somebody else saved first, the change is re-applied on top of their
version and retried rather than overwriting it. If the network is down, the
change stays in local storage and the header reads OFFLINE.
GOOGLE_CLIENT_ID / GOOGLE_CLIENT_SECRET, it keeps
Google's refresh token (encrypted) so syncing continues past the hour and on
every device you sign in on; without them the browser reads it directly for
about an hour.Groups only need the workspaces table. Accounts, friends, sharing, free now
and booking links need the rest of supabase/schema.sql.
See DEPLOY.md for hosting, database and Google sign-in setup.
supabase/rls-test.sql checks the friend-request policies against a real
database.api/_supabase.js | Shared by the handlers: reads the database settings and checks sign-in tokens. Not an endpoint. |
api/_email.js | Booking emails through Resend, off until configured (see DEPLOY.md). Not an endpoint. |
api/workspace.js | Loads and saves the shared workspace, with validation and conflict detection. |
api/groups.js | Lists a signed-in person's groups, so the list follows them between devices. |
api/calendar.js | Fetches a calendar feed server-side, with the guards an inbound URL needs. |
api/google.js | Keeps Google Calendar syncing past Google's one-hour limit, and answers booking links' free/busy checks (optional; see DEPLOY.md). |
api/book.js | Open slots, bookings and cancellations for booking links, the owner's bookings feed, and booking emails when set up. |
supabase/schema.sql | Every table, policy and function: workspaces, profiles, friend_requests, calendar_shares, sharing_settings, presence, booking_pages, bookings and google_tokens. Safe to run again. |
supabase/rls-shares-test.sql | Proves only you can write your calendar shares and only that friend can read them. |
supabase/rls-test.sql | Proves the friend-request policies hold; runs in a transaction and rolls back. |