Skip to content

Instantly share code, notes, and snippets.

@schneidr
Last active August 19, 2025 13:03
Show Gist options
  • Select an option

  • Save schneidr/9afcbdd34d8d87a6ed9ffcffba2a397c to your computer and use it in GitHub Desktop.

Select an option

Save schneidr/9afcbdd34d8d87a6ed9ffcffba2a397c to your computer and use it in GitHub Desktop.
Shell script to quickly initialize a python flask application
#!/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