Commit Graph
25 Commits
Author SHA1 Message Date
asepharyana ab3a2dc456 feat: Phase 14 — hierarchical folder structure (GitHub-style nested folders)
CI / typecheck + build (turbo) (push) Canceled after 0s
- Section index pages ([section]/page.tsx): shows folder tree + flat doc list
- Folder index pages: [section]/[...slug]/page.tsx detects folder paths
  and renders subfolder + document listing instead of 404
- Sidebar tree: hierarchical grouping from flat doc slugs, folder icons (📁)
  with proper indentation per depth level
- DocForm v2: parent folder dropdown (populated from existing folders),
  slug input for leaf name, resolved path display
- Core helpers: extractFoldersForSection + classifyPath exported from @mcpedia/core
- CTF writeup reorganized: pwn-100 ret2win moved into pwn/ subfolder
- _index.md folder intro pages for ctf/ and defcon-quals-2024/
- STANDARD_KEYS includes extraFields to avoid badge duplication
2026-08-21 08:37:41 +07:00
asepharyana ceb53adba4 fix: preserve value types in extraFields (no string coercion)
CI / typecheck + build (turbo) (push) Canceled after 0s
- DocumentMeta.extraFields type -> Record<string, unknown>
- API routes pass extraFields through without JSON.stringify coercion
- CustomFieldBadges auto-styles by value type/content (number->purple, boolean->green/red, etc.)
- DocForm help text: generic (no hardcoded field examples)
2026-08-21 00:45:32 +07:00
asepharyana edbd812c30 feat: fully dynamic custom field badges (auto-style by value, not key name)
CI / typecheck + build (turbo) (push) Canceled after 0s
- CustomFieldBadges now auto-detects styling based on VALUE TYPE+CONTENT
  (number→purple points style, difficulty strings→color-coded, event-like
  strings→purple, categories→orange, status→color-coded)
- DocForm help text made generic (no hardcoded field examples)
- Removed typed CTF fields from DocumentMeta (event/challenge/etc) —
  everything flows through extraFields JSONB for true dynamic behavior
2026-08-21 00:31:36 +07:00
asepharyana c760c3c087 feat(core): dynamic custom frontmatter fields for CTF writeup metadata
CI / typecheck + build (turbo) (push) Canceled after 0s
- Add extra_fields JSONB column to documents table (migration 0003)
- CreateDocInput/UpdateDocInput: extraFields?: Record<string, string>
- parseFile: extracts non-standard frontmatter keys as extraFields
- stringifyFile: writes extraFields dynamically to YAML frontmatter
- toMeta: spreads extraFields from DB row into DocumentMeta
- DocForm: '+ Add field' UI for content creators to add any metadata
- API routes: splitPayload() separates standard vs custom fields
- Doc page: CustomFieldBadges dynamically renders any custom field
- Add db:migrate / db:push scripts + deploy workflow migration step
- Add CTF writeup template (content/writeups/ctf/template/)
- Add sample DEF CON writeup with event/challenge/category/difficulty/points
- Add @tailwindcss/typography for table rendering (prose classes)
- Add remark-gfm for GitHub Flavored Markdown table parsing
2026-08-20 23:18:57 +07:00
asepharyana 8906ed55a0 fix: add remark-gfm plugin to Markdown component for table rendering
CI / typecheck + build (turbo) (push) Canceled after 0s
react-markdown without remark-gfm doesn't parse GitHub Flavored Markdown
tables — the pipe characters were rendered as plain text instead of <table>
HTML. Fix: install remark-gfm@4 and pass it to ReactMarkdown remarkPlugins.
Also add overflow-x-auto wrapper for table responsiveness.
2026-08-20 22:39:16 +07:00
asepharyana 3938aeb38d fix(web-ui): add @tailwindcss/typography plugin to fix table rendering in docs
The Markdown component uses 'prose' classes (prose-lg prose-headings:)
but @tailwindcss/typography was not installed/registered. Tables and other
MD elements rendered unstyled. Fix: install @tailwindcss/typography@latest,
register via @plugin directive in globals.css, add custom dark-theme
table styles, and remove redundant tailwind.config.js.
2026-08-20 22:32:07 +07:00
asepharyana be9211ef21 feat(web-ui): widen main content container for better card grid layout
CI / typecheck + build (turbo) (push) Canceled after 0s
Increase max-width from 3xl to 4xl/5xl/6xl for xl screens to give the
homepage card grid and docs index more breathing room while keeping
the sidebar at 256px.
2026-08-20 21:46:55 +07:00
asepharyana d9e09dceea feat(web-ui): overhaul homepage with hero section, section overview cards, recent docs strip, and MCP info
- Hero: large headline + tagline + dual CTA buttons + search box
- Section overview: 4-column card grid with icons, descriptions, counts
- Recent documents: card grid sorted by updatedAt
- MCP info footer with server endpoint
- Consistent with docs page layout overhaul
2026-08-20 21:42:52 +07:00
asepharyana d35dd8c887 fix: remove duplicate tag display from section cards
CI / typecheck + build (turbo) (push) Canceled after 0s
2026-08-20 21:38:34 +07:00
asepharyana 44b887a9a0 fix(web-ui): remove client-side onKeyDown from server component to fix 500 on /docs
The search input's onKeyDown handler used window.location.href which is
unavailable during SSR, causing the /docs page to crash. Replaced with
a Link wrapper so it's fully server-rendered.
2026-08-20 21:34:42 +07:00
asepharyana a82af10851 fix: remove prose-lg class (typography plugin not installed) causing 500 on doc pages
CI / typecheck + build (turbo) (push) Canceled after 0s
2026-08-20 21:22:43 +07:00
asepharyana 4bbdbb9647 feat(web-ui): overhaul docs index, doc page, and sidebar with card-based layout
CI / typecheck + build (turbo) (push) Canceled after 0s
- Docs index: hero section with search bar, card grid with metadata/tags, recent strip
- Doc page: section badges, card-style related docs, improved revision history
- Sidebar: section icons, active state highlighting, better typography
2026-08-20 21:18:03 +07:00
asepharyana 050ca518c0 fix(web): Sidebar as client component (no DB during SSG)
- Sidebar.tsx is now "use client" — fetches /api/docs at runtime instead of
  calling listDocuments() during SSG (CI has no DB, causes ECONNREFUSED)
- GET /api/docs added to route.ts (returns doc list for sidebar)
- Removed SidebarContent.tsx (merged into Sidebar.tsx)
- Fixed isAuthorized double-brace typo
2026-08-20 17:06:16 +07:00
asepharyana 167d95c5e8 feat(web): full layout overhaul — Linear design system
CI / typecheck + build (turbo) (push) Canceled after 0s
Complete UI/UX overhaul, not just style changes:

Layout:
- Dark-mode-first (near-black #08090a canvas, whiteOpacity borders)
- Sticky header with brand + nav + theme toggle
- Sticky sidebar (xl+) with hierarchical doc tree
- Main content in max-w-3xl centered column
- Inter font system (via @font-face + CSS vars)
- Font feature settings cv01/ss03 for Linear-geometric Inter

Components rewritten in Linear aesthetic:
- Homepage: editorial-style doc listing with tags, section headers
- Doc page: breadcrumb-style nav links, metadata bar (author/date/tags),
  clean prose, Related + History sections
- TOC: rehype-slug heading anchors + github-slugger matching
- Create/Edit: inline form with Linear-style inputs/buttons
- Login: centered card-style, brand-indigo CTA button
- Docs index: sectioned listing with tag previews
- Search: dark-themed search with result cards + snippets
- ThemeToggle: system-default + localStorage persistence

Typography:
- prose with custom Tailwind classes matching Linear's:
  headings #f7f8f8 font-light, body #d0d6e0,
  links #7170ff with hover #828fff,
  code blocks #191a1b bg with #23252a border

New deps: rehype-slug (heading anchors), github-slugger (TOC matching)
Files: layout.tsx (overhaul), page.tsx, create/, login/, docs/,
       [section]/[...slug]/page.tsx, Sidebar.tsx, ThemeToggle.tsx,
       TOC.tsx, DocForm.tsx, Markdown.tsx, Search page
2026-08-20 16:57:30 +07:00
asepharyana 8ed8c677e8 fix(web): split PUT/DELETE into /api/docs/[...slug]/route.ts
CI / typecheck + build (turbo) (push) Canceled after 0s
Next.js App Router doesn't match DELETE/PUT on /api/docs/route.ts for
nested paths; need a dynamic segment. POST stays at /api/docs, PUT+DELETE
move to /api/docs/[...slug]. Verified DELETE works locally + via Caddy.
2026-08-20 13:38:26 +07:00
asepharyana 98437cb999 fix(web): /api/docs accepts web cookie OR x-webhook-secret (not both required)
CI / typecheck + build (turbo) (push) Canceled after 0s
Web UI login sets mcpedia_admin cookie; /api/docs/route.ts required the
x-webhook-secret header which the browser form also sends, but the dual-auth
path was brittle. Now accepts either: header (API/MCP style) OR cookie (web
login). Also set ADMIN_PASSWORD on VPS .env and restart web.
2026-08-20 13:30:22 +07:00
asepharyana 1dd16ebcba feat(web): Phase 11 UI/UX — TOC, dark mode toggle, /docs index
- Install rehype-slug (proper heading anchors) + github-slugger (matching TOC)
- TOC component: auto-generated from h2/h3 headings, clickable anchors
- Dark mode toggle: ThemeToggle (localStorage + system default), class-based
- /docs index page (lists all docs by section)
- Markdown.tsx uses rehype-slug for stable heading ids
- globals.css: @custom-variant dark (.dark class) for class-based dark mode
- layout.tsx: nav includes ThemeToggle

Note: per user instruction, installed real deps (rehype-slug, github-slugger,
@types/hast) instead of hacky inline any-cast hacks.
2026-08-20 13:21:53 +07:00
asepharyana b998826b71 chore: remove stale docs/create route (using /create instead)
CI / typecheck + build (turbo) (push) Canceled after 0s
2026-08-20 13:08:35 +07:00
asepharyana 57f90018da feat: Phase 11 — CRUD (create/update/delete) + auth + web UI
- Core: createDocument/updateDocument/deleteDocument (file + DB + revision + chunks)
- Parser: stringifyFile (serialize markdown with frontmatter to disk)
- API: tRPC CRUD routers (auth-gated via requireWriteAuth middleware)
- API: createContext now passes expectedSecret from deps (request-scoped auth)
- MCP: 3 new write tools (create_document, update_document, delete_document)
- Web: /create page + ?edit=1 form, /api/auth/login (cookie-based), /api/docs REST CRUD
- Web: Edit buttons on homepage + doc pages (auth-gated)
- Tests: 8 new tests (5 tRPC CRUD + 3 MCP CRUD auth), 40 total all green
2026-08-20 13:08:27 +07:00
asepharyana 2d974b8952 fix(web): fix doubled section prefix in doc links (404 on click)
CI / typecheck + build (turbo) (push) Canceled after 0s
Home page, search results, and doc page Related links all
generated hrefs as /${section}/${slug} but slug already
includes the section prefix (e.g. 'docs/websocket/contract'),
producing doubled URLs like /docs/docs/websocket/contract → 404.
Fix: href={`/${d.slug}`} everywhere.
2026-08-20 12:33:35 +07:00
asepharyana 8790a4f65a fix(web): render content pages dynamically so next build needs no DB
CI / typecheck + build (turbo) (push) Canceled after 0s
The home, doc, and search pages queried Postgres during SSG/static data
collection, so 'next build' failed in CI (no DB). Mark them
force-dynamic (and drop generateStaticParams from the doc page) so they
render at request time — instant at this corpus scale and build-safe
without a live database.
2026-08-19 22:56:01 +07:00
asepharyana c7697666fe fix(web): remove stray create-next-app layout.tsx (LayoutProps<'/'> removed in Next 16)
The file sat outside app/ so next build ignored it, but turbo typecheck's
tsc compiles all *.tsx and failed on the Next-15-only LayoutProps type.
The real layout is apps/web/app/layout.tsx. Deleting the dead scaffold
lets CI typecheck pass.
2026-08-19 22:46:14 +07:00
asepharyana b92f6f91fa feat(mcpedia): Phase 4 — operability + correctness hardening
Reinterpreted from the plan's YAGNI 'Scale-out' (OpenSearch/object-storage
/multi-tenant deferred at KB scale). Phase 4 = make the Phase 3 async +
revision system correct, secure, observable, deployable.

- T1 (correctness bug): restoreRevision now rebuilds semantic chunks via new
  @mcpedia/core reindexChunks(slug) so semantic/hybrid search stay consistent
  after a restore (previously document_chunks held the NEW body while
  documents.body held the restored OLD body -> stale search).
- T2 (security): /hooks/* git-sync webhooks now require x-webhook-secret header
  matching WEBHOOK_SECRET (401 otherwise); API fails fast at startup if unset.
  Added WEBHOOK_SECRET to @mcpedia/config + .env.example; set real secret in .env.
- T3 (UX): web doc page shows a History panel (revision no/reason/date/length)
  with per-revision Restore; app/api/revisions/restore/route.ts calls
  restoreRevision + revalidatePath (server-component only, no client JS).
- T4: listRevisions gains offset paging; summary never includes body.
- T5 (ops): deploy/mcpedia-api.service + deploy/mcpedia-worker.service systemd
  units (Restart=on-failure, EnvironmentFile=.env). Not auto-enabled on host.

Verified against live imrnes Redis + Postgres: turbo typecheck+build green;
restore-rebuilds-chunks (marker present -> gone after restore); webhook 401/200;
web restore route redirects to doc + reverts body; revisions API returns summary
(no body); systemd-analyze verify passes.
2026-08-19 21:54:54 +07:00
asepharyana 9397303f01 feat(mcpedia): Phase 2 — semantic + hybrid search, tRPC/Hono API
- @mcpedia/embeddings: OpenRouter provider (9router /v1, encoding_format float),
  chunkText + embedChunks; EMBED_DIM=2048
- document_chunks table (real[] embedding) — pgvector NOT available on shared
  imrnes Postgres, so cosine is computed in-app (KB-scale fine); pgvector deferred
- indexer: chunk + embed + upsert per document
- @mcpedia/search: semanticSearch (cosine) + hybridSearch (FTS+cosine RRF)
- apps/api: Hono + tRPC v11 (6 procedures), serve on :4020
- MCP: semantic_search + hybrid_search tools (6 total)
- web: keyword/hybrid toggle; .env.example + README + PHASES updated
2026-08-19 19:00:29 +07:00
asepharyana ec3a2867d4 feat(mcpedia): Phase 1 MVP — monorepo, Core, Web UI, MCP server, Postgres FTS
- bun workspaces + Turborepo monorepo (apps/web, apps/mcp; packages/*, scripts)
- @mcpedia/core single business-logic layer (Document/Content/Search services)
- @mcpedia/db Drizzle schema: documents + weighted tsvector (GIN) for FTS
- @mcpedia/parser frontmatter, @mcpedia/search Postgres FTS (ts_rank+ts_headline)
- Next.js 16 Web UI (home/doc SSG, search dynamic) + react-markdown render
- MCP server (stdio) with 4 tools + in-memory smoke test
- scripts/indexer walks content/ -> upserts into Postgres
- 4 seed docs; README + PHASES status
2026-08-19 17:40:14 +07:00