Skip to content

ImadSaddik/ImadSaddikWebsite

Repository files navigation

Imad Saddik's website

ci_pipeline_status Backend Coverage Frontend Coverage gitHub_license website_status

The source code for my website, imadsaddik.com, is stored in this repository. The frontend is built with Vue.js, and the backend uses FastAPI. The site is deployed on DigitalOcean, and the search feature is powered by Meilisearch.

I created this website to bring together everything I do online. You will find helpful blog posts about programming, courses I have worked on, and astronomy tutorials if you enjoy space 🌝

readme_thumbnail

Project showcase

Check out the video below for a quick tour of the website!

Watch the Project Tour

Project setup

To set up the project locally, follow these steps:

Frontend

Install pnpm if you don't have it using npm:

npm install -g pnpm@latest-10

Note

You can install pnpm using other methods. For more details, check the official pnpm installation guide.

After installing pnpm, navigate to the frontend directory and install the dependencies:

cd frontend
pnpm install

Next, create a .env file by copying the example file:

cp .env.example .env

Finally, start the development server:

pnpm dev

Open your browser and go to http://localhost:8080/ to view the frontend. Don't worry about the backend connection at this point.

Backend

Navigate to the backend directory and create a virtual environment. I prefer to use anaconda, but you can also use venv, uv, or any other tool of your choice.

# Using conda
conda create -n venv python=3.13 -y
conda activate venv

# Using venv
python -m venv venv
source venv/bin/activate  # On Windows use `venv\Scripts\activate`

Next, install the required dependencies. Don't forget to activate your virtual environment if you haven't done so already:

pip install -r requirements.txt

Now, create a .env file by copying the example file. You don't need to modify anything once you copy it:

cp .env.example .env

Finally, start the FastAPI development server:

uvicorn main:app --reload --host 0.0.0.0 --port 8000

You are almost done! The next and final step is to start Meilisearch, and populate it with data. This will enable the search functionality, list blogs, courses, and more.

Configuration

Both the frontend and backend use .env files to manage configuration.

In the backend, the .env file contains the following variables:

  • MEILISEARCH_URL: The URL of your Meilisearch instance (default: http://localhost:7700).
  • MEILISEARCH_MASTER_KEY: The master key to secure your search engine. Must match the key used when starting Meilisearch.
  • MEILISEARCH_INDEX_NAME: The name of the index to store articles (default: articles).
  • ENVIRONMENT: Set to development or production.

In the frontend, the .env file contains the following variables:

  • VITE_API_BASE_URL: The URL of the backend API (default: http://localhost:8000).
  • BASE_URL: The base URL used by Playwright for E2E testing (default: http://localhost:8080).

Meilisearch

Installation

Before installing Meilisearch, decide where you want to store the Meilisearch data. Create a directory for Meilisearch data storage somewhere on your system, for example:

mkdir -p ~/meilisearch_data

Now, move to that directory and download the latest stable release of Meilisearch:

cd ~/meilisearch_data
curl -L https://install.meilisearch.com | sh

Start Meilisearch:

./meilisearch --master-key='aStrongMasterKey'

Note

The master key used here is a dummy key for local development. In a production environment, make sure to use a strong and secure master key.

aStrongMasterKey is the same key used in the .env file created earlier.

If that last command fails with a permission error like this:

2026-01-03T21:01:04.724569Z ERROR meilisearch: error=Permission denied (os error 13)
Error: Permission denied (os error 13)

Retry starting Meilisearch with sudo:

sudo ./meilisearch --master-key='aStrongMasterKey'

The output should look like this:

888b     d888          d8b 888 d8b                                            888
8888b   d8888          Y8P 888 Y8P                                            888
88888b.d88888              888                                                888
888Y88888P888  .d88b.  888 888 888 .d8888b   .d88b.   8888b.  888d888 .d8888b 88888b.
888 Y888P 888 d8P  Y8b 888 888 888 88K      d8P  Y8b     "88b 888P"  d88P"    888 "88b
888  Y8P  888 88888888 888 888 888 "Y8888b. 88888888 .d888888 888    888      888  888
888   "   888 Y8b.     888 888 888      X88 Y8b.     888  888 888    Y88b.    888  888
888       888  "Y8888  888 888 888  88888P'  "Y8888  "Y888888 888     "Y8888P 888  888

Config file path: "none"
Database path: "./data.ms"
Server listening on: "http://localhost:7700"
Environment: "development"
Commit SHA: "unknown"
Commit date: "unknown"
Package version: "1.18.0"

Thank you for using Meilisearch!

...

Populate Meilisearch with data

To load the initial settings and documents into Meilisearch, run the following script from the project root:

python backend/scripts/seed_meilisearch.py

For more details about the seed data, refer to the seed README.

Run all services using tmux

If you don't want to start each server in a separate window manually, you can use run_all_services_tmux.sh to start everything in a tmux session.

Warning

Open the bash script and make sure that the paths, and commands are correct before running it.

Now, install tmux if you don't have it already. On Debian or Ubuntu, you can install it using:

sudo apt install tmux

For other operating systems, refer to the official tmux installation guide.

After installing tmux, navigate to the bash_scripts directory and run the script:

cd bash_scripts
./run_all_services_tmux.sh

This will create a new tmux session named imad_saddik_personal_website with three panes: one for Meilisearch, one for the frontend, and one for the backend.

The backend pane is located at the bottom and spans the full width of the window, while the top half is split into two panes for Meilisearch (left) and the frontend (right).

Useful tools & scripts

This repository contains several helper tools to assist with maintenance and analysis:

  • Dashboard analysis: A collection of tools to analyze Nginx logs using GoAccess data. Useful for tracking traffic and identifying bad actors.

  • Bash scripts: A set of utility scripts for tasks such as:

    • Optimizing images (optimize_jpeg_images.sh, optimize_png_images.sh)
    • Finding large media files (find_media.sh)
    • Managing backups (clean_backups.sh)

    Check the respective README files in those directories for more usage details.

Production infrastructure

The infrastructure/ directory contains configuration files and scripts used to deploy the website in a production environment:

  • nginx/: Configuration files for the Nginx web server, including Cloudflare-specific settings.
  • supervisor/: Configuration for Supervisor to manage the backend process.
  • systemd/: Systemd service files (e.g., for Meilisearch).
  • scripts/: Deployment and maintenance scripts, such as Gunicorn startup and monthly cleanup tasks.

For more details, refer to the infrastructure README.

Contributing

Contributions are welcome! To keep the code clean and consistent, please follow these simple steps:

Pre-commit hooks

I use pre-commit hooks to check the code automatically before every commit. This helps catch small mistakes early.

First, install pre-commit in your virtual environment:

pip install pre-commit

Then, set up the hooks:

pre-commit install

Note

The pre-commit hooks will also automatically regenerate the sitemap.xml file if you make changes to the frontend.

Code style (Linting and Formatting)

Please make sure your code follows the project style. You can run these commands to fix most style issues:

  • Frontend: Run pnpm lint and pnpm format in the frontend folder.
  • Backend: Run ruff check . --fix in the backend folder.

Testing

Before submitting your changes, run the tests to make sure everything still works:

Inside the frontend folder run these tests:

  • Unit tests: pnpm run test:run
  • E2E tests: pnpm run test:e2e (requires the frontend, meilisearch, and backend to be running)

Inside the backend folder run these tests:

  • Unit tests: pytest tests/unit

  • Integration tests: pytest tests/integration (requires Meilisearch to be running)

  • Load tests:

    locust -f tests/load/locustfile.py

    Then open http://localhost:8089 to start the swarm.

If you find a typo or have a suggestion, feel free to open an issue or a pull request!

Licence

This project is licensed under the MIT License. See the LICENSE file for details.

Contact

You can reach me through:

Packages

No packages published

Contributors 5