From 7c9248088b64b10cb2df7b8b4ac7750ce78caa00 Mon Sep 17 00:00:00 2001 From: Martin Alexander Kaminski Date: Thu, 5 Nov 2026 22:48:56 +0100 Subject: [PATCH 1/9] docs: add contributing guidelines --- CONTRIBUTING.md | 225 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 225 insertions(+) create mode 100644 CONTRIBUTING.md diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 00000000..8ae00c91 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,225 @@ +# Contributing to Readr + +Thank you for contributing to the project! +We appreciate all issues, pull requests and other comments regarding the project. + +Use this document as a reference when writing code, opening issues and pull requests and otherwise contributing to Readr. + +The keywords "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY" and "OPTIONAL" in this document are to be interpreted as in [RFC 2119](https://www.rfc-editor.org/info/rfc2119/). (This may be somewhat unknown or obscure to some, however, we think it makes the guidelines very clear.) + +## Git usage + +Commits MUST use [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/). +This makes the git history easier to search through and makes the purpose of each commit clearer. +If you're not sure which commit type fits best, you MUST pick one instead of leaving it completely empty. Trust your gut feeling. + +Some of the commit tags we use: + +- `feat`: Introduces a new feature +- `fix`: Fixes a bug or other smaller issue +- `refactor`: Code change that neither adds nor removes a feature, but cleans up the code in some way +- `style`: Adjusts formatting of code, but does not change it as substantially as a refactor, e.g. whitespace changes, missing semicolons, etc. +- `chore`: Smaller change that "just needs to be done", usually some routine task +- `build`: Something changed in the build system, e.g. package installed with `pnpm`, `package.json` or `vite.config.ts` changed +- `test`: Adding or modifying tests +- `docs`: Changes in documentation like Markdown files and similar +- `perf`: Code change that improves the performance of the app + +If you performed a breaking change, especially if this means other changes are required to make the app function as expected, mark the commit. +This is done by appending an exclamation mark (`!`) after the commit type and adding `BREAKING CHANGE` with a description in the commit footer. + +Example of a commit introducing a breaking change: + +``` +feat!: enforce stricter search rules + +BREAKING CHANGE: Old search needs to be updated. +We must adjust it so... +``` + +## Creating issues + +Issue descriptions do not need to be extremely detailed or long, but they MUST have enough explanations to understand the purpose of the issue and how to resolve it. + +Furthermore, issues MUST NOT be empty, i.e., have no description. + +Checklists or TODO lists are RECOMMENDED for large issues that require multiple tasks to be done. + +## Code style + +Code MUST be readable and maintainable. If you see you are writing spaghetti, it's time to refactor - preferably immediately. + +We use [Prettier](https://prettier.io/) as our code formatter. It is strongly RECOMMENDED to add it to your IDE so the code is formatted on save. +Please see the [VS Code Extensions](#vs-code-extensions) section for details. + +### Function definitions + +Arrow functions SHOULD be used for situations where it saves space and is more readable. +For larger, stand-alone functions with multiple lines of code (approximately 10+), the code MUST use the standard function syntax: + +```ts +// Prefer this: +function handleCalculations(arg1: string, arg2: number) { + // ... +} + +// Over this: +const handleCalculations = (arg1: string, arg2: number) => { + // ... +} +``` + +Helper functions inside components MUST also use the standard function syntax. + +### Exports + +Variables, functions and other objects that will be exported, MUST be exported at the end of the file: + +```ts +function func() { + // ... +} + +const SOMETHING_IMPORTANT = "value"; + +type Computer = { + name: string; + model: string; + ram: number; +} + +export { + func, + SOMETHING_IMPORTANT, + type Computer +} +``` + +The code MUST NOT export immediately: + +```ts +export function ... + +export const ... + +export type ... +``` + +Exceptions: + +- React Router routes need default export for the route itself and functions like `meta` +- Generated GraphQL resolver files (`backend/src/schema/[name]/resolvers/...`) +- Generated GraphQL type files (`*.generated.*`) + +### Generated files + +Files that are generated by Apollo Codegen or other tools, i.e. all `*.generated.*` files, MUST NOT be edited manually. +Any manual changes in these files will be overwritten the next time `pnpm codegen` is run. + +## Components + +### Folder structure + +Each component lives in its own folder to allow for a test file. + +Components which are used on multiple pages MUST use the following folder structure: + +`frontend/app/components/ComponentName/ComponentName.tsx` + +Components which are used on one page only MUST use the following folder structure: + +`frontend/app/components/pageName/ComponentName/ComponentName.tsx` + +The `pageName` SHOULD match the route file name, i.e. `frontend/app/routes/pageName.tsx`. + +> [!NOTE] +> Please note the casing of these folders and files. +> We use `camelCase` for page names and `PascalCase` for component names. + +Exceptions: + +- The `frontend/app/components/ui/` folder includes only files from [shadcn/ui](https://ui.shadcn.com/) that have been modified to fit our project where needed. + These do not need tests, and therefore they are not placed in their own folders. +- The components in `frontend/app/components/forms/` are grouped together because they are a part of forms used in the app. + +### Definitions + +All components MUST be defined as functions, and they MUST NOT use the arrow function syntax. + +A separate `ComponentNameProps` type SHOULD be used when the component uses many props, or if they have an advanced type. +Otherwise, using such a type is OPTIONAL. + +Example: + +```tsx +interface FavoriteButtonProps { + book: SearchBook; +} + +function FavoriteButton({ book }: FavoriteButtonProps) { + // Some data and calculations... + + return ( + + ); +} + +export { FavoriteButton }; +``` + +## VS Code Extensions + +We have added an [.vscode/extensions.json](./.vscode/extensions.json) to suggest great Visual Studio Code extensions that are useful for contributing to this project. +It's completely OPTIONAL to install these. + +Recommended extensions (in alphabetical order): + +- [Auto Rename Tag](https://marketplace.visualstudio.com/items?itemName=formulahendry.auto-rename-tag) +- [Code Spell Checker](https://marketplace.visualstudio.com/items?itemName=streetsidesoftware.code-spell-checker) +- [ESLint](https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint) +- [Prettier](https://marketplace.visualstudio.com/items?itemName=esbenp.prettier-vscode) +- [Pretty TypeScript Errors](https://marketplace.visualstudio.com/items?itemName=yoavbls.pretty-ts-errors) +- [Tailwind CSS IntelliSense](https://marketplace.visualstudio.com/items?itemName=bradlc.vscode-tailwindcss) + +## Before creating a pull request + +The app MUST be in a buildable state with no TypeScript and ESLint errors. + +Before opening a pull request, these commands MUST report no issues: + +```sh +# For the frontend: +cd frontend +pnpm lint +pnpm typecheck +pnpm test +pnpm build + +# And the backend: +cd ../backend +pnpm typecheck +pnpm build +``` + +## Working in this repository + +`main` is protected — you cannot push to it directly. Work on a branch and +open a pull request: + +```bash +git checkout -b feat/my-feature +git push -u origin feat/my-feature +``` + +Before a pull request can be merged: + +1. **A member of IT2810-H26-T37 MUST approve it.** You cannot approve your own pull + request, and approvals from staff do not count — you review each other's + code. +2. **Every review comment MUST be marked resolved.** Reply to each one, fix it + or explain why not, then click _Resolve conversation_. +3. **Pushing new commits dismisses the approval**, so if you change something + after being approved, ask for another review. This is deliberate: what was + approved is what gets merged. From 6c0097d72a28d63c78c7eaf1f711a850ded2eb54 Mon Sep 17 00:00:00 2001 From: Martin Alexander Kaminski Date: Thu, 5 Nov 2026 22:49:10 +0100 Subject: [PATCH 2/9] docs: refactor README sections to one list --- README.md | 62 ++++++++++++++++--------------------------------------- 1 file changed, 18 insertions(+), 44 deletions(-) diff --git a/README.md b/README.md index f498f9f6..626c1df3 100644 --- a/README.md +++ b/README.md @@ -14,47 +14,21 @@ In order to get started with the project, check the READMEs for the respective p - [Frontend README.md](./frontend/README.md) - [Backend README.md](./backend/README.md) -## Project choices and reasoning - -For more information about our project choices and reasoning for these, please see the [Project choices and reasoning documentation](./docs/choices-and-reasoning.md). - -## Infrastructure - -For a full walkthrough of the project's infrastructure and an example of how it's used in practice, please see our [Infrastructure documentation](./docs/infrastructure.md). - -## Deployment - -For more details on deploying the solution on a VM, see the [deployment documentation](/docs/deployment.md). - -## Sustainability - -Details about how we have developed the project with sustainability in mind can be found in the [sustainability documentation](/docs/sustainability.md). - -## Accessibility - -Details about how we have worked with accessibility can be found in the [accessibility documentation](/docs/accessibility.md). - -## Use of AI in this project - -Details about how we have used AI during development can be found in the [AI documentation](/docs/ai-documentation.md). - -## Working in this repository - -`main` is protected — you cannot push to it directly. Work on a branch and -open a pull request: - -```bash -git checkout -b my-feature -git push -u origin my-feature -``` - -Before a pull request can be merged: - -1. **A member of IT2810-H26-T37 must approve it.** You cannot approve your own pull - request, and approvals from staff do not count — you review each other's - code. -2. **Every review comment must be marked resolved.** Reply to each one, fix it - or explain why not, then click _Resolve conversation_. -3. **Pushing new commits dismisses the approval**, so if you change something - after being approved, ask for another review. This is deliberate: what was - approved is what gets merged. +## Contributing to the project + +Check out [CONTRIBUTING.md](./CONTRIBUTING.md) for further details regarding code style, standards regarding git usage, commits, issues, pull requests and more. + +## Other documentation + +- [Project choices and reasoning](./docs/choices-and-reasoning.md) + - Tech stack and tool choices, discussions and reasoning behind the decisions +- [Infrastructure](./docs/infrastructure.md) + - Describes our infrastructure and how it works in practice +- [Deployment](/docs/deployment.md) + - How the app is deployed on the provided VM +- [Sustainability](/docs/sustainability.md) + - More about how we've kept sustainability in mind when developing the application +- [Accessibility](/docs/accessibility.md) + - What steps we've taken to make the app accessible to everyone +- [AI documentation](/docs/ai-documentation.md) + - How AI was used during development From 6d6db8ee6a66dcd5573fd5773dd5ab37f2097744 Mon Sep 17 00:00:00 2001 From: Martin Alexander Kaminski Date: Thu, 5 Nov 2026 22:54:52 +0100 Subject: [PATCH 3/9] style: move exports to end of file --- backend/src/auth/index.ts | 4 +++- backend/src/schema/books/schema.mappers.ts | 4 +++- frontend/app/api/types/index.ts | 4 +++- frontend/app/hooks/formContext.ts | 4 +++- frontend/app/hooks/useAppForm.ts | 4 +++- 5 files changed, 15 insertions(+), 5 deletions(-) diff --git a/backend/src/auth/index.ts b/backend/src/auth/index.ts index 0ed79a6d..4050d6f0 100644 --- a/backend/src/auth/index.ts +++ b/backend/src/auth/index.ts @@ -3,7 +3,7 @@ import { drizzleAdapter } from "@better-auth/drizzle-adapter/relations-v2"; import { db } from "~/db"; import * as schema from "~/db/schema"; -export const auth = betterAuth({ +const auth = betterAuth({ database: drizzleAdapter(db, { provider: "pg", schema, @@ -32,3 +32,5 @@ export const auth = betterAuth({ }, trustedOrigins: [process.env.FRONTEND_URL ?? "http://localhost:5173"], }); + +export { auth }; diff --git a/backend/src/schema/books/schema.mappers.ts b/backend/src/schema/books/schema.mappers.ts index 3987890d..4f49314a 100644 --- a/backend/src/schema/books/schema.mappers.ts +++ b/backend/src/schema/books/schema.mappers.ts @@ -2,4 +2,6 @@ import type { SelectBook } from "~/db/schema/books"; // Resolvers return the DB row for a book. // The genres are resolved by the Book field resolver instead -export type BookMapper = SelectBook; +type BookMapper = SelectBook; + +export { type BookMapper }; diff --git a/frontend/app/api/types/index.ts b/frontend/app/api/types/index.ts index b19b8122..d5b21d03 100644 --- a/frontend/app/api/types/index.ts +++ b/frontend/app/api/types/index.ts @@ -1,6 +1,8 @@ -export interface BookFilters { +interface BookFilters { genres?: string[]; language?: string; bookFormat?: string; pages?: { min?: number; max?: number }; } + +export { type BookFilters }; diff --git a/frontend/app/hooks/formContext.ts b/frontend/app/hooks/formContext.ts index 8ac038fa..9e18575f 100644 --- a/frontend/app/hooks/formContext.ts +++ b/frontend/app/hooks/formContext.ts @@ -1,4 +1,6 @@ import { createFormHookContexts } from "@tanstack/react-form"; -export const { fieldContext, formContext, useFormContext, useFieldContext } = +const { fieldContext, formContext, useFormContext, useFieldContext } = createFormHookContexts(); + +export { fieldContext, formContext, useFormContext, useFieldContext }; diff --git a/frontend/app/hooks/useAppForm.ts b/frontend/app/hooks/useAppForm.ts index b9bba60e..7ca75ec1 100644 --- a/frontend/app/hooks/useAppForm.ts +++ b/frontend/app/hooks/useAppForm.ts @@ -4,7 +4,7 @@ import { TextareaField } from "~/components/forms/TextareaField/TextareaField"; import { TextField } from "~/components/forms/TextField/TextField"; import { fieldContext, formContext } from "~/hooks/formContext"; -export const { useAppForm } = createFormHook({ +const { useAppForm } = createFormHook({ fieldContext, formContext, fieldComponents: { @@ -15,3 +15,5 @@ export const { useAppForm } = createFormHook({ SubmitButton, }, }); + +export { useAppForm }; From 6b4964ced98282caabe60959f41c4bf8cfa71915 Mon Sep 17 00:00:00 2001 From: Martin Alexander Kaminski Date: Thu, 5 Nov 2026 23:03:10 +0100 Subject: [PATCH 4/9] docs: add guidelines for branches and pull requests --- CONTRIBUTING.md | 26 ++++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 8ae00c91..a3ae1032 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -9,6 +9,8 @@ The keywords "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SH ## Git usage +### Commits + Commits MUST use [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/). This makes the git history easier to search through and makes the purpose of each commit clearer. If you're not sure which commit type fits best, you MUST pick one instead of leaving it completely empty. Trust your gut feeling. @@ -37,6 +39,12 @@ BREAKING CHANGE: Old search needs to be updated. We must adjust it so... ``` +### Branches + +Branch names MUST use a conventional commit type, followed by a short name of the branch content. + +Example: `feat/new-book-search` + ## Creating issues Issue descriptions do not need to be extremely detailed or long, but they MUST have enough explanations to understand the purpose of the issue and how to resolve it. @@ -183,11 +191,13 @@ Recommended extensions (in alphabetical order): - [Pretty TypeScript Errors](https://marketplace.visualstudio.com/items?itemName=yoavbls.pretty-ts-errors) - [Tailwind CSS IntelliSense](https://marketplace.visualstudio.com/items?itemName=bradlc.vscode-tailwindcss) -## Before creating a pull request +## Pull requests + +### Checklist beforehand The app MUST be in a buildable state with no TypeScript and ESLint errors. -Before opening a pull request, these commands MUST report no issues: +Before opening a pull request, these commands MUST NOT report any issues: ```sh # For the frontend: @@ -203,6 +213,18 @@ pnpm typecheck pnpm build ``` +### Creating a pull request + +All pull requests (PRs): + +- MUST have a description. Again, it does not need to be extremely detailed, but it MUST explain what has been done +- MUST be assigned to the main contributor(s) of the commits in the PR +- MUST be connected to a milestone +- MUST be connected to an issue +- SHOULD have a fitting label, but it MAY be skipped in some rare cases + +For pull requests which change multiple aspects of the app, it is RECOMMENDED to use lists in order to provide explanations in a compact manner. + ## Working in this repository `main` is protected — you cannot push to it directly. Work on a branch and From 0a9f6edf98a3614b91d6f5da7c4f73e830662970 Mon Sep 17 00:00:00 2001 From: Martin Alexander Kaminski Date: Sat, 7 Nov 2026 17:47:44 +0100 Subject: [PATCH 5/9] docs: more detailed instructions about issues --- CONTRIBUTING.md | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index a3ae1032..1839ab34 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -47,9 +47,16 @@ Example: `feat/new-book-search` ## Creating issues -Issue descriptions do not need to be extremely detailed or long, but they MUST have enough explanations to understand the purpose of the issue and how to resolve it. - -Furthermore, issues MUST NOT be empty, i.e., have no description. +All GitHub issues: + +- MUST have a description with enough explanations to understand the purpose of the issue and how to resolve it, but they do not need to be extremely detailed or long + - We want to state explicitly that issues MUST NOT be empty, i.e., have no description +- MUST have a fitting type ("Bug", "Feature" or "Task") +- MUST be connected to a milestone, if a fitting one is available. Otherwise, this is OPTIONAL +- MUST be assigned to the person(s) working on the issue as soon as you being work + - This helps us avoid duplicate work being done +- MUST be connected to a pull request as soon as a PR that will resolve this issue is opened +- SHOULD have a fitting label, but it MAY be skipped in some rare cases Checklists or TODO lists are RECOMMENDED for large issues that require multiple tasks to be done. @@ -179,7 +186,7 @@ export { FavoriteButton }; ## VS Code Extensions -We have added an [.vscode/extensions.json](./.vscode/extensions.json) to suggest great Visual Studio Code extensions that are useful for contributing to this project. +We have added an [.vscode/extensions.json](./.vscode/extensions.json) file to suggest great Visual Studio Code extensions that are useful for contributing to this project. It's completely OPTIONAL to install these. Recommended extensions (in alphabetical order): @@ -219,7 +226,7 @@ All pull requests (PRs): - MUST have a description. Again, it does not need to be extremely detailed, but it MUST explain what has been done - MUST be assigned to the main contributor(s) of the commits in the PR -- MUST be connected to a milestone +- MUST be connected to a milestone, if a fitting one is available. Otherwise, this is OPTIONAL - MUST be connected to an issue - SHOULD have a fitting label, but it MAY be skipped in some rare cases From 70cb96d5cd83c61332eae5a139be4b600bb6f7b6 Mon Sep 17 00:00:00 2001 From: Martin Alexander Kaminski Date: Sun, 8 Nov 2026 16:22:44 +0100 Subject: [PATCH 6/9] docs: add comment about Lucide icons naming --- CONTRIBUTING.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 1839ab34..7f49c1a5 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -131,6 +131,15 @@ Exceptions: Files that are generated by Apollo Codegen or other tools, i.e. all `*.generated.*` files, MUST NOT be edited manually. Any manual changes in these files will be overwritten the next time `pnpm codegen` is run. +### Lucide icons + +Icons from [Lucide](https://lucide.dev/) are great, and we use them actively in the project. + +However, they provide at least two exports for each of their icons, namely the components `Name` and `NameIcon`, e.g. `Sun` and `SunIcon`. +The component name `Sun` does not make it immediately clear what it is. + +Therefore, the code MUST import and use the Lucide icons that use the full name, ending with `Icon`, e.g. `SunIcon`. + ## Components ### Folder structure From c14db0eb844f13c4d4347a234b17475aae11d910 Mon Sep 17 00:00:00 2001 From: Martin Alexander Kaminski Date: Sun, 8 Nov 2026 16:24:09 +0100 Subject: [PATCH 7/9] docs: clarify Lucide icons --- CONTRIBUTING.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 7f49c1a5..62e64e24 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -138,7 +138,7 @@ Icons from [Lucide](https://lucide.dev/) are great, and we use them actively in However, they provide at least two exports for each of their icons, namely the components `Name` and `NameIcon`, e.g. `Sun` and `SunIcon`. The component name `Sun` does not make it immediately clear what it is. -Therefore, the code MUST import and use the Lucide icons that use the full name, ending with `Icon`, e.g. `SunIcon`. +Therefore, code that uses Lucide icons MUST import and use components with their full name, ending with `Icon`, e.g. `SunIcon`. ## Components From 20993e5c4c3087ee9b76c87660e51d1e59b7a71e Mon Sep 17 00:00:00 2001 From: Martin Alexander Kaminski Date: Tue, 10 Nov 2026 20:30:58 +0100 Subject: [PATCH 8/9] docs: add guidelines about SQL code --- CONTRIBUTING.md | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 62e64e24..1c62aaa0 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -140,6 +140,23 @@ The component name `Sun` does not make it immediately clear what it is. Therefore, code that uses Lucide icons MUST import and use components with their full name, ending with `Icon`, e.g. `SunIcon`. +### SQL Code + +[Drizzle ORM](https://orm.drizzle.team/) provides a lot of utilities for writing SQL queries, but for some advances ones, we still write a little bit of raw SQL code. +This is done using the `sql` function. + +Raw SQL, both in code and SQL migration, MUST be written in UPPERCASE: + +```ts +sql`${books.rating} ASC NULLS LAST` +``` + +Avoid the following: + +```ts +sql`${books.rating} asc nulls last` +``` + ## Components ### Folder structure From a957e45fda735355e06f8463fb5737b295ad2cb5 Mon Sep 17 00:00:00 2001 From: Martin Alexander Kaminski Date: Tue, 10 Nov 2026 20:31:31 +0100 Subject: [PATCH 9/9] docs: typo in contributing --- CONTRIBUTING.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 1c62aaa0..a2cbd6b3 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -142,8 +142,8 @@ Therefore, code that uses Lucide icons MUST import and use components with their ### SQL Code -[Drizzle ORM](https://orm.drizzle.team/) provides a lot of utilities for writing SQL queries, but for some advances ones, we still write a little bit of raw SQL code. -This is done using the `sql` function. +[Drizzle ORM](https://orm.drizzle.team/) provides a lot of utilities for writing SQL queries, but for some advanced ones, we still write a little bit of raw SQL code. +This is done using the `sql` function so the parameters are parsed in a safe way. Raw SQL, both in code and SQL migration, MUST be written in UPPERCASE: