Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
85 commits
Select commit Hold shift + click to select a range
4e69e7a
feat: script generation for sensebox devices
umut0 Jan 21, 2026
5d339b6
fix: remove redundant tailwind and app.css and import correct css (#711)
scheidtdav Jan 22, 2026
0630d90
Small fixes to the project setup (#712)
scheidtdav Jan 26, 2026
f12a1b3
feat: bump node to the latest lts release (#713)
scheidtdav Jan 26, 2026
8f9f8ad
Fix/custom device model crash (#714)
jona159 Jan 30, 2026
aad01a9
fix: store only selected subset of sensors from model (#719)
jona159 Feb 5, 2026
1eca659
Implement UI for device security and refactor implementation (#736)
scheidtdav Feb 6, 2026
48195cc
add missing cron.database_name to docker-compose.yml (#731)
scheidtdav Feb 9, 2026
11cab0c
Fix/device detail show last measurement (#738)
jona159 Feb 9, 2026
d4e4a87
Fix/rename sensebox to device (#740)
jona159 Feb 9, 2026
b8ede37
Feat/sort table createdat (#741)
jona159 Feb 9, 2026
1b873fb
Fix/error selecting 2nd pheno (#742)
jona159 Feb 9, 2026
14a6133
Fix/pinch to zoom (#734)
jona159 Feb 9, 2026
a5e4f6d
Chore/prettier (#739)
jona159 Feb 9, 2026
375506d
build(deps): bump @react-email/components from 1.0.1 to 1.0.7 (#744)
dependabot[bot] Feb 11, 2026
d1c6380
Show the device count in short scale notation (#717)
JerryVincent Feb 11, 2026
2e11c92
Show email confirmation status of the user in the settings page and r…
JerryVincent Feb 11, 2026
91aec3f
Fix recurring test timeouts (#748)
scheidtdav Feb 11, 2026
4cdaa3f
fix: remove pinned buildx version (#753)
scheidtdav Feb 18, 2026
b3b1e54
build(deps): bump isbot from 5.1.31 to 5.1.35 (#752)
dependabot[bot] Feb 18, 2026
6973279
Add env var to disable mailing (#756)
scheidtdav Feb 18, 2026
0f3145c
Fix/password reset (#755)
jona159 Feb 18, 2026
d50c8ff
Feat/mqtt json schema (#732)
jona159 Feb 20, 2026
7f704dd
fix: regression (#765)
jona159 Feb 20, 2026
05627bd
fix: store single phenos instead of all phenos from sensor type (#767)
jona159 Feb 23, 2026
3cdd54e
fix: restore sensor mappings (#768)
jona159 Feb 23, 2026
5a2cf7a
add custom header for device api key as alternative to HTTP Authoriza…
scheidtdav Feb 24, 2026
4568dc2
Fix/edit integrations (#771)
jona159 Feb 24, 2026
1cf5a19
build(deps-dev): bump @vitejs/plugin-react from 5.1.1 to 5.1.4 (#772)
dependabot[bot] Feb 25, 2026
955084f
build(deps): bump close-with-grace from 2.3.0 to 2.5.0 (#773)
dependabot[bot] Feb 25, 2026
90b4fda
build(deps): bump @formatjs/intl from 3.1.8 to 4.1.2 (#743)
dependabot[bot] Feb 25, 2026
66735e1
build(deps): bump bcryptjs from 3.0.2 to 3.0.3 (#696)
dependabot[bot] Feb 25, 2026
731eab7
feat: add cagg retention policies (#775)
jona159 Mar 2, 2026
eaec51f
Enable Users to Select the appropriate sensor while creating a new De…
JerryVincent Mar 2, 2026
0528acc
feat: remove enhancement label from template (#778)
scheidtdav Mar 3, 2026
68c3684
build(deps): bump execa from 9.6.0 to 9.6.1 (#791)
dependabot[bot] Mar 4, 2026
c790542
Remove duplication of login and signup forms (#787)
scheidtdav Mar 4, 2026
d6ca422
fix: editing email flow (#792)
jona159 Mar 4, 2026
083f53b
fix: properly parse env var for mail disabling (#793)
scheidtdav Mar 4, 2026
32866fa
Fixes the re-generation of API key upon clicking save button. (#795)
JerryVincent Mar 4, 2026
bd6b758
Fix/public profile permissions (#796)
jona159 Mar 4, 2026
904fdb1
This commit enhances the error-message component to show more details…
JerryVincent Mar 4, 2026
7f15661
Move remaining /api/device routes to /api/boxes (#799)
scheidtdav Mar 4, 2026
aea2052
fix: make the whole menu item clickable (#804)
jona159 Mar 9, 2026
d474d1e
Feat/enhanced error message (#800)
JerryVincent Mar 9, 2026
e286d47
fix: device creation translations and prevent to submit form twice (#…
jona159 Mar 10, 2026
9e7041e
feat: ui for device transfer (#805)
jona159 Mar 10, 2026
50d667e
Make device overview page a little more responsive and add copy to cl…
scheidtdav Mar 10, 2026
01b03d3
build(deps-dev): bump postcss from 8.5.6 to 8.5.8 (#814)
dependabot[bot] Mar 11, 2026
b6f3427
build(deps): bump docker/login-action from 3 to 4 (#810)
dependabot[bot] Mar 11, 2026
ace3886
build(deps): bump docker/setup-buildx-action from 3 to 4 (#812)
dependabot[bot] Mar 11, 2026
4d117b7
build(deps): bump docker/build-push-action from 6 to 7 (#811)
dependabot[bot] Mar 11, 2026
fa9f2c8
Fix for the behavior issue of the measurement graph. (#815)
JerryVincent Mar 11, 2026
ec72d53
test: increase hook timeout in ci (#823)
jona159 Mar 13, 2026
c6661d0
build(deps): bump docker/metadata-action from 5 to 6 (#813)
dependabot[bot] Mar 13, 2026
f36b626
fix: add translation (#822)
jona159 Mar 13, 2026
166cd0b
Use CMS to grab imprint (#817)
scheidtdav Mar 13, 2026
eebc768
Feat/orphaned state (#824)
jona159 Mar 13, 2026
65b50ce
Fix/replace minio with rustfs (#821)
jona159 Mar 16, 2026
83b192c
Fix/device images on map (#827)
jona159 Mar 16, 2026
39ace92
Fix/simplify user profile name (#816)
jona159 Mar 17, 2026
227eeac
build(deps-dev): bump start-server-and-test from 2.1.2 to 2.1.5 (#829)
dependabot[bot] Mar 18, 2026
29d3b0a
feat: only allow show on map on public profile (#826)
scheidtdav Mar 18, 2026
0812baf
Generic Error Boundary (#828)
scheidtdav Mar 23, 2026
39d1564
fix: show device name in html (#837)
jona159 Mar 23, 2026
b299207
Allows the users to swap the sensor order while editing and persists …
JerryVincent Mar 23, 2026
7730650
Feat/convert description to markdown (#838)
jona159 Mar 23, 2026
16661fd
fix: public profile error (#842)
jona159 Mar 23, 2026
99bd86d
Feat/cronjob archive inactive devices (#807)
jona159 Mar 24, 2026
ef3aca4
Feat/tos (#777)
jona159 Mar 25, 2026
c7e42f4
feat: add stored procedure: delete users, orphanize devices (#843)
jona159 Mar 25, 2026
106beb4
Remove external links to images (#832)
JerryVincent Mar 25, 2026
c5c6df9
This commit fixes the issue of adding new sensors after editing a sen…
JerryVincent Mar 25, 2026
c5dd269
fix: typo in package.json (#852)
scheidtdav Mar 25, 2026
9e2bc0d
feat: add missing images (#853)
scheidtdav Mar 25, 2026
0c95ad4
migrate i18next to use middleware (#844)
scheidtdav Mar 25, 2026
24285e7
build(deps): bump @turf/bbox from 7.2.0 to 7.3.4 (#846)
dependabot[bot] Mar 25, 2026
a4b9aac
build(deps): bump nick-fields/retry from 3.0.2 to 4.0.0 (#845)
dependabot[bot] Mar 25, 2026
a0fbaed
refactor: show support link only for senseboxes, rename column to dev…
scheidtdav Mar 25, 2026
943abde
build(deps): bump react-globe.gl from 2.36.0 to 2.37.0 (#861)
dependabot[bot] Apr 1, 2026
290f5ef
fix: allow duplicate locations during data upload (#863)
mashazyu Apr 1, 2026
ddb8805
Feat/mention privacy policy on signup (#870)
zven Apr 2, 2026
1573ca6
feat: script generation for sensebox devices
umut0 Jan 21, 2026
85b24fe
Merge branch 'feat/script-generation-sensebox' of github.com:openSens…
umut0 Apr 7, 2026
eef576f
feat: compile and download sketch for sensebox home devices
umut0 Apr 7, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
16 changes: 10 additions & 6 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@ MAPBOX_GEOCODING_API="https://api.mapbox.com/geocoding/v5/mapbox.places/"
OSEM_API_URL="https://api.opensensemap.org/"
DIRECTUS_URL="https://coelho.opensensemap.org"
SENSORWIKI_API_URL="https://api.sensors.wiki/"
INGRESS_DOMAIN="ingress.opensensemap.org"

MQTT_SERVICE_URL="http://localhost:3001"
MQTT_SERVICE_KEY="dev-service-key-change-in-production"

MYBADGES_API_URL = "https://api.v2.mybadges.org/"
MYBADGES_URL = "https://mybadges.org/"
Expand All @@ -26,15 +30,15 @@ MYBADGES_ISSUERID_OSEM = ""
MYBADGES_CLIENT_ID = ""
MYBADGES_CLIENT_SECRET = ""

DISABLE_MAILING = "false"
SMTP_HOST = "localhost"
SMTP_PORT = "1025"
SMTP_SECURE = "false"
SMTP_USERNAME = "ignored"
SMTP_PASSWORD = "ignored"

S3_ENDPOINT=http://localhost:9000
S3_REGION=eu-norht-1
S3_BUCKET=device-images
S3_ACCESS_KEY=minioadmin
S3_SECRET_KEY=minioadmin123
S3_PUBLIC_URL=http://localhost:9000/device-images
S3_ENDPOINT=https://images.staging.opensensemap.org
S3_REGION="eu-north-1"
S3_BUCKET="device-images"
S3_ACCESS_KEY="rustfsadmin"
S3_SECRET_KEY="rustfsadmin123"
4 changes: 3 additions & 1 deletion .github/FUNDING.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,6 @@ lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cl
polar: # Replace with a single Polar username
buy_me_a_coffee: # Replace with a single Buy Me a Coffee username
thanks_dev: # Replace with a single thanks.dev username
custom: ['https://www.betterplace.org/en/projects/89947-opensensemap-org-the-free-map-for-environmental-data'] # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']
custom: [
'https://www.betterplace.org/en/projects/89947-opensensemap-org-the-free-map-for-environmental-data',
] # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']
2 changes: 1 addition & 1 deletion .github/ISSUE_TEMPLATE/feature.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
name: Feature Request
description: Suggest a new feature or improvement
labels: ['enhancement']
labels: []
assignees: []

body:
Expand Down
18 changes: 9 additions & 9 deletions .github/dependabot.yaml
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
version: 2

updates:
- package-ecosystem: "github-actions"
directory: "/"
- package-ecosystem: 'github-actions'
directory: '/'
schedule:
interval: "weekly"
- package-ecosystem: "docker"
directory: "/"
interval: 'weekly'
- package-ecosystem: 'docker'
directory: '/'
schedule:
interval: "weekly"
- package-ecosystem: "npm"
directory: "/"
interval: 'weekly'
- package-ecosystem: 'npm'
directory: '/'
schedule:
interval: "weekly"
interval: 'weekly'
28 changes: 20 additions & 8 deletions .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -53,12 +53,20 @@ jobs:
- name: 📥 Install deps
run: npm install

- name: 🧾 Generate OpenAPI spec
run: npm run build:docs

- name: 🔎 Type check
run: npm run typecheck --if-present

vitest:
name: ⚡ Test
runs-on: ubuntu-latest
permissions:
# Required to checkout the code
contents: read
# Required to put a comment into the pull-request
pull-requests: write
steps:
- name: ⬇️ Checkout repo
uses: actions/checkout@v6
Expand All @@ -81,10 +89,10 @@ jobs:
# the sleep is just there to give time for postgres to get started
run: docker compose -f docker-compose.ci.yml up -d && sleep 30
env:
DATABASE_URL: "postgresql://postgres:postgres@localhost:5432/postgres"
DATABASE_URL: 'postgresql://postgres:postgres@localhost:5432/postgres'

- name: 🛠 Setup Database
uses: nick-fields/retry@v3.0.2
uses: nick-fields/retry@v4.0.0
with:
timeout_minutes: 10
max_attempts: 5
Expand Down Expand Up @@ -112,9 +120,7 @@ jobs:
uses: actions/checkout@v6

- name: 🐳 Set up Docker Buildx
uses: docker/setup-buildx-action@v3
with:
version: v0.9.1
uses: docker/setup-buildx-action@v4

# Setup cache
- name: ⚡️ Cache Docker layers
Expand All @@ -127,19 +133,24 @@ jobs:

- name: 📋 Docker meta
id: meta
uses: docker/metadata-action@v5
uses: docker/metadata-action@v6
with:
images: ghcr.io/opensensemap/frontend

- name: 👓 Read .nvmrc
id: nvmrc
run: |
echo "NODE_VERSION=$(cat .nvmrc)" >> $GITHUB_OUTPUT

- name: 🔑 GitHub Registry Auth
uses: docker/login-action@v3
uses: docker/login-action@v4
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: 🐳 Docker build
uses: docker/build-push-action@v6
uses: docker/build-push-action@v7
with:
context: .
file: ./other/Dockerfile
Expand All @@ -148,6 +159,7 @@ jobs:
labels: ${{ steps.meta.outputs.labels }}
build-args: |
COMMIT_SHA=${{ github.sha }}
NODE_VERSION=${{ steps.nvmrc.outputs.NODE_VERSION }}
cache-from: type=local,src=/tmp/.buildx-cache
cache-to: type=local,mode=max,dest=/tmp/.buildx-cache-new

Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/purge-pr.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,4 @@ jobs:
organization: ${{ github.repository_owner}}
container: ${{ github.event.repository.name }}
tag-regex: pr-${{github.event.pull_request.number}}$
dry-run: false
dry-run: false
4 changes: 2 additions & 2 deletions .github/workflows/purge.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name: 🗑️ Purge untagged images
on:
schedule:
- cron: "0 0 * * *"
- cron: '0 0 * * *'

permissions:
packages: write
Expand All @@ -16,4 +16,4 @@ jobs:
token: ${{ secrets.GITHUB_TOKEN }}
organization: ${{ github.repository_owner}}
container: ${{ github.event.repository.name }}
prune-untagged: true
prune-untagged: true
6 changes: 5 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,8 @@ measurements.csv

.react-router/

/coverage
/coverage

/minio-data
/rustfs-data
/public/openapi.json
2 changes: 1 addition & 1 deletion .nvmrc
Original file line number Diff line number Diff line change
@@ -1 +1 @@
v24.4.1
24.13.0
4 changes: 2 additions & 2 deletions .prettierignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,5 @@ node_modules
.env

/postgres-data

/app/styles/**/*.css
/db/seeds/**/*
/drizzle/**/*
111 changes: 76 additions & 35 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,22 @@
![openSenseMap](https://github.com/openSenseMap/frontend/blob/dev/public/openSenseMap.png)

This repository contains the code of the new _openSenseMap_ frontend running at [https://beta.opensensemap.org](https://beta.opensensemap.org).
This repository contains the code of the new _openSenseMap_ frontend running at
[https://beta.opensensemap.org](https://beta.opensensemap.org).

Originally, the _openSenseMap_ was built as part of the bachelor thesis of [@mpfeil](https://github.com/mpfeil) at the ifgi (Institute for Geoinformatics, University of Münster). Between 2016 and 2022 development was partly funded by the German Ministry of Education and Research (BMBF) in the projets senseBox and senseBox Pro. This version has been developed by [@mpfeil](https://github.com/mpfeil) and [@freds-dev](https://github.com/freds-dev).
Originally, the _openSenseMap_ was built as part of the bachelor thesis of
[@mpfeil](https://github.com/mpfeil) at the ifgi (Institute for Geoinformatics,
University of Münster). Between 2016 and 2022 development was partly funded by
the German Ministry of Education and Research (BMBF) in the projets senseBox and
senseBox Pro. This version has been developed by
[@mpfeil](https://github.com/mpfeil) and
[@freds-dev](https://github.com/freds-dev).

<img width="1438" alt="Screenshot OSeM" src="https://github.com/user-attachments/assets/a7bf16fb-44a2-4a21-9c0f-d4bf431ab9b5">

## Project setup

If you do need to set the project up locally yourself, feel free to follow these instructions:
If you do need to set the project up locally yourself, feel free to follow these
instructions:

### System Requirements

Expand All @@ -19,7 +27,8 @@ If you do need to set the project up locally yourself, feel free to follow these

### Variables

You can configure the API endpoint and/or map tiles using the following environmental variables:
You can configure the API endpoint and/or map tiles using the following
environmental variables:

| ENV | Default value |
| ------------------- | ------------------------------------ |
Expand All @@ -34,23 +43,28 @@ You can create a copy of `.env.example`, rename it to `.env` and set the values.
1. Clone the repo: `git clone https://github.com/openSenseMap/frontend`
2. Copy `.env.example` into `.env`
3. Run `npm install` to install dependencies
4. Optionally run `docker compose up` to start a docker container running your local postgres DB
- If it is the first time doing this, you may need to bootstrap the database by running `npm run db:setup`
- If you want some example data run `npm run db:seed`. **WARNING**: Do not run this on a production database. It will delete all existing data.
4. Optionally run `docker compose up` to start a docker container running your
local postgres DB
- If it is the first time doing this, you may need to bootstrap the database
by running `npm run db:setup`
- If you want some example data run `npm run db:seed`. **WARNING**: Do not
run this on a production database. It will delete all existing data.
5. Run `npm run dev` to start the local server

### Contributing

We welcome all kind of constructive contributions to this project.
If you are planning to implement a new feature or change something, please create an issue first.
We welcome all kind of constructive contributions to this project. If you are
planning to implement a new feature or change something, please create an issue
first.

Afterwards follow these steps:

1. Fork this repository
2. Create your feature branch (`git checkout -b my-new-feature`)
3. Make and commit your changes
4. Push to the branch (`git push origin my-new-feature`)
5. Create a new pull request against this repository's `dev` branch, linking your issue.
5. Create a new pull request against this repository's `dev` branch, linking
your issue.

#### How the repository is organized

Expand All @@ -75,18 +89,39 @@ Afterwards follow these steps:

#### openSenseMap API

The api is implemented using [Remix resource routes](https://remix.run/docs/en/main/guides/resource-routes).
Resource routes may not export a component but only [loaders](https://remix.run/docs/en/main/route/loader) (for `GET` requests) and [actions](https://remix.run/docs/en/main/route/action) (for `POST`, `PUT`, `DELETE` etc) and therefore live in `.ts` (not `.tsx`) files.
All resource routes start with `api` (e.g. `api.user.ts` for `/api/user`).

The api logic is shared with the frontend. Therefore api routes should not implement the actual business logic of an endpoint. They are responsible for checking the request for validity and for transforming the data into the correct output format.
Logic should be implemented in corresponding services, that may be used by loaders/ actions of page routes that access the same functionality.

For example: User registration is possible from both the api and the frontend. The logic for it is implemented in `lib/user.service.ts` and it is being used by both `api.user.ts` (resource route) as well as `explore.register.tsx` (page route), preventing duplication of common logic while also providing the flexibility to adjust the outputs to the needs of the respective use case.
The api is implemented using
[Remix resource routes](https://remix.run/docs/en/main/guides/resource-routes).
Resource routes may not export a component but only
[loaders](https://remix.run/docs/en/main/route/loader) (for `GET` requests) and
[actions](https://remix.run/docs/en/main/route/action) (for `POST`, `PUT`,
`DELETE` etc) and therefore live in `.ts` (not `.tsx`) files. All resource
routes start with `api` (e.g. `api.user.ts` for `/api/user`).

The api logic is shared with the frontend. Therefore api routes should not
implement the actual business logic of an endpoint. They are responsible for
checking the request for validity and for transforming the data into the correct
output format. Logic should be implemented in corresponding services, that may
be used by loaders/ actions of page routes that access the same functionality.

For example: User registration is possible from both the api and the frontend.
The logic for it is implemented in `lib/user.service.ts` and it is being used by
both `api.user.ts` (resource route) as well as `explore.register.tsx` (page
route), preventing duplication of common logic while also providing the
flexibility to adjust the outputs to the needs of the respective use case.

##### Documenting an API Route

The [swaggerJsdoc Library](https://www.npmjs.com/package/swagger-jsdoc) reads the JSDoc-annotated source code in the api-routes and generates an openAPI(Swagger) specification and is rendered using [Swaggger UI](https://swagger.io/tools/swagger-ui/). The [JSDoc annotations](https://github.com/Surnet/swagger-jsdoc) is usually added before the loader or action function in the API Routes. The documentation will then be automatically generated from the JSDoc annotations in all the api routes. When testing the api during development do not forget to change the server to [Development Server](http://localhost:3000). To authorize a user you must provide the token obtained after sign-in. You can just copy and paste the token in the value field and then hit the authorize button.
The [swaggerJsdoc Library](https://www.npmjs.com/package/swagger-jsdoc) reads
the JSDoc-annotated source code in the api-routes and generates an
openAPI(Swagger) specification and is rendered using
[Swaggger UI](https://swagger.io/tools/swagger-ui/). The
[JSDoc annotations](https://github.com/Surnet/swagger-jsdoc) is usually added
before the loader or action function in the API Routes. The documentation will
then be automatically generated from the JSDoc annotations in all the api
routes. When testing the api during development do not forget to change the
server to [Development Server](http://localhost:3000). To authorize a user you
must provide the token obtained after sign-in. You can just copy and paste the
token in the value field and then hit the authorize button.

##### JSDoc Example

Expand Down Expand Up @@ -144,29 +179,35 @@ Here's an example of how to document an API route using JSDoc annotations:
* description: Internal server error
*/
export async function loader({ params }) {
const { id } = params;

try {
const user = await getUserById(id);
if (!user) {
throw new Response("User not found", { status: 404 });
}
return Response.json({ user });
} catch (error) {
throw new Response("Internal server error", { status: 500 });
}
const { id } = params

try {
const user = await getUserById(id)
if (!user) {
throw new Response('User not found', { status: 404 })
}
return Response.json({ user })
} catch (error) {
throw new Response('Internal server error', { status: 500 })
}
}
```

This JSDoc annotation will automatically generate comprehensive API documentation including endpoint details, parameters, response schemas, and example values.
This JSDoc annotation will automatically generate comprehensive API
documentation including endpoint details, parameters, response schemas, and
example values.

#### Testing

Tests are placed in the [tests/](./tests/) folder whose structure is similar to the [app/](./app/) folder.
When adding a test, use the same name as the file you are testing but change the file extension to `.spec.ts`, e.g. when creating tests for [`./app/utils`](./app/utils.ts) name the test file [`./tests/utils.spec.ts`](./tests/utils.spec.ts).
Tests are placed in the [tests/](./tests/) folder whose structure is similar to
the [app/](./app/) folder. When adding a test, use the same name as the file you
are testing but change the file extension to `.spec.ts`, e.g. when creating
tests for [`./app/utils`](./app/utils.ts) name the test file
[`./tests/utils.spec.ts`](./tests/utils.spec.ts).

To run the tests, make sure you have a working database connection (e.g. by running `docker compose up` with the corresponding environment variables to use your local database).
Then simply run `npm test`.
To run the tests, make sure you have a working database connection (e.g. by
running `docker compose up` with the corresponding environment variables to use
your local database). Then simply run `npm test`.

## License

Expand Down
1 change: 0 additions & 1 deletion app/app.css

This file was deleted.

Loading
Loading