Last active
August 22, 2022 18:36
-
-
Save body20002/22f60cb6fe90303306bfe3a0ff61115f to your computer and use it in GitHub Desktop.
FJPT Stack (FastAPI + Jinja2 + Preact + tailwindcss)
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
<!doctype html> | |
<html> | |
<head> | |
{% block head %} | |
<meta charset="UTF-8"> | |
<meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
<link href="{{ url_for('static', path='css/style.css') }}" rel="stylesheet"> | |
<title>{% block title %} | |
{{ '%s | Your Name' % title or 'Your Name' }} | |
{% endblock %} | |
</title> | |
<script> | |
function connect(){ | |
var timeout = 250; | |
var ws = new WebSocket("ws://localhost:8000/dev") | |
ws.onclose = function(event){ | |
setTimeout(connect, timeout); | |
timeout += timeout; | |
}; | |
ws.onmessage = function(event) { | |
const data = event.data; | |
if (data == 'reload'){ | |
ws.send("close") | |
window.location.reload(); | |
} | |
}; | |
}; | |
connect(); | |
</script> | |
{% endblock %} | |
</head> | |
<body> | |
{% block body %} | |
{% endblock %} | |
</body> | |
</html> |
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
{% extends "base.html" %} | |
{% block body %} | |
<h1 class="text-3xl font-bold underline"> | |
Hello world! | |
</h1> | |
<script type="module"> | |
import { html, render } from 'https://unpkg.com/htm/preact/index.mjs?module' | |
const CustomApp = () => { | |
return html`<button onClick=${() => console.log("Hello, World!")}> | |
Click ME | |
</button>`; | |
} | |
render(html`<${CustomApp} />`, document.getElementById("custom-app")) | |
</script> | |
<span id="custom-app"></span> | |
{% endblock %} |
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
import asyncio | |
import contextlib | |
from fastapi import FastAPI, Request, WebSocket, WebSocketDisconnect, status | |
from fastapi.responses import HTMLResponse | |
from fastapi.staticfiles import StaticFiles | |
from fastapi.templating import Jinja2Templates | |
from watchdog.observers import Observer | |
from watchdog.events import FileSystemEventHandler | |
APP_DIR = Path(__file__).resolve() | |
TEMPLATES_DIR = APP_DIR / "templates" | |
app = FastAPI() | |
app.mount("/static", StaticFiles(directory=TEMPLATES_DIR / "static"), name="static") | |
templates = Jinja2Templates(directory=TEMPLATES_DIR) | |
@app.get("/", response_class=HTMLResponse) | |
def index(request: Request): | |
return templates.TemplateResponse("index.html", {"request": request}) | |
@app.exception_handler(status.HTTP_404_NOT_FOUND) | |
def not_found(request: Request, _): | |
return templates.TemplateResponse("404.html", {"request": request, "title": "404 Not Found"}) | |
@app.exception_handler(status.HTTP_500_INTERNAL_SERVER_ERROR) | |
def internal_server_error(request: Request, _): | |
return templates.TemplateResponse("500.html", {"request": request}) | |
class Handler(FileSystemEventHandler): | |
def __init__(self, websocket: WebSocket) -> None: | |
super().__init__() | |
self.ws = websocket | |
def on_modified(self, _): | |
asyncio.run(self.ws.send_text("reload")) | |
@app.websocket("/dev") | |
async def reload_files(websocket: WebSocket): | |
event_handler = Handler(websocket) | |
observer = Observer() | |
observer.schedule(event_handler, TEMPLATES_DIR, recursive=False) | |
observer.schedule(event_handler, TEMPLATES_DIR / "static", recursive=True) | |
observer.schedule(event_handler, TEMPLATES_DIR / "tailwind/src", recursive=True) | |
observer.start() | |
await websocket.accept() | |
with contextlib.suppress(RuntimeError): | |
try: | |
with contextlib.suppress(WebSocketDisconnect): | |
while (await websocket.receive_text()) != "close": | |
pass | |
observer.stop() | |
finally: | |
with contextlib.suppress(WebSocketDisconnect): | |
await websocket.close(code=status.WS_1000_NORMAL_CLOSURE) | |
observer.join() | |
if __name__ == "__main__": | |
import uvicorn | |
uvicorn.run("main:app", port=8000, reload=True) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment