# About

This is a template for building a webapp using the following tech stack:

- **Frontend**:
    - [Vue.js](https://vuejs.org/guide/introduction.html) - frontend JS framework
    - [Vue Router](https://router.vuejs.org/guide/) - frontend router for Vue
    - [TailwindCSS](https://tailwindcss.com/docs/configuration) - CSS framework
    - [Axios](https://axios-http.com/docs/intro) - library for making API requests from the frontend
    - [Parcel](https://parceljs.org/docs/) - bundler used for frontend module resolution and asset optimization
    - [npm](https://docs.npmjs.com/cli/v7/configuring-npm/package-json) - node package manager for JavaScript packages
- **Backend**:
    - [FastAPI](https://fastapi.tiangolo.com/) - Python-framework for backend APIs
    - [Uvicorn](https://www.uvicorn.org/) - Python-ASGI-server used to serve the FastAPI backend
- **Other**:
    - [Caddy](https://caddyserver.com/docs/) - webserver and reverse proxy used for serving static files and HTTP routing
    - [Dockerfile](https://docs.docker.com/engine/reference/builder/) - recipes for building Docker images
    - [Docker Compose](https://docs.docker.com/compose/compose-file/) - used to deploy interconnected Docker containers for development and/or production

Two different configurations are provided and instanced using the docker-related files in this template repository:

- The [production configuration](#production-configuration) is used for preformance-optimized production deployments of your web application
- The [development configuration](#development-configuration) is used during development of your web application, providing features such as hot-reloading and debugging information

This should go without saying, but **do not serve the development configuration** on a public production server.

## Production Configuration

The production-ready configuration can be deployed using the `production.docker-compose.yml` file, by running (as root):

```sh
docker-compose -f production.docker-compose.yml up -d --force-recreate --build --remove-orphans
```

This starts two containers, called `backend` and `frontend`, and exposes the deployed web application on port `8000`.
You can open a browser and navigate to [http:localhost:8000/](http:localhost:8000/) to try it out.

To stop the containers, run the following as root:
```sh
docker-compose -f production.docker-compose.yml down
```

### Production Frontend Container

The `frontend` production Docker image is built according to `production.frontend.Dockerfile`.
It is based on Debian and initially installs Caddy, as well as npm, and creates a non-root-user to run Caddy as.

Next up, the image copies over and bundles the frontend code and assets using Parcel.

Finally, it starts an instance of Caddy, which is a web server used to route HTTP traffic and serve static files.

The files bundled by Parcel are then served as static files by Caddy, with `/frontend/src/html/index.html` as the site root (served at
[http:localhost:8000/](http:localhost:8000/).

Caddy is configured to forward any requests with the `/api/`-prefix to the [backend-container](#production-backend-container).

Because Parcel renames files when bundling them, Caddy is also configured to serve unbundled static files in this template.
All files and folders under the `/public/static/` directory are copied into the image and served under the `/static/`-prefix by Caddy,
without being bundled (and renamed) by Parcel.
For example: the file `/public/static/images/tux.svg` can be accessed at [http://localhost:8000/static/images/tux.svg](http://localhost:8000/static/images/tux.svg)
in your browser.

The `/robots.txt` and `/sitemap.xml` files are served by Caddy, and are sourced from the `/robots/`-directory, where you should [customize](#customization)
them as necessary.
You can view the results at [http://localhost:8000/robots.txt](http://localhost:8000/robots.txt) and
[http://localhost:8000/sitemap.xml](http://localhost:8000/sitemap.xml) respectively.

### Production Backend Container

The `backend`-container serves FastAPI-endpoints using [uvicorn](https://www.uvicorn.org/).
All HTTP requests requesting paths under `/api/` are routed here by Caddy (which runs within the [frontend-container](#production-frontend-container)).

Uvicorn's root path is configured such that the backend code does not need to include the `/api/`-prefix of the route.
As an example, take a look at the `hello()`-endpoint declared in `/backend/main.py`: in the code, it is declared at `/hello/`,
but in the browser, you access the endpoint at [http://localhost:8000/api/hello/](http://localhost:8000/api/hello/).

This prevents repetition when writing your endpoint code and allows you to access the interactive Swagger API documentation at
[http://localhost:8000/api/docs](http://localhost:8000/api/docs), which is auto-generated by FastAPI.

## Development Configuration

The development configuration can be deployed using the `development.docker-compose.yml` file, by running (as root):

```sh
docker-compose -f development.docker-compose.yml up -d --build --force-recreate --remove-orphans
```

This starts three containers, called `backend`, `parcel` and `frontend`, and exposes the deployed web application on port `8000`.
You can open a browser and navigate to [http:localhost:8000/](http:localhost:8000/) to try it out.

To stop the containers, run the following as root:
```sh
docker-compose -f development.docker-compose.yml down
```

The development containers work very similarly to the production containers, with the exception that hot reloading of configuration
and sourcecode files is enabled.

This means that when you modify the frontend or backend sourcecode while the development container is running, the changes are detected
and applied automatically, restarting the containers is usually not required.

# Customization

A number of default configuration files and placeholder assets for the frontend are already present in the repository.

You should, at **minimum**, adjust the following things according to your requirements (otherwise things will not work as expected):

- [ ] `package.json`
- [ ] [robots.txt and sitemap.xml](#robots-and-sitemap)
- [ ] the `<meta>`-tags in `/frontend/src/html/index.html`
- [ ] [OG Image](#og-image) and [favicon](#favicon)

## Assets

The template in this repo provides and references some placeholder-assets which you should replace with your own.

### Favicon

The standards for accepted favicon formats are all over the place and, depending on browser- and OS-vendors, expect a different format.

A quick and easy way to create a set of favicons with broad compatibility is to create your favicon as an `.svg`/`.png`-file,
and then use [realfavicongenerator.net](https://realfavicongenerator.net/) to create a set of relevant files and HTML references
for your favicon.

Place the generated icons into `/frontend/assets/images/common/favicon/` and be sure to adjust the generated HTML to point to
the files placed under this path. Parcel will resolve the paths accordingly.

For reference, I created `/frontend/assets/images/common/favicon/favicon.svg`, and uploaded it to the favicongenerator.
I placed the resulting files into `/frontend/assets/images/common/favicon/` and updated `/frontend/src/html/index.html` accordingly.

### OG Image

The OG image should ideally be a `.webp`-file, and its dimensions should be at least 1200 x 630 pixels, as according to the
[OGP standard](https://developers.facebook.com/docs/sharing/webmasters/images/).

A placeholder OG image can be found at `/frontend/assets/images/common/og-image.webp`.

### Robots and Sitemap

The `/robots/robots.txt` and `/robots/sitemap.xml` files are added to the [frontend docker container](#production-frontend-container)
and served at the site root upon deployment.

Both files are crucial for search engine visibility and SEO, so you should adjust them as necessary (depending on whether you want your site to be indexed).

### Fonts

Static font files are stored under `/frontend/assets/fonts/` and declared for use in CSS within `/frontend/src/css/fonts.css`.
The added font families can be accessed using TailwindCSS after configuring them inside `tailwind.config.js`.

You can add or remove fonts here as necessary.

## Configuration Files

Depending on the configuration you wish to customize, please refer to each component's [relevant documentation](#about).

# TODOs / Roadmap

1. Add sqlite/postgres containers
2. Minify CSS in prod
3. Add testing tools
