About This Site
Does the layout of this website look familiar? That’s because it’s made with Material for MkDocs, a template used by many popular software projects for their documentations, such as FastAPI, uvicorn, and pydantic.
When I was looking for a template for a personal website, the natural choice would have been WordPress. But I wanted to try something else. I had noticed how well websites based on Material for MkDocs render on both desktop and mobile devices. Also, I like how fast and snappy Material for MkDocs is.
Many software projects host their documentation on GitHub Pages, but I wanted to take care of hosting myself. It turned out that serving a website based on MkDocs is really straightforward. After editing the content and layout (via markdown text files and a yml configuration file, as explained here), you can run the build command, which automatically generates all HTML, CSS, and JavaScript files for you:
mkdocs build
The build command creates a site
directory containing all files required to serve the website.
At work, I often serve microservices with FastAPI and uvicorn. As it turns out, the same approach can be used for serving a static website built with MkDocs, with just a few lines of Python code:
from fastapi import FastAPI
from fastapi.staticfiles import StaticFiles
from starlette.responses import RedirectResponse
app = FastAPI()
app.mount("/site", StaticFiles(directory="site", html=True), name="static")
@app.get("/")
async def root():
return RedirectResponse(url="/site/index.html")
The website can now be served with uvicorn server:app
(from the bash command line).
One can even extend this approach and server dynamic content in form of a Plotly dashboard (credits to this repository):
from fastapi import FastAPI
from fastapi.middleware.wsgi import WSGIMiddleware
from starlette.responses import RedirectResponse
# Import your Dash app; see
# https://realpython.com/python-dash/
# for a tutorial on how to create your own Dash app
from my_app import create_dash_app
app = FastAPI()
@app.get("/")
async def root():
return RedirectResponse(url="/mydashapp/")
dash_app = create_dash_app(routes_pathname_prefix="/mydashapp/")
app.mount("/", WSGIMiddleware(dash_app.server))
The website can be hosted on a small virtual private server. Perhaps a bit unconventional, but definitely a minimalist, lightweight solution.