diff --git a/.github/workflows/deploy-backend.yml b/.github/workflows/deploy-backend.yml
new file mode 100644
index 0000000..5ea6656
--- /dev/null
+++ b/.github/workflows/deploy-backend.yml
@@ -0,0 +1,19 @@
+name: deploy-backend
+
+on:
+ push:
+ branches: [ "main" ]
+
+steps:
+ - uses: actions/checkout@v3
+ name: Check out code
+
+ - uses: mr-smithers-excellent/docker-build-push@v6
+ name: Build & push Docker image
+ with:
+ image: cess-advisor-backend
+ tags: latest
+ registry: ghcr.io
+ dockerfile: Dockerfile
+ username: ${{ secrets.GHCR_USERNAME }}
+ password: ${{ secrets.GHCR_TOKEN }}
diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml
deleted file mode 100644
index be83a3a..0000000
--- a/.github/workflows/deploy.yml
+++ /dev/null
@@ -1,20 +0,0 @@
-name: deploy
-
-on:
- push:
- branches: [ "main" ]
-
-jobs:
- deploy:
- name: Deploy
- runs-on: ubuntu-latest
- steps:
- - name: executing remote ssh commands
- uses: appleboy/ssh-action@v1.0.3
- with:
- command_timeout: 30m
- host: ${{ secrets.HOST }}
- username: ${{ secrets.USERNAME }}
- port: ${{ secrets.PORT }}
- key: ${{ secrets.KEY }}
- script: ${{ secrets.SCRIPT }}
diff --git a/.gitignore b/.gitignore
index 30b98b3..d0b4476 100644
--- a/.gitignore
+++ b/.gitignore
@@ -14,5 +14,6 @@ package
.env
.env.*
!.env.example
+!.env.template
vite.config.js.timestamp-*
vite.config.ts.timestamp-*
diff --git a/README.md b/README.md
index 6bb43d3..0a18128 100644
--- a/README.md
+++ b/README.md
@@ -4,10 +4,9 @@
**Cess Advisor** 🐪🚽 is a _stupid_ yet really _useful_ web app that helps you find a _suitable toilet_ when you are in a hurry.
-
## Tech stack
-In short: **OCaml** 🐪 (Sihl) + **JavaScript** 🤢 (Svelte) + **PostgreSQL** 🐘 + Docker 🐳 + GitHub Actions 🚀
+TL;DR: **OCaml** 🐪 (Sihl) + **JavaScript** 🤢 (Svelte) + **PostgreSQL** 🐘
> [!TIP]
> If you want to preserve your mental health, you should **NOT** write JavaScript code _(and frontends in general)_. OCaml is just better.
@@ -17,25 +16,47 @@ In short: **OCaml** 🐪 (Sihl) + **JavaScript** 🤢 (Svelte) + **PostgreSQL**
- Backend: **OCaml** 🐪
- [Sihl](https://github.com/oxidizing/sihl): OCaml framework for building web apps
- - [Opium](https://github.com/rgrinberg/opium/): OCaml framework for managing HTTP requests
+ - [Opium](https://github.com/rgrinberg/opium/): OCaml library for managing HTTP requests
- [Caqti](https://github.com/paurkedal/ocaml-caqti): OCaml library for interacting with databases
- [Yojson](https://github.com/ocaml-community/yojson): OCaml library for JSON serialization
- [Validate](https://github.com/Axot017/validate): OCaml library for validating schemas
-- Frontend: **JavaScript** ⚛️
- - [Sveltekit](https://kit.svelte.dev/): JavaScript framework for frontend web development
+- Frontend: **JavaScript** 🤢
+ - [Sveltekit](https://kit.svelte.dev/): JavaScript framework for web development
- [Tailwind CSS](https://tailwindcss.com/): CSS framework
- [DaisyUI](https://daisyui.com/): Tailwind components library
- Database: 🐘
- [PostgreSQL](https://www.postgresql.org/): relational database
-- Deployment: 🐳
- - [Docker](https://www.docker.com/): containerization
- - [GitHub Actions](https://docs.github.com/en/actions): CI/CD
+
+
+## Deployment
+
+TL;DR: **Docker** 🐳 + **GitHub Actions** 🤖 for backend and **Cloudflare Pages** ☁️ for frontend
+
+
+Detailed deployment
+
+- Backend: **Docker** 🐳 + **GitHub Actions** 🤖
+ - each time a commit is pushed to the `main` branch, `deploy` GitHub action is triggered
+ - the action builds the Docker image and pushes it to the GitHub container registry
+ - the image is then pulled by my homelab server (periodically checked with Watchtower) and the container is started
+ - the backend is available at [https://cessadvisorapi.favo02.dev](https://cessadvisorapi.favo02.dev)
+
+- **Frontend**: **Cloudflare Pages** ☁️
+ - each time a commit is pushed to the `main` branch, the Cloudflare pages integration detects the change
+ - the integration builds the Sveltekit app with some magic
+ - the frontend is available at [https://cessadvisor.pages.dev](https://cessadvisor.pages.dev) (and [https://cessadvisor.favo02.dev](https://cessadvisor.favo02.dev))
+## Contributing
+
+Each contribution is **welcome**, especially building alteranive better frontends _(if you are brave enough to write JavaScript code)_ that uses the same API.
+
+Please follow the [conventions](#conventions) below.
+
## Conventions
diff --git a/backend/backend.opam b/backend/backend.opam
index 269a655..8af5365 100644
--- a/backend/backend.opam
+++ b/backend/backend.opam
@@ -10,13 +10,13 @@ doc: "https://github.com/Favo02/cess-advisor"
bug-reports: "https://github.com/Favo02/cess-advisor/issues"
depends: [
"ocaml" {>= "5.0.0"}
- "dune" {>= "3.10" & >= "3.15.0"}
- "sihl" {>= "3.0.5"}
- "caqti-driver-postgresql" {>= "2.1.1"}
- "lwt_ppx" {>= "2.1.0"}
- "ppx_yojson_conv" {>= "v0.16.0"}
- "validate" {>= "1.1.0"}
- "safepass" {>= "3.0"}
+ "dune" {>= "3.10"}
+ "sihl"
+ "caqti-driver-postgresql"
+ "lwt_ppx"
+ "ppx_yojson_conv"
+ "validate"
+ "safepass"
"odoc" {with-doc}
]
build: [
diff --git a/backend/dune-project b/backend/dune-project
index abbc1ec..26ba5f8 100644
--- a/backend/dune-project
+++ b/backend/dune-project
@@ -21,10 +21,10 @@
(description "REST API for Cess Advisor, a toilet review system")
(depends
(ocaml (>= 5.0.0))
- (dune (>= 3.15.0))
- (sihl (>= 3.0.5))
- (caqti-driver-postgresql (>= 2.1.1))
- (lwt_ppx (>= 2.1.0))
- (ppx_yojson_conv (>= v0.16.0))
- (validate (>= 1.1.0))
- (safepass (>= 3.0))))
+ dune
+ sihl
+ caqti-driver-postgresql
+ lwt_ppx
+ ppx_yojson_conv
+ validate
+ safepass))
diff --git a/backend/src/main.ml b/backend/src/main.ml
index 8325c32..a9c477c 100644
--- a/backend/src/main.ml
+++ b/backend/src/main.ml
@@ -27,7 +27,7 @@ let auth = Web.choose ~scope: "/api" ~middlewares: [ require_login; verify_expir
Web.post "/reviews/create" Handlers.Reviews.create;
]
-let router = Web.choose ~middlewares: [ logger; ] [
+let router = Web.choose ~middlewares: [ logger; Opium.Middleware.allow_cors (); ] [
public;
no_auth;
auth;
diff --git a/docker-compose.yml b/docker-compose.yml
deleted file mode 100644
index 4b7e7e5..0000000
--- a/docker-compose.yml
+++ /dev/null
@@ -1,13 +0,0 @@
-version: '3'
-
-services:
-
- backend:
- container_name: cess-advisor-backend
- restart: unless-stopped
- build:
- context: .
- volumes:
- - './logs:/app/logs'
- ports:
- - 3057:3000
diff --git a/frontend/.env.template b/frontend/.env.template
new file mode 100644
index 0000000..4c78f38
--- /dev/null
+++ b/frontend/.env.template
@@ -0,0 +1,7 @@
+# template for .env file
+
+# production (the default URL is already set)
+VITE_API_URL=https://cessadvisorapi.favo02.dev
+
+# development
+# VITE_API_URL=http://localhost:3000
diff --git a/frontend/src/routes/+page.svelte b/frontend/src/routes/+page.svelte
index ca60e35..f5bb561 100644
--- a/frontend/src/routes/+page.svelte
+++ b/frontend/src/routes/+page.svelte
@@ -11,7 +11,7 @@
onMount(async () => {
try {
- const response = await axios.get("/api/stats");
+ const response = await axios.get(`${import.meta.env.VITE_API_URL}/api/stats`);
users_count = response.data.users;
toilets_count = response.data.toilets;
reviews_count = response.data.reviews;
diff --git a/frontend/src/routes/login/+page.svelte b/frontend/src/routes/login/+page.svelte
index bc489c2..779549e 100644
--- a/frontend/src/routes/login/+page.svelte
+++ b/frontend/src/routes/login/+page.svelte
@@ -9,7 +9,7 @@
try {
loading = true;
- const response = await axios.post("/api/login", { username, password });
+ const response = await axios.post(`${import.meta.env.VITE_API_URL}/api/login`, { username, password });
if (response.status === 200) {
alert("Login successful");
diff --git a/frontend/src/routes/logout/+page.svelte b/frontend/src/routes/logout/+page.svelte
index 369be6a..528e472 100644
--- a/frontend/src/routes/logout/+page.svelte
+++ b/frontend/src/routes/logout/+page.svelte
@@ -7,7 +7,7 @@
try {
loading = true;
- const response = await axios.post("/api/logout");
+ const response = await axios.post(`${import.meta.env.VITE_API_URL}/api/logout`);
if (response.status === 200) {
alert("Logout successful");
diff --git a/frontend/src/routes/profile/+page.svelte b/frontend/src/routes/profile/+page.svelte
index d161e45..bbfa813 100644
--- a/frontend/src/routes/profile/+page.svelte
+++ b/frontend/src/routes/profile/+page.svelte
@@ -1,7 +1,7 @@
Profile
diff --git a/frontend/vite.config.js b/frontend/vite.config.js
index c3711ae..bbf8c7d 100644
--- a/frontend/vite.config.js
+++ b/frontend/vite.config.js
@@ -2,10 +2,5 @@ import { sveltekit } from '@sveltejs/kit/vite';
import { defineConfig } from 'vite';
export default defineConfig({
- plugins: [sveltekit()],
- server: {
- proxy: {
- '/api': 'http://localhost:3000'
- }
- }
+ plugins: [sveltekit()]
});