Last active
August 19, 2025 13:03
-
-
Save schneidr/9afcbdd34d8d87a6ed9ffcffba2a397c to your computer and use it in GitHub Desktop.
Shell script to quickly initialize a python flask application
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/env bash | |
| set -e | |
| if [ $# -eq 0 ]; then | |
| >&2 echo "No arguments provided" | |
| >&2 echo "Usage: $0 <projectname>" | |
| exit 1 | |
| fi | |
| PROJECT_NAME="$1" | |
| PROJECT_DIR="$PWD/$PROJECT_NAME" | |
| TEMPLATES_DIR="$PROJECT_DIR/templates" | |
| STATIC_DIR="$PROJECT_DIR/static" | |
| DOWNLOAD_DIR="$HOME/Downloads" | |
| TMP_DIR=$(mktemp -d --suffix "-python-init") | |
| mkdir -p "$DOWNLOAD_DIR" | |
| mkdir -p "$PROJECT_DIR" | |
| mkdir -p "$TEMPLATES_DIR" | |
| mkdir -p "$STATIC_DIR"/{css,js} | |
| curl -s https://api.github.com/repos/twbs/bootstrap/releases/latest \ | |
| | jq -r ".assets[] | select(.name | test(\"-dist.zip$\")) | .browser_download_url" \ | |
| | xargs -I {} curl -sL {} -z "$DOWNLOAD_DIR/bootstrap.zip" -o "$DOWNLOAD_DIR/bootstrap.zip" | |
| unzip -d "$TMP_DIR" -q "$DOWNLOAD_DIR/bootstrap.zip" | |
| cp "$TMP_DIR"/bootstrap-*-dist/css/bootstrap.min.css "$STATIC_DIR/css/" | |
| cp "$TMP_DIR"/bootstrap-*-dist/js/bootstrap.bundle.min.js "$STATIC_DIR/js/" | |
| curl -s https://api.github.com/repos/FortAwesome/Font-Awesome/releases/latest \ | |
| | jq -r ".assets[] | select(.name | test(\"-web.zip$\")) | .browser_download_url" \ | |
| | xargs -I {} curl -sL {} -z "$DOWNLOAD_DIR/fontawesome.zip" -o "$DOWNLOAD_DIR/fontawesome.zip" | |
| unzip -d "$TMP_DIR" -q "$DOWNLOAD_DIR"/fontawesome.zip | |
| cp "$TMP_DIR"/fontawesome-*-web/css/{brands,fontawesome,solid}.min.css "$STATIC_DIR/css/" | |
| cp -r "$TMP_DIR"/fontawesome-*-web/webfonts "$STATIC_DIR"/ | |
| rm -rf "$TMP_DIR" | |
| cd "$PROJECT_DIR" || exit 2 | |
| python3 -m venv . || exit 3 | |
| source "$PROJECT_DIR/bin/activate" | |
| cat << EOF > "$PROJECT_DIR/requirements.txt" | |
| Flask | |
| Flask-Babel | |
| EOF | |
| cat << EOF > "$PROJECT_DIR/$PROJECT_NAME.py" | |
| from flask import flash, Flask, Response | |
| from flask import redirect, render_template, request, session, url_for | |
| from flask_babel import Babel, gettext | |
| app = Flask(__name__) | |
| # app.config.from_pyfile('settings.cfg') | |
| # app.secret_key = app.config['SECRET_KEY'] | |
| babel = Babel(app) | |
| @app.route("/") | |
| def index(): | |
| return render_template('index.html') | |
| @app.errorhandler(401) | |
| def page_not_found(error): | |
| return render_template('unauthorized.html'), 401 | |
| @app.errorhandler(404) | |
| def page_not_found(error): | |
| return render_template('page_not_found.html'), 404 | |
| EOF | |
| cat << EOF > "$TEMPLATES_DIR/index.html" | |
| {% extends 'base.html' %} | |
| {% block title %}Index{% endblock %} | |
| {% block content %} | |
| {% endblock %} | |
| {% block scripts %} | |
| {% endblock %} | |
| EOF | |
| cat << EOF > "$TEMPLATES_DIR/base.html" | |
| <!doctype html> | |
| <html lang="en"> | |
| <head> | |
| <meta charset="utf-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1"> | |
| <title>{% block title %}{% endblock %} - $PROJECT_NAME</title> | |
| <link href="{{ url_for('static', filename='css/bootstrap.min.css') }}" rel="stylesheet" crossorigin="anonymous"> | |
| <link href="{{ url_for('static', filename='css/fontawesome.min.css') }}" rel="stylesheet" crossorigin="" /> | |
| <link href="{{ url_for('static', filename='css/brands.min.css') }}" rel="stylesheet" crossorigin="" /> | |
| <link href="{{ url_for('static', filename='css/solid.min.css') }}" rel="stylesheet" crossorigin="" /> | |
| </head> | |
| <body style="height:100vh"> | |
| <nav class="navbar navbar-expand-lg bg-body-tertiary"> | |
| <div class="container-fluid"> | |
| <a class="navbar-brand" href="#">$PROJECT_NAME</a> | |
| <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation"> | |
| <span class="navbar-toggler-icon"></span> | |
| </button> | |
| <div class="collapse navbar-collapse" id="navbarSupportedContent"> | |
| <ul class="navbar-nav me-auto mb-2 mb-lg-0"> | |
| <li class="nav-item"> | |
| <a class="nav-link" aria-current="page" href="#">One</a> | |
| </li> | |
| <li class="nav-item"> | |
| <a class="nav-link" aria-current="page" href="#">Two</a> | |
| </li> | |
| <li class="nav-item"> | |
| <a class="nav-link" aria-current="page" href="#">Three</a> | |
| </li> | |
| </ul> | |
| </div> | |
| </div> | |
| </nav> | |
| {% block content %}{% endblock %} | |
| <script src="{{ url_for('static', filename='js/bootstrap.bundle.min.js') }}" crossorigin="anonymous"></script> | |
| {% block scripts %}{% endblock %} | |
| </body> | |
| </html> | |
| EOF | |
| cat << EOF > "$PROJECT_DIR/.gitignore" | |
| __pycache__ | |
| lib/ | |
| lib64 | |
| bin/ | |
| *.cfg | |
| *.db | |
| EOF | |
| pip install -r "$PROJECT_DIR/requirements.txt" | |
| if type git > /dev/null; then | |
| git init --quiet | |
| git add -A | |
| git commit -m "initial skeleton" --quiet | |
| fi |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment