All projects

Project management SaaS for freelancers

Knoxt.io

A full-stack freelancer project management SaaS for managing clients, collaborative projects, Kanban tasks, notes, project knowledge, notifications, and deployment-ready workflows.

Solo: product, fullstack, DevOps04/2026 – 07/2026SaaS14 tools
knoxt.io.vn
Knoxt.io landing page introducing its documentation-first project workspace

01 · The problem

Context

Freelancers keep client work in a CRM, a task board, a notes app, and chat, all at once.

Decisions and requirements get lost in chat threads, nothing links a client to the tasks and notes about them, and inviting a client into a tool usually means giving them access to everything.

02 · What I built

  1. 01Modelled one workspace where clients, projects, Kanban tasks, notes, and project knowledge link to each other (27 PostgreSQL models).
  2. 02Designed a GraphQL API (84 operations) on NestJS + Prisma, inside a Turborepo monorepo with shared types and UI packages.
  3. 03Built project-level roles (Viewer, Editor, Admin, Owner) checked on the backend, with email invitations.
  4. 04Added Project Memory (decisions, meetings, action items, requirements) so project context lives longer than a chat thread.
  5. 05Shipped through CI/CD: lint, type-check, tests, Docker build, Trivy scans, and a SHA-verified VPS deploy.
Client CRMProject RBACKanban boardHierarchical notesProject MemorySecure sharingNotificationsCI/CD

03 · Decisions & trade-offs

Order keys for Kanban drag-and-drop

Each task stores a fractional order key, so moving a card updates one row instead of renumbering every task in the column.

The backend decides permissions

The UI hides or disables controls by role, but the server re-checks every mutation. Hiding a button isn't security.

Version numbers on notes

A save with an outdated expectedVersion is rejected instead of silently overwriting a teammate's edit.

Public links stored as hashes

Share links use random tokens that are stored only as hashes, so a database leak doesn't hand out working links.

04 · Inside the product

Architecture

Monorepo designed for product growth

The codebase separates product apps from reusable packages so the React SPA, NestJS API, Prisma schema, shared types, and UI utilities can evolve without turning into one large application folder.

  • apps/web for the React product surface
  • apps/api for the NestJS GraphQL API
  • packages/database, types, config, ui, graphql, and utilities

Customers

Client CRM connected to delivery work

Freelancers can keep customer records close to the projects, notes, and delivery context they belong to, instead of treating contacts as a disconnected address book.

  • CRUD customer profiles with email, phone, company, and status
  • Soft delete, pagination, detail pages, and related project lists
  • Customer links across projects and notes for better context

Collaboration

RBAC, invitations, and Kanban in one workflow

Project membership is enforced in the backend and reflected in the UI, while Kanban interactions stay fast through order keys instead of rewriting every task after drag-and-drop.

  • Viewer, Editor, Admin, and Owner permissions
  • Invitation token flow with SMTP and in-app notifications
  • Custom columns, assignment, tags, priorities, and due dates

Notes

A workspace for structured project knowledge

The notes module works like a lightweight project wiki with hierarchy, rich editing, search, recovery, and secure sharing, so delivery decisions do not disappear into chat threads.

  • Parent-child note trees with drag-and-drop movement
  • TipTap rich-text editing, autosave, tags, pins, and breadcrumbs
  • Permission sharing, subtree sharing, and hashed public links

Memory

Project Memory for decisions and follow-up

Knoxt.io separates reusable delivery knowledge from ordinary task tracking by modeling decisions, meetings, action items, requirements, and activity history.

  • Decision logs with reason, impact, and lifecycle status
  • Meetings with summaries, recording URLs, and participants
  • Action items and requirements with filters, search, and task conversion

Quality

Production pipeline with security gates

The deployment path checks code quality, database schema safety, tests, Docker images, secrets, dependencies, and server SHA before production is updated.

  • 72 backend test cases verified in the reviewed environment
  • Dependency audit, Trivy secret scan, and container scan
  • Fast-forward VPS deployment with health checks

05 · Who can do what

PermissionViewerEditorAdminOwner
View project
Edit tasks and notes
Invite members
Manage roles
Delete project

06 · Release pipeline

Nothing reaches the server without passing every step.

  1. 1Install with frozen lockfile
  2. 2Prisma validate and generate
  3. 3Lint and type-check
  4. 4Run automated tests
  5. 5Build Docker images
  6. 6Trivy security scan
  7. 7SHA-verified VPS deploy

07 · Screens

Knoxt.io project knowledge sharing with member roles and a public read-only link
Knoxt.io project knowledge sharing with member roles and a public read-only link
Knoxt.io hierarchical document workspace with rich-text and Markdown editing
Knoxt.io hierarchical document workspace with rich-text and Markdown editing
Knoxt.io DevOps Roadmap project overview and drag-and-drop Kanban board
Knoxt.io DevOps Roadmap project overview and drag-and-drop Kanban board

08 · Result

What changed

  • Live at knoxt.io.vn.
  • 72 backend test cases passing across 23 test files.
  • Every deploy passes quality and security gates before it reaches the server.

What I'd keep doing

  • “Drawing monorepo boundaries that still make sense as the product grows.”
  • “Building SaaS permissions that the backend enforces, not just the UI.”
  • “Using tests and good DX to keep complex flows readable.”

09 · Engineering notes

The detailed version, for engineers who want the specifics.

ArchitectureMonorepo and backend domain structure
  • Organized the system as a pnpm/Turborepo monorepo with apps for web and API plus reusable packages for database, shared types, configuration, UI, GraphQL, and utilities.
  • Split backend domains around authentication, users, customers, projects, tasks, notes, project knowledge, notifications, and AI sessions.
  • Used a resolver-service-repository flow for selected domains, injecting repository interfaces through tokens so business logic stays testable and less coupled to Prisma.
SecurityAuthentication, validation, and authorization
  • Implemented email/password authentication with bcrypt cost factor 12, JWT authentication, Passport guards, and Google ID token verification on the backend.
  • Linked Google accounts to existing users by email and automatically accepted pending project invitations after signup or Google login.
  • Added global validation that strips unknown fields, rejects undeclared input, transforms payloads, validates environment variables at startup, and hides internal GraphQL errors in production.
CollaborationProjects, members, invitations, and Kanban
  • Built project CRUD with active, on-hold, completed, and archived states, customer linking, date tracking, recent notes, pinned notes, attachments, and soft delete.
  • Implemented Viewer, Editor, Admin, and Owner roles with the backend as the source of permission truth and frontend controls hidden or disabled based on role.
  • Developed a drag-and-drop Kanban board with custom columns, assignment, due dates, tags, priorities, task modal create/edit flows, and orderKey-based sorting to avoid rewriting every task on reorder.
NotesHierarchical note workspace and secure sharing
  • Built independent and project/customer-linked notes with parent-child hierarchy, drag-and-drop movement, TipTap rich-text editing, tables, task lists, Markdown support, and autosave.
  • Added optimistic concurrency through version and expectedVersion values to detect conflicting note updates.
  • Supported pinning, tags, case-insensitive search, breadcrumbs, fullscreen editing, soft delete, trash restore, attachment metadata, direct sharing by viewer/editor permission, subtree sharing, and secure public links that store only hashed random tokens.
KnowledgeProject Memory for decisions and delivery context
  • Modeled structured project knowledge with decision logs, meetings, action items, requirements, activity logs, and role-based access.
  • Supported meeting summaries, recording URLs, internal or external participants, action item owners, due dates, status tracking, and conversion from action item to Kanban task.
  • Added unified search and filters across decisions, meetings, requirements, status, priority, and date ranges.
QualityTesting, CI/CD, and production readiness
  • Added tests for auth service, project authorization, project service, task service and repository, ordering algorithm, notes, note sharing, Project Knowledge, health checks, SMTP invitation template, Kanban board, Project Memory UI, auth context, and landing page.
  • Verified 72 backend test cases passing in the reviewed environment, with the logging suite blocked by sandbox network binding rather than business assertions.
  • Built a GitHub Actions pipeline for frozen dependency install, Prisma validation and client generation, Docker Compose validation, lint, type-check, test coverage, builds, tracked-file cleanliness, dependency audit, Trivy secret scanning, image scanning, and SHA-verified VPS deployment.
Clean Architecture-style service/repository splitGraphQL code-first API designJWT and Google OAuth authenticationFractional ordering for drag-and-drop tasksOptimistic concurrency with note versioningHashed public share tokensSoft delete and restore workflowsPrisma migrations and PostgreSQL indexingDocker multi-stage production buildsTrivy dependency, secret, and container scanning

Stack

React 18TypeScriptViteReact RouterApollo ClientGraphQLTailwind CSSMaterial UINestJSPrismaPostgreSQLDockerNginxGitHub Actions

Next case study

Ballot Survey & voting platform

Knoxt.io case study | Bui Thuy Ngoc