A secure laundry data-entry and reporting system for Nandlal Laundry. The app supports customer management, daily laundry entry, correction history, dynamic laundry-item reporting, CSV/PDF/print exports, and Supabase-backed authentication with server-side login rate limiting.
- Features
- Laundry Items
- Tech Stack
- Getting Started
- Environment Variables
- Database Notes
- Security and Hardening
- Reports
- Project Structure
- Available Scripts
- Deployment
- Testing Checklist
- Roadmap
- License
- β Secure Login using Supabase Auth.
- β Server-side failed-login protection with 5 failed attempts followed by a 10-minute cooldown.
- β Customer Management with customer search and customer creation from the entry screen.
- β Daily Entry Form with dynamic laundry-item quantities.
- β Dry Cleaning UI Grouping on the New Entry page to keep frequent-use items simple.
- β Duplicate Prevention for customer/date entries.
- β Correction Workflow with current-version tracking and correction history.
- β Dashboard Recent Entries updated for all current laundry-item fields.
- β All Entries Page with dynamic item columns, totals, filtering, pagination, and CSV export.
- π Daily Report
- π₯ Customer Report
- π Date Range Report
- π Change History Report
- π₯ CSV Export
- π Professional PDF Export using client-side
pdfmake - π¨οΈ Improved Browser Print Output
- π Consistent Date Format:
dd/mm/yyyy - π Consistent Timestamp Format:
dd/mm/yyyy, 10:23:18 AM
- π Supabase Auth integration.
- π‘οΈ Row Level Security-ready Supabase design.
- π¦ Server-side login rate limiting through
/api/auth/login. - π§Ύ Login attempt audit table support.
- π Security headers configured in
next.config.js. - π Server-only Supabase secret key usage.
- π« No screenshot-based PDF export path.
Laundry items are centralized through lib/laundry-items.ts and used across entry screens, dashboard, reports, CSV export, PDF export, and print.
Current item set:
| Key | Display Label | Short Label |
|---|---|---|
ironing |
Iron | Iron |
saree_ironing |
Saree Iron | Saree Iron |
gown |
Gown | Gown |
dhoti |
Dhoti | Dhoti |
coat_blazer |
Coat / Blazer | Coat / Blazer |
dry_cleaning |
Dry Cleaning | Dry Cleaning |
dress_dc |
Dress - Dry Cleaning | Dress - DC |
gown_dc |
Gown - Dry Cleaning | Gown - DC |
coat_blazer_dc |
Coat / Blazer - Dry Cleaning | Coat / Blazer - DC |
The New Entry page keeps Dry Cleaning fields collapsed by default:
- Dry Cleaning
- Dress - Dry Cleaning
- Gown - Dry Cleaning
- Coat / Blazer - Dry Cleaning
The Correction page intentionally keeps all fields visible for full correction visibility.
| Category | Technology |
|---|---|
| Framework | Next.js 16.2.7 |
| UI | React 19.2.7 |
| Language | TypeScript 5.8.3 |
| Styling | Tailwind CSS 3.4.17 |
| Backend/Auth/Database | Supabase |
| Supabase Client | @supabase/supabase-js, @supabase/ssr |
| PDF Reports | pdfmake |
| Icons | lucide-react |
| Deployment Target | Vercel |
| Runtime | Node.js 20.9+ |
- Node.js
>=20.9.0 - npm
- Supabase project
- Vercel account for deployment
git clone <your-repository-url>
cd nlde-app
npm installnpm run devOpen:
http://localhost:3000For LAN testing, use your local network IP, for example:
http://192.168.20.10:3000Create a local .env.local file:
NEXT_PUBLIC_SUPABASE_URL=your_supabase_project_url
NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY=your_supabase_publishable_key
SUPABASE_SECRET_KEY=your_supabase_secret_keyImportant:
NEXT_PUBLIC_SUPABASE_URLandNEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEYare safe for browser use.SUPABASE_SECRET_KEYis server-only and must never be exposed to client code.- Add the same variables in Vercel Project Settings for Production and Preview environments as needed.
The app uses Supabase/PostgreSQL with RLS-enabled tables.
Core tables include:
customersentriesuser_profileslogin_attempts
Important data model notes:
- Entries use
is_current_versionfor current/correction tracking. - Historical correction rows are retained.
- Only one current entry should exist per customer/date.
- All laundry item quantity columns should default to
0and be non-null. login_attemptsshould be inaccessible to browser users and accessed only by the service role from server code.
Recommended login_attempts access model:
- RLS enabled.
- No access for
anon. - No access for
authenticated. - Service role only.
The login page posts credentials to:
/api/auth/loginThe server-side route enforces:
- Safe JSON parsing.
- Email format validation.
- Server-side failed-attempt tracking.
- 5 failed attempts.
- 10-minute cooldown.
- Login attempt audit writes.
- Generic safe error handling.
The UI also includes:
- Disabled Sign In button until email/password are entered.
- Password show/hide button.
- Lockout countdown display.
Security headers are configured in next.config.js through headers().
Configured headers include:
Content-Security-PolicyX-Frame-OptionsX-Content-Type-OptionsReferrer-PolicyPermissions-PolicyX-DNS-Prefetch-ControlStrict-Transport-Securityin production mode
The CSP allows:
- Self-hosted app assets.
- Supabase HTTP/WebSocket connections.
- Local development origins.
- LAN development origin.
- Cloudflare tunnel development origin when configured.
Current API routes reviewed:
app/api/auth/login/route.tsapp/api/auth/callback/route.ts
Hardening applied:
- Auth callback uses the server Supabase client.
- Auth callback handles exchange errors safely.
- Login route has server-side validation and rate limiting.
- Audit insert/delete errors are checked.
- Server-only admin client is isolated under
lib/supabase/admin.ts.
Reports use centralized laundry item metadata and support all current item columns.
- Daily Report
- Customer Report
- Date Range Report
- Change History Report
| Format | Status |
|---|---|
| On-screen report | Supported |
| CSV | Supported |
Supported through client-side pdfmake |
|
| Browser print | Supported with improved print helper |
PDF reports are generated from structured report data using pdfmake. They are not screenshots.
Benefits:
- Sharper text.
- Selectable/searchable PDF content.
- Better table layout.
- Better page handling.
- Professional report formatting.
Browser print uses lib/printUtils.ts and supports:
- A4 landscape orientation.
- Compact mode for Change History.
- Repeated table headers.
- Better page-break behavior.
- Consistent report headers and timestamps.
app/
api/
auth/
callback/
route.ts
login/
route.ts
dashboard/
page.tsx
entries/
page.tsx
new/
page.tsx
[id]/
correct/
page.tsx
login/
page.tsx
reports/
page.tsx
components/
types/
utils/
components/
CustomerAutocomplete.tsx
layout/
ui/
lib/
auth.ts
laundry-items.ts
pdf/
report-pdf.ts
printUtils.ts
supabase/
admin.ts
client.ts
server.ts
proxy.ts
next.config.jsnpm run dev
npm run build
npm run start
npm run lint
npm run lint:fix
npm run type-checkRecommended pre-deployment check:
npm run type-check
npm run lint
npm run buildThe app is prepared for Vercel deployment.
Deployment checklist:
- Push code to GitHub.
- Import the project into Vercel.
- Add environment variables:
NEXT_PUBLIC_SUPABASE_URLNEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEYSUPABASE_SECRET_KEY
- Deploy.
- Verify security headers in browser DevTools.
- Test login, reports, PDF export, print, and rate limiting.
Note: output: 'standalone' is not required for Vercel deployment and should remain removed unless self-hosting.
Before production use, verify:
- Valid login redirects to dashboard.
- Invalid password shows remaining attempts.
- 5 failed attempts trigger 10-minute cooldown.
- Refresh does not bypass cooldown.
- Callback route redirects correctly.
- New entry saves correctly.
- Duplicate customer/date entries are blocked.
- Dry Cleaning section expands/collapses on New Entry page.
- Correction page shows all fields.
- Correction history displays correctly.
- Daily Report works.
- Customer Report works.
- Date Range Report works.
- Change History Report works.
- CSV export uses
dd/mm/yyyy. - PDF export uses
dd/mm/yyyy. - Print uses
dd/mm/yyyy. - Generated timestamp uses
dd/mm/yyyy, 10:23:18 AM.
- Vercel environment variables are set.
- Supabase Auth redirect URLs are configured.
- CSP does not block required production resources.
- Response headers are present in production.
Potential future improvements:
- Supabase Auth dashboard hardening review:
- password strength
- leaked password protection
- email confirmation/recovery settings
- CAPTCHA/Turnstile if needed
- RLS verification pass.
- Admin user management UI.
- Dashboard charts and analytics.
- Bulk entry mode.
- Database backup/export workflow.
- More granular audit logging.
- Optional direct βOpen Existing Entryβ action from duplicate-entry warning.
Distributed under the MIT License.
For internal support, contact the project maintainer.
Built with care for Nandlal Laundry.
Last Updated: June 2026
Version: 2.0.0