TreeMap
A free, open-source disk-space visualizer. Squarified treemap, duplicate hunting, disk-full forecasting, and cleanup that only ever moves files to the Trash.
翻譯準備中
尚未偵測到更新。GitHub 發布版本後會顯示在這裡。
個人 GitHub 帳號下公開儲存庫的擁有者可以登入並驗證所有權,自行管理介紹,無需管理員核准。
登入並產生驗證檔案,在 30 分鐘內將其提交至此儲存庫的預設分支。其他分支或分叉儲存庫中的檔案無效。然後在下方檢查檔案,即可無需管理員核准直接管理專案。請保留檔案以維持管理權限。
如需登入,將前往登入頁面。登入後請回到此處,再次點擊所選的驗證按鈕。
在專案資料夾中執行 /nomorevibe verify,即可驗證所有權並自行管理介紹。
一分鐘完成驗證Glowworm: a Fireflies.ai meeting-assistant clone (Next.js, FastAPI, SQLite)
翻譯準備中
取自儲存庫 README
正在載入完整 README。 以下為已儲存的摘錄。
A clone of the Fireflies.ai meeting assistant, built as an SDE Fullstack take-home: a library of past meetings, an interactive transcript synced with a (simulated) media player, AI-style notes (overview, keywords, chapters, action items), and full create / edit / delete.
Stack: Next.js (App Router), TypeScript and Tailwind CSS on Vercel · FastAPI, SQLAlchemy 2.0 and Pydantic v2 on Render · SQLite with FTS5 full-text search.檢視完整 README ↗A clone of the Fireflies.ai meeting assistant, built as an SDE Fullstack take-home. It has:
On top of that come all six bonus features, three extras (CI, speaker analytics, background processing), a responsive layout and an optional intro tour.
The API runs on Render's free tier, which sleeps when idle. The first request after a quiet spell can take up to a minute; the app shows a "waking up the server" note while it waits. A restart also resets the database to the six demo meetings.
/meetings):
/meetings/{id}):
.txt, .vtt or .json file (picked or dragged in) or pasted.openai/gpt-oss-120b) and cites timestamps you can click. Without an API key, it answers from search instead.| Layer | Choice |
|---|---|
| Frontend | Next.js 16 (App Router), TypeScript (strict), Tailwind CSS v4, lucide-react, sonner (toasts), next-themes |
| Backend | Python 3.12, FastAPI, SQLAlchemy 2.0 (sync), Pydantic v2, fpdf2 (PDF export) |
| Database | SQLite (own schema) with FTS5 full-text search |
| AI chat | Groq (openai/gpt-oss-120b) through the official openai SDK, called from the backend only |
| Hosting | Vercel (frontend) · Render (backend, render.yaml Blueprint) |
| Quality | pytest, ruff, ESLint, Prettier; GitHub Actions CI on every push and pull request |
flowchart LR
browser(["User's browser"])
subgraph vercelHost [Vercel]
fe["Next.js app<br/>App Router · TypeScript · Tailwind"]
end
subgraph renderHost [Render]
api["FastAPI on uvicorn<br/>routers → services → models"]
db[("SQLite file<br/>tables + FTS5 index")]
end
llm["LLM provider API<br/>Groq (OpenAI-compatible)"]
browser -- "1 · loads pages and JavaScript" --> fe
browser -- "2 · JSON over HTTPS to /api/* (CORS)" --> api
api -- "SQLAlchemy 2.0 (sync)" --> db
api -.->|chat only, optional| llm
llm/ is the only code that knows the AI provider's SDK.NEXT_PUBLIC_API_URL. The AI key exists only on the server.POST /api/meetings answers 202 with the meeting as processing. A background job parses the transcript and writes everything in one transaction, then marks it ready, or failed with the reason. The browser polls until it's done.You need Python 3.12 and Node.js 22.
Backend (in backend/). It serves http://localhost:8000, with docs at /docs:
python -m venv .venv
source .venv/bin/activate # Windows: .venv\Scripts\Activate.ps1
pip install -r requirements-dev.txt
uvicorn app.main:app --reload
On first start it creates app.db and seeds six demo meetings. Delete app.db to start fresh (needed after a schema change, because tables are created, not migrated).
Frontend (in frontend/). It serves http://localhost:3000:
npm install
npm run dev # use `npm run dev -- -p 3001` if port 3000 is taken
The frontend calls http://localhost:8000 by default, and the backend's default CORS settings allow ports 3000 and 3001. No .env file is needed. Without LLM_API_KEY, the chat answers from search.
| Variable | Where | Default |
|---|---|---|
DATABASE_URL | backend | sqlite:///./app.db |
CORS_ORIGINS | backend, comma-separated | http://localhost:3000,http://localhost:3001 |
LLM_PROVIDER, LLM_MODEL | backend (chat) | groq, openai/gpt-oss-120b |
LLM_API_KEY | backend only, never the frontend (chat) | unset: the chat answers from search |
NEXT_PUBLIC_API_URL | frontend, built into the bundle | http://localhost:8000 |
Sample files for every format are in backend/samples/. Try uploading offline-launch-plan.vtt.
| Format | Shape |
|---|---|
.txt | One utterance per line: [HH:MM:SS] Speaker Name: text (or [MM:SS]). Without timestamps (Speaker Name: text), times are estimated at about 150 words per minute. |
.vtt | Standard WebVTT cues. The speaker comes from <v Name> or a Name: prefix. |
.json | [{"speaker": "...", "start": 12.5, "end": 18.0, "text": "..."}], with times in seconds. |
Everyone who speaks becomes a participant. A missing title, an unknown format or an empty transcript is rejected at once (HTTP 422). A file that can't be parsed becomes a Failed meeting whose message names the line or item number.
The six demo meetings have hand-written notes. New meetings get notes from a rule-based generator (backend/app/services/summary_generator.py, no LLM):
Every route is under /api. The interactive docs at /docs show each request and response model; the full reference is ARCHITECTURE.md §7. Errors are always {"detail": "..."}, and validation errors also list each field.
| Area | Endpoints |
|---|---|
| Health | GET /health: status, SQLite version, FTS5 support, and whether an AI key is configured (never the key) |
| Meetings | GET, POST /meetings (list filters: q, participant_id, tag_id, date_from, date_to, sort) · GET, PATCH, DELETE /meetings/{id}. POST answers 202: the transcript is processed in the background. |
| Action items | POST /meetings/{id}/action-items · PATCH, DELETE /action-items/{id} |
| People and tags | GET /participants · GET, POST /tags · DELETE /tags/{id} |
| Export | GET /meetings/{id}/export?content=transcript|summary&format=txt|md|pdf |
| Search | GET /search?q=: full-text search over every transcript |
| Highlights, comments, soundbites | PUT, DELETE /segments/{id}/highlight · GET, POST /segments/{id}/comments · PATCH, DELETE /comments/{id} · GET, POST /meetings/{id}/soundbites · PATCH, DELETE /soundbites/{id} |
| Chat | GET, POST, DELETE /meetings/{id}/chat (questions up to 500 characters; 10 a minute per meeting) |
| Speaker analytics | GET /meetings/{id}/analytics |
Status codes: 200, 201 (created), 202 (create accepted), 204 (deleted), 404, 409 (a conflict, such as a duplicate tag, removing a speaker, or editing a meeting that isn't ready), 422 (invalid input) and 429 (chat rate limit).
SQLite with foreign keys enforced; SQLAlchemy creates the tables at startup. Columns, constraints, cascades and index decisions are in ARCHITECTURE.md §6.
| Table | Holds |
|---|---|
users | The default user (there's no real login). |
meetings | Title, date, duration, source, and status (processing, ready or failed) with error_message. |
participants, meeting_participants | People, shared across meetings. |
transcript_segments | The transcript lines: speaker, start and end in ms, text. segments_fts indexes them for search. |
summaries, chapters, action_items | The AI notes. |
tags, meeting_tags | Tags. |
highlights, segment_comments, soundbites | Annotations. |
chat_messages | The "Ask about this meeting" history. |
erDiagram
users ||--o{ meetings : "owns"
meetings ||--o{ meeting_participants : "has"
participants ||--o{ meeting_participants : "attends"
meetings ||--o{ transcript_segments : "contains"
participants ||--o{ transcript_segments : "speaks"
meetings ||--o| summaries : "summarised by"
meetings ||--o{ chapters : "outlined by"
meetings ||--o{ action_items : "has"
participants |o--o{ action_items : "assigned"
meetings ||--o{ meeting_tags : "has"
tags ||--o{ meeting_tags : "labels"
transcript_segments ||--|| segments_fts : "indexed by"
transcript_segments ||--o{ highlights : "highlighted in"
transcript_segments ||--o{ segment_comments : "discussed in"
meetings ||--o{ soundbites : "clipped into"
meetings ||--o{ chat_messages : "asked about in"
users ||--o{ highlights : "makes"
users ||--o{ segment_comments : "writes"
users ||--o{ soundbites : "creates"
users ||--o{ chat_messages : "sends"
Delete rules:
cd backend && pytest && ruff check . && ruff format --check . # 91 tests: parsers, notes generator, every API area
cd frontend && npm run lint && npx prettier --check . && npm run build # the build also type-checks
Continuous integration: .github/workflows/ci.yml runs on every push and pull request to main, as two parallel jobs:
ruff check, ruff format --check, pytest.engines in package.json, which Vercel also uses): npm ci, npm run lint, npm run format:check, npx next typegen, npx tsc --noEmit, npm run build.No secrets are needed: the chat tests replace the AI with a fake. The badge at the top shows the latest result.
The live app is also checked with scripted headless-browser tests, at desktop, tablet and phone sizes:
render.yaml defines one free web service:
backend/, built with pip install -r requirements.txt and started with uvicorn app.main:app --host 0.0.0.0 --port $PORT;/api/health, and Python 3.12.7;CORS_ORIGINS set to the Vercel address, and the AI provider and model.LLM_API_KEY to a Groq key. The Blueprint declares it without a value, so it's never in the repository.frontend/, and set NEXT_PUBLIC_API_URL to the Render URL, for example https://glowworm-api.onrender.com.main. Render redeploys when a push changes backend/ (its root directory), and re-applies render.yaml when that changes. CI runs alongside the deploys; it doesn't block them.get_current_user).BackgroundTasks).
backend/app/ FastAPI app: routers (HTTP) → services (rules) → models (SQLAlchemy);
parsers, notes generator, llm/ (AI client and prompt), seed data
backend/tests/ pytest suite (91 tests)
backend/samples/ example transcripts in every supported format
frontend/src/ Next.js app: app/ (routes), components/ (layout, meetings, meeting-detail,
tour, ui), hooks/ (player clock, status polling), lib/ (API client, helpers)
docs/ ARCHITECTURE.md: design, schema, API and data flows
render.yaml Render Blueprint for the backend
.github/ CI workflow (GitHub Actions)