A lightweight, client-side budget justification verifier for research administrators. No backend, no build step — hosted on GitHub Pages.
- Upload a budget justification (
.docx) and its spreadsheet (.csv/.xls/.xlsx) to catch mismatches before you submit. - AI labels every dollar value, matches it against the spreadsheet, and groups discrepancies by root cause.
- A guided chat walks you through each finding — confirm it, explain it away, or click "Ignore Issue" to skip it.
- The justification and spreadsheet are shown side-by-side with the chat, with flagged values highlighted and auto-tracked as you go.
- Ends with a plain-language summary and a downloadable marked-up copy of the justification with flagged values highlighted.
- Drag-and-drop uploads, an animated scan → label → match → audit → summarize progress sequence (full technical log available via "Expand Analysis Details"), and a "How It Works" walkthrough for first-time users.
- "Try it out!" at the end of the walkthrough launches a guided, sample-document run-through of the whole Verifier flow, with on-screen arrows pointing to what to click next. Exit it at any time.
- API keys are stored only in your browser's
localStorage— a warning reminds you to check your key's data-sharing terms before use.
| Concern | Library |
|---|---|
| Spreadsheet parsing | SheetJS |
| Word document parsing | Mammoth.js |
| AI generation | Gemini API (structured JSON output) |
| Word document generation | docx (built programmatically) |
| Verifier progress animation | anime.js (CDN) |
| Settings & review-chat persistence | Browser localStorage |
justintime/
├── index.html # SPA shell
├── css/
│ └── styles.css
├── js/
│ ├── app.js # Boot, tab routing
│ ├── settings.js # Settings tab + localStorage CRUD
│ ├── generator.js # Generator workflow orchestration
│ ├── parser.js # SheetJS parsing + source-of-truth extraction
│ ├── api.js # Universal API adapter: Gemini direct (standalone) or Vandalizer proxy (DGX-hosted)
│ ├── schemas.js # Full JSON schemas per template type + VerifierSchemas
│ ├── sections.js # Section registry: ordered section definitions per template
│ ├── verifier.js # Portable two-step verification core: Verifier.run(text, csv, key)
│ ├── verifier-tab.js # Verifier tab UI: file handling, orchestration, results rendering
│ ├── verify-anim.js # Animated scan/label/match/audit/summarize progress sequence
│ ├── verifier-chat.js # Chat-driven findings review, persists/resumes via localStorage
│ ├── highlighter.js # DOCX markup: injects <w:highlight> into flagged runs via JSZip
│ ├── doc-preview.js # Live in-browser justification preview
│ ├── sheet-preview.js # Live in-browser spreadsheet preview
│ ├── document.js # docx output + download trigger
│ └── try-it-tutorial.js # Guided "Try it out!" sample-document walkthrough
├── templates/
│ └── nsf.txt # Reference: NSF section layout and field definitions
└── examples/ # Sample justification + spreadsheet used by "Try it out!"
DGX / Vandalizer deployments: AI calls route through the
/api/apps/generateproxy automatically. No Gemini API key needed.
Just-In-Time uses the Gemini API when running standalone. A free key is available through Google AI Studio — no billing required for standard use.
Get a key:
- Go to aistudio.google.com and sign in with any Google account.
- Click Get API key in the sidebar, then Create API key.
- Copy the generated string.
Security note: Treat this key like a password. Never commit it to a public repository.
Configure it in Just-In-Time:
- UI (recommended): Settings tab → paste into Gemini API Key → Save API Key. Stored in
localStorage, never leaves your device. - Environment variable (local backend use): add
GEMINI_API_KEY=your_actual_api_key_hereto a.envfile in the project root.
No build step. Open index.html directly, or serve the directory:
npx serve .Push to main — GitHub Pages serves index.html from the repository root automatically.
- Go to the Verifier tab.
- Upload a budget justification
.docxand its spreadsheet. - Click Verify Budget.
- Work through the chat that opens for each flagged finding — confirm, dismiss, or ignore it.
- Review the summary and download the marked-up document.
Behind the scenes: values are labeled, matched against the spreadsheet, audited, and grouped by root cause before the chat opens. On DGX/Vandalizer deployments, large documents are processed in batches of 25 automatically; direct Gemini API calls batch at 50+ values to avoid truncation on very large documents.