Building the operating
system for India's
freelancers.
Portly started as a question: why do the best freelancers still chase payments over WhatsApp? We set out to build the tool we wished existed — and ended up shipping a full operations platform.
India has 15 million freelancers.
Most of them run their businesses on WhatsApp and spreadsheets.
Invoice chaos
PDF invoices emailed manually, tracked in spreadsheets, chased over WhatsApp. Payment status unknown until money arrives.
Fragmented tools
One app for invoicing. Another for project tracking. A third for time tracking. None of them talk to each other.
TDS blindspots
Section 194J compliance — 10% TDS above ₹50k per client per fiscal year — is a tax landmine most freelancers discover too late.
"The best freelancers are excellent at their craft. But they're spending 20–30% of their week on operational overhead that has nothing to do with it."
— The strategic audit that started Portly
Most invoicing tools are built for the freelancer. We built Portly for the client experience first.
Most tools optimize for the person sending the invoice. Portly's core insight was different: if the client experience is frictionless, the freelancer gets paid faster, looks more professional, and builds stronger relationships.
This led to the product's defining feature: a zero-login client portal. No account creation. No password. Clients click a link, and immediately see project progress, milestone status, deliverables, and an invoice they can act on — all without touching a signup form.
That one decision shaped the entire architecture. It forced us to think carefully about security, consent, and trust — and the answers produced something genuinely different from every other tool in this space.
The zero-login decision
Clients access their project portal via a unique shareToken embedded in a URL. No account. No password. The token is stored in Firestore, validated server-side, and scoped to a single project. Access can be revoked instantly by the freelancer.
Clients see work immediately. No signup friction = no abandoned links.
Relies on token obscurity + HTTPS. Acceptable for short-term client collaboration. Token revocation gives freelancer full control.
Not an invoicing app. An operations platform.
Portly covers every layer of a freelancer's business — from first lead to paid invoice, with everything in between.
Operations Dashboard
The command centre. Every number that matters, live.
Total outstanding, cash received, overdue amount, lead-to-booking rate, on-time payment rate, repeat client count — all live.
Visualises the full pipeline: Lead recorded → Qualified → Invoice sent → Paid. Shows conversion at every stage.
Per-client payment reliability score, last contacted date, and suggested next action — all surfaced automatically.
Invoice Engine
Built for India's payment reality.
- check_circle GST toggle (18%) with auto-calculation
- check_circle Payment milestones (30/40/30 default, fully customisable)
- check_circle UPI QR code generated dynamically in invoice email
- check_circle TDS tracker (Section 194J, ₹50k threshold, Apr–Mar FY)
- check_circle Status audit trail: draft → sent → viewed → partial → paid
Zero-Login Client Portal
The feature that makes everything else matter.
- check_circle Project progress, tasks, deliverables — real-time
- check_circle Invoice with payment options embedded
- check_circle Consent-gated comments (GDPR-style privacy flag)
- check_circle Freelancer moderates comments before publish
- check_circle QR code + shareable link + instant revocation
Lead Pipeline
Kanban-style sales tracking, built for one-person teams.
- check_circle Kanban: New → Contacted → Proposal → Negotiating → Won/Lost
- check_circle Lead score (0–100), source tracking, stage history
- check_circle One-click convert lead → client → project
Time Tracker + CRM
Billable hours and client relationships, in the same place.
- check_circle Live timer with billable/non-billable flag
- check_circle Cost rate vs. bill rate per entry
- check_circle Client interaction log (meetings, calls, proposals)
- check_circle Follow-up reminders with recurrence (daily/weekly)
The decisions that made this product possible — and fast.
Architecture is strategy made concrete. Here are the choices that mattered.
Firestore REST API — not the SDK — inside Cloudflare Workers
Cloudflare Workers have a 10MB bundle size limit. The Firestore SDK alone is ~2MB. Calling Firestore via its REST API keeps the Worker lean, gives full control over error handling and retries, and eliminates SDK overhead. The trade-off: manual JWT generation and OAuth2 token exchange. Worth it.
Magic link auth — no passwords stored
When a user signs up, there's no password. An email with a 1-hour expiring link is sent. The token is SHA-256 hashed before storage — what's in Firestore is the hash, never the raw token. Single-use: verified and deleted in one transaction. Email receipt proves identity. No password database = no password breach.
Status history as an append-only audit trail
Every state change — invoice status, lead stage — is appended to a statusHistory array instead of overwriting. This gives a full audit trail: when did the invoice move from sent to viewed? Which lead sat in negotiating for 3 weeks? It's event sourcing without a separate event store.
{"{ from: 'draft', to: 'sent', changedAt: '…', source: 'manual' }"}
{"{ from: 'sent', to: 'viewed', changedAt: '…', source: 'webhook' }"}
{"{ from: 'viewed', to: 'paid', changedAt: '…', source: 'manual' }"}
]
Optimistic UI with rollback — feels instant, fails gracefully
Every user action (toggle a task, update status) updates the UI immediately before the API call completes. If the API fails, the previous state is restored and an error is shown. On Indian mobile connections with variable latency, this makes the app feel native-speed regardless of network conditions.
Idempotent operations — network timeouts can't create duplicate invoices
Every create endpoint accepts an optional idempotencyKey. If the same key is sent twice (e.g., user retried after a timeout), the existing resource is returned instead of creating a duplicate. No double invoices. No duplicate projects. The client-side generates the key; the server enforces uniqueness.
The full stack
5 automated emails. Each one earns its keep.
A live, production SaaS product — built the same way we'd build yours.
Portly is our own product, built using the same process we use for every client: strategy audit first, architecture decisions second, code last. It's not a demo. It's live at portly.online.
A MellowKraft production
← Back to MellowKraft