A membership system built inside a shared hosting box
Registration, payment verification, digital membership cards and renewal reminders for a volunteer-run health non-profit in Singapore. Built on the hosting the organisation already had, which ruled out most of the obvious answers and decided the shape of everything else.
The organisation, and the box it came in
The society runs on volunteers. Membership administration was a manual process, and manual processes in volunteer organisations do not fail loudly. They fail by consuming the time of the one person who understands them, and by quietly losing renewals that nobody had time to chase.
The organisation already had a WordPress site on Vodien shared hosting, which I had been maintaining for years. That was the environment: cPanel, PHP, MySQL, scheduled tasks via cron, and no ability to run a custom backend service. Any solution that needed a Node process, a container, or a paid platform tier was not a solution, because the ongoing cost and the ongoing maintenance both land on a volunteer committee after I am no longer the person answering the phone.
So the system was built as a PHP application deployed alongside the existing site, sharing its hosting and its domain.
- Member registration and account flow
- PayNow and bank transfer payment paths
- Administrator verification queue for incoming payments
- Digital membership cards
- Transactional email notifications
- Cron-driven membership expiry and renewal reminders
- Administrator dashboard
- Ongoing maintenance of the surrounding WordPress site, including performance and multilingual setup
No real member data appears in this case study. Every screenshot uses invented records, and the administrator views shown are reconstructions rather than captures of the live system. What is shown is the design reasoning: how a membership lifecycle gets built inside a hosting environment that rules out most of the standard tooling, and who the system is actually optimised for.
A volunteer organisation cannot maintain what it cannot afford to run. The right architecture was the one that survives me leaving.
Building for the hosting you have
The instinct with a project like this is to pick a modern stack and a managed platform, and it is usually the correct instinct. It was not here, and the reason is not technical.
A non-profit that runs on volunteers has no engineering function. Every dependency I add is a bill someone has to remember to pay and an account someone has to be able to access after the person who set it up moves on. Shared hosting is unglamorous, but the society already pays for it, already knows how to renew it, and already has more than one person with the login.
The same reasoning had already settled an earlier question. When the society wanted a chatbot for the main site, I assessed hosted options and a self-built one, and the shared hosting ruled out running a custom backend at all. Knowing that boundary in advance is what made the membership system's architecture a two-minute decision rather than a two-week detour.
Goals
- Remove the manual administration burden without adding a recurring cost.
- Keep everything inside infrastructure the committee already controls.
- Make renewals happen without anyone having to remember to chase them.
- Leave a system a non-technical volunteer can operate and a future developer can pick up.
No long-running processes, so anything scheduled runs through cron rather than a job queue. No modern deployment pipeline. Email deliverability becomes the application's problem rather than a provider's. Each of those is a real limitation, and each was worth accepting for an architecture the organisation can keep running on its own.
Keeping a human in the loop, on purpose
Members pay by PayNow or bank transfer. Neither returns a webhook the way a card gateway does, so the system cannot know on its own that money has arrived. That is usually described as a limitation. Here it is closer to a feature, and the design leans into it rather than fighting it.
A card gateway would have meant per-transaction fees on small annual subscriptions from a non-profit's members, plus a compliance surface the committee would have to own. PayNow is what people in Singapore already use, it costs the society nothing, and members do not have to learn anything new.
So the flow was designed around verification rather than around automation. A member registers and submits payment. The submission lands in an administrator queue with everything needed to match it against the bank record. An administrator confirms, and confirmation is the event that activates the membership.
Designing around the pause
The manual step introduces a gap between paying and being a member, and an unexplained gap is where support emails come from. The system's job in that window is to make the state legible: the member can see that their payment is awaiting verification rather than seeing nothing, and the administrator gets a queue rather than an inbox.
That is the actual product decision in this chapter. The automation that was unavailable was never the important part. Making the wait understandable was.
Membership as a thing that expires
The failure mode a membership system exists to prevent is not registration, it is lapse. People join once and then stop being members by doing nothing at all, which is the easiest possible thing to do.
Expiry reminders run on cron, so the chase happens whether or not a volunteer has time that month. This is the single highest-value piece of the system relative to its complexity: a scheduled query and a templated email, doing the job that previously depended on someone remembering.
The digital membership card
Members get a digital card rather than a posted one. It removes a printing and mailing cycle from a volunteer committee, it can be reissued instantly when someone loses it, and it gives membership a visible artefact, which matters more than it sounds. A membership with nothing to show for it is easy to forget you have.
Email as infrastructure
Registration confirmations, verification results and renewal reminders all depend on mail actually arriving. On shared hosting, that is not a given: authentication records have to be configured correctly or the messages land in spam, where they fail invisibly. Deliverability is the part of this system I would have underestimated at the start, and it is still the part with open work on it.
Designing for the volunteer, not the member
A member touches this system twice a year: once to join or renew, once if something goes wrong. An administrator touches it every week, and they are not a trained operator. They are a volunteer with a day job who agreed to help.
That inverts the usual weighting. The member-facing flow needs to be obvious and then get out of the way. The administrator side is where the design effort actually pays back, because it is used constantly by someone who cannot be trained, cannot be expected to remember conventions between sessions, and will not raise a bug report when something is confusing. They will just stop using it and go back to the spreadsheet.
The dashboard is the operational surface: what is waiting, what is expiring, what needs a decision. Anything that requires interpretation is a design failure, because interpretation is exactly what the volunteer does not have time for.
Live, and not finished
The system is deployed and in use, and it is not done. Two things are open. Email deliverability still needs proper authentication records and a migration to a dedicated mail library, which is the highest-priority item because a reminder that silently lands in spam is worse than no reminder: the system reports success and the member never renews. The administrator dashboard also has statistics that display incorrectly, which is cosmetic against the payment flow but corrosive against trust, since a dashboard nobody believes is a dashboard nobody reads.
Listing those here rather than waiting until they are closed is deliberate. This is a live system for a real organisation, and the honest state of it is more useful than a tidier version.
Architecture is a maintenance decision
The best stack for a volunteer organisation is the one they can keep paying for and keep logging into after the developer moves on. Shared hosting cost me modern tooling and bought them independence.
Automate the chasing, not the judgement
Expiry reminders on a schedule were the highest-value piece for the least complexity. Payment verification stayed human because the payment rails have no callback and the fees of the alternative fell on the members.
Optimise for the person who uses it weekly
Members visit twice a year. Volunteers are in it constantly and will not file a bug, they will just go back to the spreadsheet. The admin surface is where the design effort returns the most.