- Progressive Web App with Express + JSON backend - PIN-based auth, multi-device sync - Invoice + Statement PDF generation (branded, Grandstander + Nunito) - Mobile + Desktop responsive layouts - n8n backup integration - Custom logo upload - Settings for business info, fees, banking - Bulk invoice generation - Web Share API integration
6.2 KiB
Slim Uiltjies AfterCare — Invoice System
A beautiful, fully offline Progressive Web App for managing parents, children, invoices and payments for Slim Uiltjies AfterCare — built to match the look of the original branded receipt.
"A safe place to learn, grow and shine!"
What's included
- Parents — manage parent / guardian info (name, phone, email, address)
- Children — link learners to parents, set plan (Full Day / Half Day) and monthly fee
- Invoices — generate monthly invoices, auto-numbered (e.g.
SU-0001) - Payments — record cash / EFT / other payments, mark invoices paid
- Statements — beautiful "Statement of Payments Received" matching the original receipt
- Sharing — Share PDF via WhatsApp, email, or any app on the phone (Web Share API). Falls back to download + WhatsApp deep-link.
- PWA — installable on phone home screen, works fully offline, with custom owl mascot icons
- Backup / restore — export all data as JSON, import on any device
- Branded — cream paper background, purple primary, pink / yellow / green / blue accents, owl mascot
Run it locally
This is a static app — no build step.
# Option 1: Python (built-in on macOS / Linux)
cd /path/to/SLIMUILTIES
python3 -m http.server 8080
# Option 2: Node
npx serve -l 8080
# Option 3: Any static server
Then open http://localhost:8080 in any browser.
Tip: For PWA install + service worker to work, you need
localhostorhttps://. Plainfile://won't.
Install on a phone
Once deployed (locally or on the web):
- Open the URL in Chrome (Android) or Safari (iOS).
- Android Chrome: tap the menu (⋮) → "Install app" or "Add to Home screen".
- iOS Safari: tap the Share button → "Add to Home Screen".
The app will appear on the home screen with the owl icon and open full-screen like a native app.
Deploy to the web
Because it's 100% static, you can host it anywhere:
- Netlify: drag the folder onto app.netlify.com/drop
- Vercel:
vercel deployfrom the project folder - Cloudflare Pages: connect a Git repo
- GitHub Pages: push to a repo, enable Pages
- Any web host: upload the files via FTP
HTTPS is required for the service worker (PWA install).
Project structure
SLIMUILTIES/
├── index.html # App shell + splash screen
├── manifest.webmanifest # PWA manifest (install + shortcuts)
├── sw.js # Service worker (offline cache)
├── css/
│ └── styles.css # Design system + components
├── js/
│ ├── app.js # Router + init
│ ├── views.js # All screens (home, parents, invoices, etc.)
│ ├── invoice.js # Invoice + statement HTML render
│ ├── pdf.js # html2canvas + jsPDF wrapper
│ ├── share.js # Web Share API + WhatsApp fallback
│ ├── db.js # IndexedDB layer
│ ├── seed.js # Sample data (Slim Uiltjies example)
│ └── icons.js # Inline SVG brand mark
├── vendor/
│ ├── jspdf.umd.min.js # Vendored offline (357 KB)
│ └── html2canvas.min.js # Vendored offline (194 KB)
├── icons/
│ ├── icon.svg # SVG owl (used in manifest)
│ ├── icon-192.png # PWA icon 192×192
│ ├── icon-512.png # PWA icon 512×512
│ ├── apple-touch-icon.png # iOS install icon
│ └── favicon-32.png # Browser favicon
└── README.md
Total payload: ~600 KB (icons + CSS + JS + libs). Loads instantly after first install.
Data model (IndexedDB)
| Store | Shape | Notes |
|---|---|---|
business |
single record id='business' |
name, tagline, fees, banking, footer |
parents |
{id, name, phone, email, address, notes} |
|
children |
{id, parentId, name, plan, monthlyFee, startDate} |
indexed by parentId |
invoices |
{id, number, childId, parentId, period, items[], subtotal, total, paid, balance, status, notes} |
indexed by childId, parentId, period, status |
payments |
{id, invoiceId, date, amount, method, receivedBy} |
indexed by invoiceId |
meta |
{id, value} |
seeded flag, next receipt number |
All data lives on the device — never sent to a server. Export to JSON for backup.
How sharing works
- User taps Share PDF on an invoice.
- The invoice HTML is rendered off-screen.
- html2canvas captures it as a pixel-perfect PNG.
- jsPDF wraps the PNG into a multi-page A4 PDF.
- Web Share API opens the phone's native share sheet — user picks WhatsApp / Gmail / Telegram / print / save to drive / etc.
- If Web Share isn't available (older desktop browser), it falls back to a direct PDF download. A "WhatsApp" button also opens a
wa.medeep-link with a pre-filled message.
Default sample data
On first launch, the app seeds with realistic data:
- 3 parents: Valentine, Nomsa Dlamini, Pieter van Wyk
- 4 children: Tshireletso, Lerato, Themba, Mia (mix of Full Day / Half Day)
- Historical payments matching the original receipt (R500 / R1000 patterns)
- Current-month invoices for unpaid + paid examples
Tap Settings → Data → Load sample data to reseed anytime.
Customization checklist
Go to Settings in the app:
- Business name, tagline, address, phone, email, Facebook
- Footer message on invoices
- Default full-day & half-day fees
- Receipt prefix & auto-numbering
- Banking details (shown on every invoice)
- Payment reference note
Or edit directly in js/seed.js before deploying.
Browser support
| Feature | Required |
|---|---|
| IndexedDB | ✅ All modern browsers |
| Service Worker | ✅ Chrome, Edge, Firefox, Safari 11.1+ |
| Web Share API (files) | ✅ Chrome on Android, Safari on iOS |
| Web Share API (text) | ✅ All modern browsers |
display: standalone |
✅ Chrome, Edge, Safari, Firefox |
<input type="date"> |
✅ All modern browsers |
For older browsers, the app degrades gracefully — Share PDF falls back to download + WhatsApp link.
License
Built for Slim Uiltjies AfterCare. Use freely.