Kansa is a convention member management system originally developed for Worldcon 75, the World Science Fiction Convention organised in Helsinki in 2017. It is also used by Dublin 2019: An Irish Worldcon.
The system is modular and extensible. Together with its front-end client it provides the following services:
- Member admin services, including an easy-to use admin front-end
- Support for multiple membership types, as well as for non-member accounts
- Stripe integration for membership and other purchases (via credit cards or SEPA direct debit)
- Individual and bulk import of member data and transactions from other systems
- Member-facing front-end for e.g. name and address changes
- Passwordless authentication using login links sent by email
- Emails sent using Sendgrid and customisable templates
- Synchronisation of contact info to Sendgrid for mass mailings
To help with at-con registration, Kansa has:
- Pre-con badge preview and customisation (with Unicode support)
- Printable/displayable barcodes for quick member identification
- Streamlined UI for registration staff, including on-demand badge printing
- Local caching that enables continued use even during network failures
Specifically of interest to Worldcons, Kansa also provides:
- Hugo Awards nomination and voting front-end for members
- Throttled/delayed email confirmations for nominators and voters
- Canonicalisation and category correction interface for Hugo admins
- Detailed reports on nomination and vote counts & results
- Secure hosting for the Hugo packet
- Site Selection token generator for online sales
- Member-specific Site Selection ballot PDF generator
- Token verification front-end for at-con Site Selection staff
- Custom data exports for matching member data for Site Selection purposes
Setting up and maintaining your own Kansa instance will require some experience with JavaScript and PostgreSQL. The front-end is a React app, while most of the back-end services run on node.js; the various parts are wrapped up in Docker containers. Work is ongoing to make the system more configurable and customisable, so fewer changes in code are required for convention-specific changes.
To get a dev environment up and running, first clone this repo. Then you'll need to have
Docker Compose available, as that's used by default for
container orchestration. To start, run make start
or call docker-compose
directly:
docker-compose \
-f config/docker-compose.base.yaml -f config/docker-compose.dev.yaml \
-p api up --build -d # leave out the -d to not detach
Once you have all the services up and running, your development server should be available at
https://localhost:4430/
, including a relatively recent front-end client (with code hosted under
GitHub Pages). You'll need to bypass your browser's complaint about the server's self-singed
certificate:
- Chrome: Click on Advanced, then Proceed to localhost:4430. Alternatively, go to
chrome://flags/#allow-insecure-localhost
and enable the option to "Allow invalid certificates for resources loaded from localhost" - Firefox: Click on I Understand the Risks, then Add Exception..., then Get Certificate, and finally Confirm Security Exception
- IE: Click on Continue to this website (not recommended)
- Safari: Click on Show Certificate, Always Trust "example.com" when connecting to "example.com", then Continue
curl
: Use the-k
or--insecure
flag to perform "insecure" SSL connections
The development server is bootstrapped with an admin account [email protected]
using the key
key
, which you may login as by visiting either of the addresses
https://localhost:4430/login/[email protected]/key (for smooth browser redicretion) or
https://localhost:4430/api/[email protected]&key=key (direct login, with JSON response).
For production use and otherwise, the services' configuration is controlled by the Docker Compose
config files. For development use, run make
in the project root to include the base config
docker-compose.base.yaml and the development config
docker-compose.dev.yaml. For production use, the base config will
instead need to be overridden by docker-compose.prod.yaml
, which you will need to base on
docker-compose.prod-template.yaml and fill with
appropriate variable values (see make prod
). Make sure that your production secrets
are not committed to any repository!
For the most part, services are configured using environment variables, some of which need to match across services:
JWT_SECRET
andSESSION_SECRET
allow the servers to share authenticated sessionsDATABASE_URL
and*_PG_PASSWORD
are required for the services' database connections
Email messages are based on message templates, which are documented separately.
config
- System configurationhugo
- Provides the Hugo Nominations and Awards parts of the REST APIintegration-tests
- Tests for the REST API, targeting the Stripe and Sendgrid interfaces in particularkansa
- Provides the core parts of the REST APIkyyhky
- Internal mailing service & SendGrid integration for hugo & kansanginx
- An SSL-terminating reverse proxy & file server, using OpenRestypostgres
- Configuration & schemas for our databaseraami
- Art show management REST APItools
- Semi-automated tools for importing data, and for other taskstuohi
- Fills out a PDF form, forGET /people/:id/ballot
Kansa is Finnish for "people" or "tribe", and it's the name for our member registry. The Hugo Awards are awards that are nominated and selected by the members of each year's Worldcon. Kyyhky is Finnish for "pigeon", Raami is "frame", and Tuohi is the bark of a birch tree.
The particular places that may need manual adjustment are:
-
Connections to the server require TLS (HTTPS, WSS). For ease of development the repo includes a self-signed certificate for
localhost
. This will not be automatically accepted by browsers or other clients. If you have a signed certificate you can use (and therefore a publicly visible address), you'll want to add the certificate files tonginx/ssl/
and adjust the environment values set for thenginx
service in docker-compose.override.yaml and/or yourdocker-compose.prod.yaml
. -
The
CORS_ORIGIN
variables in the docker-compose config files need to be space-separated lists of addresses at which client apps may be hosted, to allow for Cross-Origin Resource Sharing. By default, the value should match thehttp://localhost:8080
address of the client Webpack dev servers. -
If you're running the server on a separate machine or if you've changed the
nginx
port configuration, you may need to tell clients where to find the server, using something likeexport API_HOST='remote.example.com'
before runningnpm start
.
If you'd like to help with this project, please fell free to fork it and submit pull requests, or get in touch with us at [email protected].