pgx
PGX — Lightweight Postgres for AI agents. Written in Rust. Thousands of isolated databases in one runtime. 🐘
Translation pending
IQC Summary Statistics - QC Audit web app with Neon backend
Translation pending
DataHTML · JavaScriptGitHub @Hodgy007OnlineOwner unconfirmed
Have you tried it? One tap is enough. No sign-in needed.
No updates detected yet. GitHub releases will appear here.
Owners of public repositories under a personal GitHub account can sign in to verify ownership and manage the introduction themselves. No administrator approval is needed.
Sign in, generate a verification file, and commit it to this repository’s default branch within 30 minutes. Files on other branches or forks do not count. Then check the file below to manage the project without administrator approval. Keep the file to retain your access.
If needed, you will go to sign-in. After signing in, return here and press your chosen verification button again.
Run /nomorevibe verify in your project folder to verify ownership and manage the introduction yourself.
Verify in one minuteAsk about other verification options
The maker's introduction consists of the line above. Read the repository README for more details. Repository README ↗
Loading the full README.
Read the full README ↗A web-based Internal Quality Control (IQC) dashboard for clinical laboratory instruments. Import QC data from AU5800 and DxI analysers, compute summary statistics (Mean, SD, CV%, n), visualise trends with Levey-Jennings charts, and export audit-ready reports.
Admins see a Try beta switch in the header. Off is the standard app; on adds the features below. The choice is remembered per browser, and non-admin accounts never see the switch or the beta features. Exports (PDF/XLSX/CSV) are unchanged by the switch.
What's new panel — while beta is on, the front screen opens with a "New in the beta" panel listing each beta update and where to find it, plus step-by-step instructions for sigma metrics (where to enter TEa, the formula Sigma = (TEa % − |Bias %|) ÷ CV %, and how to read the result). It can be hidden (remembered per browser) and reopened from Account › What's new in the beta. Switching beta on after data is loaded shows the same list in a dialog.
Design changes in the beta:
The calculations live in public/beta-logic.js (no DOM, unit-tested directly by tests/beta-logic.test.js); the UI is public/beta.js. Both are static files, so the beta adds no Serverless Functions.
| Layer | Technology |
|---|---|
| Frontend | Vanilla JavaScript single-page app |
| Backend | Node.js serverless functions (Vercel) |
| Database | PostgreSQL (Neon serverless) |
| Auth | JWT (jose) + bcrypt password hashing |
| Charts | Chart.js 4.4 + chartjs-plugin-annotation |
| PDF Export | jsPDF + jspdf-autotable |
| Excel Export | xlsx-js-style |
| Hosting | Vercel |
iqc-summary-statistics/
├── public/
│ ├── index.html # Full SPA (HTML + CSS + JS)
│ ├── beta-logic.js # Beta QC calculations (Westgard, bias, sigma, lot comparison)
│ └── beta.js # Beta UI (admin "Try beta" toggle)
├── api/ # Every file here becomes a Serverless Function
│ ├── auth/
│ │ └── [action].js # All /api/auth/* routes (see lib/auth-routes/)
│ ├── admin/
│ │ ├── users.js # GET/PUT /api/admin/users
│ │ ├── reset-password.js # POST /api/admin/reset-password
│ │ └── activity.js # GET /api/admin/activity
│ ├── activity.js # POST /api/activity (client-side logging)
│ ├── csv-store.js # GET/POST /api/csv-store
│ ├── csv-store/
│ │ └── [id].js # GET/DELETE /api/csv-store/:id
│ ├── insights.js # POST /api/insights (AI summary, streamed)
│ ├── reports.js # GET/POST /api/reports
│ ├── reports/
│ │ └── [id].js # GET/DELETE/PATCH /api/reports/:id
│ └── setup.js # GET/POST /api/setup (init DB tables)
├── lib/ # Shared modules — NOT Serverless Functions
│ ├── auth.js # JWT verification middleware
│ ├── activity.js # Activity logging helper
│ └── auth-routes/ # Handlers dispatched by api/auth/[action].js
│ ├── login.js # POST /api/auth/login
│ ├── register.js # POST /api/auth/register
│ ├── logout.js # POST /api/auth/logout
│ ├── me.js # GET /api/auth/me
│ └── change-password.js # POST /api/auth/change-password
├── tests/
│ ├── frontend-logic.js # Extracted frontend functions for testing
│ ├── frontend.test.js # Frontend unit tests (parseCSV, computeStats, etc.)
│ └── api.test.js # API handler tests with mocked DB/auth
├── package.json
├── vercel.json # Vercel routing config
├── jest.config.js
└── babel.config.js
| Method | Endpoint | Description |
|---|---|---|
| POST | /api/auth/register | Register new user. First user auto-becomes admin. |
| POST | /api/auth/login | Authenticate and receive HttpOnly JWT cookie. |
| POST | /api/auth/logout | Clear auth cookie. |
| GET | /api/auth/me | Get current user info (requires auth). |
| Method | Endpoint | Permission | Description |
|---|---|---|---|
| GET | /api/reports | Any authenticated | List all saved reports. |
| POST | /api/reports | full_access | Save a new report. Supports compressed format (gzipped base64) or legacy uncompressed JSON. |
| GET | /api/reports/:id | Any authenticated | Fetch a specific report. Compressed data is sent to client for browser-side decompression. |
| PATCH | /api/reports/:id | full_access | Append data chunks to an existing report (legacy chunked upload support). |
| DELETE | /api/reports/:id | full_access | Delete a report (cascades to report_chunks). |
| Method | Endpoint | Permission | Description |
|---|---|---|---|
| GET | /api/admin/users | admin | List all users. |
| PUT | /api/admin/users | admin | Update user status (approved/denied/pending) or permission (view_only/full_access). |
| GET | /api/admin/activity | admin | Fetch activity log (supports limit and offset query params). |
| Method | Endpoint | Permission | Description |
|---|---|---|---|
| POST | /api/activity | Any authenticated | Log a client-side action (data_process, export_pdf, export_xlsx, export_csv, data_clear, point_remove, point_restore). |
| Method | Endpoint | Description |
|---|---|---|
| GET/POST | /api/setup | Initialise database tables (reports, users, activity_log, report_chunks). Adds compressed_data column if missing. Cleans up empty/broken reports. |
Semicolon-delimited with 13 columns:
Protocol;Instrument;Parameter;Level;Date;Value;Target;SD;Status;Message;Comment;User;SampleId
Example:
TestProto;AU5800 1 L;Glucose;1;01/03/2025 08:00;5.5;5.0;0.3;Accepted;OK;;user1;SAMPLE1
AU5800 1 L -> AU/DxI-1)| Role | Status | Permission | Capabilities |
|---|---|---|---|
| admin | approved | full_access | All features + user management panel |
| user | approved | full_access | Import, export, save/load/delete reports |
| user | approved | view_only | Import, export, view reports (no save/delete) |
| user | pending | - | Cannot access dashboard until approved by admin |
| user | denied | - | Access denied |
The first registered user automatically becomes admin with full_access.
| Variable | Description |
|---|---|
DATABASE_URL | Neon PostgreSQL connection string |
JWT_SECRET | Secret key for signing JWT tokens |
# Install dependencies
npm install
# Set environment variables
export DATABASE_URL="postgresql://..."
export JWT_SECRET="your-secret-key"
# Initialise database tables
# Visit /api/setup or POST to it after deploying
# Deploy to Vercel
vercel
npm test
Tests run in Europe/London time (set in tests/global-setup.js) so date handling is exercised across BST.
Reports use a compressed storage approach to handle large datasets within Vercel's 4.5MB body size limit:
CompressionStream API, then base64-encodedcompressed_data TEXT columnDecompressionStreamfilters.removedPoints and listed in the PDF exportA typical 25MB dataset compresses to ~2-3MB for storage. The serverless function pre-warming strategy eliminates cold start delays (~45s reduced to ~1.5s).
The app is configured for Vercel with:
public/index.html served as the SPA for all non-API routesapi/ directory auto-deployed as serverless functionsmaxDuration: 60 in vercel.json)vercel.jsonThe Hobby plan allows a maximum of 12 Serverless Functions per deployment.
Exceeding it fails the deploy with exceeded_serverless_functions_per_deployment
after the build reports success, so a green build log is not proof of a
successful deploy — check the deployment state.
Every .js file under api/ counts as one function, including files that are
only ever imported by others. Shared code therefore lives in lib/ (outside
api/), and the five /api/auth/* routes are served by the single dispatcher
api/auth/[action].js.
Current count: 11 of 12. Before adding a file under api/, check the count:
find api -name "*.js" -type f | wc -l
To add a route without spending a slot, add a handler in lib/ and dispatch to
it from an existing route.