A single-page app for building queries, applying filters, reviewing results, and exporting to Excel — all without leaving the browser. Designed to work against any compatible backend.
| Feature | What it gives you |
|---|---|
| Bubble builder | Browse and select fields by category, apply filter conditions |
| Form mode | URL-driven guided forms for focused reporting workflows |
| Query history | Live status tracking — reload, rerun, cancel, or inspect past runs |
| Query templates | Save, categorize, pin, search, and reapply reusable query setups |
| Query JSON | Inspect the exact payload being sent to the backend |
| Post filters | Apply result-only filters without sending them to the backend |
| Results table | Virtualized large-table rendering with resize, sort, post-filter, and Excel export support |
| Mobile workflow | Responsive panels, mobile menu controls, and smoke-tested overlays |
The default view. Browse fields by category or search by name, then select fields to add them to your output. Click any active field to open a filter condition panel — supports equals, contains, between, before/after, starts with, and more.
Tracks every query run in the session with live status badges: running, complete, failed, and cancelled. Completed queries can be reloaded or rerun; running queries can be cancelled mid-execution. The history panel polls for live status updates and keeps the last 50 queries in memory.
Templates let users save reusable query configurations, organize them into categories, pin high-value reports, and reload them later. Template editing is integrated with the same query-state and validation flow used by the live builder.
Shows the structured JSON payload for the current query. Useful for debugging filter logic or copying the spec for reuse.
A URL-driven mode for guided workflows. Pass a JSON spec via the ?spec= parameter (raw JSON, URL-encoded, or Base64URL) to generate a focused input form instead of the full bubble builder. A form spec can define:
- title and description
- default query name
- fixed output columns
- editable inputs — text fields, dropdowns, multi-value inputs, or hidden fields
- locked filters the user cannot change
- optional limited view, which forces form mode and hides the JSON and history buttons
Results render in a virtualized table that only draws the visible viewport plus an overscan buffer for smooth performance with large datasets. Export to Excel with the download button — multi-value fields can be rendered as stacked lines in one cell or expanded into separate numbered columns using the split-columns toggle.
The table also supports sorting, expand/collapse layout, manual column resizing with live row/header alignment, a draggable scrollbar thumb, and post filters that only affect the loaded result set. Post filters are intentionally client-side and are cleared between query runs.
| Path | Purpose |
|---|---|
bubbles/ |
Bubble rendering and interaction logic |
core/ |
Query execution, state management, service facades, and shared utilities |
filters/ |
Field definitions and filter/payload logic |
history/ |
Query history rendering, request mapping, status grouping, and detail overlays |
table/ |
Result rendering, virtual scrolling, drag/drop, post filters, and Excel export |
table/drag-drop/ |
Column drag/drop, duplicate column restoration, and resize coordination |
table/virtual-table/ |
Virtualized result rendering, column layout, scrollbar, and sort helpers |
table/post-filters/ |
Client-side post-filter UI and comparison logic |
table/export/ |
Excel export workflow |
templates/ |
Query template rendering, categories, draft state, and template models |
ui/ |
App shell UI, modals, toasts, tooltips, and shared helpers |
ui/form-mode/ |
Form-mode shell, controls, spec parsing, URL sharing, and query sync |
ui/field-picker/ |
Shared field picker modal and search ranking |
styles/ |
Feature-based CSS |
styles/app.css |
Stylesheet entrypoint that imports the feature CSS files |
config/ |
Shared architecture contracts for forbidden browser globals and module boundaries |
docs/ARCHITECTURE.md |
Frontend architecture notes, quality gates, and refactor plan |
tests/architecture/ |
Architecture fitness and module-specifier checks |
tests/unit/ |
Focused pure-logic unit tests |
tests/browser/ |
Playwright browser smoke coverage |
- Static HTML, CSS, and vanilla JavaScript — no build step required
- Native browser ES modules with
"type": "module"in Node tooling - Feature-oriented folder structure with ES modules, explicit dependency registration for cross-feature services/actions, and enforced module boundaries
- ESLint, architecture fitness checks, and Playwright browser smoke tests
- Tailwind CSS and AutoNumeric are loaded from CDNs in
index.html - ExcelJS for Excel export
Install dependencies once:
npm installServe the project directory with any static server, then open the app through that server rather than directly from the filesystem:
python3 -m http.server 4173Then open:
http://127.0.0.1:4173/index.html
The backend URL currently configured in core/backendApi.js is a temporary example/testing integration. It is useful for demonstrating the request/response shape during development, and the Playwright smoke test stubs that route so local validation does not require a real external service.
The public live site should not rely on that example API as its production data source. We plan to remove project-owned API usage from the live deployment. For real use, connect your own compatible query API and provide the API URLs/settings for your environment. The app is designed around a swappable backend contract: field metadata, query execution, status/cancel, history results, and template actions can be backed by your own service as long as it returns the expected payloads.
Until runtime API settings are added to the hosted UI, local deployments can point the app at another service by updating core/backendApi.js. The intended live-site flow is to let users supply their own API URLs/configuration instead of using the checked-in example endpoint.
See docs/ARCHITECTURE.md for module boundaries, runtime flow, quality gates, and the remaining compatibility layer.
npm testRuns lint, architecture fitness checks, module-specifier checks, focused unit tests, and desktop/mobile browser smoke tests.
Individual checks:
npm run lint
npm run test:architecture
npm run test:modules
npm run test:unit
npm run test:browserThe browser smoke test starts a local static server, stubs the backend API, and covers desktop plus mobile flows: panel layout, dark/light search inputs, virtual-table scrolling and resize behavior, post filters, zero-result queries, export overlays, and mobile dialogs.
- Cleaner backend contract layer to make integrations easier to swap
- Continue splitting the remaining large legacy modules into smaller feature modules
- Add focused unit tests for form-mode schema parsing and query-state lifecycle edge cases