= Web Portal

image::web-portal-arch.drawio.svg[]

The Servala Web Portal is the central multi-tenant multi-service-provider aggregation and self-service main entrypoint for Servala.
Servala is the brand for the product formerly known as "VSHN Application Marketplace".

It offers self-service provisioning, multi-tenancy via organizations, access control, and provides central management access over multi cloud providers and the instances running this way.

The portal is a web application consuming various third party APIs to provide an aggregated and opinionated view.

External resources to read about it:

* http://vshn.ch/marketplace[vshn.ch Website^]
* https://products.vshn.ch/marketplace/index.html[VSHN products site^]

The source code can be found on the https://servala.app.codey.ch/servala/servala-portal[Servala Codey instance^].

== Technology Stack

We choose:

* Python https://docs.djangoproject.com/en/dev/internals/release-process/#term-Long-term-support-release[Django LTS^]
* PostgreSQL as database backend
* https://gunicorn.org/[Gunicorn^] Python WSGI HTTP Server
* https://caddyserver.com/[Caddy^] for serving static files and WSGI, or https://whitenoise.readthedocs.io/en/latest/[WhiteNoise^] (TBD)
* https://docs.astral.sh/uv/[Astral uv^] for Python project, dependency and build management
* https://htmx.org/[htmx] for the dynamic part in the frontend
* https://getbootstrap.com/[Bootstrap 5] for styling the frontend

A complete reasoning for this stack is available in https://vshnwiki.atlassian.net/wiki/spaces/VSHNPM/pages/402718747/Self-Service+Marketplace+Web+Application[our wiki^] (internal page).

== Development Paradigms

Keep usage of third-party dependencies low::
Every external dependency adds a burden on the maintenance of the application.
Adding a dependency must be done with care:
* Is the dependency well maintained and adopted in the ecosystem?
* Could we do it without the dependency? If not, why?
* What happens if the dependency is abandoned?
* Document the reason for each dependency, why it has been chosen and why we can't live without it.

Graceful degradation::
The application will connect to various upstream APIs which we can't control.
Should issues arise with one of these APIs, gracefully degrade the feature set and inform accordingly ("This service is currently not available - we're working on it").
Never must the application crash because and upstream API not being reachable, has slow response time or react in an undefined way.

Use database and caches wisely::
External systems like databases, caches or queues add additional complexity and burden to the application operations.
Every additional system must be chosen carefully and the reasoning documented.
Alternatives must be considered and documented.

Business logic vs. views::
Whenever possible, split business logic from views.
This allows to progress the application in the future to allow for different views (For example APIs or other alternative frontends).

Django specifics::
* We use class based views by default, exceptions can be made
* Dynamic configuration happens via environment variables
* Different environments (dev / test / prod) must be clearly separated inside the application

Testing::
Business functionality must be https://docs.djangoproject.com/en/5.1/topics/testing/[tested^] with code.
We preferrably use https://docs.pytest.org/[pytest^].
