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)