{"id":41028703,"url":"https://github.com/yorknouse/website","last_synced_at":"2026-01-22T10:04:41.340Z","repository":{"id":46177775,"uuid":"161061605","full_name":"yorknouse/website","owner":"yorknouse","description":"Public Website for University of York's Oldest Student Newspaper","archived":false,"fork":false,"pushed_at":"2026-01-02T00:43:36.000Z","size":99829,"stargazers_count":3,"open_issues_count":13,"forks_count":3,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-01-02T06:10:46.286Z","etag":null,"topics":["astro","cms","mysql","news","nextjs","php"],"latest_commit_sha":null,"homepage":"https://nouse.co.uk","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/yorknouse.png","metadata":{"files":{"readme":"Readme.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2018-12-09T17:00:48.000Z","updated_at":"2025-12-31T16:05:31.000Z","dependencies_parsed_at":"2025-10-03T02:38:37.578Z","dependency_job_id":"bdf70c2d-8844-45c1-bc05-e93d19f4a56a","html_url":"https://github.com/yorknouse/website","commit_stats":null,"previous_names":[],"tags_count":255,"template":false,"template_full_name":null,"purl":"pkg:github/yorknouse/website","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yorknouse%2Fwebsite","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yorknouse%2Fwebsite/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yorknouse%2Fwebsite/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yorknouse%2Fwebsite/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/yorknouse","download_url":"https://codeload.github.com/yorknouse/website/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yorknouse%2Fwebsite/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28661068,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-22T01:17:37.254Z","status":"online","status_checked_at":"2026-01-22T02:00:07.137Z","response_time":144,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["astro","cms","mysql","news","nextjs","php"],"created_at":"2026-01-22T10:04:40.769Z","updated_at":"2026-01-22T10:04:41.334Z","avatar_url":"https://github.com/yorknouse.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Nouse Website\n\nNouse was based on \"bCMS\" originally, a custom built content management system.\nThere's probably going to always be some debate about whether this was the best idea for Nouse,\nbut it has enabled us to do some really great custom stuff over the years,\nand overcome crippling performance issues on Wordpress.\n\n## Local Development\n\nPlease see `LOCAL.md` for instructions.\n\n## Repo Structure\n\n~~Firstly, an apology.\nThis repo was, in its early life,\na 3-year labour of love of over 580 commits just trying to keep up with Nouse as the society grew and its needs developed.\nThere are no tests or migrations and documentation is limited.\nCode quality and style varies as the project grew alongside its creators skill set.\nNo linting is provided or used.~~\n\nActually *firstly*, an apology.\nThis repo is still in somewhat early development but is getting there in maturity.\nThis is a 5 (almost 6)\nyear labour of love of over 1,300 commits just trying to keep up with Nouse as the society grew and its needs developed.\nThere are very few tests and documentation is fragmented if even there in the first place.\nLinting has been a project to put in for some semblance of consistency but oh wow it has been a struggle\n(coming from a current alum who is still dedicating their time to helping out).\nFor ease of development for future developers we are moving away from PHP as a language for easier to learn languages like TypeScript.\n**Assume all documentation below is incorrect and wrong** and I will be doing more work to improve future developers'\nexperience as I have spent an ungodly number of hours just trying to understand the structure and trying to get dev working.\n\nFor performance reasons, the site does not use a router, and instead leaves routing to Apache.\nCaddy sits in front of apache to terminate SSL and do some reverse proxying.\nThe project is structured around three directories within /html:\n\nadmin - The \"backend\" edit dashboard\ncommon - (not publicly accessible) Classes, Functions \u0026 Templates shared by both other directories\nfrontend - \"Public Site\" nouse.co.uk\n\n### Ajax?....\n\nTo improve user performance \u0026 error handling the backend site is not based around a conventional laravel-esque form structure for user interaction.\nInstead, most data from the database is returned to the user through a normal dynamically loaded page,\ngenerating html from a twig template.\n\nWhen a user interacts with the page,\nsuch as pressing a button,\nthis triggers a JQuery function (all defined in that pages' twig template) which makes an \"api call\"\nto a php script within the `admin/api/` folder and executes the change\n(such as an insert/delete/update).\nOnce this completes successfully two things can happen.\nThe first, a legacy behaviour, is that the page reloads to reflect the changes in the page itself.\nThe second option is that the page calls a function to update what's displayed, without needing a page re-load.\nThere are quite a few endpoints in `admin/api` that provide access to retrieving data as well,\nas this is how the mobile app downloads its data which it then displays.\n\nWith hindsight this was not a great way to do this.\n\n# Server Setup\n\n## Docker\n\nThe whole stack runs off one docker-compose file which makes this all a lot simpler!\n\n1. Make sure you're the root user `sudo su` then `cd /root/`\n2. `apt update \u0026\u0026 apt install docker.io docker-compose`\n3. `systemctl enable docker` to ensure docker boots on startup\n4. Clone the repo `git clone git@github.com:yorknouse/website.git`\n5. `cd website` to get into it\n6. Download the Cloudflare Origin Certificate - place the certificate (`.crt` file) in the `ssl` directory, \nwith the `ssl.key` file\n7. Create `nouseprod.env` based on the example file, and fill out the details (do this with `nano nouseprod.env`)\n8. Run `docker-compose up -d` to get the site running\n\n## Deploy webhook\n\nSome pages in the website are statically built, nominally the home page.\nTo rebuild them,\nthe host vm needs a webhook that can be triggered from the admin panel and causes the docker images to be rebuilt.\n\nSetting up:\n\n```sh\nsudo apt-get install webhook\n```\n\nIn the `/root` directory, create a `rebuild-webhook.json` file with the following content:\n\n```json\n[\n  {\n    \"id\": \"rebuild-webhook\",\n    \"execute-command\": \"/root/rebuild.sh\",\n    \"command-working-directory\": \"/root/website\"\n  }\n]\n```\n\nStill in the `/root` folder, create the `rebuild.sh` file with the following content:\n\n```sh\n#!/bin/sh\ngit pull \u0026\u0026 docker-compose -f docker-compose.yml build --no-cache nouse \u0026\u0026 docker-compose -f docker-compose.yml up -d\n```\n\nAnd make the script executable:\n\n```bash\nchmod +x /root/rebuild.sh\n```\n\nNow we need a service to start webhook on boot.\nCreate the `/etc/systemd/system/rebuild.service` file with the following content:\n\n```sh\n[Unit]\nDescription=Webhook Rebuild Service\nAfter=network.target\n\n[Service]\nExecStart=/usr/bin/webhook -hooks=/root/rebuild-webhook.json -hotreload=false -port=9000 -secure=false -verbose=true -nopanic\nKillMode=process\nRestart=on-failure\n\n[Install]\nWantedBy=multi-user.target\n```\n\nFinally, reload the systemd daemon, disable the default webhook service and enable ours:\n\n```sh\nsystemctl daemon-reload \u0026\u0026 systemctl disable webhook.service \u0026\u0026 systemctl enable rebuild.service\n```\n\n## Updating\n\nWatchtower does the updating for you anytime you push a new tag (which triggers a docker build) but if you update the docker compose file or the config you'll need to run `git pull \u0026\u0026 docker-compose up -d` (in the Nouse directory)\n\n## Backblaze Setup\n\nYou need to setup the CORS on the bucket to allow uploads from any host, and downloads from any host\n\nFirst download and authenticate the AWS Cli (using your Backblaze credentials),\nthen download the cors.json file from this repo and run:\n\n`aws s3api put-bucket-cors --bucket=nousePublicBackendUploads --endpoint-url=https://s3.eu-central-003.backblazeb2.com  --cors-configuration=file://cors.json`\n\n# Database\n\n## MySQL Setup\n\nTo transfer a MySQL dump file (named `nouseBackup.sql`) run:\n\n```\ncat nouseBackup.sql | docker exec -i db /usr/bin/mysql -u root --password=rootPass nouse\n```\n\n## MySQL Backups\n\n`mysql-backup` runs a backup every day at about 2:30am and pops it in our S3 bucket.\nThat's all automatic, but you do need to set up a lifecycle rule for the spaces/S3 bucket.\nThis is so the backups are deleted after 40 days and we don't get bankrupted by them.\n\n- Set the lifecycle policy for the bucket using the `lifecycle.xml` file\n\n## MySQL remote access\n\nphpmyadmin is accessible at http://yusunouse01.york.ac.uk/tools/phpmyadmin, with login = nouseAdmin and password = [nouseAdminPassword set in nouseprod.env]\n\n# Netdata\n\nnetdata is accessible at http://yusunouse01.york.ac.uk/tools/netdata, with login = nouseAdmin and password = [nouseAdminPassword set in nouseprod.env]\n\n# Grafana\n\nGrafana (stats.nouse.co.uk) runs as an instance inside the MySQL server.\nIt has full root access to the database due to Docker limitations so as such no users have edit permissions.\nInstead, set up your queries and graphs in the text files under `\"`docker/grafana/dashboards`.\nYou can also generate these locally by running grafana and using the UI to export JSON files.\n\nGrafana security is managed by an oauth hook from the main admin site.\n\n## Licence\n\nCopyright (C) 2018-2025 Nouse, University of York Students' Union and its contributors\n\nThis program is free software: you can redistribute it and/or modify\nit under the terms of the GNU General Public License as published by\nthe Free Software Foundation, version 3 of the License\n\nThis program is distributed in the hope that it will be useful,\nbut WITHOUT ANY WARRANTY; without even the implied warranty of\nMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\nGNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License\nalong with this program. If not, see \u003chttps://www.gnu.org/licenses/\u003e.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fyorknouse%2Fwebsite","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fyorknouse%2Fwebsite","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fyorknouse%2Fwebsite/lists"}