============ Architecture ============ The tale of sewifurs.org's architecture is that of gradual evolution, not up-front design. History ======= When sewifurs.org was created in November 2021, it was a static website. It was converted to a Flask web app and an accompanying bot in March 2022. The bot gained moderation functions in February 2024. Basic Telegram-based logins (for Bluesky Social custom handles) were supported in March 2025. Following this, another developer joined the project, and I started to get inquiries from furries elsewhere who were interested in using sewifurs.org as a base for local furry community websites of their own. Major improvements were needed to allow sewifurs.org to grow. July and August 2025 saw the replacement of hardcoded privileges with a runtime-configurable permission system, a split into multiple independently-runnable modules, and a cloud-friendlier settings system. Integration testing came in September 2025, and Docker Compose in November 2025. As of writing, sewifurs.org still requires a hard fork to use; branding, chat directory entries, and other details are hardcoded as SEWI Furs. However, as this project's architecture continues to evolve, a future split into two projects may be possible: an unbranded core (tentatively called FurHome), and a branded client consuming that core (the 'future' SEWI Furs). Modules ======= sewifurs.org is split into the following modules: - :mod:`sewifurs.bot`, the Telegram bot - Requires Telegram bot credentials. - Does not require a web server. - :mod:`sewifurs.linkchecker`, the chat directory link checker - Does not require Telegram bot credentials. - Does not require a web server. - :mod:`sewifurs.website`, the Flask web app - Does not require Telegram bot credentials, but some functionality won't be available without them. - Requires a web server. When doing local development, if you only need to interact with one part of sewifurs.org, you can run only that module with ``python3 -m sewifurs.module``, replacing ``module`` with the appropriate name. :mod:`sewifurs.website` will spin up Flask's built-in development server on port 5000 if run directly. When deployed using Docker, all modules are started in a single container by `run.sh`, which also prepares static assets for serving by the nginx container, runs database migrations, and uses uWSGI to serve :data:`sewifurs.website.app` behind nginx. Current state ============= .. mermaid:: architecture-beta group compose(cloud)[Docker Compose] group world(cloud)[Persistence] service bot(server)[Bot] in compose service linkchecker(server)[Link checker] in compose service website(server)[Website] in compose service script(disk)[Run script] in compose service sqlite(database)[sqlite3 database] in world service uwsgi(server)[uWSGI] in compose service telegram(internet)[Telegram] in world service dns(internet)[DNS providers] in world service nginx(server)[nginx] in compose service static(disk)[Static assets] in compose service docs(disk)[Documentation] in compose service config(disk)[Configuration] in world service sphinx(server)[Sphinx] in compose website:B -- T:uwsgi uwsgi:B -- T:nginx static:R -- L:nginx docs:L -- R:nginx docs:B -- T:sphinx script:B -- T:website bot:R -- L:script linkchecker:L -- R:script config{group}:B -- T:script{group}