A comprehensive, offline-first ISP management platform that replaces paper records and spreadsheets β organizing subscribers by hierarchical area and town, generating monthly bills with LIFO payment logic, tracking full financial ledgers, and importing/exporting Excel files with smart parsing.
π Live Demo: https://flowforgeisp.vercel.app/
- Overview
- Live Demo
- Tech Stack
- Key Features
- LIFO Billing Logic
- Role-Based Access Control
- System Architecture
- Project Structure
- TypeScript Interfaces
- Getting Started
- Usage Guide
- Excel Import Format
- Data Export
- Deployment
- Limitations & Roadmap
- Contributing
- Author
- License
- Acknowledgements
FlowForge β ISP Town Manager is a production-ready, offline-first web application built specifically for Internet Service Providers (ISPs) who still manage their subscriber base through paper records, physical ledgers, or disconnected spreadsheets. It provides a unified digital platform to organise subscribers by geographic Area and Town, run monthly billing cycles, accept payments with a psychologically-designed LIFO clearing system, and generate Excel reports β all without needing a backend server.
The application runs entirely in the browser using localStorage as its persistence layer. This makes it instantly deployable on any static host with zero infrastructure cost, while keeping all subscriber data private on the operator's device.
π‘ Real-world context: This application was built for Pakistani ISP operators who typically use informal record-keeping systems. The 4-area structure (A, B, C, D), CNIC fields, Easypaisa/JazzCash payment methods, and Mbps-based package tracking reflect actual field operator workflows. The LIFO billing logic was specifically designed around the "common man" psychological preference for clearing the current month's bill before tackling old debt.
| Environment | URL |
|---|---|
| Production (Vercel) | net-dev-jade.vercel.app |
| Repository | github.com/ibtesaamaslam/FlowForge |
| Technology | Version | Purpose |
|---|---|---|
| React | 19 | UI framework β Hooks, Context API, useReducer |
| TypeScript | 5.x (99%) | End-to-end static typing across all components and services |
| Vite | Latest | Build tool and dev server |
| Tailwind CSS | Latest | Utility-first responsive styling |
| Lucide React | Latest | SVG icon set |
| SheetJS (xlsx) | Latest | Excel .xlsx import parsing and export generation |
| localStorage | Browser API | Data persistence β no backend or database required |
| ES Modules via importmap | β | index.html-based module resolution, no complex bundler needed |
| Vercel | β | Production static hosting and CI/CD |
- 4 color-coded areas (A, B, C, D) β each area groups its own towns and tracks outstanding balances, active subscriber counts, and revenue independently.
- Full Town CRUD β create, edit, and delete towns within specific areas with confirmation prompts before destructive actions.
- Stats at a glance β every town card shows active subscriber count, total outstanding balance, and monthly revenue in real time.
- Detailed profiles β Name, Phone number, CNIC, Package speed (Mbps), Physical address, and free-text Notes per subscriber.
- Status tracking β
Active,Suspended, andDisconnectedstates with colour-coded visual badges. - Real-time search & filter β filter the subscriber list by name, phone number, subscriber ID, or status on every keystroke.
- Pagination β optimised tables handle large subscriber lists without UI performance degradation.
- Previous Pending vs Current Bill split β dues are displayed as two distinct cards: old accumulated debt (Previous Pending) and the current month's charge (Current Bill).
- LIFO payment application β payments clear the Current Month's Bill first, then reduce Previous Pending. See LIFO Billing Logic for a full walkthrough.
- Full transaction ledger β complete Debit/Credit history per subscriber in
MemberLedger.tsx. - Bulk monthly billing β generate bills for all Active subscribers in an entire area with one click via
BillingModal.tsx. - Payment receipt modals β visual confirmation showing balance before and after every recorded payment.
- Revenue tracking across all areas.
- Daily subscriber and payment metrics.
- Active subscriber utilization per area.
- Low-stock and equipment inventory alerts.
- Activity log of recent actions.
- Drag-and-drop
.xlsxfile upload with smart heuristic parsing. - Auto-detects town header rows and member data rows.
- Preview parsed data before committing β cancel or confirm.
- Bulk creates towns and subscriber profiles in a single operation.
- Download full subscriber lists and financial ledger data for any town.
- Formatted output ready for external accounting or management reporting.
The payment system uses Last-In, First-Out (LIFO) logic β the most recently generated bill is cleared before older debt is reduced.
Psychologically, subscribers feel they have "cleared this month" even with existing old debt. This reduces immediate billing disputes and makes the payment interaction feel productive β the current obligation is resolved first, even if the longer-term backlog remains visible.
Initial State:
Previous Pending β PKR 1,200 (accumulated old debt)
Current Bill β PKR 500 (February bill just generated)
Total Owed β PKR 1,700
Subscriber pays PKR 500:
LIFO applies 500 to Current Bill first
β February Bill: β
PAID (cleared)
β Previous Pending: PKR 1,200 (unchanged β visible, follow-up required)
β Total Owed: PKR 1,200
Dashboard reflects:
Outstanding: PKR 1,200
Feb billing: Completed
| Entry | Type | Amount | Description |
|---|---|---|---|
| Monthly billing run | Debit | +500 | BILL OF FEB |
| Payment received | Credit | -500 | Payment Received |
| Running balance | β | 1,200 | Previous Pending unchanged |
| Feature | Admin | Operator |
|---|---|---|
| Executive Dashboard | β | β |
| Create / edit / delete Towns | β | β |
| Add / edit / delete Subscribers | β | β |
| Record payments | β | β |
| Run bulk monthly billing | β | β |
| View full subscriber ledger | β | β |
| Excel import wizard | β | β |
| Excel / CSV export | β | β |
| View inventory / alerts | β | β |
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β BROWSER (Client) β
β β
β React 19 + TypeScript + Vite β
β β
β ββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β App.tsx β Main Routing & Layout β β
β β β β
β β DashboardView β TownView β MemberLedger β β
β β ImportWizard β BillingModal β β
β ββββββββββββββββββββββββββββ¬ββββββββββββββββββββββββββββ β
β β β
β ββββββββββββββββββββββββββββΌββββββββββββββββββββββββββββ β
β β services/ β β
β β storageService.ts ββ localStorage β β
β β excelParser.ts β .xlsx (SheetJS) β β
β β csvService.ts β .xlsx / .csv (SheetJS) β β
β ββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Architecture decisions:
- No React Router β navigation between views (Dashboard, Town, Ledger) uses a simple state variable in
App.tsxkeeping the bundle small. - Service layer abstraction β all localStorage CRUD is in
storageService.ts; components never touchlocalStoragedirectly. This makes a future database migration a service-layer swap. - ES Modules importmap β
index.htmluses a browser-native importmap for module resolution, eliminating the need for a bundler during basic development. - SheetJS for all Excel I/O β both import parsing and export generation use the same library, ensuring format consistency.
FlowForge/
β
βββ index.html # Entry point β importmap + Tailwind CDN
βββ index.tsx # React DOM root mount
βββ App.tsx # Main routing and layout logic
βββ types.ts # TypeScript interfaces β Member, Town, LedgerEntry
βββ metadata.json # App metadata (Google AI Studio template config)
βββ package.json # Dependencies and npm scripts
βββ tsconfig.json # TypeScript compiler configuration
βββ vite.config.ts # Vite build configuration
β
βββ components/ # All UI page components
β βββ DashboardView.tsx # Executive summary, charts, alerts
β βββ TownView.tsx # Subscriber list, CRUD, search, status
β βββ MemberLedger.tsx # Full debit/credit history + payment modal
β βββ ImportWizard.tsx # Drag-and-drop .xlsx upload + preview
β βββ BillingModal.tsx # Bulk monthly billing interface
β βββ (additional components)
β
βββ services/ # Business logic and data access
βββ storageService.ts # All localStorage read/write CRUD operations
βββ excelParser.ts # Heuristic-based Excel row classification
βββ csvService.ts # Excel and CSV export generation
All core data shapes are defined in types.ts and used across every component and service:
// User role
type Role = 'admin' | 'operator';
// Area identifier
type AreaId = 'A' | 'B' | 'C' | 'D';
// Full subscriber profile
interface Member {
id: string;
name: string;
phone: string;
cnic: string;
packageMbps: number;
address: string;
notes?: string;
status: 'active' | 'suspended' | 'disconnected';
totalDue: number; // running total ever owed
balance: number; // current unpaid balance
}
// Town within an area
interface Town {
id: string;
areaId: AreaId;
name: string;
members: Member[];
}
// Single ledger transaction
interface LedgerEntry {
id: string;
memberId: string;
type: 'debit' | 'credit';
amount: number;
description: string; // e.g. "BILL OF FEB" | "Payment Received" | "Clear Full Dues"
date: string; // ISO date string
previousBalance: number;
newBalance: number;
}- A modern web browser (Chrome 80+, Edge 80+, Firefox 75+)
- A local static server (Python, Node, or VS Code Live Server)
# 1. Clone the repository
git clone https://github.com/ibtesaamaslam/FlowForge.git
cd FlowForge
# 2. Install dependencies (for Vite-based development)
npm install
# 3. Start development server
npm run dev
# β http://localhost:5173
# OR serve directly without bundler (ES Modules via importmap)
# Python
python3 -m http.server 8000
# Node
npx http-server .
# β http://localhost:8000npm run build
# Output β dist/
# Deploy to Vercel, Netlify, GitHub Pages, or any static host- Open the app and select your role (Admin or Operator).
- Navigate to Area A (or any area) from the sidebar.
- Click "Add Town" and enter the town name.
- The town card appears showing 0 subscribers and PKR 0 outstanding.
- Click a town to open
TownView. - Click "Add Subscriber".
- Fill in: Name, Phone, CNIC, Package (Mbps), Address, and optional Notes.
- Set status to Active.
- Save β the subscriber appears in the paginated list.
- In
TownView, click the Credit Card icon next to a subscriber. MemberLedgeropens showing full transaction history.- The top section displays:
- Previous Pending β accumulated old debt
- Current Bill β this month's generated bill
- Click "Receive Payment" and enter the amount, or "Clear Full Dues" to zero out the balance.
- A receipt modal confirms the transaction with before/after balances.
- From the Dashboard, click an Area tile.
- Click "Run Billing" (or use
BillingModal). - Confirm the month and amount.
- The system generates a
BILL OF [MONTH]debit entry for every Active subscriber in that area.
β οΈ This permanently deletes all towns, subscribers, and ledger entries.
- Open browser DevTools (
F12). - Navigate to Application β Local Storage β your domain.
- Right-click β Clear.
- Refresh the page.
The ImportWizard uses heuristic parsing to auto-detect town headers and member rows.
| Col A | Col B | Col C | Col D |
|---|---|---|---|
| 01. My Town Name | |||
| 1 | John Doe 03001234567 | 5 Mb | 500 |
| 2 | Jane Smith | 10 Mb | 1000 |
| 02. Another Town | |||
| 1 | Ahmad Khan | 20 Mb | 2000 |
| Element | Rule |
|---|---|
| Town header | Col A starts with a number followed by a dot: 01., 02., etc. |
| Member serial | Col A is an integer |
| Name + phone | Col B contains the subscriber's name; phone number in same cell is extracted automatically |
| Package | Col C β e.g. 5 Mb, 10 Mb, 20 Mb |
| Bill amount | Col D β numeric bill amount (PKR) |
- Go to Import Excel in the sidebar.
- Drag-and-drop or click to upload your
.xlsxfile. - Preview the parsed towns and members.
- Click Confirm to create all records, or Cancel to discard.
From any TownView:
- Click the Export button in the toolbar.
- Choose
.xlsxor.csvformat. - The file downloads immediately via
csvService.ts+ SheetJS.
Exported columns: Subscriber ID Β· Name Β· Phone Β· CNIC Β· Package Β· Status Β· Balance Β· Total Due Β· Last Payment Date
The project is live at https://flowforgeisp.vercel.app/ via Vercel's GitHub integration:
- Push to the
mainbranch. - Vercel runs
npm run buildautomatically. - The
dist/output is deployed globally.
npm run build
# Netlify
netlify deploy --prod --dir=dist
# GitHub Pages
# Push dist/ to gh-pages branch
# Cloudflare Pages
# Set build command: npm run build Β· output: dist| Limitation | Impact |
|---|---|
| localStorage only | Data is device-specific; clearing browser storage deletes all records |
| No real-time sync | Two operators on different devices see different data |
| No authentication | Role selection is not password-protected in this release |
| No payment gateway | Payment recording is manual β no Easypaisa / JazzCash API |
| No SMS notifications | Subscriber reminder preference is stored but no message is sent |
| Single-device use | No cloud backup; device loss = data loss |
- Real backend β Node.js / Firebase / Supabase to replace localStorage for cross-device sync
- JWT authentication β password-protected Admin and Operator sessions
- SMS payment reminders β auto-notify subscribers before billing due date via local SMS gateway
- Easypaisa / JazzCash integration β online bill collection via mobile wallet APIs
- PWA / mobile-first β Progressive Web App for field operators collecting payments on-site
- AI demand prediction β predict churn and bandwidth demand from subscriber history
- Multi-branch support β manage multiple ISP offices under a single account
- Automated monthly billing β scheduled bill generation instead of manual trigger
# 1. Fork the repository
# 2. Clone your fork
git clone https://github.com/YOUR-USERNAME/FlowForge.git
cd FlowForge
# 3. Install dependencies
npm install
# 4. Create a feature branch
git checkout -b feature/supabase-backend
# 5. Make changes and commit
git add .
git commit -m "feat: replace localStorage with Supabase SDK in storageService.ts"
# 6. Push and open a Pull Request
git push origin feature/supabase-backendGood first contributions: Supabase backend integration, JWT authentication, dark mode toggle, additional Excel export columns, or SMS gateway connection.
MIT License
Copyright (c) 2024 Ibtesaam Aslam
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
| Permission | Status |
|---|---|
| β Commercial use | Allowed |
| β Modification | Allowed |
| β Distribution | Allowed |
| β Private use | Allowed |
| β Liability | No warranty provided |
| β Trademark use | Not granted |
- SheetJS β for the robust, battle-tested Excel parsing and generation library that powers both the Import Wizard and all export functionality.
- Lucide React β for the clean, consistent SVG icon set used throughout the interface.
- Tailwind CSS β for the utility-first CSS framework enabling rapid, responsive UI development.
- React 19 Team β for Concurrent Features and improved hook performance that make the real-time filtering and pagination smooth even on large datasets.
- Vercel β for zero-configuration static hosting with automatic GitHub deployments.
β If FlowForge helped streamline your ISP operations, please consider starring it on GitHub!
π https://flowforgeisp.vercel.app/
Replacing paper records with smart ISP management β Built with β€οΈ by Ibtesaam Aslam