# Beacon

Beacon card

A location-based social network. [![Release Status](https://img.shields.io/github/actions/workflow/status/ColoradoSchoolOfMines/beacon/release.yml?label=Release&style=flat-square)](https://github.com/ColoradoSchoolOfMines/beacon/actions/workflows/release.yml) > [!WARNING] > This project is under active development and is not yet ready for production use. ## Documentation ### Setup 1. Install dependencies - [NodeJS](https://nodejs.org/en/download/) (LTS recommended) - [Git](https://git-scm.com/downloads) - If running Supabase locally: - [Docker/Docker Engine](https://docs.docker.com/engine/install/) 2. Clone the repository: ```bash git clone https://github.com/ColoradoSchoolOfMines/beacon.git ``` 3. Inside the repository, install the dependencies: ```bash npm install ``` 4. If you want to run Supabase locally, start the Docker container: ```bash # This can take a while the first time you run it because it has to download a bunch of Docker images npm run supabase:start # Check the status of the Supabase (Including the dashboard URL and mock email server URL) npm run supabase:status ``` 5. Update [`.env`](.env) with the appropriate values (See [Frontend Environment Variables](#frontend-environment-variables)). 6. Still inside the repository, start the development server: ```bash npm run dev ``` 7. Open [`http://localhost:3000`](http://localhost:3000) in your browser to access the frontend 8. If running Supabase locally, reset the database after each schema change: ```bash npm run supabase:reset ``` ### Production #### Build To build the frontend for production, run: ```bash docker build -t beacon -f Dockerfile . ``` #### Run To run the frontend in production, run: ```bash docker run -p 80:8080 beacon ``` ### Frontend Environment Variables | Development Name (i.e.: not in the container) | Production Name (i.e.: in the container) | Description | Default/Required | | --------------------------------------------- | ---------------------------------------- | ------------------------------ | ------------------------------------------------------------------------------------------------------------------------ | | `VITE_HCAPTCHA_SITE_KEY` | `CADDY_HCAPTCHA_SITE_KEY` | The hCaptcha site key | Required ( :warning: **Must be manually set** :warning:; see [hCaptcha dashboard](https://dashboard.hcaptcha.com/sites)) | | `VITE_SUPABASE_URL` | `CADDY_SUPABASE_URL` | The absolute Supabase API URL | Required (Automatically set by the setup script) | | `VITE_SUPABASE_ANON_KEY` | `CADDY_SUPABASE_ANON_KEY` | The Supabase API anonymous key | Required (Automatically set by the setup script) | | `VITE_SENTRY_DSN` | `CADDY_SENTRY_DSN` | The Sentry DSN | Optional (Automatically set by the setup script) | ### Technologies - Frontend - Language: [TypeScript](https://www.typescriptlang.org) - Web framework: [React](https://reactjs.org) + [Vite](https://vitejs.dev) - Component library: [Ionic React](https://ionicframework.com/docs/react) - Styling: [UnoCSS (Wind preset)](https://unocss.dev/presets/wind#wind-preset) (Tailwind/WindiCSS compatible) - Backend: [Supabase](https://supabase.com) ### Algorithm Beacon's ranking algorithm is somewhat inspired by the [Lemmy algorithm](https://join-lemmy.org/docs/contributors/07-ranking-algo.html), but has the following properties: | Description | Reasoning | | ----------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------- | | Quadratic distance **contribution** | Posts that are closer to the user should have a higher rank. This helps users see posts that are more geographically relevant to them. | | Logarithmic score **contribution** | The first $10$, next $100$, next $1000$, etc. votes should have the same contribution to the rank. This helps counteract the bandwagon effect. | | Exponential age **reduction** | The older a post is, the less relevant it likely is. This helps newer posts rank higher. | The algorithm is as follows: $$ \text{Distance component} = (\text{Distance weight} - 1) \cdot (\min\bigg(1, \frac{\text{Distance}}{\text{Distance range}}\bigg) - 1)^{2} + 1 $$ $$ \text{Score component} = \log_{10}(\max(1, (\text{Upvotes} - \text{Downvotes}) - \text{Score threshold} + 1)) $$ $$ \text{Age component} = \text{Age weight}^{- \text{Age}} $$ $$ \text{Rank} = \lfloor(\text{Scale} \cdot \text{Distance component} \cdot \text{Score component} \cdot \text{Age component}\rfloor $$ with the following variables: | Name | Definition | Min value | Default value | Max value | | ------------------------ | ------------------------------------------------------------- | ---------------------------- | ------------- | --------- | | $\text{Rank}$ | Integer post sorting order (Higher will be sorted first) | - | - | - | | $\text{Scale}$ | Ranking scale factor (To allow the rank to be rounded) | $1$ (Don't rank) | $10000$ | - | | $\text{Distance}$ | Distance between the post and the user's location (In meters) | - | - | - | | $\text{Distance weight}$ | Distance weight factor | $1$ (Don't rank by distance) | $5$ | - | | $\text{Distance range}$ | Maximum distance to be considered (In meters) | $1$ | $5000$ | $50000$ | | $\text{Upvotes}$ | Post upvotes | - | - | - | | $\text{Downvotes}$ | Post downvotes | - | - | - | | $\text{Score threshold}$ | Minimum score threshold considered | $-5$ | $-5$ | - | | $\text{Age}$ | Post age (In hours) | - | - | - | | $\text{Age weight}$ | Age weight factor | $1$ (Don't weight by age) | $1.075$ | - |