From f50ba452dfec9dc5a73c995f16721e7e7280c23f Mon Sep 17 00:00:00 2001 From: Ayo Ayco Date: Sun, 9 Mar 2025 11:41:17 +0100 Subject: [PATCH] initial commit --- .gitignore | 169 +++++++++++++++++++++++++++++++++++++++++ README.md | 61 +++++++++++++++ __init__.py | 0 app.py | 14 ++++ blueprintname.py | 20 +++++ cache.py | 2 + requirements.txt | 2 + static/button.css | 29 +++++++ static/card.css | 175 +++++++++++++++++++++++++++++++++++++++++++ static/reset.css | 78 +++++++++++++++++++ static/variables.css | 31 ++++++++ templates/_home.html | 175 +++++++++++++++++++++++++++++++++++++++++++ templates/nav.html | 1 + 13 files changed, 757 insertions(+) create mode 100755 .gitignore create mode 100644 README.md create mode 100644 __init__.py create mode 100755 app.py create mode 100755 blueprintname.py create mode 100644 cache.py create mode 100644 requirements.txt create mode 100644 static/button.css create mode 100644 static/card.css create mode 100644 static/reset.css create mode 100644 static/variables.css create mode 100644 templates/_home.html create mode 100644 templates/nav.html diff --git a/.gitignore b/.gitignore new file mode 100755 index 0000000..cace76f --- /dev/null +++ b/.gitignore @@ -0,0 +1,169 @@ +config.json + +# Deployment Unix socket +*.sock + +# Temp files +*~ +*swp +*swo + +# web +node_modules/ + +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +*.py,cover +.hypothesis/ +.pytest_cache/ +cover/ + +# Translations +*.mo +*.pot + +# Django stuff: +*.log +local_settings.py +db.sqlite3 +db.sqlite3-journal + +# Flask stuff: +instance/ +.webassets-cache + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_build/ + +# PyBuilder +.pybuilder/ +target/ + +# Jupyter Notebook +.ipynb_checkpoints + +# IPython +profile_default/ +ipython_config.py + +# pyenv +# For a library or package, you might want to ignore these files since the code is +# intended to run in multiple environments; otherwise, check them in: +# .python-version + +# pipenv +# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. +# However, in case of collaboration, if having platform-specific dependencies or dependencies +# having no cross-platform support, pipenv may install dependencies that don't work, or not +# install all needed dependencies. +#Pipfile.lock + +# poetry +# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control. +# This is especially recommended for binary packages to ensure reproducibility, and is more +# commonly ignored for libraries. +# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control +#poetry.lock + +# pdm +# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control. +#pdm.lock +# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it +# in version control. +# https://pdm.fming.dev/#use-with-ide +.pdm.toml + +# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm +__pypackages__/ + +# Celery stuff +celerybeat-schedule +celerybeat.pid + +# SageMath parsed files +*.sage.py + +# Environments +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ + +# Spyder project settings +.spyderproject +.spyproject + +# Rope project settings +.ropeproject + +# mkdocs documentation +/site + +# mypy +.mypy_cache/ +.dmypy.json +dmypy.json + +# Pyre type checker +.pyre/ + +# pytype static type analyzer +.pytype/ + +# Cython debug symbols +cython_debug/ + +# Mastodon secrets +**/*.secret \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..e20fc35 --- /dev/null +++ b/README.md @@ -0,0 +1,61 @@ +# Python Template + +An opinionated starter project for flask python projects. It contains code for a new [Flask Blueprint]https://flask.palletsprojects.com/en/stable/blueprints/). + +**DO NOT PUSH PROJECT-SPECIFIC CHANGES** + +## Project setup + +1. Set up your **Debian** (for other environments, search for counterpart instructions) + + ```bash + # update repositories + $ sudo apt update + + # install python stuff + $ sudo apt install python3-pip python3-dev build-essential libssl-dev libffi-dev python3-setuptools python3-venv + ``` + +> For MacOS: https://docs.python.org/3/using/mac.html + +2. Install dependencies and set up the project + + ```bash + # clone the project + $ git clone git@git.sr.ht:~ayoayco/python-template [project-name] + + # go into the directory + $ cd [project-name] + + # remove template .git stuff + $ rm -rf .git + + # initialize git + $ git init . + + # create python environment: + $ python3 -m venv .venv + + # activate python env: + $ . .venv/bin/activate + + # install dependencies + (.venv)$ python -m pip install -r requirements.txt + + # create configuration from example config file + (.venv)$ cp ./example_config.json ./config.json + + # rejoice! + ``` + +3. To start development, run the following: + ```bash + (.venv)$ flask --debug run + ``` + + > Note: On a Mac, the default port 5000 is used by AirDrop & Handoff; you may have to turn those off + +4. After development session, deactivate the python env + ``bash + ` (.venv)$ deactivate + ``` diff --git a/__init__.py b/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app.py b/app.py new file mode 100755 index 0000000..c07c422 --- /dev/null +++ b/app.py @@ -0,0 +1,14 @@ +from flask import Flask +import json +from .blueprintname import blueprintname +from .cache import cache + +# TODO: Update blueprintname + +app = Flask(__name__) +cache.init_app(app, config={'CACHE_TYPE': 'SimpleCache'}) +app.register_blueprint(blueprintname, url_prefix='/') +app.config.from_file("config.json", load=json.load) + +if __name__ == '__main__': + app.run(host='0.0.0.0') diff --git a/blueprintname.py b/blueprintname.py new file mode 100755 index 0000000..e0c135e --- /dev/null +++ b/blueprintname.py @@ -0,0 +1,20 @@ +from flask import Blueprint, render_template, current_app +from .cache import cache + +blueprintname = Blueprint("blueprintname", __name__, template_folder="templates", static_folder="static") + + +def get_attribution(): + return current_app.config['ATTRIBUTION'] + +def get_app_config(): + return current_app.config['APPS']['blueprintname'] + + +@blueprintname.route("/") +@cache.cached(timeout=300) +async def home(): + + # DO STUFF... + + return render_template("_home.html", app=get_app_config(), attribution=get_attribution()) diff --git a/cache.py b/cache.py new file mode 100644 index 0000000..32a618f --- /dev/null +++ b/cache.py @@ -0,0 +1,2 @@ +from flask_caching import Cache +cache = Cache() diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..09210ce --- /dev/null +++ b/requirements.txt @@ -0,0 +1,2 @@ +flask[async] +Flask-Caching diff --git a/static/button.css b/static/button.css new file mode 100644 index 0000000..801c434 --- /dev/null +++ b/static/button.css @@ -0,0 +1,29 @@ +.btn { + text-decoration: none; + border-radius: 5px; + border: 1px solid; + color: var(--text-color-dark); + border-color: var(--border-color-light); + background-color: var(--bg-light); + padding: 0.25em 0.5em; + font-weight: bold; + font-size: var(--font-size-base); + + &:hover { + color: var(--color-brand-blue-3); + border-color: var(--color-brand-blue-3); + } +} + +@media (prefers-color-scheme: dark) { + .btn { + color: var(--text-color-light); + border-color: var(--border-color-dark); + background-color: var(--bg-dark); + + &:hover { + color: var(--color-brand-complement); + border-color: var(--color-brand-complement); + } + } +} diff --git a/static/card.css b/static/card.css new file mode 100644 index 0000000..2be7f43 --- /dev/null +++ b/static/card.css @@ -0,0 +1,175 @@ +.card_content { + & .invisible { + display: none; + } + + & .emoji { + display: inline; + height: calc(1rem + 6px); + margin-bottom: -4px; + } + + & .ellipsis::after { + content: "..."; + } + + & .body { + .hashtag:not(.pill), + .mention:not(.pill) { + color: var(--text-color-dark-faded); + text-decoration: none; + + &:hover { + text-decoration: underline; + } + } + + & code { + font-size: var(--font-size-sm); + background: rgb(245, 242, 240); + padding: 0.25em 0.3em; + border-radius: 5px; + display: inline-block; + vertical-align: text-bottom; + overflow-x: auto; + overflow-wrap: initial; + max-width: 100%; + } + + & a:has(.link-card) { + text-decoration: none; + } + + & .media, + & .link-card { + border: 1px solid; + border-color: var(--border-color-light); + color: var(--text-color-dark-faded); + border-radius: 5px; + box-shadow: 5px 25px 10px -25px rgba(34, 34, 34, 0.15); + max-width: 100%; + margin: 15px 0 1em; + object-fit: contain; + height: auto; + text-decoration: none; + text-wrap: balance; + } + + & .media:hover, + & .link-card:hover { + color: var(--color-brand-blue-3); + border: 1px solid var(--color-brand-blue-3); + text-decoration-color: var(--color-link); + } + + & p { + margin-bottom: 1em; + } + } + + & .heading { + display: grid; + grid-template-columns: auto auto; + gap: 5px; + height: 20px; + + & .author { + font-size: var(--font-size-lg); + } + + & .right_menu { + font-size: var(--font-size-sm); + text-align: right; + + & a, + & span { + line-height: 36px; + } + + & a { + color: var(--text-color-dark-faded); + text-decoration: none; + + &:hover { + color: var(--color-link); + text-decoration: underline; + } + } + } + } + + & .link-card { + color: var(--text-color-dark-faded); + text-decoration: underline; + text-decoration-color: var(--text-color-light-faded); + + & strong, + & small { + text-decoration-thickness: 1px; + display: block; + } + + padding: 1rem; + } +} + +article.card { + /* border-bottom: 1px solid; + border-color: var(--border-color-light); + */ + + & .bottom-menu { + padding: 0.25em 0 1em; + } +} + +@media (prefers-color-scheme: dark) { + .card_content { + & .action { + color: var(--color-brand-complement); + } + + & .heading .right_menu a { + color: var(--text-color-light-faded); + + &:hover { + color: var(--color-brand-complement); + } + } + + & .body { + .hashtag:not(.pill), + .mention:not(.pill) { + color: var(--text-color-light-faded); + text-decoration: none; + + &:hover { + text-decoration: underline; + } + } + + code { + background: rgb(45, 51, 59); + color: rgb(197, 209, 222); + } + + & .media, + & .link-card { + border: 1px solid; + border-color: var(--border-color-dark); + color: var(--text-color-light-faded); + background-color: var(--bg-dark); + } + + & .media:hover, + & .link-card:hover { + color: var(--color-brand-complement); + border: 1px solid var(--color-brand-complement); + } + } + } + + /* article.card { + border-color: var(--border-color-dark); + } */ +} diff --git a/static/reset.css b/static/reset.css new file mode 100644 index 0000000..0129c21 --- /dev/null +++ b/static/reset.css @@ -0,0 +1,78 @@ +/** +THANKS TO JOSH COMEAU FOR HIS CUSTOM CSS RESET +👉 https://www.joshwcomeau.com/css/custom-css-reset/ +**/ + +/* + 1. Use a more-intuitive box-sizing model. +*/ +*, +*::before, +*::after { + box-sizing: border-box; +} +/* + 2. Remove default margin + */ +* { + margin: 0; +} +/* + 3. Allow percentage-based heights in the application + */ +html, +body { + height: 100%; +} +/* + Typographic tweaks! + 4. Add accessible line-height + 5. Improve text rendering + */ +body { + line-height: 1.5; + -webkit-font-smoothing: antialiased; +} +/* + 6. Improve media defaults + */ +img, +picture, +video, +canvas, +svg, +iframe { + display: block; + max-width: 100%; + margin: 0 auto; +} +/* + 7. Remove built-in form typography styles + */ +input, +button, +textarea, +select { + font: inherit; +} +/* + 8. Avoid text overflows + */ +p, +h1, +h2, +h3, +h4, +h5, +h6 { + overflow-wrap: break-word; +} +/* + 9. Create a root stacking context + */ +#root, +#__next { + isolation: isolate; +} + + diff --git a/static/variables.css b/static/variables.css new file mode 100644 index 0000000..182f347 --- /dev/null +++ b/static/variables.css @@ -0,0 +1,31 @@ +:root { + --content-width: 700px; + --font-size-sm: clamp(0.75rem, 0.2vw + 0.66rem, 0.8rem); + --font-size-base: clamp(1rem, 0.34vw + 0.91rem, 1.19rem); + --font-size-lg: clamp(1.2rem, 0.7vw + 1.2rem, 1.5rem); + --font-size-xl: clamp(2.44rem, 2.38vw + 1.85rem, 3.75rem); + + --color-border: hsl(17, 24%, 90%); + --color-link: var(--color-brand-blue-5); + + --color-brand-blue-1: #3054bf; + --color-brand-blue-2: #203880; + --color-brand-blue-3: #416fff; + --color-brand-blue-4: #101c40; + --color-brand-blue-5: #3964e6; + + --color-brand-complement: orange; + + --ayo-gradient: linear-gradient(45deg, #3054bf, #416fff); + --text-color-dark: #232323; + --text-color-dark-faded: #555; + --text-color-light: #f8f9fa; + --text-color-light-faded: #999; + + --border-color-light: rgba(197, 209, 222, 0.7); + --bg-light: rgba(197, 209, 222, 0.15); + --border-color-dark: rgba(0, 0, 0, 0.25); + --bg-dark: #343a40; + --bg-darker: #212529; + --bg-darkest: #000; +} diff --git a/templates/_home.html b/templates/_home.html new file mode 100644 index 0000000..50333a0 --- /dev/null +++ b/templates/_home.html @@ -0,0 +1,175 @@ + + + + + + + {{ app.title }} + + + + + + + + + + + + + + + + + + +
+ {% include "nav.html" %} + +

{{ app.title }}

+
+

{{ app.description }}

+ +
+
+

CONTENT GOES HERE

+
+ + + + + + + diff --git a/templates/nav.html b/templates/nav.html new file mode 100644 index 0000000..9819269 --- /dev/null +++ b/templates/nav.html @@ -0,0 +1 @@ + \ No newline at end of file