Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
9bfd71c
Base
GnisterDev Apr 30, 2026
a0c369c
Table of content
GnisterDev Apr 30, 2026
7a53f2a
Update readme
GnisterDev Apr 30, 2026
f1815b9
Update order
GnisterDev Apr 30, 2026
057f6d7
Update Additional documentation section
GnisterDev Apr 30, 2026
61929de
Update text
GnisterDev Apr 30, 2026
a7125cb
Video comment
GnisterDev Apr 30, 2026
44bf379
started on test section of root `README.md`
GnisterDev May 1, 2026
8e90dcd
Enviorment variable table outline
GnisterDev May 1, 2026
e916150
Added e2e section
GnisterDev May 1, 2026
45d197c
Syntax fixes
GnisterDev May 1, 2026
55a04e3
Update testing section
GnisterDev May 1, 2026
b3bdb8f
Monorepo table
GnisterDev May 1, 2026
dc91c8b
Update monorepo text
GnisterDev May 1, 2026
b789ec5
TOC
GnisterDev May 1, 2026
9321bec
TOC fixed
GnisterDev May 1, 2026
ec16de2
update badge color to red
GnisterDev May 1, 2026
fc54ef7
Update badges
GnisterDev May 1, 2026
c3f8253
Merge remote-tracking branch 'origin/main' into website/root-readme
GnisterDev May 2, 2026
9a7c68b
Add video
GnisterDev May 3, 2026
bc73a7b
Delete Video - Was too big
GnisterDev May 3, 2026
561c355
Update readme
GnisterDev May 3, 2026
e65bdfc
env variables
igiwa001 May 4, 2026
4e33f25
env variables wip
igiwa001 May 4, 2026
a789a9d
wip
igiwa001 May 5, 2026
c12667e
Merge branch 'main' into website/root-readme
igiwa001 May 5, 2026
288f854
wip
igiwa001 May 5, 2026
bee5519
getting started wip
igiwa001 May 5, 2026
e25c5e1
env vars wip
igiwa001 May 5, 2026
9188b65
env vars wip
igiwa001 May 5, 2026
ac9839a
env vars
igiwa001 May 5, 2026
c72f71e
toc
igiwa001 May 5, 2026
2b65b4f
monorepo structure
igiwa001 May 5, 2026
af74d0f
architecture
igiwa001 May 5, 2026
7b8c40c
Key features
GnisterDev May 6, 2026
ef0da22
Thumbnails
GnisterDev May 6, 2026
a63da7c
...
GnisterDev May 6, 2026
d81ee24
Fix videos
GnisterDev May 6, 2026
83dc796
Video test
GnisterDev May 6, 2026
326e466
Another video test
GnisterDev May 6, 2026
a1fae8c
Video html
GnisterDev May 6, 2026
4a46f78
Update to gifs
GnisterDev May 6, 2026
a207158
Update overview
GnisterDev May 6, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added .github/media/create_event.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added .github/media/header.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added .github/media/moderate.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added .github/media/upload_image.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
238 changes: 238 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,238 @@
<div align="center">

![Logo header](.github/media/header.png)

</div>

<div align="center">

![License](https://img.shields.io/github/license/IT2901-Group-2/FLASH?style=for-the-badge)
![Issues](https://img.shields.io/github/issues/IT2901-Group-2/FLASH?style=for-the-badge)
![TypeScript](https://img.shields.io/github/actions/workflow/status/IT2901-Group-2/FLASH/ci.yaml?branch=main&style=for-the-badge)
![Last Commit](https://img.shields.io/github/last-commit/IT2901-Group-2/FLASH?style=for-the-badge)

</div>

<div align="center">

![NTNU IT2901](https://img.shields.io/badge/NTNU-IT2901-red?style=for-the-badge)

</div>

## Table of Contents

- [Overview](#overview)
- [Key Features](#key-features)
- [Architecture](#architecture)
- [Tech Stack](#tech-stack)
- [Monorepo Structure](#monorepo-structure)
- [Getting Started](#getting-started)
- [Building the Docker Image](#building-the-docker-image)
- [Running the Docker Image](#running-the-docker-image)
- [Configuration](#configuration)
- [Development](#development)
- [Requirements](#requirements)
- [Tests](#tests)
- [Test Overview](#test-overview)
- [Running Tests](#running-tests)
- [Running the Application](#running-the-application)

## Overview

FLASH is a privacy-focused web application designed to capture and share memories from weddings and other special events. Create events, let guests join and upload photos, then moderate the images - choosing which images gets rejected and which are approved. A key feature of the application is the slideshow, so you can shows all approved images on the big screen.

### Key Features

| Creating an Event | Upload Images | Moderation |
| ------------------------------------------------------- | ------------------------------------------------------- | --------------------------------------------------- |
| <img src=".github/media/create_event.gif" height="250"> | <img src=".github/media/upload_image.gif" height="250"> | <img src=".github/media/moderate.gif" height="250"> |

## Architecture

### Tech Stack

- **Frontend**: React with TypeScript + vanilla CSS
- **Framework**: Next.js (handles both frontend rendering and API routes)
- **Backend**: Node.js (via Next.js API routes)
- **PWA** support: The app can be installed and used as a Progressive Web App
- **Storage**: Configurable through the file-storage package (local by default,
optional cloud backends)
- **Testing/infrastructure**: Docker is used to run local instances of external
services (e.g. storage) during testing

### Monorepo Structure

This project uses a monorepo structure where the main application and shared
functionality are split into separate packages:

| Package | Description |
| ------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| [**`website`**](./apps/website/README.md) | The heart of `FLASH`. Built with Next.js, it contains both the React frontend and backend API routes. The frontend uses shared components from UI and styling from tokens. The backend provides endpoints for events, image handling, authentication, and admin functionality. |
| [**`file-storage`**](./packages/file-storage/README.md) | Handles all file storage operations through a common interface (upload, retrieval, deletion). The application interacts with storage exclusively through this package. Uses local filesystem storage by default, with support for alternative backends configured via environment variables. |
| [**`UI`**](./packages/ui/README.md) | Shared React component library used by the frontend. Components are intended to be reusable and consistent across the application. |
| [**`tokens`**](./packages/tokens/README.md) | Centralized TypeScript-first CSS design tokens (e.g. colors, spacing, typography) used by the UI components and frontend. |

## Getting Started

FLASH can be self-hosted on any VPS capable of running Node.js. For ease of use
we provide a `Dockerfile` which packages all the dependencies needed for FLASH
to function. For building and running the application locally, see
[Running the Application](#running-the-application).

### Building the Docker Image

Currently we do not provide pre-built docker images, so you will have to build
one yourself. The only requirement is that your computer has `Docker` installed.

Building the docker image can be done by running:

```bash
pnpm docker
# or
docker build . -t flash # If `pnpm` is not available on your system
```

### Running the Docker Image

After the docker image is built, FLASH can be started using the following
command, where `<port>` is the port number you want to expose the application
on.

```bash
docker run -p <port>:3000 flash
```

Many of FLASH's features can be configured using environment variables, which
are described in more detail [below](#configuration). They can be passed to the
docker container using the `-e` flag. For example setting the administrator
password would look like this:

```bash
docker run -p <port>:3000 -e ADMIN_PASSWORD=1234 flash
```

Another useful `docker run` flag is `-v`, which shares a host folder with the
docker container. It can be used in conjunction with the `FS` storage to persist
events and images to a local folder on the host between container runs.

```bash
docker run -p <port>:3000 -e STORAGE_BACKEND=fs -e STORAGE_DIR=/srv/flash -v <local-folder>:/srv/flash flash
```

The full `docker run` documentation can be found
[here](https://docs.docker.com/reference/cli/docker/container/run/).

### Configuration

| Variable | Default Value | Description |
| --------------------------- | ------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `ADMIN_PASSWORD` | `"Default"` | The administrator password. |
| `TOAST_DISPLAY_TIME` | `5000` (5 seconds) | The amount of time in milliseconds notification toasts stay on screen for. |
| `MULTI_FILE_UPLOAD` | `false` | Whether or not to allow users to upload multiple images at once. `"true"` and `"1"` are accepted as truthy values. |
| `SLIDESHOW_SLIDE_DURATION` | `10000` (10 seconds) | The amount of time in milliseconds before progressing to the next slide on the slideshow. |
| `MAX_IMAGE_SIZE` | `12582912` (12 MiB) | The maximum image size in bytes that the user is allowed to upload. |
| `EVENT_REFETCH_INTERVAL` | `120000` (120 seconds) | The amount of time in milliseconds to wait before polling for changes in events. |
| `PHOTOS_REFETCH_INTERVAL` | `12000` (12 seconds) | The amount of time in milliseconds to wait before polling for changes in images. |
| `JWT_SECRET` | `"SUPER_SECRET_KEY"` | The secret key to use for JWT token encryption/decryption. Keep this private. |
| `STORAGE_BACKEND` | `"fs"` | Which storage backend to use. Currently one of `"fs"` or `"gcloud"`. |
| `STORAGE_DIR` | `$tmp/flash` (N.B. The value of `$tmp` is OS-dependent) | Path to the directory to store the FLASH database in. Only relevant if `STORAGE_BACKEND="fs"`. |
| `GCP_BUCKET` | - | The name of the Google Cloud Storage bucket to save store the FLASH database to. Required for `STORAGE_BACKEND="gcloud"`, ignored otherwise. |
| `GCP_PROJECT_ID` | - | The ID of the Google Cloud Storage project to use. Only required in conjunction with `GCP_SERVICE_ACCOUNT_EMAIL` and `GCP_PRIVATE_KEY`. |
| `GCP_SERVICE_ACCOUNT_EMAIL` | - | The email of the service account to use for authentication with the Google Cloud Storage project. Only required in conjunction with `GCP_PROJECT_ID` and `GCP_PRIVATE_KEY`. |
| `GCP_PRIVATE_KEY` | - | The private key of the service account to use for authentication with the Google Cloud Storage project. Only required in conjunction with `GCP_PROJECT_ID` and `GCP_SERVICE_ACCOUNT_EMAIL`. |

Currently, two storage backends are supported; the local file system and Google
Cloud Storage. You can switch between them by setting the `STORAGE_BACKEND`
environment variable.

When using Google Cloud Storage, the environment variables `GCP_PROJECT_ID`,
`GCP_SERVICE_ACCOUNT_EMAIL` and `GCP_PRIVATE_KEY` can all be omitted in order to
authenticate using
[Application Default Credentials](https://docs.cloud.google.com/docs/authentication/provide-credentials-adc).
Otherwise, all three need to be provided.

## Development

### Requirements

- Node.js 20+
- Pnpm 10+

Project dependencies can be installed by running the following command:

```bash
pnpm install
```

Before the application or any tests can be run the local monorepo packages have
to be built with the following command:

```bash
pnpm build:packages
```

In order to run end to end tests Playwright browsers need to be installed as
well. This can be done like so:

```bash
pnpm --filter website exec playwright install
```

### Tests

FLASH includes a comprehensive test suite and a mix of testing strategies across
its packages to ensure reliability and correctness across all parts of the
application.

#### Test Overview

| Package | Unit | Accessibility | Interaction | E2E |
| ------------------ | ---- | ------------- | ----------- | --- |
| **`Website`** | ✓ | | | ✓ |
| **`file-storage`** | ✓ | | | |
| **`tokens`** | ✓ | | | |
| **`UI`** | ✓ | ✓ | ✓ | |

#### Running Tests

To run all **unit** tests across all packages and the website, run

```bash
pnpm test # For all unit tests
pnpm --filter <workspace> test # To run unit test for a specific workspace
```

To run **End-to-End** (E2E) tests for the `apps/website`, run

```bash
pnpm test:e2e
```

For storybook, the `test` command only runs the unit and interaction tests. For
visual and accessibility tests, start Storybook and use the UI to run the tests.

```bash
pnpm storybook
```

### Running the Application

After installing the dependencies and building the packages, you can start the
main application in development mode using this command:

```shell
pnpm dev
```

This will start a Next.js development server which compiles pages on-demand only
when accessed and automatically rebuilds pages when the code changes.

The application can also be built locally and started in production mode.

```bash
pnpm build # Builds every package along with the main application
# or
pnpm --filter website build # Builds only the main application (useful if you have run `pnpm build:packages` already)

pnpm start # Starts the production server
```
Loading