diff --git a/laudatory-larkspurs/.github/workflows/build.yaml b/laudatory-larkspurs/.github/workflows/build.yaml
new file mode 100644
index 00000000..4e8ac56b
--- /dev/null
+++ b/laudatory-larkspurs/.github/workflows/build.yaml
@@ -0,0 +1,84 @@
+name: Build project and publish
+
+on:
+ push:
+ branches: [main]
+ workflow_dispatch:
+
+concurrency:
+ group: build-${{ github.ref }}
+ cancel-in-progress: true
+
+permissions:
+ contents: write
+
+jobs:
+ build:
+ name: Build the project
+ runs-on: ubuntu-latest
+
+ steps:
+ - name: Checkout repository
+ uses: actions/checkout@v4
+
+ - name: Set up Python
+ uses: actions/setup-python@v5
+ with:
+ python-version: "3.12"
+
+ - name: Install dependencies
+ run: |
+ python -m pip install --upgrade pip
+ pip install .
+
+ - name: Build project
+ run: python build.py
+
+ - name: Upload build artifact
+ uses: actions/upload-artifact@v4
+ with:
+ name: build
+ path: build
+ if-no-files-found: error
+
+ publish:
+ name: Publish build artifact
+ needs: build
+ runs-on: ubuntu-latest
+ if: github.ref == 'refs/heads/main'
+
+ steps:
+ - name: Checkout repository
+ uses: actions/checkout@v4
+
+ - name: Configure Git
+ run: |
+ BOT_NAME="github-actions[bot]"
+ BOT_EMAIL="41898282+github-actions[bot]@users.noreply.github.com"
+ git config user.name "$BOT_NAME"
+ git config user.email "$BOT_EMAIL"
+
+ - name: Prepare build branch
+ run: |
+ set -e
+ if git ls-remote --exit-code origin build; then
+ git fetch origin build:build
+ git checkout build
+ else
+ git checkout --orphan build
+ fi
+ find . -mindepth 1 -maxdepth 1 ! -name '.git' -exec rm -rf {} +
+
+ - name: Download build artifact
+ uses: actions/download-artifact@v4
+ with:
+ name: build
+ path: .
+
+ - name: Commit build folder
+ run: |
+ git add .
+ git diff --cached --quiet && echo "No build changes to commit" || git commit -m "Deploying production from @ ${GITHUB_SHA::7} ๐"
+ git push origin build
+
+ timeout-minutes: 15
diff --git a/laudatory-larkspurs/.github/workflows/deploy.yaml b/laudatory-larkspurs/.github/workflows/deploy.yaml
new file mode 100644
index 00000000..68b3c3c8
--- /dev/null
+++ b/laudatory-larkspurs/.github/workflows/deploy.yaml
@@ -0,0 +1,42 @@
+name: Deploy to Vercel
+
+on:
+ workflow_run:
+ workflows: ["Build project and publish"]
+ branches: [main]
+ types: [completed]
+ workflow_dispatch:
+
+env:
+ VERCEL_ORG_ID: ${{ secrets.VERCEL_ORG_ID }}
+ VERCEL_PROJECT_ID: ${{ secrets.VERCEL_PROJECT_ID }}
+
+concurrency:
+ group: deploy-${{ github.ref }}
+ cancel-in-progress: true
+
+jobs:
+ deploy:
+ name: Deploy production build
+ if: ${{ github.event_name == 'workflow_dispatch' || (github.event.workflow_run && github.event.workflow_run.conclusion == 'success') }}
+ runs-on: ubuntu-latest
+ environment: production
+
+ steps:
+ - name: Checkout repository
+ uses: actions/checkout@v4
+ with:
+ ref: build
+
+ - name: Set up Node
+ uses: actions/setup-node@v4
+ with:
+ node-version: "22"
+
+ - name: Install Vercel CLI
+ run: npm install -g vercel@latest
+
+ - name: Deploy to Vercel
+ run: vercel deploy --prod --yes --token=${{ secrets.VERCEL_TOKEN }}
+
+ timeout-minutes: 15
diff --git a/laudatory-larkspurs/.github/workflows/lint.yaml b/laudatory-larkspurs/.github/workflows/lint.yaml
new file mode 100644
index 00000000..7f67e803
--- /dev/null
+++ b/laudatory-larkspurs/.github/workflows/lint.yaml
@@ -0,0 +1,35 @@
+# GitHub Action workflow enforcing our code style.
+
+name: Lint
+
+# Trigger the workflow on both push (to the main repository, on the main branch)
+# and pull requests (against the main repository, but from any repo, from any branch).
+on:
+ push:
+ branches:
+ - main
+ pull_request:
+
+# Brand new concurrency setting! This ensures that not more than one run can be triggered for the same commit.
+# It is useful for pull requests coming from the main repository since both triggers will match.
+concurrency: lint-${{ github.sha }}
+
+jobs:
+ lint:
+ runs-on: ubuntu-latest
+
+ env:
+ # The Python version your project uses. Feel free to change this if required.
+ PYTHON_VERSION: "3.12"
+
+ steps:
+ - name: Checkout repository
+ uses: actions/checkout@v4
+
+ - name: Set up Python ${{ env.PYTHON_VERSION }}
+ uses: actions/setup-python@v5
+ with:
+ python-version: ${{ env.PYTHON_VERSION }}
+
+ - name: Run pre-commit hooks
+ uses: pre-commit/action@v3.0.1
diff --git a/laudatory-larkspurs/.gitignore b/laudatory-larkspurs/.gitignore
new file mode 100644
index 00000000..da472080
--- /dev/null
+++ b/laudatory-larkspurs/.gitignore
@@ -0,0 +1,34 @@
+# Files generated by the interpreter
+__pycache__/
+*.py[cod]
+
+# Environment specific
+.venv
+venv
+.env
+env
+
+# Unittest reports
+.coverage*
+
+# Logs
+*.log
+
+# PyEnv version selector
+.python-version
+
+# Built objects
+*.so
+dist/
+build/
+
+# IDEs
+# PyCharm
+.idea/
+# VSCode
+.vscode/
+# MacOS
+.DS_Store
+
+build/
+.vercel
diff --git a/laudatory-larkspurs/.pre-commit-config.yaml b/laudatory-larkspurs/.pre-commit-config.yaml
new file mode 100644
index 00000000..c0a8de23
--- /dev/null
+++ b/laudatory-larkspurs/.pre-commit-config.yaml
@@ -0,0 +1,18 @@
+# Pre-commit configuration.
+# See https://github.com/python-discord/code-jam-template/tree/main#pre-commit-run-linting-before-committing
+
+repos:
+ - repo: https://github.com/pre-commit/pre-commit-hooks
+ rev: v5.0.0
+ hooks:
+ - id: check-toml
+ - id: check-yaml
+ - id: end-of-file-fixer
+ - id: trailing-whitespace
+ args: [--markdown-linebreak-ext=md]
+
+ - repo: https://github.com/astral-sh/ruff-pre-commit
+ rev: v0.12.2
+ hooks:
+ - id: ruff-check
+ - id: ruff-format
diff --git a/laudatory-larkspurs/CONTRIBUTING.md b/laudatory-larkspurs/CONTRIBUTING.md
new file mode 100644
index 00000000..1c479e04
--- /dev/null
+++ b/laudatory-larkspurs/CONTRIBUTING.md
@@ -0,0 +1,141 @@
+# Contributing
+
+## Information
+
+This project uses [Pyodide](https://pyodide.org) to run Python directly in the browser using WebAssembly (WASM).
+Almost no JavaScript is required โ the frontend is written entirely in Python and HTML/CSS.
+
+## Dev Code Checks
+
+Use `ruff check` to check your code style. and fix it
+
+```shell
+ruff check .
+ruff check . --fix
+```
+
+Use `pre-commit` to run linting before committing. `pre-commit install` to install.
+
+### Examples
+
+```shell
+pre-commit run --show-diff-on-failure --all-files
+pre-commit run ruff-check --all-files
+pre-commit run check-toml --all-files
+```
+
+**Pre-commit hooks:**
+
+- `check-toml`: Lints and corrects your TOML files.
+- `check-yaml`: Lints and corrects your YAML files.
+- `end-of-file-fixer`: Makes sure you always have an empty line at the end of your file.
+- `trailing-whitespace`: Removes whitespaces at the end of each line.
+- `ruff-check`: Runs the Ruff linter.
+- `ruff-format`: Runs the Ruff formatter.
+
+## Our coding rules
+
+1. Comment your classes, functions, and non-obvious logic.
+2. Use docstrings with author tags and short descriptions.
+
+```py
+class ClassName:
+ '''Handle user input and validation.
+
+ @author Mira
+ '''
+ ...
+
+# Short function description
+def do_something():
+ '''Perform a single-step operation.
+
+ :param paramname: does something
+ :return: None
+
+ @author Mira
+ '''
+ ...
+```
+
+## Naming Stuff Rules
+
+Use `ruff check` to check your code style. and fix it
+
+```shell
+ruff check .
+ruff check . --fix
+```
+
+**Functions**: lowercase and use underscores
+
+```py
+def my_function():
+ my_variable = "value"
+```
+
+**Classes and Variable names**: PascalCase style
+
+```py
+from typing import List
+
+class MyClass:
+ pass
+
+ListOfMyClass = List[MyClass]
+```
+
+**Constants**: SCREAMING_SNAKE_CASE style
+
+```py
+MY_CONSTANT = 1
+```
+
+**Operators**: at the start of a newline
+
+```py
+# No
+result = (
+ 1 +
+ 2 *
+ 3
+)
+# Yes
+result = (
+ 1
+ + 2
+ * 3
+)
+```
+
+**equivalent to None**: use `is`, `is not` instead of `==`
+
+```py
+if variable == None: # No
+ print("Variable is None")
+if variable is None: # Yes
+ print("Variable is None")ยจ
+```
+
+**not** positioning:
+
+```py
+if not variable is None: # No
+ print("Variable is not None")
+
+if variable is not None: # Yes, easier to read
+ print("Variable is not None")
+```
+
+**Imports**: do not import multiple modules on one line or everything from a module (\*)
+
+```py
+# No
+import pathlib, os
+from pathlib import *
+
+# Yes
+import os
+import pathlib
+from pathlib import Path
+```
diff --git a/laudatory-larkspurs/Dockerfile b/laudatory-larkspurs/Dockerfile
new file mode 100644
index 00000000..02c36cec
--- /dev/null
+++ b/laudatory-larkspurs/Dockerfile
@@ -0,0 +1,33 @@
+#############################
+# Single-stage Python image #
+#############################
+FROM python:3.12-slim
+
+LABEL org.opencontainers.image.title="good-image-terminal" \
+ org.opencontainers.image.description="A simple yet interesting image editor." \
+ org.opencontainers.image.licenses="MIT"
+
+ENV PYTHONDONTWRITEBYTECODE=1 \
+ PYTHONUNBUFFERED=1 \
+ PORT=8000
+
+# Set the working directory
+WORKDIR /app
+
+# Copy project files
+COPY build.py pyproject.toml README.md uv.lock* ./
+RUN pip install --no-cache-dir .
+
+COPY public ./public
+COPY src ./src
+
+EXPOSE 8000
+
+CMD ["bash", "-c", "python build.py --serve --port ${PORT}"]
+
+#####################################################################################################
+# Usage #
+# docker build -t good-image-terminal:latest . #
+# docker run --rm --name good-image-terminal -e PORT=8000 -p 8000:8000 good-image-terminal:latest #
+# App: http://localhost:8000 #
+#####################################################################################################
diff --git a/laudatory-larkspurs/LICENSE b/laudatory-larkspurs/LICENSE
new file mode 100644
index 00000000..3afb3122
--- /dev/null
+++ b/laudatory-larkspurs/LICENSE
@@ -0,0 +1,9 @@
+MIT License
+
+Copyright (c) 2025 Mira, Jont, Julien, Philip, Richard Szilagyi, Mark
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/laudatory-larkspurs/README.md b/laudatory-larkspurs/README.md
new file mode 100644
index 00000000..8cbbcfa9
--- /dev/null
+++ b/laudatory-larkspurs/README.md
@@ -0,0 +1,178 @@
+# Good Image Terminal
+
+
+
+
+
+
+
+
+
+
+
+
+
+ An image editor. In the terminal. In the browser.
+
+
+This project is a web-based image editing tool that runs entirely in the browser through a terminal. It uses Pyodide to enable Python-based image processing without the need for a backend server. All while letting JavaScript sit back, relax, and just load the page.
+
+The tool allows users to upload images and apply edits through various commands, all within a user-friendly interface.
+
+The inherently visual task of image editing performed entirely through programmatic terminal commands makes Good Image Terminal the "Wrong tool for the job." Despite this dissonance, we've made GIT comfortable and responsive.
+
+## Project Structure
+
+```text
+codejam-laudatory-larkspurs/
+โโ build.py # Build + serve script (Pyodide bundling)
+โโ Dockerfile # Docker configuration
+โโ pyproject.toml # Project & dependency metadata
+โโ uv.lock # Locked dependency versions
+โโ README.md / CONTRIBUTING.md
+โโ LICENSE
+โโ .pre-commit-config.yaml # Lint & format hooks
+โโ .github/workflows/
+โ โโ build.yaml # CI build pipeline
+โ โโ deploy.yaml # CI deployment pipeline
+โ โโ lint.yaml # CI lint pipeline
+โโ docs/ # Documentation files
+โโ public/ # Static assets
+โ โโ index.html
+โ โโ favicon.* / icons
+โ โโ site.webmanifest
+โ โโ templates/
+โ โโ app_template.html
+โโ src/ # Application source (runs in Pyodide)
+ โโ main.py # Entry point
+ โโ terminal.py # Terminal UI
+ โโ image.py # Image model
+ โโ commands/ # Individual terminal commands
+ โ โโ background.py
+ โ โโ base_command.py
+ โ โโ draw_circle.py
+ โ โโ draw_line.py
+ โ โโ draw_pixel.py
+ โ โโ draw_polygon.py
+ โ โโ draw_rectangle.py
+ โ โโ foreground.py
+ โ โโ help.py
+ โ โโ image_info.py
+ โ โโ load_image.py
+ โ โโ ls.py
+ โ โโ ping.py
+ โ โโ save_image.py
+ โ โโ terminal_background.py
+ โ โโ undo.py
+ โ โโ __init__.py
+ โโ gui/ # Lightweight GUI abstraction
+ โ โโ element.py
+ โ โโ layout.py
+ โ โโ components/
+ โ โ โโ description.py
+ โ โ โโ drag_drop_handler.py
+ โ โ โโ file_upload_handler.py
+ โ โ โโ image_display_manager.py
+ โ โ โโ image_preview.py
+ โ โ โโ separator.py
+ โ โ โโ terminal_gui.py
+ โ โ โโ terminal_input.py
+ โ โ โโ terminal_io.py
+ โ โ โโ __init__.py
+ โ โโ __init__.py
+ โโ images/
+ โ โโ default.png
+ โโ utils/
+ โโ color.py
+ โโ __init__.py
+```
+
+## Setup
+
+1. First we set up our python enviroment
+
+```shell
+python -m venv .venv
+```
+
+2. Entering it
+
+```shell
+# Linux, Bash
+$ source .venv/bin/activate
+# Linux, Fish
+$ source .venv/bin/activate.fish
+# Linux, Csh
+$ source .venv/bin/activate.csh
+# Linux, PowerShell Core
+$ .venv/bin/Activate.ps1
+# Windows, cmd.exe
+> .venv\Scripts\activate.bat
+# Windows, PowerShell
+> .venv\Scripts\Activate.ps1
+```
+
+3. Installing development dependecies
+
+```shell
+pip install --group dev
+```
+
+_If it gives errors try:_
+
+```shell
+python -m pip install --upgrade pip
+```
+
+4. If we want to exit our enviroment we do
+
+```shell
+deactivate
+```
+
+## Running the project
+
+To build the project, run
+
+```shell
+python build.py --serve --port 8000
+```
+
+This will serve the project on `http://localhost:8000` after building it to `build/`. If you make changes to your code, run `build.py` again to rebuild the project.
+
+### Running with Docker
+
+You can run the app without a local Python setup using the provided `Dockerfile`.
+
+Build the image:
+
+```shell
+docker build -t good-image-terminal:latest .
+```
+
+Run (default port `8000`):
+
+```shell
+docker run --rm --name good-image-terminal -e PORT=8000 -p 8000:8000 good-image-terminal:latest
+```
+
+Custom port:
+
+```shell
+docker run --rm --name good-image-terminal -e PORT=9000 -p 9000:9000 good-image-terminal:latest
+```
+
+The container runs `python build.py --serve --port $PORT` on startup:
+
+- Builds fresh each run (output in container at `/app/build`).
+- Serves the site at `http://localhost:`.
+
+Faster rebuilds during iteration:
+
+```shell
+docker build -t good-image-terminal:latest . # after changing code
+```
+
+## Contributors
+
+[](https://github.com/Miras3210/codejam-laudatory-larkspurs/graphs/contributors)
diff --git a/laudatory-larkspurs/README_template.md b/laudatory-larkspurs/README_template.md
new file mode 100644
index 00000000..3bf4bfba
--- /dev/null
+++ b/laudatory-larkspurs/README_template.md
@@ -0,0 +1,186 @@
+# Python Discord Code Jam Repository Template
+
+## A primer
+
+Hello code jam participants! We've put together this repository template for you to use in [our code jams](https://pythondiscord.com/events/) or even other Python events!
+
+This document contains the following information:
+
+1. [What does this template contain?](#what-does-this-template-contain)
+2. [How do I use this template?](#how-do-i-use-this-template)
+3. [How do I adapt this template to my project?](#how-do-i-adapt-this-template-to-my-project)
+
+> [!TIP]
+> You can also look at [our style guide](https://pythondiscord.com/events/code-jams/code-style-guide/) to get more information about what we consider a maintainable code style.
+
+## What does this template contain?
+
+Here is a quick rundown of what each file in this repository contains:
+
+- [`LICENSE.txt`](LICENSE.txt): [The MIT License](https://opensource.org/licenses/MIT), an OSS approved license which grants rights to everyone to use and modify your project, and limits your liability. We highly recommend you to read the license.
+- [`.gitignore`](.gitignore): A list of files and directories that will be ignored by Git. Most of them are auto-generated or contain data that you wouldn't want to share publicly.
+- [`pyproject.toml`](pyproject.toml): Configuration and metadata for the project, as well as the linting tool Ruff. If you're interested, you can read more about `pyproject.toml` in the [Python Packaging documentation](https://packaging.python.org/en/latest/guides/writing-pyproject-toml/).
+- [`.pre-commit-config.yaml`](.pre-commit-config.yaml): The configuration of the [pre-commit](https://pre-commit.com/) tool.
+- [`.github/workflows/lint.yaml`](.github/workflows/lint.yaml): A [GitHub Actions](https://github.com/features/actions) workflow, a set of actions run by GitHub on their server after each push, to ensure the style requirements are met.
+
+Each of these files have comments for you to understand easily, and modify to fit your needs.
+
+### Ruff: general style rules
+
+Our first tool is Ruff. It will check your codebase and warn you about any non-conforming lines.
+It is run with the command `ruff check` in the project root.
+
+Here is a sample output:
+
+```shell
+$ ruff check
+app.py:1:5: N802 Function name `helloWorld` should be lowercase
+app.py:1:5: ANN201 Missing return type annotation for public function `helloWorld`
+app.py:2:5: D400 First line should end with a period
+app.py:2:5: D403 First word of the first line should be capitalized: `docstring` -> `Docstring`
+app.py:3:15: W292 No newline at end of file
+Found 5 errors.
+```
+
+Each line corresponds to an error. The first part is the file path, then the line number, and the column index.
+Then comes the error code, a unique identifier of the error, and then a human-readable message.
+
+If, for any reason, you do not wish to comply with this specific error on a specific line, you can add `# noqa: CODE` at the end of the line.
+For example:
+
+```python
+def helloWorld(): # noqa: N802
+ ...
+
+```
+
+This will ignore the function naming issue and pass linting.
+
+> [!WARNING]
+> We do not recommend ignoring errors unless you have a good reason to do so.
+
+### Ruff: formatting
+
+Ruff also comes with a formatter, which can be run with the command `ruff format`.
+It follows the same code style enforced by [Black](https://black.readthedocs.io/en/stable/index.html), so there's no need to pick between them.
+
+### Pre-commit: run linting before committing
+
+The second tool doesn't check your code, but rather makes sure that you actually *do* check it.
+
+It makes use of a feature called [Git hooks](https://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks) which allow you to run a piece of code before running `git commit`.
+The good thing about it is that it will cancel your commit if the lint doesn't pass. You won't have to wait for GitHub Actions to report issues and have a second fix commit.
+
+It is *installed* by running `pre-commit install` and can be run manually by calling only `pre-commit`.
+
+[Lint before you push!](https://soundcloud.com/lemonsaurusrex/lint-before-you-push)
+
+#### List of hooks
+
+- `check-toml`: Lints and corrects your TOML files.
+- `check-yaml`: Lints and corrects your YAML files.
+- `end-of-file-fixer`: Makes sure you always have an empty line at the end of your file.
+- `trailing-whitespace`: Removes whitespaces at the end of each line.
+- `ruff-check`: Runs the Ruff linter.
+- `ruff-format`: Runs the Ruff formatter.
+
+## How do I use this template?
+
+### Creating your team repository
+
+One person in the team, preferably the leader, will have to create the repository and add other members as collaborators.
+
+1. In the top right corner of your screen, where **Clone** usually is, you have a **Use this template** button to click.
+ 
+2. Give the repository a name and a description.
+ 
+3. Click **Create repository from template**.
+4. Click **Settings** in your newly created repository.
+ 
+5. In the "Access" section of the sidebar, click **Collaborators**.
+ 
+6. Click **Add people**.
+7. Insert the names of each of your teammates, and invite them. Once they have accepted the invitation in their email, they will have write access to the repository.
+
+You are now ready to go! Sit down, relax, and wait for the kickstart!
+
+> [!IMPORTANT]
+> Don't forget to change the project name, description, and authors at the top of the [`pyproject.toml`](pyproject.toml) file, and swap "Python Discord" in the [`LICENSE.txt`](LICENSE.txt) file for the name of each of your team members or the name of your team *after* the start of the code jam.
+
+### Using the default pip setup
+
+Our default setup includes a dependency group to be used with a [virtual environment](https://docs.python.org/3/library/venv.html).
+It works with pip and uv, and we recommend this if you have never used any other dependency manager, although if you have, feel free to switch to it.
+More on that [below](#how-do-i-adapt-this-template-to-my-project).
+
+Dependency groups are a relatively new feature, specified in [PEP 735](https://peps.python.org/pep-0735/).
+You can read more about them in the [Python Packaging User Guide](https://packaging.python.org/en/latest/specifications/dependency-groups/).
+
+#### Creating the environment
+
+Create a virtual environment in the folder `.venv`.
+
+```shell
+python -m venv .venv
+```
+
+#### Entering the environment
+
+It will change based on your operating system and shell.
+
+```shell
+# Linux, Bash
+$ source .venv/bin/activate
+# Linux, Fish
+$ source .venv/bin/activate.fish
+# Linux, Csh
+$ source .venv/bin/activate.csh
+# Linux, PowerShell Core
+$ .venv/bin/Activate.ps1
+# Windows, cmd.exe
+> .venv\Scripts\activate.bat
+# Windows, PowerShell
+> .venv\Scripts\Activate.ps1
+```
+
+#### Installing the dependencies
+
+Once the environment is created and activated, use this command to install the development dependencies.
+
+```shell
+pip install --group dev
+```
+
+#### Exiting the environment
+
+Interestingly enough, it is the same for every platform.
+
+```shell
+deactivate
+```
+
+Once the environment is activated, all the commands listed previously should work.
+
+> [!IMPORTANT]
+> We highly recommend that you run `pre-commit install` as soon as possible.
+
+## How do I adapt this template to my project?
+
+If you wish to use Pipenv or Poetry, you will have to move the dependencies in [`pyproject.toml`](pyproject.toml) to the development dependencies of your tool.
+
+We've included a porting to both [Poetry](samples/pyproject.toml) and [Pipenv](samples/Pipfile) in the [`samples` folder](samples).
+Note that the Poetry [`pyproject.toml`](samples/pyproject.toml) file does not include the Ruff configuration, so if you simply replace the file then the Ruff configuration will be lost.
+
+When installing new dependencies, don't forget to [pin](https://pip.pypa.io/en/stable/topics/repeatable-installs/#pinning-the-package-versions) them by adding a version tag at the end.
+For example, if I wish to install [Click](https://click.palletsprojects.com/en/8.1.x/), a quick look at [PyPI](https://pypi.org/project/click/) tells me that `8.1.7` is the latest version.
+I will then add `click~=8.1`, without the last number, to my requirements file or dependency manager.
+
+> [!IMPORTANT]
+> A code jam project is left unmaintained after the end of the event. If the dependencies aren't pinned, the project will break after any major change in an API.
+
+## Final words
+
+> [!IMPORTANT]
+> Don't forget to replace this README with an actual description of your project! Images are also welcome!
+
+We hope this template will be helpful. Good luck in the jam!
diff --git a/laudatory-larkspurs/build.py b/laudatory-larkspurs/build.py
new file mode 100644
index 00000000..6edc5499
--- /dev/null
+++ b/laudatory-larkspurs/build.py
@@ -0,0 +1,56 @@
+"""The build script for the website."""
+
+import argparse
+import http.server
+import pathlib
+import shutil
+import socketserver
+
+_this_dir = pathlib.Path(__file__).parent.resolve()
+
+# Project directories
+BUILD_DIR = _this_dir / "build"
+PUBLIC_DIR = _this_dir / "public"
+SRC_DIR = _this_dir / "src"
+
+
+def _zip_dir(src: pathlib.Path, dest: pathlib.Path) -> None:
+ """Create a zip file from a directory and places it in `dest`."""
+ shutil.make_archive(str(dest), "zip", str(src))
+
+
+class _DevHandler(http.server.SimpleHTTPRequestHandler):
+ """Allows for serving the website locally for development."""
+
+ def __init__(self, request, client_address, server) -> None: # noqa: ANN001
+ super().__init__(request, client_address, server, directory=BUILD_DIR)
+
+
+def main() -> None:
+ """Define the build entry point."""
+ parser = argparse.ArgumentParser()
+ parser.add_argument("--no-clean", action="store_false", dest="clean", default=True)
+ parser.add_argument("--serve", action="store_true", default=False)
+ parser.add_argument("--port", type=int, default=8000)
+ args = parser.parse_args()
+
+ if not BUILD_DIR.exists(): # FileNotFoundError if this isn't here
+ BUILD_DIR.mkdir(exist_ok=True)
+
+ elif args.clean:
+ shutil.rmtree(BUILD_DIR)
+ BUILD_DIR.mkdir(exist_ok=True)
+
+ _zip_dir(SRC_DIR, BUILD_DIR / "src")
+ shutil.copytree(PUBLIC_DIR, BUILD_DIR, dirs_exist_ok=True)
+
+ if args.serve:
+ print(f"Serving on http://localhost:{args.port}")
+ httpd = socketserver.TCPServer(("", args.port), _DevHandler)
+ httpd.serve_forever()
+ else:
+ print("Add --serve to start")
+
+
+if __name__ == "__main__":
+ main()
diff --git a/laudatory-larkspurs/docs/.nojekyll b/laudatory-larkspurs/docs/.nojekyll
new file mode 100644
index 00000000..e69de29b
diff --git a/laudatory-larkspurs/docs/README.md b/laudatory-larkspurs/docs/README.md
new file mode 100644
index 00000000..8fe267ea
--- /dev/null
+++ b/laudatory-larkspurs/docs/README.md
@@ -0,0 +1,54 @@
+
+
+
+
+
+# Good Image Terminal
+
+## A Wrong Tool for the Job
+
+
+
+This project is a web-based image editing tool that runs entirely in the browser through a terminal. It uses [Pyodide](https://pyodide.org) to enable Python-based image processing without the need for a backend server. All while letting JavaScript sit back, relax, and just load the page.
+
+The tool allows users to upload images and apply edits through various commands, all within a user-friendly interface.
+
+The inherently visual task of image editing performed entirely through programmatic terminal commands makes Good Image Terminal the "Wrong tool for the job." Despite this dissonance, we've made GIT comfortable and responsive.
+
+## Packages
+
+This project uses the following packages:
+
+- [Pillow](https://python-pillow.org/) - for image processing
+- [Pyodide](https://pyodide.org) - to run Python in the browser and for in-browser file management
+- [Webcolors](https://pypi.org/project/webcolors/) - used to parse hex and CSS named colors
+
+## FAQ
+
+
+
How can I download the image?
+
On Chrome / Firefox / Brave / Safari / Edge, you can right-click the image and select Save image as... to download it.
+
On iOS, you can tap and hold the image to bring up the context menu, then select Add to Photos or Save Image.
+
On Android, you can tap and hold the image, then select Download Image from the context menu.
+
+
+## License
+
+This project is licensed under the MIT License - see the [LICENSE](https://github.com/Miras3210/codejam-laudatory-larkspurs/blob/main/LICENSE) file for details.
+
+### Assets & Media
+
+All project-specific assets are original to this repository and are released under the same MIT License as the source code, unless a file header or adjacent notice explicitly states otherwise.
+
+By contributing media assets you agree they are provided under MIT.
diff --git a/laudatory-larkspurs/docs/_coverpage.md b/laudatory-larkspurs/docs/_coverpage.md
new file mode 100644
index 00000000..621194bc
--- /dev/null
+++ b/laudatory-larkspurs/docs/_coverpage.md
@@ -0,0 +1,15 @@
+
+
+
+
+# Good Image Terminal 0.1.0
+
+> An image editor. In the terminal. In the browser.
+
+- Built with **Pyodide**
+- Supports basic image editing commands
+- Easy to use with a simple command-line interface
+- Runs in the browser
+
+[Start Editing](https://good-image-terminal.vercel.app)
+[Getting Started](#good-image-terminal)
diff --git a/laudatory-larkspurs/docs/_media/banner.png b/laudatory-larkspurs/docs/_media/banner.png
new file mode 100644
index 00000000..e4f1fe63
Binary files /dev/null and b/laudatory-larkspurs/docs/_media/banner.png differ
diff --git a/laudatory-larkspurs/docs/_media/banner.svg b/laudatory-larkspurs/docs/_media/banner.svg
new file mode 100644
index 00000000..fa1f5b4a
--- /dev/null
+++ b/laudatory-larkspurs/docs/_media/banner.svg
@@ -0,0 +1,118 @@
+
+
+
+
diff --git a/laudatory-larkspurs/docs/_media/icon.png b/laudatory-larkspurs/docs/_media/icon.png
new file mode 100644
index 00000000..056fdbe9
Binary files /dev/null and b/laudatory-larkspurs/docs/_media/icon.png differ
diff --git a/laudatory-larkspurs/docs/_media/icon.svg b/laudatory-larkspurs/docs/_media/icon.svg
new file mode 100644
index 00000000..88e8fcc6
--- /dev/null
+++ b/laudatory-larkspurs/docs/_media/icon.svg
@@ -0,0 +1,236 @@
+
+
+
+
diff --git a/laudatory-larkspurs/docs/_media/showcase/bg.gif b/laudatory-larkspurs/docs/_media/showcase/bg.gif
new file mode 100644
index 00000000..25207f55
Binary files /dev/null and b/laudatory-larkspurs/docs/_media/showcase/bg.gif differ
diff --git a/laudatory-larkspurs/docs/_media/showcase/draw_circle.gif b/laudatory-larkspurs/docs/_media/showcase/draw_circle.gif
new file mode 100644
index 00000000..326d9dd5
Binary files /dev/null and b/laudatory-larkspurs/docs/_media/showcase/draw_circle.gif differ
diff --git a/laudatory-larkspurs/docs/_media/showcase/draw_line.gif b/laudatory-larkspurs/docs/_media/showcase/draw_line.gif
new file mode 100644
index 00000000..cbd98169
Binary files /dev/null and b/laudatory-larkspurs/docs/_media/showcase/draw_line.gif differ
diff --git a/laudatory-larkspurs/docs/_media/showcase/draw_pixel.gif b/laudatory-larkspurs/docs/_media/showcase/draw_pixel.gif
new file mode 100644
index 00000000..2cb6768d
Binary files /dev/null and b/laudatory-larkspurs/docs/_media/showcase/draw_pixel.gif differ
diff --git a/laudatory-larkspurs/docs/_media/showcase/draw_polygon.gif b/laudatory-larkspurs/docs/_media/showcase/draw_polygon.gif
new file mode 100644
index 00000000..174e9162
Binary files /dev/null and b/laudatory-larkspurs/docs/_media/showcase/draw_polygon.gif differ
diff --git a/laudatory-larkspurs/docs/_media/showcase/draw_rectangle.gif b/laudatory-larkspurs/docs/_media/showcase/draw_rectangle.gif
new file mode 100644
index 00000000..93a259a1
Binary files /dev/null and b/laudatory-larkspurs/docs/_media/showcase/draw_rectangle.gif differ
diff --git a/laudatory-larkspurs/docs/_media/showcase/fg.gif b/laudatory-larkspurs/docs/_media/showcase/fg.gif
new file mode 100644
index 00000000..b1fa7763
Binary files /dev/null and b/laudatory-larkspurs/docs/_media/showcase/fg.gif differ
diff --git a/laudatory-larkspurs/docs/_navbar.md b/laudatory-larkspurs/docs/_navbar.md
new file mode 100644
index 00000000..a4c5f1ab
--- /dev/null
+++ b/laudatory-larkspurs/docs/_navbar.md
@@ -0,0 +1,3 @@
+
+
+* [Summer Code Jam 12](/code-jam-12/)
diff --git a/laudatory-larkspurs/docs/_sidebar.md b/laudatory-larkspurs/docs/_sidebar.md
new file mode 100644
index 00000000..ef6cd9bb
--- /dev/null
+++ b/laudatory-larkspurs/docs/_sidebar.md
@@ -0,0 +1,8 @@
+
+
+* [Home](/ "Good Image Terminal docs")
+* [Features](features.md)
+* [Installation](installation.md)
+* [Commands](commands.md)
+* [Color Formats](color_formats.md)
+* [Contribution](contribution.md)
diff --git a/laudatory-larkspurs/docs/code-jam-12/README.md b/laudatory-larkspurs/docs/code-jam-12/README.md
new file mode 100644
index 00000000..e3ae61ab
--- /dev/null
+++ b/laudatory-larkspurs/docs/code-jam-12/README.md
@@ -0,0 +1,21 @@
+
+
+
+
+# Summer Code Jam 12
+
+This project is created as a part of the [Summer Code Jam 12](https://www.pythondiscord.com/events/code-jams/12/) event hosted by the Python Discord community.
+
+> A Code Jam is a chance to create something with a team. In each jam, you are paired up with a group of other users just like yourself who will then be given a type of program to make and a theme to help guide it. You then have a little over a week's time to create the best project you can.
+>
+> Source: [Python Discord โ What is a Code Jam?](https://www.pythondiscord.com/events/code-jams/#what-is-code-jam)
+
+## Technology
+
+For this year's Code Jam, the chosen technology is **Python in the Browser**.
+
+## Theme
+
+The theme for this year is **Wrong tool for the job**.
diff --git a/laudatory-larkspurs/docs/code-jam-12/_sidebar.md b/laudatory-larkspurs/docs/code-jam-12/_sidebar.md
new file mode 100644
index 00000000..fecb839c
--- /dev/null
+++ b/laudatory-larkspurs/docs/code-jam-12/_sidebar.md
@@ -0,0 +1,2 @@
+* [Home](/ "Docs: Good Image Terminal")
+* [Summer Code Jam 12](/code-jam-12/)
diff --git a/laudatory-larkspurs/docs/color_formats.md b/laudatory-larkspurs/docs/color_formats.md
new file mode 100644
index 00000000..3372a8e5
--- /dev/null
+++ b/laudatory-larkspurs/docs/color_formats.md
@@ -0,0 +1,28 @@
+
+
+# Color Formats
+
+These color formats are accepted by commands that take a `` argument (e.g. `bg`, `fg`, `draw_*`, `terminal_background`, etc.).
+
+## Supported Formats
+
+- Space- or comma-separated `R G B [A]` (0โ255)
+- Hex `#RRGGBB`
+- Named CSS colors
+ - List can be found [here](https://developer.mozilla.org/en-US/docs/Web/CSS/named-color)
+- Functional notations:
+ - `rgb(r g b)` / `rgb(r, g, b)`
+ - `rgba(r g b a)` / `rgba(r, g, b, a)`
+ - `hsv(h s v)` / `hsva(h s v a)`
+
+## Examples
+
+- `255 255 255`
+- `100,0,0,255`
+- `gold`
+- `#C0FFEE`
+- `rgb(0 200 150)`
+- `rgba(0 255 255 100)`
+- `hsv(360 100 100)`
+
+> Alpha channel (A) is optional. Values are rejected if out of bounds.
diff --git a/laudatory-larkspurs/docs/commands.md b/laudatory-larkspurs/docs/commands.md
new file mode 100644
index 00000000..6cdd8f61
--- /dev/null
+++ b/laudatory-larkspurs/docs/commands.md
@@ -0,0 +1,267 @@
+
+
+# Commands
+
+## `bg`
+
+Sets the background color of the canvas. All subsequent drawing will be rendered on top of this background.
+
+### Arguments
+
+- ``: The background color to set.
+
+#### Color Argument
+
+See [Color Formats](color_formats.md) for supported color syntaxes and examples.
+
+### Usage: bg
+
+```bash
+bg
+```
+
+
+
+## `draw_circle`
+
+Draws a circle on the canvas at a specified position with customizable radius, colors, and outline thickness.
+
+### Arguments
+
+- ``: The x-coordinate of the center of the circle.
+- ``: The y-coordinate of the center of the circle.
+- ``: The radius of the circle.
+- `--fg `: The foreground color for the circle (optional).
+- `--bg `: The background color for the circle (optional).
+- `--outline `: The outline thickness (optional).
+- `--no-fill`: If specified, the circle will not be filled.
+
+#### Color Argument
+
+See [Color Formats](color_formats.md) for supported color syntaxes and examples.
+
+### Usage: draw_circle
+
+```bash
+draw_circle [--fg ] [--bg ] [--outline ] [--no-fill]
+```
+
+
+
+## `draw_line`
+
+Draws a straight line between two points. The line color can be customized.
+
+### Arguments
+
+- ``: The x-coordinate of the start point.
+- ``: The y-coordinate of the start point.
+- ``: The x-coordinate of the end point.
+- ``: The y-coordinate of the end point.
+- `--fg `: The foreground color for the line (optional).
+
+#### Color Argument
+
+See [Color Formats](color_formats.md) for supported color syntaxes and examples.
+
+### Usage: draw_line
+
+```bash
+draw_line [--fg ]
+```
+
+
+
+## `draw_pixel`
+
+Places a single pixel at the specified coordinates. The color can be defined with the foreground option.
+
+### Arguments
+
+- ``: The x-coordinate of the pixel.
+- ``: The y-coordinate of the pixel.
+- `--fg `: The foreground color for the pixel (optional).
+
+#### Color Argument
+
+See [Color Formats](color_formats.md) for supported color syntaxes and examples.
+
+### Usage: draw_pixel
+
+```bash
+draw_pixel [--fg ]
+```
+
+
+
+## `draw_polygon`
+
+Draws a polygon using the provided vertices, with options for fill, outline, and colors.
+
+### Arguments
+
+- ``: A list of points defining the polygon, e.g., `x1,y1 x2,y2 x3,y3 ...`.
+- `--fg `: The foreground color for the polygon (optional).
+- `--bg `: The background color for the polygon (optional).
+- `--outline `: The outline thickness (optional).
+- `--no-fill`: If specified, the polygon will not be filled.
+
+#### Color Argument
+
+See [Color Formats](color_formats.md) for supported color syntaxes and examples.
+
+### Usage: draw_polygon
+
+```bash
+draw_polygon [--fg ] [--bg ] [--outline ] [--no-fill]
+```
+
+
+
+## `draw_rectangle`
+
+Draws a rectangle on the canvas at the specified position and dimensions.
+
+### Arguments
+
+- ``: The x-coordinate of the top-left corner.
+- ``: The y-coordinate of the top-left corner.
+- ``: The width of the rectangle.
+- ``: The height of the rectangle.
+- `--fg `: The foreground color for the rectangle (optional).
+- `--bg `: The background color for the rectangle (optional).
+- `--outline `: The outline thickness (optional).
+- `--no-fill`: If specified, the rectangle will not be filled.
+
+#### Color Argument
+
+See [Color Formats](color_formats.md) for supported color syntaxes and examples.
+
+### Usage: draw_rectangle
+
+```bash
+draw_rectangle
+```
+
+
+
+## `fg`
+
+Sets the foreground color for use in drawing commands.
+
+#### Arguments
+
+- ``: The color to set as the foreground color.
+
+#### Color Argument
+
+See [Color Formats](color_formats.md) for supported color syntaxes and examples.
+
+### Usage: fg
+
+```bash
+fg
+```
+
+
+
+## `help`
+
+Displays information about available commands. When a specific command is given, it shows detailed usage instructions.
+
+### Arguments
+
+- `[command]`: The command to get help for (optional).
+- `[page]`: The specific page of help to display (optional).
+
+### Usage: help
+
+```bash
+help [command] [page]
+```
+
+## `image_info`
+
+Displays details about the currently loaded image, such as dimensions and format.
+
+### Usage: image_info
+
+```bash
+image_info
+```
+
+## `load_image`
+
+Loads an image file into the canvas for editing or manipulation.
+
+### Arguments
+
+- ``: The name of the image file to load.
+
+### Usage: load_image
+
+```bash
+load_image
+```
+
+## `ls`
+
+Lists available files in the current working directory.
+
+### Usage: ls
+
+```bash
+ls
+```
+
+## `ping`
+
+Pong!
+
+### Usage: ping
+
+```bash
+ping
+```
+
+## `save_image`
+
+Saves the current canvas to an image file with the specified name.
+
+### Usage: save_image
+
+### Arguments
+
+- ``: The name of the image file to save.
+
+```bash
+save_image
+```
+
+## `terminal_background`
+
+Changes the background color of the terminal (not the canvas).
+
+### Arguments
+
+- ``: The color to set as the terminal background.
+
+### Color Argument
+
+See [Color Formats](color_formats.md) for supported color syntaxes and examples.
+
+### Usage: terminal_background
+
+```bash
+terminal_background
+```
+
+## `undo`
+
+Reverts the most recent drawing action on the canvas.
+
+### Usage: undo
+
+```bash
+undo
+```
diff --git a/laudatory-larkspurs/docs/contribution.md b/laudatory-larkspurs/docs/contribution.md
new file mode 100644
index 00000000..7b31c8db
--- /dev/null
+++ b/laudatory-larkspurs/docs/contribution.md
@@ -0,0 +1,204 @@
+
+
+# Contributing Guidelines
+
+## How to Contribute
+
+1. Fork and clone the repo from .
+2. Make some changes to the source code.
+3. Run code checks to make sure nothing breaks.
+4. Push your changes and open a pull request.
+
+## Code Checks
+
+Use `ruff check` to check your code style and fix it.
+
+```shell
+ruff check .
+ruff check . --fix
+```
+
+Use `pre-commit` to run linting before committing.
+
+> [!NOTE]
+> `pre-commit install` to install.
+
+### Examples
+
+```shell
+pre-commit run --show-diff-on-failure --all-files
+pre-commit run ruff-check --all-files
+pre-commit run check-toml --all-files
+```
+
+**Pre-commit hooks:**
+
+- `check-toml`: Lints and corrects your TOML files.
+- `check-yaml`: Lints and corrects your YAML files.
+- `end-of-file-fixer`: Makes sure you always have an empty line at the end of your file.
+- `trailing-whitespace`: Removes whitespaces at the end of each line.
+- `ruff-check`: Runs the Ruff linter.
+- `ruff-format`: Runs the Ruff formatter.
+
+## Rules
+
+1. Comment your classes, functions, and non-obvious logic.
+2. Use docstrings with author tags and short descriptions.
+
+```py
+class ClassName:
+ '''Handle user input and validation.
+
+ @author Mira
+ '''
+ ...
+
+# Short function description
+def do_something():
+ '''Perform a single-step operation.
+
+ :param paramname: does something
+ :return: None
+
+ @author Mira
+ '''
+ ...
+```
+
+## Naming Conventions
+
+### Variables and Functions
+
+All variables and functions use lowercase naming with underscores.
+
+```py
+def my_function():
+ my_variable = "value"
+```
+
+### Classes and Type Aliases
+
+Classes use the PascalCase naming convention.
+
+```py
+from typing import List
+
+class MyClass:
+ pass
+
+ListOfMyClass = List[MyClass]
+```
+
+### Constants
+
+Constants use the SCREAMING_SNAKE_CASE naming convention.
+
+```py
+MY_CONSTANT = 1
+```
+
+### Operators
+
+Place operators at the start of a newline.
+
+```py
+# No
+result = (
+ 1 +
+ 2 *
+ 3
+)
+# Yes
+result = (
+ 1
+ + 2
+ * 3
+)
+```
+
+### Equivalent to `None`
+
+Use `is` or `is not` instead of `==`.
+
+```py
+if variable == None: # No
+ print("Variable is None")
+if variable is None: # Yes
+ print("Variable is None")ยจ
+```
+
+### `not` positioning
+
+```py
+if not variable is None: # No
+ print("Variable is not None")
+
+if variable is not None: # Yes, easier to read
+ print("Variable is not None")
+```
+
+### **Imports**
+
+Do not import multiple modules on one line or everything from a module (`*`)
+
+```py
+# No
+import pathlib, os
+from pathlib import *
+
+# Yes
+import os
+import pathlib
+from pathlib import Path
+```
+
+## Contributors
+
+
+
+### Mira
+
+**Team Leader**
+
+
+
+- Python image editing and handling
+- Some of commands listed in [/commands](commands.md)
+- bugfixing pyodide's filesystem
+ - handling image files
+
+### Philip
+
+
+
+- Command parser/environment and command framework
+- Written/maintained a Majority of the commands listed in [/commands](commands.md) as the system evolved
+ - notable ones being help and bg/fg
+- Came up with the initial idea. (which then got misinterpreted twice)
+
+### Ricky
+
+
+
+- Implemented functionality for image file upload through a drag and drop interface
+- Created components for image display manager and GUI preview
+- Simple RGB color information extraction and display feature
+- Integrated Docker for containerized development
+- Set up continuous deployment using GitHub Actions workflows
+
+### Jont
+
+
+
+- Developed core GUI microframework
+- Created build script and initial HTML structure with Pyodide integration
+- Implemented the terminal UI
+
+### Julien
+
+
+
+- app layout design
+- help with gui
+- new feature ideas
+- testing
diff --git a/laudatory-larkspurs/docs/favicon.ico b/laudatory-larkspurs/docs/favicon.ico
new file mode 100644
index 00000000..c70b5834
Binary files /dev/null and b/laudatory-larkspurs/docs/favicon.ico differ
diff --git a/laudatory-larkspurs/docs/features.md b/laudatory-larkspurs/docs/features.md
new file mode 100644
index 00000000..8bc3728f
--- /dev/null
+++ b/laudatory-larkspurs/docs/features.md
@@ -0,0 +1,25 @@
+
+
+
+
+# Features
+
+## Terminal-like UI
+
+The core interface mimics a terminal, with command input, output history, and colored feedback for success or error.
+
+To implement the UI, we developed a custom lightweight GUI abstraction that wraps HTML elements. This abstraction allows us to create custom stateful GUI elements that can be easily extended and manipulated to create complex user interfaces.
+
+## Command Suggestions
+
+As you type, get realtime suggestions for available commands.
+
+## Image Preview
+
+The app provides a preview of the image you are currently editing. Also, you can drag and drop an image file onto the preview area to upload it for editing.
+
+## Color/Position Information
+
+The app provides information about the current cursor position and color of the pixel under the cursor.
diff --git a/laudatory-larkspurs/docs/index.html b/laudatory-larkspurs/docs/index.html
new file mode 100644
index 00000000..3148d094
--- /dev/null
+++ b/laudatory-larkspurs/docs/index.html
@@ -0,0 +1,89 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/laudatory-larkspurs/docs/installation.md b/laudatory-larkspurs/docs/installation.md
new file mode 100644
index 00000000..91da6330
--- /dev/null
+++ b/laudatory-larkspurs/docs/installation.md
@@ -0,0 +1,81 @@
+# Installation Guide
+
+Choose one of the methods below to get started.
+
+## Source code
+
+### 1. Fork the repository
+
+```bash
+git clone https://github.com/Miras3210/codejam-laudatory-larkspurs.git && cd codejam-laudatory-larkspurs
+```
+
+### 2. Setup and activate a Python environment
+
+```bash
+python -m venv .venv
+```
+
+Linux / macOS
+
+```bash
+source .venv/bin/activate
+```
+
+Windows, cmd.exe
+
+```
+.venv\Scripts\activate.bat
+```
+
+Windows, PowerShell
+
+```
+.venv\Scripts\Activate.ps1
+```
+
+### 3. Install dependencies
+
+```bash
+pip install .
+```
+
+> [!NOTE]
+> If you encounter issues, try upgrading pip.
+
+```bash
+pip install --upgrade pip
+```
+
+### 4. Build and serve the project
+
+```bash
+python build.py --serve --port 8000
+```
+
+Open [http://localhost:8000](http://localhost:8000).
+
+## Dev Install
+
+```bash
+pip install --upgrade pip
+pip install --group dev
+```
+
+## Docker
+
+You can run the app without a local Python setup using the provided `Dockerfile`.
+
+### 1. Build the image
+
+```bash
+docker build -t good-image-terminal:latest .
+```
+
+### 2. Run on default port `8000`
+
+```bash
+docker run --rm --name good-image-terminal -e PORT=8000 -p 8000:8000 good-image-terminal:latest
+```
+
+Then visit [http://localhost:8000](http://localhost:8000).
diff --git a/laudatory-larkspurs/public/android-chrome-192x192.png b/laudatory-larkspurs/public/android-chrome-192x192.png
new file mode 100644
index 00000000..2f2a6678
Binary files /dev/null and b/laudatory-larkspurs/public/android-chrome-192x192.png differ
diff --git a/laudatory-larkspurs/public/android-chrome-512x512.png b/laudatory-larkspurs/public/android-chrome-512x512.png
new file mode 100644
index 00000000..bf88c148
Binary files /dev/null and b/laudatory-larkspurs/public/android-chrome-512x512.png differ
diff --git a/laudatory-larkspurs/public/apple-touch-icon.png b/laudatory-larkspurs/public/apple-touch-icon.png
new file mode 100644
index 00000000..a450f56a
Binary files /dev/null and b/laudatory-larkspurs/public/apple-touch-icon.png differ
diff --git a/laudatory-larkspurs/public/favicon.ico b/laudatory-larkspurs/public/favicon.ico
new file mode 100644
index 00000000..c70b5834
Binary files /dev/null and b/laudatory-larkspurs/public/favicon.ico differ
diff --git a/laudatory-larkspurs/public/favicon.svg b/laudatory-larkspurs/public/favicon.svg
new file mode 100644
index 00000000..88e8fcc6
--- /dev/null
+++ b/laudatory-larkspurs/public/favicon.svg
@@ -0,0 +1,236 @@
+
+
+
+
diff --git a/laudatory-larkspurs/public/index.html b/laudatory-larkspurs/public/index.html
new file mode 100644
index 00000000..d1130f59
--- /dev/null
+++ b/laudatory-larkspurs/public/index.html
@@ -0,0 +1,69 @@
+
+
+
+
+
+
+
+ Good Image Terminal
+
+
+
+
+
+
+
+
+
+
+