Transcendence.site: Technical Case Study

Role: Designer, architect, and sole developer
Status: Live in production
URL: transcendence.site
Stack: Django · PostgreSQL · Docker Compose · Jitsi · DocuSeal · Stripe · GatewayAPI · Matomo · Nginx · Cloudflare


Overview

Transcendence is a privacy-focused online platform for hypnotherapy and cognitive behavioural work. It is not a brochure site with a contact form attached. The platform handles client onboarding, signed therapeutic agreements, session booking, payment, private video sessions, structured reflection tools, therapist-side client management, appointment reminders by email and SMS, public taster-session booking, and subject access request fulfilment, as a coherent, integrated system.

The project was designed and built from scratch, by a single developer, for a privacy-sensitive professional context. Every decision was made against two constraints that pull in opposite directions: the system must be capable enough to replace a scattered collection of third-party tools, and it must handle sensitive health data with the discretion that work requires.

At a glance


Why It Was Built

Private therapy work can easily fragment across generic video tools, commercial form builders, external signing services, payment links, reminders and email threads. That makes the workflow harder to manage and spreads sensitive context across too many places.

Transcendence replaces that scatter with a controlled workflow: one system, defined boundaries, auditable state, and no third-party advertising or behavioural profiling in the therapeutic workflow.


Technical Stack

Application Framework: Django

Django was chosen initially because it is a robust, easy-to-code Python framework for server-rendered applications, with built-in support for models, forms, authentication, admin workflows and migrations.

That made it a good fit for a workflow-heavy system with client state, agreements, payments, session access, reminders and therapist-side administration. Django's conventions also gave AI-assisted development a safer structure to work inside: models, forms, views, templates, permissions and migrations all had established places to live.

A PHP/MySQL implementation would have been technically possible for a simpler brochure-style site. For this system, with state transitions, permission rules, webhook callbacks and cross-service coordination, Django/PostgreSQL provided the better fit.

Database: PostgreSQL

The data is relational and stateful. Clients, bookings, agreements, payments, sessions, and reflection records all carry relationships, constraints, and dependencies that need reliable transactional behaviour. PostgreSQL fits that model cleanly. Django's migration system supports controlled schema evolution over time.

MySQL or MariaDB would have been the obvious alternative. PostgreSQL was the stronger choice for several concrete reasons: pgcrypto, used here for PGP symmetric encryption of therapy notes, is a PostgreSQL-native extension with no direct MySQL equivalent. Transactional DDL means schema migrations can be rolled back cleanly if something goes wrong, which matters in a system where client data is live. PostgreSQL's reputation for correctness and constraint enforcement over raw speed reflects the right set of priorities for a system handling sensitive health records.

Deployment: Docker Compose

The platform is deployed via Docker Compose on a Linux server. Docker provides a repeatable, auditable way to manage the application alongside its supporting services: database, signing system, analytics, video infrastructure, and reverse proxy, with clear separation between them. It also makes the difference between development and production environments legible and controllable.

Version control is via Git with GitHub as the remote. Deployment is a straightforward pull-and-restart workflow: changes are committed locally, pushed to GitHub, pulled onto the production server, and services restarted via Docker Compose. Ansible was considered at the outset and prototyped, but for a single-server deployment of this scale it added process overhead without meaningful operational benefit. Removing it kept the deployment path simple, auditable, and operable without additional tooling or abstraction.

Reverse Proxy and TLS: Nginx Proxy Manager / Cloudflare

TLS termination and routing are handled by Nginx Proxy Manager, which manages certificate provisioning and renewal, upstream routing, and header forwarding without requiring manual Nginx configuration. Cloudflare sits in front for DNS and a small number of edge rules. The combination means this layer required minimal setup and has needed little attention since, which is the intended outcome.

Video Sessions: Jitsi (self-hosted)

Private one-to-one sessions run over Jitsi, self-hosted. The decision not to use Zoom or Teams was deliberate: commercial video platforms process session metadata under their own terms of service. A practitioner cannot reasonably tell a therapy client that their session data passed through a third-party commercial infrastructure stack. Self-hosting closes that gap. Session access is tied to booking and client state within the platform.

Document Signing: DocuSeal (self-hosted)

Therapy requires signed agreements before work begins: informed consent, therapeutic agreements, preparation forms. DocuSeal provides the e-signature workflow; Django records agreement state and receives webhook callbacks to update the platform accordingly. Self-hosting means signed client documents do not leave the practice's own infrastructure. The integration keeps agreement completion part of the coherent onboarding workflow rather than a detached manual process.

Payments: Stripe

Session fee collection is handled through Stripe. Stripe manages PCI-DSS compliance for card processing; no card data touches the application server. The Django platform tracks payment state, session access, and package status internally. The payment system connects to booking state, client access rules, and taster session flows.

Appointment Reminders: GatewayAPI / Infomaniak

SMS appointment reminders are dispatched via GatewayAPI; email via Infomaniak. Clients control which reminder types they receive from their account settings. Reminder dispatch state is recorded per client to prevent duplicate sends and support operational review. Both services sit behind a thin integration layer and could be swapped without changes to the core application logic.

Analytics: Matomo (self-hosted)

Usage analytics are collected via a self-hosted Matomo instance. No Google Analytics, no Meta Pixel, no third-party behavioural data. Page view and interaction data stays on infrastructure the practice controls, is not profiled against individuals, and is not shared or sold. This is the only analytics setup consistent with a privacy policy that means what it says.

Frontend

The frontend is server-rendered Django templates. The UI is built on Bootstrap 5 for layout and components, with jQuery present primarily to satisfy django-mfa2 dependencies and support a small number of interaction patterns. Flatpickr handles date and time picking in booking flows. These are loaded from CDN with subresource integrity hashes.

Site-specific styling is held in a consolidated CSS file built on top of Bootstrap, using CSS custom properties for palette, spacing and typographic scale. The CSS was developed with AI assistance and then refined through browser testing. Custom JavaScript is minimal and purposeful: cookie banner handling, session countdown, arrival state and form sequence unlocking. There is no frontend build pipeline; assets are versioned by query string. The visual identity, including logotype and colour palette, was developed as part of the project.


Security Architecture

Security is treated as part of the product, not as decoration applied after deployment.

The platform is built around:

The distinction between security and privacy matters here and is treated as such. Security asks whether unauthorised people can access data. Privacy asks whether the data should be collected or stored at all. Both questions need answers; they are not the same question.


Privacy by Design

Privacy is a structural principle, not a compliance statement added at the end.

Design choices that follow from this:

The platform is designed to support therapy rather than measure engagement for its own sake.


What Was Deliberately Not Built

Restraint is part of the design. The platform does not aim to become:

These decisions were made explicitly and held under pressure as scope temptation arose during development. The goal is therapeutic usefulness, not maximum feature surface.


Development Approach

The project was developed feature by feature using a method closer to feature proving than formal test-driven development. Features are built, run, and verified through actual end-to-end workflows rather than unit assertions in isolation.

A typical proving cycle for a new feature covers:

This approach is necessary for a system where a single user action crosses Django, Stripe, DocuSeal, Jitsi, email, browser session handling, and reverse proxy configuration simultaneously. It is not a substitute for automated regression coverage; that is identified as future work, with priority on the highest-risk state transitions.


Operational Lessons

A system that looks straightforward on a whiteboard earns its complexity in production. Areas that required careful attention:

The real work of a project like this is not writing the first version of a feature. It is making the feature survive contact with browsers, proxies, certificates, containers, users, and the general operational friction of a running system.


AI-Assisted Development

AI tooling was used as a development assistant throughout the build, using GPT-5 chat throughout, with Claude used agentically at the end of the project. The assistance covered architecture discussion, Django model design, form logic, template iteration, deployment debugging, webhook handling, CSS refinement, and documentation drafting.

AI was not treated as authoritative. All code and configuration required human review, adaptation, and verification before use. This was especially true for authentication flows, payment handling, signed document workflows, database migrations, and anything touching production deployment or client privacy.

In practice, AI tooling reduced the distance between idea and working feature. It did not remove the need for systems judgement, particularly in a domain where the cost of a poorly considered decision is not a broken UI element but a breach of therapeutic trust.


Backup and Operational Housekeeping

Scheduled operations are managed via cron, with each job logging to a dedicated directory. Nightly encrypted backups cover the database, application configuration, media and supporting service state, with offsite replication and healthcheck reporting.

Operational housekeeping runs as Django management commands on the live container rather than as raw shell or SQL jobs. Held appointment slots expire automatically. Scheduled account closures are processed on a defined cadence. DocuSeal artefacts are pruned after seven days, enforcing at the operational layer the same data minimisation principle stated in the privacy policy.

Appointment reminders run with flock-based concurrency control, ensuring overlapping cron invocations cannot produce duplicate sends. The crontab reflects the same design discipline as the application: clear boundaries, logged outcomes, and no assumption that things will simply work without being watched.


Future Work

Identified development priorities include:


Summary

Transcendence.site is a full-stack Django application for a privacy-sensitive professional context, deployed on self-managed Linux infrastructure via Docker Compose, integrating a suite of self-hosted and carefully selected external services under a coherent privacy-led architecture.

It demonstrates:

The project demonstrates that therapy infrastructure needs the same qualities as good systems infrastructure: clear boundaries, reliable state, minimal unnecessary exposure, careful access control, useful feedback, human responsibility, and respect for failure modes.


Code Availability

The repository is private but the code is available on request at no charge. Installation, customisation, and ongoing support are available at standard rates.


Built by LIS ltd · Made in Scotland