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。 以下為已儲存的摘錄。
A developer portfolio template + personal CMS. Clone it, edit one config file, deploy. Optionally connect Supabase to unlock a full admin dashboard — blog, tasks, finance, habits, learning, calendar, and more.
One config file. 56 themes. Zero lock-in.
No database. No env vars. No API keys required.
Foliokit auto-detects its mode at runtime based on environment variables.
• Reads everything from portfolio.config.ts
• No database, no auth, no backend
• Fully static-exported (output: "export")
• Deploys to GitHub Pages, Vercel, Netlify, Cloudflare Pages, or any static host檢視完整 README ↗
A developer portfolio template + personal CMS. Clone it, edit one config file, deploy. Optionally connect Supabase to unlock a full admin dashboard — blog, tasks, finance, habits, learning, calendar, and more.
One config file. 56 themes. Zero lock-in.
# 1. Clone
git clone https://github.com/akshay-bharadva/foliokit.git
cd foliokit && npm install
# 2. Configure
# Open portfolio.config.ts and replace demo values with yours.
# 3. Run
npm run dev # Dev server at http://localhost:8889
npm run build # Static export to ./out/
No database. No env vars. No API keys required.
Foliokit auto-detects its mode at runtime based on environment variables.
portfolio.config.tsoutput: "export")Set NEXT_PUBLIC_SUPABASE_URL and NEXT_PUBLIC_SUPABASE_ANON_KEY and you unlock:
/admin dashboard (20 protected routes)The public site stays statically exported — all data fetching happens client-side against Supabase.
portfolio.config.ts is the single source of truth in static mode, and the initial seed in dynamic mode.
| Section | What it controls |
|---|---|
name, title, description | Hero identity |
bio | About-page paragraphs |
logo.{main,highlight} | Two-tone header logo |
headline, proof | The home page's promise, and the results under it |
process | "How I work" steps |
product | The /kit product page and its plans |
defaultTheme | One of 56 themes |
typographyPreset | One of 14 font pairings |
portfolioMode | "multi-page" or "single-page" |
statusPanel | Right-side hero widget — minimal, terminal, or bento variant |
socialLinks | GitHub, LinkedIn, email, Twitter, etc. |
navLinks | Header navigation |
experience | Work timeline |
techStack, tools | Skills grid + tooling |
education | Education timeline |
projects | Featured projects |
showcase | Deep-dive case studies |
services | /contact offerings |
blogPosts | Static Markdown blog posts |
lifeUpdates | /updates feed entries |
updatesLayout | "timeline" or "scrapbook" |
github | Live GitHub repo fetch (filters, pagination) |
contact | Availability badge, services panel, contact form toggle |
Two parts of the config exist to sell — you, and the kit itself.
headline and proof turn the home page into a pitch: the headline
becomes the main heading with your name as the byline, and proof (up to
four figures) closes the hero as a results strip. Both are editable later in
Admin → Settings → Hero. Leave them empty and the hero leads with your
name, as before.process feeds the "How I work" section. In dynamic mode, add a section
with the Process or FAQ layout to any page from Admin → Pages.product powers /kit, a product page for Foliokit: figures counted
from the code, the workspace, a live theme preview, your plans, getting
started and an FAQ. Prices are yours to set. Set show: false to remove
/kit and the footer's "Built with" credit.56 curated themes, all CSS-variable based and each gated at WCAG AA. Visitors can switch live; your default is just the starting point.
defaultTheme: "theme-nord",
| Category | Themes |
|---|---|
| Ink (default) | theme-ink-light, theme-ink-dark |
| Dark | theme-dracula, theme-nord, theme-tokyo-night, theme-catppuccin-mocha, theme-github-dark, theme-onedark-pro, theme-rose-pine, theme-monokai, theme-ayu-dark |
| Light | theme-solarized-light, theme-catppuccin-latte, theme-github-light, theme-arctic, theme-paper |
| Special | theme-blueprint, theme-cyberpunk, theme-ocean, theme-matrix, theme-terminal |
| High contrast | theme-hc-dark, theme-hc-light |
| Neobrutalism | theme-neobrutalism-light, theme-neobrutalism-dark, theme-neobrutalism-punk |
| Glass | theme-glass-dark, theme-glass-frost, theme-glass-aurora, theme-glass-ocean |
| Retro | theme-synthwave, theme-retrowave |
Want custom colors? Dynamic mode ships a theme-custom option that takes 6 hex values and converts them to HSL at runtime.
14 font-pair presets. Set via typographyPreset in config, or live-switch in admin settings.
typo-default, typo-editorial, typo-modern-tech, typo-elegant, typo-bold-quirky, typo-futuristic, typo-classic-pro, typo-geometric
.github/workflows/next-deploy.yml handles the rest.For dynamic mode, add these as GitHub Secrets:
NEXT_PUBLIC_SUPABASE_URLNEXT_PUBLIC_SUPABASE_ANON_KEYNEXT_PUBLIC_SITE_URL (your deployed URL)Import the repo, add env vars if using Supabase, deploy. No config needed.
npm run build # Outputs ./out/
Upload ./out/ to any static host.
| Workflow | Static mode | Dynamic mode |
|---|---|---|
next-deploy.yml | Optional — builds + deploys on push to main | Required — injects Supabase secrets at build |
keep-supabase-active.yml | Auto-skipped when NEXT_PUBLIC_SUPABASE_URL is unset | Required — pings Supabase every 24h so the free tier doesn't pause after 7 days of inactivity |
Want the admin dashboard? Four steps:
.env.example to .env.local and fill in keysdb/schema.sql in the Supabase SQL editor (creates 50 tables + RLS policies + seed)assetsThen visit /admin/signup to create your admin account. You'll be prompted to enroll TOTP MFA on first login.
If a step is missing, the sign-in screen says which: without Supabase keys, or with keys but no schema, it shows the remaining steps instead of a login form. Once you're in, Get your site ready on the dashboard walks you through the rest — identity, headline, theme, links, pages, a first post, and the bucket.
Single-admin and MFA are enforced in the database, not just the client: write policies
require an AAL2 session, and a trigger on auth.users rejects further signups once an
admin exists. The client-side guard is UX, not the security boundary.
20 protected routes. The (protected) route group's layout runs the guard once
(useAdminGuard, requires AAL2 / MFA) and wraps every module in the admin shell.
| Route | Feature |
|---|---|
/admin | Dashboard overview (tasks, finance, habits, learning KPIs) |
/admin/blog | Blog post editor (Tiptap/Novel) |
/admin/content | Pages — sections + items per page, with live preview |
/admin/analytics | Visitors and what they read — no IP address stored |
/admin/inbox | Contact-form messages, with optional Discord alerts |
/admin/library | Books and articles, with highlights |
/admin/discover | Markets, the job market and the news |
/admin/life-updates | /updates feed editor |
/admin/tasks | Task manager — Kanban / Table / Tree views, sub-tasks |
/admin/finance | Income, expenses, recurring transactions, goals, monthly analytics |
/admin/habits | Habit tracker with heatmaps + streaks |
/admin/learning | Subjects, topics, timed study sessions |
/admin/calendar | FullCalendar unified view (tasks + events + habits) |
/admin/notes | Sticky-notes editor |
/admin/inventory | Personal inventory CRUD |
/admin/assets | Storage bucket browser + usage scan |
/admin/navigation | Reorder public nav links |
/admin/settings | Brand, theme, typography, hero, GitHub, contact, social, footer |
/admin/security | Lockdown level, password change, MFA unenroll |
foliokit/
├── portfolio.config.ts # YOUR CONFIG — edit this
├── next.config.js # output: "export", trailingSlash, unoptimized images
├── tailwind.config.js # Tailwind + CSS-variable theme wiring
├── .env.example # Env vars for dynamic mode
├── .github/workflows/
│ ├── next-deploy.yml # GH Pages deploy on push to main
│ └── keep-supabase-active.yml # Daily Supabase heartbeat ping
├── db/
│ ├── schema.sql # 50 tables + RLS + seed
│ └── john-doe.sample.sql # Demo persona seed
├── public/ # Static assets
└── src/
├── app/ # App Router tree (static export)
│ ├── layout.tsx # Root layout + providers.tsx
│ ├── (public)/ # Public routes, shared header/footer chrome
│ └── admin/
│ ├── (auth)/ # login, signup, setup-mfa, mfa-challenge
│ └── (protected)/ # Guard + admin shell, 15 routes
├── features/ # Feature-first UI — one folder per domain
│ │ # public: home, about, contact, blog,
│ │ # updates, sections, github
│ │ # admin: tasks, notes, habits, learning,
│ │ # calendar, finance, inventory, assets,
│ │ # content, settings, security, dashboard…
│ └── sections/ # 24 CMS layouts + markdown/list fallback
├── components/
│ ├── layout/ # Shared public + admin chrome
│ ├── admin/ # Shared admin infra (patterns, editor, spinner)
│ └── ui/ # Shadcn/Radix primitives
├── store/
│ ├── api/
│ │ ├── publicApi.ts # 10 public endpoints (no auth)
│ │ ├── adminApi.ts # Barrel — import every admin hook from here
│ │ └── admin/ # Per-feature endpoint slices + query-helpers
│ └── slices/ # Focus timer + learning session state
├── lib/
│ ├── fallback-data.ts # Maps portfolio.config.ts → mock RTK payloads
│ ├── schemas.ts # Zod schemas (form validation)
│ ├── config.ts # isSupabaseConfigured + AppConfig
│ ├── themes.ts # Runtime theme/typography application
│ └── constants.ts # Theme + typography registries, enums, limits
├── hooks/ # Custom hooks (session, mobile, theme sync…)
├── supabase/client.ts # Nullable Supabase client
├── styles/
│ ├── globals.css # Tailwind, base token scale, prose, motifs
│ └── themes.css # 56 theme + 14 typography presets (unlayered)
├── test/setup.ts # Vitest + Testing Library setup
└── types/index.ts # Central TypeScript interfaces
Tests live next to their source as *.test.ts(x).
| Command | Description |
|---|---|
npm run dev | Dev server on port 8889 |
npm run build | Production build + static export to ./out/ |
npm run start | Production server |
npm run lint | ESLint |
npm run test | Vitest, single run |
npm run test:watch | Vitest in watch mode |
npm run format | Prettier |
Run one test file with npx vitest run <path>, and filter by name with -t "<name>".
Framework: Next.js 14 (App Router, static export) · React 18 · TypeScript 5
State & Data: Redux Toolkit · RTK Query · Supabase (optional)
Forms & Validation: React Hook Form · Zod · @hookform/resolvers
Styling: Tailwind CSS · Shadcn/Radix UI · Framer Motion · class-variance-authority
Content: Tiptap + Novel (rich-text) · react-markdown · rehype-prism-plus (syntax highlighting)
Visualization: Recharts · FullCalendar
Testing: Vitest · React Testing Library · jsdom
Security: Supabase Auth · mandatory TOTP MFA · RLS on every table · rehype-sanitize on all rendered Markdown
All variables are NEXT_PUBLIC_* (the app is fully client-rendered after export).
| Variable | Required? | Purpose |
|---|---|---|
NEXT_PUBLIC_SUPABASE_URL | Dynamic mode | Supabase project URL |
NEXT_PUBLIC_SUPABASE_ANON_KEY | Dynamic mode | Anon key (RLS handles authorization) |
NEXT_PUBLIC_BUCKET_NAME | Optional | Storage bucket name, default "assets" |
NEXT_PUBLIC_SITE_URL | For builds | Canonical URL (OG tags, sitemap) |
NEXT_PUBLIC_VISIT_NOTIFIER_URL | Unused | Superseded by Analytics (see note) |
NEXT_PUBLIC_CONTACT_WEBHOOK_URL | Static only | Discord webhook — contact form (see note) |
NEXT_PUBLIC_APP_NAME | Optional | MFA app name override |
NEXT_PUBLIC_MFA_ISSUER | Optional | MFA issuer override |
Static mode requires zero env vars.
Visitor analytics.
NEXT_PUBLIC_VISIT_NOTIFIER_URLis no longer read. Visits are recorded insite_visitsand shown in Admin → Analytics, and the Discord ping for a new visitor is sent by a database trigger reading the URL fromintegration_settings(Admin → Analytics → Notifications), deduplicated to the first visit of the day per visitor. Requiresdb/migrations/008-visitor-analytics.sql. No IP address is ever stored — the trigger derivessha256(secret || current_date || ip || user_agent)and keeps only that, so unique-visitor counts are accurate within a day and the column identifies nobody.
Contact notifications. With Supabase configured,
NEXT_PUBLIC_CONTACT_WEBHOOK_URLis ignored: the ping is sent by a database trigger reading the URL from the admin-onlyintegration_settingstable, so set it in Admin → Inbox → Notifications (db/migrations/007-contact-inbox.sql). Anything prefixedNEXT_PUBLIC_is compiled into the client bundle and readable by every visitor, and a Discord webhook URL is full authority to post in that channel. Static mode has no server to hide it behind, so it still uses the variable.
Contributions welcome! The workflow:
git checkout -b feat/my-feature)For larger changes, please open an issue first to discuss direction.
MIT — use it for anything, commercial or personal.
Built with Foliokit by Akshay Bharadva. If you ship something with this, I'd love to see it.