Skip to content

Repository files navigation

Pipelo

A lightweight, multi-tenant CRM built for freelancers, small teams, and growing businesses. Manage contacts, visualize your sales pipeline, and keep your team aligned — without the complexity or price tag of enterprise tools.

Built as an independent SaaS product. Spanish and English supported out of the box.


Tech Stack

Layer Technology
Framework ASP.NET Core 10 — Razor Pages
Language C# 13
Database PostgreSQL 16 (Docker locally, Neon in production)
ORM Entity Framework Core 10 + Npgsql
Auth ASP.NET Core Identity
CSS Tailwind CSS 3.4
Email Resend
Payments Lemon Squeezy (Merchant of Record)
Hosting Fly.io
Local Dev Docker Compose
i18n ASP.NET Core Localization (Spanish + English)

Features

Workspace model

  • Register creates an organization — not just a personal account
  • Admin can invite team members via email
  • All members share contacts, deals, and activities within the org
  • Two roles: Admin (full control) and Member (create/edit, no settings access)

Contacts

  • Full CRUD with search, filters (by type, tag, assignee), and pagination
  • Contact types: Lead, Client, Inactive
  • Free-form tags
  • Phone number with country code selector (global coverage)
  • Detail view: linked deals, activities, and audit timeline

Sales Pipeline

  • Visual Kanban board — columns are pipeline stages, cards are deals
  • Drag & drop to move deals between stages
  • Deal detail: value (USD), expected close date, linked contact, activity log, stage history
  • Mark deals as Won or Lost
  • Pro: configurable stages (create, rename, reorder, delete)
  • Free: predefined stages (Contact → Proposal → Negotiating → Won / Lost)

Activities & Tasks

  • Types: Call, Email, Meeting, Task, Note
  • Attach to a contact, a deal, or both
  • Assign to a team member with a due date
  • Views: Today, Upcoming (7 days), Overdue, All

Dashboard

  • Pipeline value and open deal count
  • Deals won/lost this month
  • Pending activities for today
  • Recently added contacts
  • Pro: per-member breakdown, conversion rate, metrics by stage

Team management

  • Invite by email (token expires in 7 days)
  • Change member roles
  • Remove members

Billing

  • Free plan: 2 users, 100 contacts, 10 active deals
  • Pro plan: $29/month or $290/year — unlimited everything
  • Checkout via Lemon Squeezy (hosted checkout, no card data handled by the app)
  • Subscription managed via Lemon Squeezy Customer Portal
  • Webhook-driven plan updates (HMAC-SHA256 verified, idempotent)

Other

  • Transactional emails: invitations, activity assignments, daily overdue digest
  • Full i18n: language preference per user, not per org (Spanish default or browser language)
  • SEO-ready public landing page with pricing table
  • /health endpoint for uptime monitoring

Architecture

Pipelo/
├── src/
│   └── Pipelo.Web/
│       ├── Data/               # DbContext with multi-tenant query filters
│       ├── Models/             # Domain entities (Organization, Contact, Deal, Stage, Activity...)
│       ├── Pages/              # Razor Pages — one folder per feature area
│       ├── Services/           # Email, payments, plan enforcement
│       ├── Helpers/            # Country phone codes, utilities
│       ├── Resources/          # es.resx / en.resx translation files
│       └── wwwroot/            # Static assets
├── tests/
│   └── Pipelo.Tests/
├── docker-compose.yml
└── DEPLOY.md

Multi-tenancy

Every entity holds an OrganizationId foreign key. ApplicationDbContext applies a global query filter using the org_id claim injected at login — no query ever touches another organization's data without an explicit override.

Payments flow

User clicks "Upgrade" → app calls Lemon Squeezy API → redirects to hosted checkout
                                                                     ↓
                                              Lemon Squeezy fires webhook → /webhooks/lemonsqueezy
                                                                     ↓
                                              HMAC-SHA256 verified → event deduplicated → org plan updated

Local Setup

Requirements: .NET 10 SDK, Docker Desktop, Node.js 18+

1. Clone and start the database

git clone https://github.com/DMGarcia17/pipelo.git
cd pipelo
docker-compose up -d

This starts PostgreSQL 16 on port 5433.

2. Configure local settings

Create src/Pipelo.Web/appsettings.Development.local.json (excluded from git):

{
  "ConnectionStrings": {
    "DefaultConnection": "Host=localhost;Port=5433;Database=pipelo_db;Username=pipelo;Password=pipelo"
  },
  "Resend": {
    "ApiKey": ""
  },
  "LemonSqueezy": {
    "ApiKey": "",
    "StoreId": "",
    "WebhookSecret": "",
    "Variants": {
      "ProMonthly": "",
      "ProAnnual": ""
    }
  }
}

Leaving Resend__ApiKey empty is fine locally — emails are logged to the console instead.

3. Run migrations and seed demo data

cd src/Pipelo.Web
dotnet ef database update
dotnet run -- seed        # optional: populate demo org, users, contacts, deals

4. Start the app

# Terminal 1 — app
dotnet run

# Terminal 2 — Tailwind watcher
npm install
npm run css:watch

App runs at https://localhost:5001. Demo login (after seeding): admin@demo.com / Demo1234!


Environment Variables

Variable Description Required
ConnectionStrings__DefaultConnection PostgreSQL connection string Yes
Resend__ApiKey Resend API key Production
LemonSqueezy__ApiKey Lemon Squeezy API key Production
LemonSqueezy__StoreId Lemon Squeezy store ID Production
LemonSqueezy__WebhookSecret Webhook signing secret Production
LemonSqueezy__Variants__ProMonthly Variant ID for Pro Monthly Production
LemonSqueezy__Variants__ProAnnual Variant ID for Pro Annual Production
INTERNAL_API_TOKEN Bearer token for /internal/* endpoints (overdue digest cron) Production
PLAN_FREE_MAX_CONTACTS Override Free plan contact limit (default: 100) No
PLAN_FREE_MAX_DEALS Override Free plan active deal limit (default: 10) No
PLAN_FREE_MAX_USERS Override Free plan user limit (default: 2) No

In production (Fly.io), set secrets with:

flyctl secrets set LemonSqueezy__ApiKey=your_key

See DEPLOY.md for the full production setup guide (Fly.io + Neon + Cloudflare).


Roadmap

MVP (Sprints 0–10) — complete

  • Multi-tenant workspace with invitations
  • Contacts CRUD
  • Kanban pipeline with drag & drop
  • Activities and tasks
  • Dashboard and metrics
  • Freemium limits
  • Lemon Squeezy billing integration
  • Email notifications (Resend)
  • Public landing page
  • i18n (Spanish + English)

V1 — in progress

  • Lemon Squeezy store approval
  • Production deploy on Fly.io + Neon
  • End-to-end payment flow tested

V2 — planned

  • CSV import / export for contacts
  • Global search (contacts + deals + activities)
  • Saved filter views
  • REST API for external integrations
  • QuoteLab integration (auto-create quote when a deal is won)
  • Mobile app

License

Copyright © 2025 Daniel Moreno. All rights reserved.

This is proprietary software. The source code is publicly visible for reference and portfolio purposes only. You may not use, copy, modify, distribute, or deploy this software — in whole or in part — without explicit written permission from the author.

About

Multi-tenant CRM SaaS built with ASP.NET Core 8, PostgreSQL, and EF Core. Includes Kanban pipeline, contacts, deals, and billing integration.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages