diff --git a/.env b/.env
new file mode 100644
index 0000000..1d5f734
--- /dev/null
+++ b/.env
@@ -0,0 +1,3 @@
+DB_NAME=tailfin
+MONGO_USERNAME=tailfin
+MONGO_PASSWORD=tailfin-api-password
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..44b4642
--- /dev/null
+++ b/README.md
@@ -0,0 +1,199 @@
+
+
+
+
+
+Tailfin
+
+A self-hosted digital flight logbook
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+## Table of Contents
+
+- [About](#about)
+- [Getting Started](#getting_started)
+ - [Docker](#docker)
+ - [From Source](#from_source)
+- [Configuration](#configuration)
+- [Usage](#usage)
+- [Roadmap](#roadmap)
+
+## About
+
+Tailfin is a digital flight logbook designed to be hosted on a personal server, computer, or cloud solution.
+
+I created this because I was disappointed with the options available for digital logbooks. The one provided by
+ForeFlight is likely most commonly used, but my proclivity towards self-hosting drove me to seek out another solution.
+Since I could not find any ready-made self-hosted logbooks, I decided to make my own.
+
+## Getting Started
+
+### Docker
+
+|:exclamation: Note :exclamation: |
+|---------------------------------|
+| Docker builds are considered unstable at this point and cannot be guaranteed to work without customization. Proceed at your own risk |
+
+1. Clone the repo
+
+```
+$ git clone https://git.github.com/azpsen/tailfin.git
+$ cd tailfin
+```
+
+2. Configure `docker-compose.yml` and `.env`
+
+3. Build/pull the images and start the service
+
+```
+$ docker compose build
+$ docker compose pull
+$ docker compose up -d
+```
+
+4. Log in to the web UI at `localhost:3000`
+
+### From Source
+
+#### Prerequisites
+
+- nodejs
+- npm
+- python 3.11
+- mongodb 7.0.4
+
+#### Installation
+
+##### 1. Clone the repo
+
+```
+$ git clone https://git.github.com/azpsen/tailfin.git
+$ cd tailfin
+```
+
+##### 2. Set up database
+
+[Install MongoDB](https://www.mongodb.com/docs/manual/installation/)
+
+[Enable Authentication](https://www.geeksforgeeks.org/how-to-enable-authentication-on-mongodb/)
+
+Add the `tailfin` user:
+
+```
+$ mongosh -u "yourAdminUsername" -p
+> use tailfin
+> db.createUser(
+ {
+ user: "tailfin-api",
+ pwd: "tailfin-api-password", // or passwordPrompt() for secure entry
+ db: "tailfin",
+ roles: [ { role: "readWrite", db: "tailfin" } ]
+ }
+)
+```
+
+##### 3. Set up backend
+
+```
+$ cd api
+```
+
+(Optional) Create and activate python virtual environment:
+
+```
+$ python -m venv tailfin-env
+$ source
+```
+
+Install python requirements:
+
+```
+$ pip install -r requirements.txt
+```
+
+[Configure the backend](#backend_configuration)
+
+##### 4. Set up frontend
+
+Install NPM requirements:
+
+```
+cd ../web
+$ npm install
+```
+
+Build and run the web app:
+
+```
+$ npm run build && npm run start
+```
+
+5. Access the web UI at `localhost:3000`
+
+## Configuration
+
+The URL for the Tailfin API can be set with the environment variable `TAILFIN_API_URL`. It defaults to `http://localhost:8081`, which assumes the API runs on the same machine and uses the default port.
+
+### Backend
+
+
+To configure Tailfin, modify the `.env` file. Some of these options should be changed before running the server. All
+available options are detailed below:
+
+`DB_URI`: Address of MongoDB instance. Default: `localhost`
+
+`DB_PORT`: Port of MongoDB instance. Default: `27017`
+
+`DB_NAME`: Name of the database to be used by Tailfin. Default: `tailfin`
+
+`DB_USER`: Username for MongoDB authentication. Default: `tailfin-api`
+
+`DB_PWD`: Password for MongoDB authentication. Default: `tailfin-api-password`
+
+`REFRESH_TOKEN_EXPIRE_MINUTES`: Duration in minutes to keep refresh token active before invalidating it. Default:
+`10080` (7 days)
+
+`ACCESS_TOKEN_EXPIRE_MINUTES`: Duration in minutes to keep access token active before invalidating it. Default: `30`
+
+`JWT_ALGORITHM`: Encryption algorithm to use for access and refresh tokens. Default: `HS256`
+
+`JWT_SECRET_KEY`: Secret key used to encrypt and decrypt access tokens. Default: `please-change-me`
+
+`JWT_REFRESH_SECRET_KEY`: Secret key used to encrypt and decrypt refresh tokens. Default: `change-me-i-beg-of-you`
+
+`TAILFIN_ADMIN_USERNAME`: Username of the default admin user that is created on startup if no admin users exist.
+Default: `admin`
+
+`TAILFIN_ADMIN_PASSWORD`: Password of the default admin user that is created on startup if no admin users exist.
+Default: `change-me-now`
+
+`TAILFIN_PORT`: Port to run the local Tailfin API server on. Default: `8081`
+
+Once the backend is running, full API documentation is available at `localhost:8081/docs`
+
+## Roadmap
+
+- [x] Create, view, edit, and delete flight logs
+- [x] Aircraft managment and association with flight logs
+- [x] Dashboard with statistics
+- [x] Attach photos to log entries
+- [ ] Import from other log applications (partially working for MyFlightBook)
+- [ ] Admin dashboard to manage all users and server configuration
+- [ ] GPS track recording and map display
+- [ ] Calendar view
+- [ ] PDF Export
+- [ ] Integrate database of airports and waypoints that can be queried to find nearest
diff --git a/api/dockerfile b/api/dockerfile
new file mode 100644
index 0000000..1662025
--- /dev/null
+++ b/api/dockerfile
@@ -0,0 +1,18 @@
+# Use an official Python runtime as a parent image
+FROM python:3.9
+
+# Set the working directory in the container to /app
+WORKDIR /app
+
+# Copy the current directory contents into the container at /app
+COPY . /app
+
+# Install any needed packages specified in requirements.txt
+RUN pip install --no-cache-dir -r requirements.txt
+
+# Make port 8081 available to the world outside this container
+EXPOSE 8081
+
+# Run app.py when the container launches
+CMD ["python", "app.py"]
+
diff --git a/docker-compose.yml b/docker-compose.yml
new file mode 100644
index 0000000..006bf38
--- /dev/null
+++ b/docker-compose.yml
@@ -0,0 +1,36 @@
+version: '3'
+services:
+ web:
+ build: ./web
+ container_name: tailfin-web
+ ports:
+ - 3000:3000
+ depends_on:
+ - api
+ api:
+ build: ./api
+ container_name: tailfin-api
+ environment:
+ - TAILFIN_DB_URI=db
+ - TAILFIN_DB_PORT=27017
+ - TAILFIN_DB_NAME=${DB_NAME}
+ - TAILFIN_DB_USER=${MONGO_USERNAME}
+ - TAILFIN_DB_PWD=${MONGO_PASSWORD}
+ - JWT_SECRET_KEY="please-change-me"
+ - JWT_REFRESH_SECRET_KEY="change-me-i-beg-of-you"
+ - TAILFIN_ADMIN_USERNAME="admin"
+ - TAILFIN_ADMIN_PASSWORD="change-me-now"
+ - TAILFIN_PORT=8081
+ depends_on:
+ - db
+ ports:
+ - 8081:8081
+ db:
+ image: mongo
+ container_name: tailfin-db
+ environment:
+ - MONGO_INITDB_ROOT_USERNAME=${MONGO_USERNAME}
+ - MONGO_INITDB_ROOT_PASSWORD=${MONGO_PASSWORD}
+ - MOGNO_INITDB_DATABASE=${DB_NAME}
+ ports:
+ - 27017:27017
diff --git a/img/logo.png b/img/logo.png
new file mode 100644
index 0000000..18e04e3
Binary files /dev/null and b/img/logo.png differ
diff --git a/img/mockup.png b/img/mockup.png
new file mode 100644
index 0000000..b564a21
Binary files /dev/null and b/img/mockup.png differ
diff --git a/web/dockerfile b/web/dockerfile
new file mode 100644
index 0000000..720a4e4
--- /dev/null
+++ b/web/dockerfile
@@ -0,0 +1,22 @@
+# Use an official Node runtime as a parent image
+FROM node:21-alpine
+
+# Set the working directory in the container to /app
+WORKDIR /app
+
+# Copy package.json and package-lock.json before other files
+# Utilise Docker cache to save re-installing dependencies if unchanged
+COPY package*.json ./
+
+# Install dependencies
+RUN npm install
+
+# Copy all files
+COPY . .
+
+# Build the app
+RUN npm run build
+
+# Serve the app on port 3000
+EXPOSE 3000
+CMD ["npm", "start"]