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,即可驗證所有權並自行管理介紹。
一分鐘完成驗證正在載入完整 README。 以下為已儲存的摘錄。
Where teams host their work — A focused project tracker for small teams, built for hackathon PS 09.
Hostlink sits between scattered chat threads and heavyweight tools like Jira, giving teams enough structure to stay aligned without the complexity of enterprise project management software.檢視完整 README ↗Where teams host their work — A focused project tracker for small teams, built for hackathon PS 09.
Hostlink sits between scattered chat threads and heavyweight tools like Jira, giving teams enough structure to stay aligned without the complexity of enterprise project management software.
Small teams need clarity on who's doing what, when things are due, and what's ready to ship — but most tools either bury you in features you'll never use or leave you stitching updates together from Slack threads. Hostlink gives teams a shared workspace that's light enough to use daily and clear enough to trust.
Implemented:
hostlink/
├── app/ # Next.js App Router pages and API routes
│ ├── (app)/ # Main app layout group
│ │ ├── [section]/ # Dynamic routes for /my-tasks, /analytics, /team, /settings
│ │ └── projects/ # Project routes
│ │ ├── [id]/ # Project detail with [[...view]] catch-all for /board, /list, /analytics
│ │ └── page.tsx # Projects home
│ ├── api/ # API Route Handlers
│ │ ├── users/ # GET /api/users
│ │ ├── projects/ # CRUD for projects
│ │ │ └── [id]/ # Project detail, tasks, analytics
│ │ ├── tasks/ # Task CRUD, move, comments
│ │ ├── comments/ # Comment deletion
│ │ └── my-tasks/ # Personal task list
│ ├── login/ # Demo login page
│ ├── page.tsx # Marketing landing page
│ └── layout.tsx # Root layout
├── components/ # React components
│ ├── analytics/ # Chart components (burndown, completion ring, workload)
│ ├── board/ # Kanban board, columns, task cards, quick-add
│ ├── landing/ # Marketing page, login page, product preview
│ ├── layout/ # App shell, sidebar, topbar, breadcrumbs, search
│ ├── list/ # Task table, status dropdown, filters
│ ├── projects/ # Project list, cards, new project modal
│ ├── task/ # Task drawer, modal, fields, activity feed, toolbar
│ ├── ui/ # Base UI components (button, dialog, badge, etc.)
│ └── workspace/ # My Tasks, Team, Settings, Workspace Analytics
├── lib/ # Utilities and business logic
│ ├── api.ts # API client functions (calls backend routes)
│ ├── db.ts # Prisma client singleton
│ ├── hooks.ts # React hooks (useSWR wrappers)
│ ├── seed.ts # Database seed script
│ ├── store.ts # Zustand state (UI state only, domain data from API)
│ ├── types.ts # TypeScript types
│ ├── utils.ts # Utility functions (transitions, analytics, sorting)
│ └── *.test.ts # Test files
├── prisma/
│ └── schema.prisma # Database schema
├── public/ # Static assets
├── .env # Environment variables
├── package.json # Dependencies and scripts
└── README.md # This file
The database uses Prisma ORM with the following tables:
id (String, primary key)name (String)email (String, unique)role (String) — e.g. "Team Lead", "Developer", "Designer"color (String) — for avatar themingcreatedAt (DateTime)id (String, primary key)name (String)description (String, optional)color (String) — for project card/iconcreatedAt (DateTime)updatedAt (DateTime, optional)members (ProjectMember[]), tasks (Task[]), taskEvents (TaskEvent[])id (String, primary key, auto-generated UUID)projectId (String, foreign key)userId (String, foreign key)(projectId, userId)id (String, primary key)key (String, unique) — e.g. "HL-12"projectId (String, foreign key)title (String)description (String, optional)assigneeId (String, foreign key → User)priority (String) — "urgent" | "high" | "normal"status (String) — "backlog" | "in_progress" | "review" | "done"dueDate (String) — ISO date format (yyyy-MM-dd)createdAt (DateTime)movedAt (DateTime) — last status changecompletedAt (DateTime, optional) — set when status becomes "done"comments (Comment[]), events (TaskEvent[])(projectId, status), assigneeIdid (String, primary key)taskId (String, foreign key)authorId (String, foreign key → User)body (String)createdAt (DateTime)taskIdid (String, primary key)taskId (String, foreign key)projectId (String, foreign key)userId (String, foreign key → User)fromStatus (String, optional) — null for task creationtoStatus (String)createdAt (DateTime)(projectId, createdAt), taskIdCascading Deletes: Deleting a project cascades to its tasks, comments, project members, and task events. Deleting a task cascades to its comments and events.
All routes return JSON. Errors return { error: string } with appropriate HTTP status codes.
| Method | Path | Purpose |
|---|---|---|
| GET | /api/users | List all users |
| GET | /api/projects | List projects with computed stats (task count, completion %, overdue count) |
| POST | /api/projects | Create a new project |
| GET | /api/projects/:id | Get project details |
| PATCH | /api/projects/:id | Update project (name, description, color, members) |
| DELETE | /api/projects/:id | Delete project (cascades) |
| GET | /api/projects/:id/tasks | List tasks for a project (supports ?q=, ?assignee=, ?priority=, ?status= filters) |
| POST | /api/projects/:id/tasks | Create a task in a project |
| GET | /api/projects/:id/analytics | Per-project analytics (completion %, burndown, workload, overdue) |
| GET | /api/tasks/:id | Get task details with comments and events |
| PATCH | /api/tasks/:id | Update task fields (title, description, assignee, priority, due date) |
| DELETE | /api/tasks/:id | Delete task (cascades) |
| POST | /api/tasks/:id/move | Move task to new status — validates transition, updates status, stamps timestamps, creates TaskEvent. Returns 422 with { error, allowed: [...] } on invalid transitions. |
| GET | /api/tasks/:id/comments | List comments for a task |
| POST | /api/tasks/:id/comments | Add a comment to a task |
| DELETE | /api/comments/:id | Delete a comment |
| GET | /api/my-tasks?userId= | Tasks assigned to a user across all projects |
Enforced server-side in /api/tasks/:id/move:
| From Status | Allowed To |
|---|---|
| Backlog | In Progress |
| In Progress | Backlog, Review |
| Review | In Progress, Done |
| Done | Review (reopen) |
Invalid transitions return HTTP 422 with { error: string, allowed: Status[] }.
# Clone the repository
git clone <your-repo-url>
cd hostlink
# Install dependencies
npm install
# or
pnpm install
# Set up environment variables
# Create a .env file in the project root (see Environment Variables section below)
# Initialize the database
npx prisma db push
# Seed the database with demo data
npx tsx lib/seed.ts
# Run the development server
npm run dev
The app will be available at http://localhost:3000.
Create a .env file in the project root with the following variables:
| Variable | Purpose | Example Value |
|---|---|---|
DATABASE_URL | Prisma database connection string | file:./dev.db (SQLite) or postgresql://... (Postgres) |
For SQLite (default, local development):
DATABASE_URL="file:./dev.db"
For Postgres (production):
DATABASE_URL="postgresql://user:password@host:5432/hostlink?schema=public"
Note: The schema in prisma/schema.prisma supports both SQLite (provider = "sqlite") and PostgreSQL. For production deployment, change the provider to "postgresql" and update DATABASE_URL.
| Script | Command | Description |
|---|---|---|
dev | npm run dev | Start the Next.js development server (Turbopack) on port 3000 |
build | npm run build | Build the production bundle |
start | npm run start | Start the production server |
test | npm run test | Run the test suite (via tsx --test) |
typecheck | npm run typecheck | Run TypeScript type checking without emitting files |
| Prisma | ||
prisma db push | npx prisma db push | Push the Prisma schema to the database (creates/updates tables) |
prisma generate | npx prisma generate | Generate the Prisma Client |
prisma studio | npx prisma studio | Open Prisma Studio to browse and edit database data |
| Seed | ||
seed | npx tsx lib/seed.ts | Populate the database with demo users, projects, and tasks |
The project includes test files (lib/*.test.ts) that were written for an earlier in-memory implementation. These tests are currently not functional and need to be rewritten to work with the real Prisma database and API routes.
Test coverage areas (to be updated):
To run tests (once updated):
npm run test
Recommended approach for test updates:
test.db via DATABASE_URL)prisma db push before tests to initialize the schemabeforeEach hooksjest-mock-extended or vitestHostlink is optimized for deployment on Vercel (Next.js's native platform):
Push your code to GitHub/GitLab/Bitbucket
Import the project on Vercel
Set environment variables in the Vercel dashboard:
DATABASE_URL="file:./dev.db"DATABASE_URL to the connection stringUpdate prisma/schema.prisma for Postgres:
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}
Add a build command (if not auto-detected):
prisma generate && next buildnpm install (or pnpm install if using pnpm)Deploy
After deploying, seed the database:
Option 1: Via Vercel CLI
vercel env pull .env.local
npx tsx lib/seed.ts
Option 2: Create a one-time seed API route
// app/api/seed/route.ts
import { exec } from 'child_process'
import { promisify } from 'util'
const execAsync = promisify(exec)
export async function POST(request: Request) {
// Add authentication/secret check here
const { secret } = await request.json()
if (secret !== process.env.SEED_SECRET) {
return Response.json({ error: 'Unauthorized' }, { status: 401 })
}
await execAsync('npx tsx lib/seed.ts')
return Response.json({ success: true })
}
Then call POST /api/seed once with your secret, then delete the route.
Hostlink includes a "Continue as demo user" flow — no authentication required, perfect for hackathon demonstrations or trying the app.
The seeded database includes three users you can switch between:
u1u2u3All demo users are members of both projects and own various tasks.
/projects)Built for Hackathon PS 09 | © 2026 Hostlink | Demo preview — No persistent storage beyond the database