An Informationally-Dense Index Page

by Audrey M. Roy Greenfeld | Sun, Feb 9, 2025

Now that I have a lot of notebooks, it would be nice to have a more compact index page. I want to see more of my posts from mobile all at once. I'm going to prototype it in Tailwind.


from datetime import datetime
from execnb.nbio import read_nb
from fastcore.utils import *
from fasthtml.common import *
from fasthtml.jupyter import *
from monsterui import franken
from monsterui.all import Theme
def get_nb_paths(): 
    root = Path() if IN_NOTEBOOK else Path("nbs/")
    return L(root.glob("*.ipynb")).sorted(reverse=True)
nbpaths = get_nb_paths()
nbpaths

Use tighter notebook links instead of notebook cards

def get_date_from_iso8601_prefix(fname):
    "Gets date from first 10 chars YYYY-MM-DD of `fname`, where `fname` is like `2025-01-12-Get-Date-From-This.whatever"
    try:
        return datetime.fromisoformat(str(fname)[0:10])
    except ValueError: return datetime.now()
def get_title_and_desc(fpath):
    nb = read_nb(fpath)
    title = nb.cells[0].source.lstrip("# ")
    desc = nb.cells[1].source
    return title,desc
app,rt = fast_app(pico=False)
def NBLink(title, desc, href, date):
    return Div(
        A(f"{date:%b %-d}{title}", href=href, cls="text-md font-semibold hover:text-blue-600 no-underline block"),
        P(desc, cls="text-s text-gray-500 mt-0.5 mb-2"),
        cls="py-1 break-inside-avoid")
def mk_nblink_from_nbpath(nbpath):
    date = get_date_from_iso8601_prefix(nbpath.name) or datetime.now()
    return NBLink(*get_title_and_desc(nbpath), href=f'/nbs/{nbpath.name[:-6]}', date=date)
@rt
def index():
    nbpaths = get_nb_paths()
    return (
        Theme.blue.headers(),
        Title("audrey.feldroy.com"),
        Div(
            H1('audrey.feldroy.com', cls="text-3xl font-bold mb-2"), 
            P(
                "The experimental Jupyter notebooks of Audrey M. Roy Greenfeld. This website and all its notebooks are open-source at ", 
                A("github.com/audreyfeldroy/audrey.feldroy.com", 
                        href="https://github.com/audreyfeldroy/arg-blog-fasthtml",
                        cls="text-blue-600 hover:text-blue-800"), 
                cls="mb-8 text-gray-600"
            ),
            Table(
                *nbpaths.map(mk_nblink_from_nbpath), 
                
            ),
            cls="px-4 py-8 w-full columns-1 md:columns-2 lg:columns-3 gap-6"
        )
    )

Improving this visually while providing extreme information density and compactness:

@rt
def index():
    nbpaths = get_nb_paths()
    return (
        Script(src="https://unpkg.com/@tailwindcss/browser@4"),
        Title("audrey.feldroy.com"),
        Div(
            H1('audrey.feldroy.com', cls="text-2xl font-bold mb-2 dark:text-gray-100"), 
            P(
                "The experimental Jupyter notebooks of Audrey M. Roy Greenfeld. This website and all its notebooks are open-source at ", 
                A("github.com/audreyfeldroy/audrey.feldroy.com", 
                        href="https://github.com/audreyfeldroy/arg-blog-fasthtml",
                        cls="text-blue-600 hover:text-blue-800 dark:text-blue-400 dark:hover:text-blue-300"), 
                cls="mb-4 text-gray-600 dark:text-gray-300 text-sm"
            ),
            Div(
                *nbpaths.map(mk_nblink_from_nbpath),
                cls="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-x-6 gap-y-2"
            ),
            cls="mx-auto px-2 py-4 dark:bg-gray-900 min-h-screen"
        ),
    )

def NBLink(title, desc, href, date):
    return Div(
        A(
            Div(
                f"{date:%b %-d}", 
                cls="text-xs font-medium text-gray-500 dark:text-gray-400"
            ),
            Div(
                title,
                cls="text-base font-medium leading-snug hover:text-blue-600 dark:text-gray-100 dark:hover:text-blue-400"
            ),
            P(
                desc,
                cls="text-xs text-gray-600 dark:text-gray-400 mt-0.5 line-clamp-2"
            ),
            href=href,
            cls="block no-underline hover:bg-gray-50 dark:hover:bg-gray-800 p-2 rounded transition-colors"
        ),
        cls="break-inside-avoid"
    )
server = JupyUvi(app)
HTMX(index)
# server.stop()