Skip to content

Instantly share code, notes, and snippets.

@simonMoisselin
Created February 18, 2025 08:05
Show Gist options
  • Select an option

  • Save simonMoisselin/f63c52f087704c99b6a62bf3d7e14805 to your computer and use it in GitHub Desktop.

Select an option

Save simonMoisselin/f63c52f087704c99b6a62bf3d7e14805 to your computer and use it in GitHub Desktop.
main code for blog in fasthtml
from fasthtml.common import *
from monsterui.all import *
from helpers import Post, get_posts_by_language, DEFAULT_LANG, get_post
app, rt = fast_app(hdrs=Theme.zinc.headers(highlightjs=True), debug=True, live=True)
posts_by_lang = get_posts_by_language()
def lang_str(lang: str): return "🇫🇷 FR" if lang == "fr" else "🇬🇧 EN"
def render_dropdown_language_post(post: Post):
return Form(Select((Option(lang_str(lang), value=lang, selected=lang == post.metadata["language"]) for lang in ["en", "fr"]), cls="flex justify-end", hx_post="/setlanguage",
name="lang"),
Hidden(value=post.metadata["slug"], name="slug"),
hx_target="#post-container",
hx_trigger="change")
def render_post(post: Optional[Post]):
if not post: return Container(
Div(
H1("Post not found", cls="text-4xl font-bold mb-8 text-center pt-4"),
cls="max-w-3xl mx-auto px-4"
)
)
return Container(
Div(
Div(
render_dropdown_language_post(post),
H1(post.metadata["title"], cls="text-3xl font-bold mb-4"),
P(post.metadata["description"], cls="text-gray-600 mb-6"),
cls="bg-gray-50 p-6 rounded-t-lg"
),
Div(render_md(post.content), cls="p-6"),
cls="border rounded-lg shadow-sm mx-auto"
),
id="post-container",
)
def get_card_post(post: Post):
return A(
Div(
H2(post.metadata["title"], cls="text-2xl font-semibold hover:text-blue-600"),
P(post.metadata["description"], cls="text-gray-600 mt-2"),
Div(
P(f"By {post.metadata['author']}", cls="text-sm text-gray-500"),
P(f"Posted on {post.metadata['date']}", cls="text-sm text-gray-500"),
cls="flex gap-4 mt-1"
),
Div(*(
Span(tag, cls="px-2 py-1 text-xs bg-gray-100 rounded")
for tag in post.metadata["tags"]
), cls="flex gap-2 mt-2"),
cls="p-6 border rounded-lg hover:shadow-lg transition-shadow duration-200 mb-4"
),
href=f"/posts/{post.metadata['slug']}",
cls="block no-underline"
)
def nav():
return NavBar(
nav_links=[
A("Blogs", href="/posts"),
A("About", href="/"),
],
title=H3("Simon Moisselin's Blog"),
)
@app.get("/")
def about():
return Container(
nav(),
Div(
H1("About Me", cls="text-4xl font-bold mb-8 text-center pt-4"),
P("Hi, I'm Simon Moisselin. I write about Python, web development and other tech topics.",
cls="text-gray-600 mb-4 text-center"),
cls="max-w-3xl mx-auto px-4"
)
)
@app.get("/posts")
def home(session):
posts = posts_by_lang[session.get('language', DEFAULT_LANG)]
return (
nav(),
Div(
H1("Blog of Simon Moisselin", cls="text-4xl font-bold mb-8 text-center pt-4"),
P("Made with FastHTML", cls="text-gray-600 mb-8 text-center"),
Div(*(get_card_post(post) for post in posts), cls="space-y-6"),
cls="max-w-3xl mx-auto px-4"
)
)
@app.get("/posts/{slug}")
def post(session, slug: str):
post = get_post(slug, session.get('language', DEFAULT_LANG), posts_by_lang)
return (
nav(),
render_post(post)
)
@app.post("/setlanguage")
def set_language(session, lang: str, slug: str):
session['language'] = lang
return render_post(get_post(slug, lang, posts_by_lang))
serve()
@SilasK
Copy link
Copy Markdown

SilasK commented Jul 8, 2025

Hey, your automatic translation system is very cool. I would like to implement something similar. Could you share the helpers functions. Which I assume are some other code of you.
Thank you very much.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment