Added helper functions for portfolio

This commit is contained in:
Kevin Veen-Birkenbach 2025-03-20 00:23:35 +01:00
parent 8e280de139
commit 412a7bae16
No known key found for this signature in database
GPG Key ID: 44D8F11FD62F878E
3 changed files with 315 additions and 86 deletions

133
README.md
View File

@ -1,20 +1,22 @@
# Portfolio CMS: Flask-based Portfolio Management🚀
[![GitHub Sponsors](https://img.shields.io/badge/Sponsor-GitHub%20Sponsors-blue?logo=github)](https://github.com/sponsors/kevinveenbirkenbach) [![Patreon](https://img.shields.io/badge/Support-Patreon-orange?logo=patreon)](https://www.patreon.com/c/kevinveenbirkenbach) [![Buy Me a Coffee](https://img.shields.io/badge/Buy%20me%20a%20Coffee-Funding-yellow?logo=buymeacoffee)](https://buymeacoffee.com/kevinveenbirkenbach) [![PayPal](https://img.shields.io/badge/Donate-PayPal-blue?logo=paypal)](https://s.veen.world/paypaldonate)
```markdown
# Portfolio CMS: Flask-based Portfolio Management 🚀
[![GitHub Sponsors](https://img.shields.io/badge/Sponsor-GitHub%20Sponsors-blue?logo=github)](https://github.com/sponsors/kevinveenbirkenbach) [![Patreon](https://img.shields.io/badge/Support-Patreon-orange?logo=patreon)](https://www.patreon.com/c/kevinveenbirkenbach) [![Buy Me a Coffee](https://img.shields.io/badge/Buy%20me%20a%20Coffee-Funding-yellow?logo=buymeacoffee)](https://buymeacoffee.com/kevinveenbirkenbach) [![PayPal](https://img.shields.io/badge/Donate-PayPal-blue?logo=paypal)](https://s.veen.world/paypaldonate)
This software allows individuals and institutions to set up an easy portfolio/landingpage/homepage to showcase their projects and online presence. It is highly customizable via a YAML configuration file.
## Features ✨
- **Dynamic Navigation**: Easily create dropdown menus and nested links.
- **Customizable Cards**: Showcase your skills, projects, or services.
- **Cache Management**: Optimize your assets with automatic caching.
- **Responsive Design**: Beautiful on any device with Bootstrap.
- **Easy Configuration**: Update content using a YAML file.
- **Dynamic Navigation:** Easily create dropdown menus and nested links.
- **Customizable Cards:** Showcase your skills, projects, or services.
- **Cache Management:** Optimize your assets with automatic caching.
- **Responsive Design:** Beautiful on any device with Bootstrap.
- **Easy Configuration:** Update content using a YAML file.
- **Command Line Interface:** Manage Docker containers with the `portfolio` CLI.
## Access 🌐
### Locale
### Local Access
Access the application locally at [http://127.0.0.1:5000](http://127.0.0.1:5000).
## Getting Started 🏁
@ -26,6 +28,8 @@ Access the application locally at [http://127.0.0.1:5000](http://127.0.0.1:5000)
### Installation 🛠️
#### Installation via git clone
1. **Clone the repository:**
```bash
git clone <repository_url>
@ -40,9 +44,40 @@ Access the application locally at [http://127.0.0.1:5000](http://127.0.0.1:5000)
docker-compose up --build
```
4. **Access your portfolio:** Open your browser and navigate to [http://localhost:5000](http://localhost:5000).
4. **Access your portfolio:**
Open your browser and navigate to [http://localhost:5000](http://localhost:5000).
## Configuration Guide 🔧
### Installation via Kevin's Package Manager
You can install the `portfolio` CLI using [Kevin's package manager](https://github.com/kevinveenbirkenbach/package-manager). Simply run:
```bash
pkgmgr install portfolio
```
This will install the CLI tool, making it available system-wide.
### Available Commands
After installation, you can access the help information for the CLI by running:
```bash
portfolio --help
```
This command displays detailed instructions on how to use the following commands:
- **build:** Build the Docker image for the portfolio application.
- **up:** Start the application using docker-compose (with build).
- **down:** Stop and remove the Docker container.
- **run-dev:** Run the container in development mode with hot-reloading.
- **run-prod:** Run the container in production mode.
- **logs:** Display the logs of the running container.
- **dev:** Start the application in development mode using docker-compose.
- **prod:** Start the application in production mode using docker-compose.
- **cleanup:** Remove all stopped Docker containers to clean up your Docker environment.
## YAML Configuration Guide 🔧
The portfolio is powered by a YAML configuration file (`config.yaml`). This file allows you to define the structure and content of your site, including cards, navigation, and company details.
@ -95,77 +130,11 @@ company:
### Understanding the `children` Key 🔍
The `children` key allows hierarchical nesting of elements. Each child can itself have children, enabling the creation of multi-level navigation menus or grouped content. Example:
```yaml
children:
- name: Parent Item
description: Parent description.
icon:
class: fa-solid fa-folder
children:
- name: Child Item
description: Child description.
icon:
class: fa-solid fa-file
url: https://example.com
```
This structure will render a parent menu or section containing nested child elements. Each child can be further customized with icons, descriptions, and links.
The `children` key allows hierarchical nesting of elements. Each child can itself have children, enabling the creation of multi-level navigation menus or grouped content.
### Understanding the `link` Key 🔗
The `link` key allows you to reference another part of the YAML configuration by its path. This is useful for avoiding duplication and maintaining consistency. Example:
```yaml
children:
- name: Blog
description: My blog posts.
icon:
class: fa-solid fa-blog
url: https://example.com/blog
- name: Featured Blog
link: accounts.children[0].children[0] # References the "Blog" item above
```
In this example, `Featured Blog` will inherit all properties from the `Blog` item, including its name, description, and URL. This feature ensures that any updates to the `Blog` item are automatically reflected in all linked entries.
## Administrate Docker 🐳
### Stop and Destroy
```bash
docker stop portfolio; docker rm portfolio
```
### Build
```bash
docker build -t application-portfolio .
```
### Run
#### Run Development Environment
```bash
docker run -d -p 5000:5000 --name portfolio -v $(pwd)/app/:/app -e FLASK_APP=app.py -e FLASK_ENV=development application-portfolio
```
#### Run Production Environment
```bash
docker run -d -p 5000:5000 --name portfolio application-portfolio
```
### Debug
```bash
docker logs -f portfolio
```
## Development Mode 🧑‍💻
To run the app in development mode with hot-reloading:
```bash
FLASK_ENV=development docker-compose up
```
The `link` key allows you to reference another part of the YAML configuration by its path, which helps avoid duplication and maintain consistency.
## Deployment 🚢
@ -175,10 +144,10 @@ For production deployment, ensure to:
- Secure your site with SSL/TLS.
- Use a production-ready database if required.
## Author ✍️
This software was created by [Kevin Veen-Birkenbach](https://www.veen.world/).
## License 📜
This project is licensed under the GNU Affero General Public License Version 3. See the [LICENSE](./LICENSE) file for details.
## Author ✍️
This software was created by [Kevin Veen-Birkenbach](https://www.veen.world/).

View File

@ -1,10 +1,10 @@
services:
landingpage:
portfolio:
build:
context: .
dockerfile: Dockerfile
image: application-landingpage
container_name: landingpage
image: application-portfolio
container_name: portfolio
ports:
- "5000:5000"
volumes:

260
main.py Executable file
View File

@ -0,0 +1,260 @@
#!/usr/bin/env python3
"""
main.py - A CLI tool for managing the Portfolio CMS Docker application.
This script provides commands to build and run the Docker container for the
portfolio application. It mimics the functionality of a Makefile with additional
explanatory text using argparse.
Commands:
build - Build the Docker image.
up - Start the application using docker-compose (with build).
down - Stop and remove the running container.
run-dev - Run the container in development mode (with hot-reloading).
run-prod - Run the container in production mode.
logs - Display the logs of the running container.
dev - Start the application in development mode using docker-compose.
prod - Start the application in production mode using docker-compose.
cleanup - Remove all stopped containers.
"""
import argparse
import subprocess
import sys
import os
def run_command(command, dry_run=False):
"""Utility function to run a shell command."""
print(f"Executing: {' '.join(command)}")
if dry_run:
print("Dry run enabled: command not executed.")
return
try:
subprocess.check_call(command)
except subprocess.CalledProcessError as e:
print(f"Error: Command failed with exit code {e.returncode}")
sys.exit(e.returncode)
def build(args):
"""
Build the Docker image for the portfolio application.
Command:
docker build -t application-portfolio .
This command creates a Docker image named 'application-portfolio'
from the Dockerfile in the current directory.
"""
command = ["docker", "build", "-t", "application-portfolio", "."]
run_command(command, args.dry_run)
def up(args):
"""
Start the application using docker-compose with build.
Command:
docker-compose up --build
This command uses docker-compose to build (if necessary) and start
all defined services. It is useful for quickly starting your
development or production environment.
"""
command = ["docker-compose", "up", "--build"]
run_command(command, args.dry_run)
def down(args):
"""
Stop and remove the Docker container named 'portfolio'.
Commands:
docker stop portfolio
docker rm portfolio
These commands stop the running container and remove it from your Docker host.
The '-' prefix is used to ignore errors if the container is not running.
"""
command_stop = ["docker", "stop", "portfolio"]
command_rm = ["docker", "rm", "portfolio"]
run_command(command_stop, args.dry_run)
run_command(command_rm, args.dry_run)
def run_dev(args):
"""
Run the container in development mode with hot-reloading.
Command:
docker run -d -p 5000:5000 --name portfolio -v $(pwd)/app/:/app \
-e FLASK_APP=app.py -e FLASK_ENV=development application-portfolio
This command starts the container in detached mode (-d), maps port 5000,
mounts the local 'app/' directory into the container, and sets environment
variables to enable Flask's development mode.
"""
current_dir = os.getcwd()
volume_mapping = f"{current_dir}/app/:/app"
command = [
"docker", "run", "-d",
"-p", "5000:5000",
"--name", "portfolio",
"-v", volume_mapping,
"-e", "FLASK_APP=app.py",
"-e", "FLASK_ENV=development",
"application-portfolio"
]
run_command(command, args.dry_run)
def run_prod(args):
"""
Run the container in production mode.
Command:
docker run -d -p 5000:5000 --name portfolio application-portfolio
This command starts the container in detached mode, mapping port 5000,
and runs the production version of the portfolio application.
"""
command = [
"docker", "run", "-d",
"-p", "5000:5000",
"--name", "portfolio",
"application-portfolio"
]
run_command(command, args.dry_run)
def logs(args):
"""
Display the logs of the 'portfolio' container.
Command:
docker logs -f portfolio
This command follows the logs (using -f) of the running container,
which is helpful for debugging and monitoring.
"""
command = ["docker", "logs", "-f", "portfolio"]
run_command(command, args.dry_run)
def dev(args):
"""
Run the application in development mode using docker-compose.
Command:
FLASK_ENV=development docker-compose up -d
This command sets the FLASK_ENV environment variable to 'development'
and starts the application using docker-compose, enabling hot-reloading.
"""
env = os.environ.copy()
env["FLASK_ENV"] = "development"
command = ["docker-compose", "up", "-d"]
print("Setting FLASK_ENV=development")
run_command(command, args.dry_run)
def prod(args):
"""
Run the application in production mode using docker-compose.
Command:
docker-compose up --build
This command builds the Docker image if needed and starts the application
using docker-compose for a production environment.
"""
command = ["docker-compose", "up", "--build"]
run_command(command, args.dry_run)
def cleanup(args):
"""
Remove all stopped Docker containers.
Command:
docker container prune -f
This command cleans up your Docker environment by forcefully removing
all stopped containers. It is useful to reclaim disk space and remove
unused containers.
"""
command = ["docker", "container", "prune", "-f"]
run_command(command, args.dry_run)
def main():
parser = argparse.ArgumentParser(
description="CLI tool to manage the Portfolio CMS Docker application."
)
parser.add_argument(
"--dry-run",
action="store_true",
help="Print the commands without executing them."
)
subparsers = parser.add_subparsers(
title="Commands",
description="Available commands to manage the application",
dest="command"
)
# Build command
parser_build = subparsers.add_parser(
"build", help="Build the Docker image."
)
parser_build.set_defaults(func=build)
# Up command (docker-compose up)
parser_up = subparsers.add_parser(
"up", help="Start the application using docker-compose (with build)."
)
parser_up.set_defaults(func=up)
# Down command
parser_down = subparsers.add_parser(
"down", help="Stop and remove the Docker container."
)
parser_down.set_defaults(func=down)
# Run-dev command
parser_run_dev = subparsers.add_parser(
"run-dev", help="Run the container in development mode (with hot-reloading)."
)
parser_run_dev.set_defaults(func=run_dev)
# Run-prod command
parser_run_prod = subparsers.add_parser(
"run-prod", help="Run the container in production mode."
)
parser_run_prod.set_defaults(func=run_prod)
# Logs command
parser_logs = subparsers.add_parser(
"logs", help="Display the logs of the running container."
)
parser_logs.set_defaults(func=logs)
# Dev command (docker-compose with FLASK_ENV)
parser_dev = subparsers.add_parser(
"dev", help="Start the application in development mode using docker-compose."
)
parser_dev.set_defaults(func=dev)
# Prod command (docker-compose production)
parser_prod = subparsers.add_parser(
"prod", help="Start the application in production mode using docker-compose."
)
parser_prod.set_defaults(func=prod)
# Cleanup command
parser_cleanup = subparsers.add_parser(
"cleanup", help="Remove all stopped Docker containers."
)
parser_cleanup.set_defaults(func=cleanup)
args = parser.parse_args()
if args.command is None:
parser.print_help()
sys.exit(1)
# Execute the chosen subcommand function
args.func(args)
if __name__ == "__main__":
main()