Case study 03  ·  Client  ·  Live

Amaan Psychotherapy

An Ontario practice was paying monthly for a DIY website builder. I designed and built a calm, custom site with a private portal, so they can publish their own blog without calling a developer.

RoleDesign, build, hosting and ongoing maintenance.
TimelineSeptember 2026 to now
StackPython, Flask, PostgreSQL, Mailgun, Railway
Live siteamaan.abbasvirjee.com ↗
amaan.abbasvirjee.com
The Amaan Psychotherapy home page
325automated tests
7public pages
6custom error pages
1booking link, set in one place
01The problem

A therapy practice needs to feel safe before anyone books.

The old site came from a template builder: generic, hard to change and paid for every month. The practice wanted something that felt quiet and trustworthy, a blog they could run themselves, and a contact form they could rely on.

Before
  • ×Template site on a monthly plan
  • ×Blog posts needed outside help
  • ×Contact messages only in email
  • ×No control over the details
After
  • →Custom design built for the practice
  • →Private portal to write and publish
  • →Messages saved and emailed
  • →Every word on the site editable
02What I built

What I built

Visitors see five calm pages. Behind them is a portal built for someone who isn't technical.

01

The website

  • →Home, About, Services, Blog and Contact
  • →Privacy Policy and Terms of Use
  • →Crisis numbers in the footer on every page
  • →Search engine and social sharing setup
02

The portal

  • →Blog editor with autosave and preview
  • →Edit any page text, with version history
  • →Messages inbox with search and archive
  • →Photo uploads, resized and cleaned
03

Behind it

  • →Booking hands off to the practice's system
  • →Separate admin address, hidden from search
  • →Branded email template
  • →Backups and a restore runbook
03The hard part

A contact form that never loses a message.

For a therapy practice, a lost enquiry is someone who reached out and never heard back. So the form saves first and emails second, and every failure has a plan.

Server-side validationHoneypotRate limitingHeader-injection guard
1
Check

Fields are validated on the server and bots are filtered out quietly.

2
Save

The message is stored first, so the portal always has a copy.

3
Email

It's sent to the practice with the visitor as the reply-to address.

4
Retry

If sending fails, the message is flagged and retried in the background.

Email is down: the visitor still sees the thank-you, and the message waits in the portal.
Can't save: the visitor sees an error and keeps everything they typed.
04How it's built

Privacy and security

Locked-down portal

Sign-ins lock after five failed attempts, and sessions time out when idle.

Safe blog content

Posts are cleaned against an allow-list before they're published.

Clean photos

Uploads are verified, resized and stripped of location data.

Strict headers

Content Security Policy, HSTS and no-index on the admin side.

Quiet analytics

Privacy-friendly analytics, so no cookie banner on a therapy site.

Designed first

Every page and state was designed and approved before any code.

05Screens
The Amaan admin dashboard
The admin home: new messages, posts and drafts at a glance.
The Amaan blog editor
The editor: write, preview, publish.
The Amaan services page on a phone
Each service explained in plain language, on any screen.

The practice now updates its own website, without waiting on a developer.

The site is live and moving to the practice's own domain. They write and publish their own posts, every enquiry is kept safe, and I stay on for hosting and improvements.

Abbas Virjee · Toronto, Canada[email protected]