Vache prompts. Claude codes.How it works

MagicLog: Building a Construction RFC/Submittal Tracker in 5 Days

·7 min read·by Vache Sarkissian
Updated June 3, 2026
·
Reviewed March 30, 2026
magiclognext.jsconvexconstructionfull-stackcase-study
📚Top of Funnel

Written by Claude (Opus 4.6) Vache prompted, reviewed, and published. The data and benchmarks are real; the prose is AI-generated.

Building a Construction RFC Tracker in 5 Days

MagicLog is a Next.js + Convex app for construction project document management. I prompted Claude to build it over 5 days: Excel import, PDF upload, audit trails, real-time notifications, and client-facing share links.

Status update (April 2026): The code is live but the project isn't in real use yet. My dad hasn't migrated his real project data in. This post documents the 5-day build; whether it actually replaces his spreadsheets is still TBD.

The Problem: Construction project managers track hundreds of RFCs (Requests for Clarification), submittals, and change orders across multiple projects in spreadsheets. Missing RFC deadlines can delay $40M+ builds. Missing change orders can mean $200K+ cost overruns. Spreadsheets have no audit trails, version control, or deadline alerts.

The Build: My dad, a project manager, asked if I could build something better. I opened Claude Code and went.

The Problem

Construction project management has a document tracking problem. A single hospital project generates:

  • 50–100 RFCs — questions from contractors that need architect responses within contractual deadlines
  • 200+ submittals — shop drawings, material specs, and samples that need review and approval
  • 20–50 change orders — scope changes with cost implications that need tracking through approval chains

These documents flow between architects, contractors, owners, and engineers. Each has deadlines. Each has status. Many have dollar amounts attached. When they live in Excel, things slip through the cracks.

Existing tools (Procore, PlanGrid, Bluebeam) are designed for general contractors — not architectural PMs. They're expensive, bloated, and don't match how an architect actually tracks their obligations.

The Stack

  • Next.js 15 with App Router and TypeScript
  • Convex for the real-time database and server functions
  • Tailwind CSS for styling
  • Clerk for auth (with demo mode fallback)
  • Vercel for deployment

I chose Convex because I've shipped Linesheet on it and know the patterns cold. Real-time reactivity means status changes appear instantly across tabs — no refresh needed. The mutation/query model with TypeScript end-to-end means I catch schema mismatches at compile time, not in production.

Day 1: Schema and Seed Data

The first commit was the data model. Seven tables: projects, rfcs, submittals, ccds (change orders), documents, obligations, and notifications. Every table has organizationId for multi-tenant isolation and by_org indexes.

I wrote 51KB of seed data — three realistic construction projects with varied statuses, priorities, dollar amounts, and dates. Riverside Medical Center (active, 120 days in), Pacific Plaza Office Tower (active, 100 days in), and Westbrook Library Renovation (recently completed). This isn't placeholder data — the RFCs reference real construction scenarios like "structural steel moment connection clarification" and "HVAC ductwork routing conflict at Level 3."

Good seed data is worth more than good UI early on. It exposes schema gaps, makes the dashboard feel real during development, and gives you something to demo before real data exists.

Day 2: The Big Feature Commit

Auth, CRUD, Excel import, PDF upload, notifications, and the urgency dashboard — all in one commit. Here's why that works:

Auth: Every Convex mutation starts with requireAuth(ctx) returning { userId, orgId }. Demo mode falls back to demo-org-001 when no Clerk keys are configured, gated behind an environment variable so it can't accidentally leak into production.

CRUD: Full create/update/delete for all record types with form dialogs and confirmation modals. Status and priority are editable inline — click a badge, pick from a dropdown, mutation fires immediately. No save button needed.

Excel Import: This is the killer feature for adoption. My dad's data lives in Excel. The import system:

  1. Drag-and-drop an .xlsx file
  2. Auto-detects sheet type (RFC/Submittal/CCD) from column headers
  3. Shows a column mapping UI for non-standard headers
  4. Previews the first 10 rows
  5. Validates every row against the schema
  6. Reports errors per-row with details
  7. Batch-inserts up to 500 rows

I replaced the xlsx library (which had CVEs) with ExcelJS. The column mapping is critical — every firm's spreadsheet format is slightly different.

Urgency Dashboard: Three tiers, color-coded:

  • Critical (red) — overdue items
  • Warning (amber) — due within 7 days
  • On Track (green) — everything else

The dashboard shows stats cards, project progress bars, and an activity feed. The urgency panel is what makes this useful — at a glance, you know what needs attention today.

Day 3: Audit Trail and Import Tracking

Two features that separate a toy from a tool:

Audit trail: Every mutation to an RFC, submittal, or CCD logs who changed what and when. Construction is contractual — "when did we respond to RFC-023?" is a question that comes up in disputes. The audit trail answers it.

Import tracking with undo: The saga pattern — each import gets a unique ID, a progress bar during bulk inserts, and a history page showing past imports. If you import the wrong file, you can undo the entire batch. This is the kind of feature that's invisible until you need it, and then it saves your day.

Day 4: Notifications and Search

Notifications: A cron job runs daily, checking due dates across all record types. Items due within 7 days get a notification. Overdue items get escalated. The bell icon in the header shows unread count with a dropdown. Mark-as-read, mark-all-as-read.

I built graduated urgency into the notification system — 4 tiers with anti-windup. An item that's been overdue for 30 days doesn't keep re-notifying at the same priority. It escalated once and stays there.

Full-text search: Convex's built-in search index across all record types. Filter by type, filter by project. Results link directly to the project detail page.

Day 5: Security Audit and Deploy

The last day was hardening:

  • Gated demo mode behind DEMO_MODE environment variable
  • Audited every mutation for org isolation
  • Made searchIndex.addChunk an internalMutation (not callable from clients)
  • Verified file upload ownership checks
  • Optimized search indexes with type filtering and org scoping

Then: npx convex deploy, push to GitHub, Vercel auto-deploys. The code is running — but "live" in the sense of real users using it on real projects hasn't happened yet.

What I'd Do Differently

Start with the import flow, not the CRUD. My dad's adoption path is: import existing Excel → see it rendered nicely → start making edits. The CRUD forms are secondary to the import experience. I built CRUD first because it's the natural order, but if I were optimizing for time-to-value, I'd flip it.

Mobile-first for the dashboard. The responsive design works (hamburger menu, stacking grids), but my dad checks this on his phone at job sites. The dashboard cards should be bigger touch targets with more prominent urgency indicators. That's a polish pass, not a rebuild.

The Real Lesson

The speed came from three things:

  1. Convex patterns I already knew. Tenant isolation, auth guards, batch operations, cron jobs — I've written these patterns dozens of times in Linesheet. No time spent figuring out the framework.

  2. Realistic seed data on day 1. Every page had real content to test against from the start. I never built UI against empty states and then discovered it broke with real data.

  3. Knowing when to stop. MagicLog doesn't have role-based access control, granular permissions, email notifications, or a mobile app. It has the features my dad actually needs to stop losing track of RFCs. Ship the 80% that matters, iterate on the rest.

The plan was: demo March 18, my dad imports his real project data, I find out if the column mapping is flexible enough and the urgency thresholds are calibrated right. As of April 2026 that hasn't happened yet. The code is ready; the adoption isn't. Whether a tool built in 5 days can replace spreadsheets that have (barely) worked for 20 years is still an open question.

Further Reading

Sources

About the Author

Vache Sarkissian

Building research infrastructure and products at the intersection of knowledge systems and machine learning. Creator of Linesheet Pro, vault-search, and the vachsark learning engine.

View Full Bio →
© 2026 Vache Sarkissian·Built with Claude Code
vachsark.com