#| default_exp main
audrey.feldroy.com
The experimental notebooks of Audrey M. Roy Greenfeld. This website and all its notebooks are open-source at github.com/audreyfeldroy/audrey.feldroy.com
# This Site Is Now Powered by This Notebook
by Audrey M. Roy Greenfeld | Thu, Jan 23, 2025
Here in this Jupyter notebook I rewrite audrey.feldroy.com and use nb_export to export it as my new main.py for arg-blog-fasthtml.
#| export from datetime import datetime from execnb.nbio import read_nb from nb2fasthtml.core import render_code_output from fasthtml.common import * from fasthtml.jupyter import * from IPython.display import display, HTML from monsterui import franken from monsterui.all import Theme import mistletoe import pygments from pygments import highlight from pygments.lexers import PythonLexer from pygments.formatters import HtmlFormatter
tags = ["Python", "Jupyter"]
Background
Before this notebook, the code for my blog was a main.py that I maintained by editing it in VS Code. The index page and notebooks were rendered without MonsterUI. I wanted to keep it minimal because sometimes I do crazy CSS experiments.
Yesterday in Customizing FastHTML Headers From Notebook Contents I discovered that different routes can have different HTML headers thanks to _xt_cts
. I then modified my notebook detail view to include MonsterUI headers only when I tag the notebook with "MonsterUI".
Today I was inspired by Solve It With Code Lesson 11 to try rewriting more of my blog in MonsterUI.
Setup
#| export app,rt = fast_app(pico=False)
server = JupyUvi(app)
Notebook Index: Cards
def NBCard(t,d): return franken.Card(d, header=franken.H3(t))
NBCard("First Post", "This is a description of what my post is about")
<div class="uk-card ">
<div class="uk-card-header ">
<h3 class="uk-h3 ">First Post</h3>
</div>
<div class="uk-card-body space-y-6">This is a description of what my post is about</div>
</div>
div((div((h3(('First Post',),{'class': 'uk-h3 '}),),{'class': 'uk-card-header '}), div(('This is a description of what my post is about',),{'class': 'uk-card-body space-y-6'})),{'class': 'uk-card '})show(NBCard("First Post", "This is a description of what my post is about"))
First Post
#| export def get_nb_paths(): return L(sorted(Path().glob("nbs/*.ipynb"), reverse=True))
Note: change to glob("*.ipynb")
to run this from the notebook
nb_paths = get_nb_paths() nb_paths
read_nb(nb_paths[0]).cells[0].source.lstrip("# ")
This is the title of the first notebook.
#| export def get_title_and_desc(fpath): nb = read_nb(fpath) title = nb.cells[0].source.lstrip("# ") desc = nb.cells[1].source return title,desc
get_title_and_desc(nb_paths[0])
show(NBCard(*get_title_and_desc(nb_paths[0])))
Using My Blog to Rewrite Itself
def mk_nbcard_from_nb_path(nb_path): return NBCard(*get_title_and_desc(nb_path))
mk_nbcard_from_nb_path(nb_paths[0])
<div class="uk-card ">
<div class="uk-card-header ">
<h3 class="uk-h3 ">Using My Blog to Rewrite Itself</h3>
</div>
<div class="uk-card-body space-y-6">Here I use my blog made of Jupyter notebooks to rewrite itself.</div>
</div>
div((div((h3(('Using My Blog to Rewrite Itself',),{'class': 'uk-h3 '}),),{'class': 'uk-card-header '}), div(('Here I use my blog made of Jupyter notebooks to rewrite itself.',),{'class': 'uk-card-body space-y-6'})),{'class': 'uk-card '})nb_paths.map(mk_nbcard_from_nb_path)[:2]
show(*nb_paths.map(mk_nbcard_from_nb_path)[:2])
Using My Blog to Rewrite Itself
Troubleshooting MonsterUI on This Site
Notebook Index: Add Dates to Cards
#| export 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)[4:14]) except ValueError: return None
nb_paths[0]
date = get_date_from_iso8601_prefix(nb_paths[0])
Div(f"{date:%a, %b %-d, %Y}", style="font-size: 0.875rem;color:#666;")
<div style="font-size: 0.875rem;color:#666;">Thu, Jan 23, 2025</div>
div(('Thu, Jan 23, 2025',),{'style': 'font-size: 0.875rem;color:#666;'})franken.PSmall(f"{date:%a, %b %-d, %Y}", cls="uk-text-muted")
<p class="uk-text-small uk-text-muted">Thu, Jan 23, 2025</p>
p(('Thu, Jan 23, 2025',),{'class': 'uk-text-small uk-text-muted'})def NBCard(t,d): return franken.Card( franken.CardTitle(franken.H3(t)), franken.PSmall(f"{date:%a, %b %-d, %Y}", cls="uk-text-muted"), franken.P(d), body_cls='space-y-2' )
c = mk_nbcard_from_nb_path(nb_paths[0]) c
<div class="uk-card ">
<div class="uk-card-body space-y-2">
<div class="uk-card-title ">
<h3 class="uk-h3 ">Using My Blog to Rewrite Itself</h3>
</div>
<p class="uk-text-small uk-text-muted">Thu, Jan 23, 2025</p>
<p>Here I use my blog made of Jupyter notebooks to rewrite itself.</p>
</div>
</div>
div((div((div((h3(('Using My Blog to Rewrite Itself',),{'class': 'uk-h3 '}),),{'class': 'uk-card-title '}), p(('Thu, Jan 23, 2025',),{'class': 'uk-text-small uk-text-muted'}), p(('Here I use my blog made of Jupyter notebooks to rewrite itself.',),{})),{'class': 'uk-card-body space-y-2'}),),{'class': 'uk-card '})show(c)
Using My Blog to Rewrite Itself
Thu, Jan 23, 2025
Here I use my blog made of Jupyter notebooks to rewrite itself.
Notebook Index: Linkify Cards
#| export def NBCard(title,desc,href,date): return A( franken.Card( franken.CardTitle(franken.H3(title)), franken.PSmall(f"{date:%a, %b %-d, %Y}", cls="uk-text-muted"), franken.P(desc), body_cls='space-y-2' ), href=href)
#| export def mk_nbcard_from_nb_path(nb_path): date = get_date_from_iso8601_prefix(nb_path) return NBCard(*get_title_and_desc(nb_path), href=f'/nbs/{nb_path.name[:-6]}', date=date)
c = mk_nbcard_from_nb_path(nb_paths[1]) c
<a href="/nbs/2025-01-23-Troubleshooting-MonsterUI-on-This-Site"> <div class="uk-card ">
<div class="uk-card-body space-y-2">
<div class="uk-card-title ">
<h3 class="uk-h3 ">Troubleshooting MonsterUI on This Site</h3>
</div>
<p class="uk-text-small uk-text-muted">Thu, Jan 23, 2025</p>
<p>My first MonsterUI notebook isn't rendering correctly. Here I debug it.</p>
</div>
</div>
</a>
a((div((div((div((h3(('Troubleshooting MonsterUI on This Site',),{'class': 'uk-h3 '}),),{'class': 'uk-card-title '}), p(('Thu, Jan 23, 2025',),{'class': 'uk-text-small uk-text-muted'}), p(("My first MonsterUI notebook isn't rendering correctly. Here I debug it.",),{})),{'class': 'uk-card-body space-y-2'}),),{'class': 'uk-card '}),),{'href': '/nbs/2025-01-23-Troubleshooting-MonsterUI-on-This-Site'})show(c)
Troubleshooting MonsterUI on This Site
Thu, Jan 23, 2025
My first MonsterUI notebook isn't rendering correctly. Here I debug it.
Notebook Index Page
#| export @rt def index(): nb_paths = get_nb_paths() return ( Theme.blue.headers(), franken.Container( Div( franken.H1('audrey.feldroy.com'), franken.PParagraph("The experimental Jupyter notebooks of Audrey M. Roy Greenfeld. This website and all its notebooks are open-source at ", franken.A("github.com/audreyfeldroy/arg-blog-fasthtml", href="https://github.com/audreyfeldroy/arg-blog-fasthtml"), cls="mb-6"), ), franken.Grid(*nb_paths.map(mk_nbcard_from_nb_path), cols_sm=1, cols_md=1, cols_lg=2, cols_xl=3) ) )
Notebook Detail: Frontmatter
t,d = get_title_and_desc(nb_paths[1]) t,d
mistletoe.markdown(d)
My first MonsterUI notebook isn't rendering correctly. Here I debug it.
\n"Notebook Detail: Non-Frontmatter
nb_paths[1]
Use StyledCode (Pygments) for Code Cells
nb = read_nb(nb_paths[1])
nb.cells[5]
{ 'cell_type': 'code',
'execution_count': 3,
'id': 'cb344dfb',
'idx_': 5,
'metadata': {},
'outputs': [ { 'data': { 'text/markdown': [ '```html\n',
'<h1 class="uk-h1 ">Hi</h1>\n',
'\n',
'```'],
'text/plain': ["h1(('Hi',),{'class': 'uk-h1 '})"]},
'execution_count': 3,
'metadata': {},
'output_type': 'execute_result'}],
'source': 'H1("Hi")'}
{'cell_type': 'code',
'execution_count': 3,
'id': 'cb344dfb',
'metadata': {},
'outputs': [{'data': {'text/markdown': ['```html\n',
'Hi
\n', '\n', '```'], 'text/plain': ["h1(('Hi',),{'class': 'uk-h1 '})"]}, 'execution_count': 3, 'metadata': {}, 'output_type': 'execute_result'}], 'source': 'H1("Hi")', 'idx_': 5}#| export def StyledCode(c, style='monokai'): fm = HtmlFormatter(style=style, cssclass=style) h = highlight(c, PythonLexer(), fm) sd = fm.get_style_defs(f".{style}") return Div(Style(sd), NotStr(h), id=style)
HTML(to_xml(StyledCode(nb.cells[2].source)))
from fasthtml.common import * from monsterui.all import *
HTML(to_xml(StyledCode(nb.cells[5].source)))
H1("Hi")
Use Mistletoe for Markdown Cells
nb.cells[4]
{ 'cell_type': 'markdown',
'id': 'b91fdff1',
'idx_': 4,
'metadata': {},
'source': '[MonsterUI Buttons and '
'Links](https://audrey.feldroy.com/nbs/2025-01-22-MonsterUI-Buttons-and-Links) '
'is the notebook with the problem.\n'
'\n'
'Let\'s start with a subset of the problem: the H1 text "MonsterUI '
'Buttons and Links" is showing up as normal text.'}
{'cell_type': 'markdown',
'id': 'b91fdff1',
'metadata': {},
'source': '[MonsterUI Buttons and Links](https://audrey.feldroy.com/nbs/2025-01-22-MonsterUI-Buttons-and-Links) is the notebook with the problem.\n\nLet\'s start with a subset of the problem: the H1 text "MonsterUI Buttons and Links" is showing up as normal text.',
'idx_': 4}#| export def StyledMd(m): return Safe(mistletoe.markdown(m))
HTML(StyledMd(nb.cells[4].source))
MonsterUI Buttons and Links is the notebook with the problem.
Let's start with a subset of the problem: the H1 text "MonsterUI Buttons and Links" is showing up as normal text.
Use Mistletoe for Output Data of Code Cells
HTML(to_xml(StyledMd(nb.cells[5].outputs[0].data["text/markdown"])))
<h1 class="uk-h1 ">Hi</h1>
#| export def StyledCell(c): if c.cell_type == "markdown": return StyledMd(c.source) if c.cell_type == "code": if not c.outputs: return StyledCode(c.source) return StyledCode(c.source), render_code_output(c)
L(nb.cells).map(StyledCell)
Troubleshooting MonsterUI on This Site
\n',"My first MonsterUI notebook isn't rendering correctly. Here I debug it.
\n",div((style(('pre { line-height: 125%; }\ntd.linenos .normal { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }\nspan.linenos { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }\ntd.linenos .special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }\nspan.linenos.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }\n.monokai .hll { background-color: #49483e }\n.monokai { background: #272822; color: #F8F8F2 }\n.monokai .c { color: #959077 } /* Comment */\n.monokai .err { color: #ED007E; background-color: #1E0010 } /* Error */\n.monokai .esc { color: #F8F8F2 } /* Escape */\n.monokai .g { color: #F8F8F2 } /* Generic */\n.monokai .k { color: #66D9EF } /* Keyword */\n.monokai .l { color: #AE81FF } /* Literal */\n.monokai .n { color: #F8F8F2 } /* Name */\n.monokai .o { color: #FF4689 } /* Operator */\n.monokai .x { color: #F8F8F2 } /* Other */\n.monokai .p { color: #F8F8F2 } /* Punctuation */\n.monokai .ch { color: #959077 } /* Comment.Hashbang */\n.monokai .cm { color: #959077 } /* Comment.Multiline */\n.monokai .cp { color: #959077 } /* Comment.Preproc */\n.monokai .cpf { color: #959077 } /* Comment.PreprocFile */\n.monokai .c1 { color: #959077 } /* Comment.Single */\n.monokai .cs { color: #959077 } /* Comment.Special */\n.monokai .gd { color: #FF4689 } /* Generic.Deleted */\n.monokai .ge { color: #F8F8F2; font-style: italic } /* Generic.Emph */\n.monokai .ges { color: #F8F8F2; font-weight: bold; font-style: italic } /* Generic.EmphStrong */\n.monokai .gr { color: #F8F8F2 } /* Generic.Error */\n.monokai .gh { color: #F8F8F2 } /* Generic.Heading */\n.monokai .gi { color: #A6E22E } /* Generic.Inserted */\n.monokai .go { color: #66D9EF } /* Generic.Output */\n.monokai .gp { color: #FF4689; font-weight: bold } /* Generic.Prompt */\n.monokai .gs { color: #F8F8F2; font-weight: bold } /* Generic.Strong */\n.monokai .gu { color: #959077 } /* Generic.Subheading */\n.monokai .gt { color: #F8F8F2 } /* Generic.Traceback */\n.monokai .kc { color: #66D9EF } /* Keyword.Constant */\n.monokai .kd { color: #66D9EF } /* Keyword.Declaration */\n.monokai .kn { color: #FF4689 } /* Keyword.Namespace */\n.monokai .kp { color: #66D9EF } /* Keyword.Pseudo */\n.monokai .kr { color: #66D9EF } /* Keyword.Reserved */\n.monokai .kt { color: #66D9EF } /* Keyword.Type */\n.monokai .ld { color: #E6DB74 } /* Literal.Date */\n.monokai .m { color: #AE81FF } /* Literal.Number */\n.monokai .s { color: #E6DB74 } /* Literal.String */\n.monokai .na { color: #A6E22E } /* Name.Attribute */\n.monokai .nb { color: #F8F8F2 } /* Name.Builtin */\n.monokai .nc { color: #A6E22E } /* Name.Class */\n.monokai .no { color: #66D9EF } /* Name.Constant */\n.monokai .nd { color: #A6E22E } /* Name.Decorator */\n.monokai .ni { color: #F8F8F2 } /* Name.Entity */\n.monokai .ne { color: #A6E22E } /* Name.Exception */\n.monokai .nf { color: #A6E22E } /* Name.Function */\n.monokai .nl { color: #F8F8F2 } /* Name.Label */\n.monokai .nn { color: #F8F8F2 } /* Name.Namespace */\n.monokai .nx { color: #A6E22E } /* Name.Other */\n.monokai .py { color: #F8F8F2 } /* Name.Property */\n.monokai .nt { color: #FF4689 } /* Name.Tag */\n.monokai .nv { color: #F8F8F2 } /* Name.Variable */\n.monokai .ow { color: #FF4689 } /* Operator.Word */\n.monokai .pm { color: #F8F8F2 } /* Punctuation.Marker */\n.monokai .w { color: #F8F8F2 } /* Text.Whitespace */\n.monokai .mb { color: #AE81FF } /* Literal.Number.Bin */\n.monokai .mf { color: #AE81FF } /* Literal.Number.Float */\n.monokai .mh { color: #AE81FF } /* Literal.Number.Hex */\n.monokai .mi { color: #AE81FF } /* Literal.Number.Integer */\n.monokai .mo { color: #AE81FF } /* Literal.Number.Oct */\n.monokai .sa { color: #E6DB74 } /* Literal.String.Affix */\n.monokai .sb { color: #E6DB74 } /* Literal.String.Backtick */\n.monokai .sc { color: #E6DB74 } /* Literal.String.Char */\n.monokai .dl { color: #E6DB74 } /* Literal.String.Delimiter */\n.monokai .sd { color: #E6DB74 } /* Literal.String.Doc */\n.monokai .s2 { color: #E6DB74 } /* Literal.String.Double */\n.monokai .se { color: #AE81FF } /* Literal.String.Escape */\n.monokai .sh { color: #E6DB74 } /* Literal.String.Heredoc */\n.monokai .si { color: #E6DB74 } /* Literal.String.Interpol */\n.monokai .sx { color: #E6DB74 } /* Literal.String.Other */\n.monokai .sr { color: #E6DB74 } /* Literal.String.Regex */\n.monokai .s1 { color: #E6DB74 } /* Literal.String.Single */\n.monokai .ss { color: #E6DB74 } /* Literal.String.Symbol */\n.monokai .bp { color: #F8F8F2 } /* Name.Builtin.Pseudo */\n.monokai .fm { color: #A6E22E } /* Name.Function.Magic */\n.monokai .vc { color: #F8F8F2 } /* Name.Variable.Class */\n.monokai .vg { color: #F8F8F2 } /* Name.Variable.Global */\n.monokai .vi { color: #F8F8F2 } /* Name.Variable.Instance */\n.monokai .vm { color: #F8F8F2 } /* Name.Variable.Magic */\n.monokai .il { color: #AE81FF } /* Literal.Number.Integer.Long */',),{}), 'from fasthtml.common import *\nfrom monsterui.all import *\n
Understand the Problem
\n','MonsterUI Buttons and Links is the notebook with the problem.
\nLet\'s start with a subset of the problem: the H1 text "MonsterUI Buttons and Links" is showing up as normal text.
\n',(div((style(('pre { line-height: 125%; }\ntd.linenos .normal { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }\nspan.linenos { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }\ntd.linenos .special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }\nspan.linenos.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }\n.monokai .hll { background-color: #49483e }\n.monokai { background: #272822; color: #F8F8F2 }\n.monokai .c { color: #959077 } /* Comment */\n.monokai .err { color: #ED007E; background-color: #1E0010 } /* Error */\n.monokai .esc { color: #F8F8F2 } /* Escape */\n.monokai .g { color: #F8F8F2 } /* Generic */\n.monokai .k { color: #66D9EF } /* Keyword */\n.monokai .l { color: #AE81FF } /* Literal */\n.monokai .n { color: #F8F8F2 } /* Name */\n.monokai .o { color: #FF4689 } /* Operator */\n.monokai .x { color: #F8F8F2 } /* Other */\n.monokai .p { color: #F8F8F2 } /* Punctuation */\n.monokai .ch { color: #959077 } /* Comment.Hashbang */\n.monokai .cm { color: #959077 } /* Comment.Multiline */\n.monokai .cp { color: #959077 } /* Comment.Preproc */\n.monokai .cpf { color: #959077 } /* Comment.PreprocFile */\n.monokai .c1 { color: #959077 } /* Comment.Single */\n.monokai .cs { color: #959077 } /* Comment.Special */\n.monokai .gd { color: #FF4689 } /* Generic.Deleted */\n.monokai .ge { color: #F8F8F2; font-style: italic } /* Generic.Emph */\n.monokai .ges { color: #F8F8F2; font-weight: bold; font-style: italic } /* Generic.EmphStrong */\n.monokai .gr { color: #F8F8F2 } /* Generic.Error */\n.monokai .gh { color: #F8F8F2 } /* Generic.Heading */\n.monokai .gi { color: #A6E22E } /* Generic.Inserted */\n.monokai .go { color: #66D9EF } /* Generic.Output */\n.monokai .gp { color: #FF4689; font-weight: bold } /* Generic.Prompt */\n.monokai .gs { color: #F8F8F2; font-weight: bold } /* Generic.Strong */\n.monokai .gu { color: #959077 } /* Generic.Subheading */\n.monokai .gt { color: #F8F8F2 } /* Generic.Traceback */\n.monokai .kc { color: #66D9EF } /* Keyword.Constant */\n.monokai .kd { color: #66D9EF } /* Keyword.Declaration */\n.monokai .kn { color: #FF4689 } /* Keyword.Namespace */\n.monokai .kp { color: #66D9EF } /* Keyword.Pseudo */\n.monokai .kr { color: #66D9EF } /* Keyword.Reserved */\n.monokai .kt { color: #66D9EF } /* Keyword.Type */\n.monokai .ld { color: #E6DB74 } /* Literal.Date */\n.monokai .m { color: #AE81FF } /* Literal.Number */\n.monokai .s { color: #E6DB74 } /* Literal.String */\n.monokai .na { color: #A6E22E } /* Name.Attribute */\n.monokai .nb { color: #F8F8F2 } /* Name.Builtin */\n.monokai .nc { color: #A6E22E } /* Name.Class */\n.monokai .no { color: #66D9EF } /* Name.Constant */\n.monokai .nd { color: #A6E22E } /* Name.Decorator */\n.monokai .ni { color: #F8F8F2 } /* Name.Entity */\n.monokai .ne { color: #A6E22E } /* Name.Exception */\n.monokai .nf { color: #A6E22E } /* Name.Function */\n.monokai .nl { color: #F8F8F2 } /* Name.Label */\n.monokai .nn { color: #F8F8F2 } /* Name.Namespace */\n.monokai .nx { color: #A6E22E } /* Name.Other */\n.monokai .py { color: #F8F8F2 } /* Name.Property */\n.monokai .nt { color: #FF4689 } /* Name.Tag */\n.monokai .nv { color: #F8F8F2 } /* Name.Variable */\n.monokai .ow { color: #FF4689 } /* Operator.Word */\n.monokai .pm { color: #F8F8F2 } /* Punctuation.Marker */\n.monokai .w { color: #F8F8F2 } /* Text.Whitespace */\n.monokai .mb { color: #AE81FF } /* Literal.Number.Bin */\n.monokai .mf { color: #AE81FF } /* Literal.Number.Float */\n.monokai .mh { color: #AE81FF } /* Literal.Number.Hex */\n.monokai .mi { color: #AE81FF } /* Literal.Number.Integer */\n.monokai .mo { color: #AE81FF } /* Literal.Number.Oct */\n.monokai .sa { color: #E6DB74 } /* Literal.String.Affix */\n.monokai .sb { color: #E6DB74 } /* Literal.String.Backtick */\n.monokai .sc { color: #E6DB74 } /* Literal.String.Char */\n.monokai .dl { color: #E6DB74 } /* Literal.String.Delimiter */\n.monokai .sd { color: #E6DB74 } /* Literal.String.Doc */\n.monokai .s2 { color: #E6DB74 } /* Literal.String.Double */\n.monokai .se { color: #AE81FF } /* Literal.String.Escape */\n.monokai .sh { color: #E6DB74 } /* Literal.String.Heredoc */\n.monokai .si { color: #E6DB74 } /* Literal.String.Interpol */\n.monokai .sx { color: #E6DB74 } /* Literal.String.Other */\n.monokai .sr { color: #E6DB74 } /* Literal.String.Regex */\n.monokai .s1 { color: #E6DB74 } /* Literal.String.Single */\n.monokai .ss { color: #E6DB74 } /* Literal.String.Symbol */\n.monokai .bp { color: #F8F8F2 } /* Name.Builtin.Pseudo */\n.monokai .fm { color: #A6E22E } /* Name.Function.Magic */\n.monokai .vc { color: #F8F8F2 } /* Name.Variable.Class */\n.monokai .vg { color: #F8F8F2 } /* Name.Variable.Global */\n.monokai .vi { color: #F8F8F2 } /* Name.Variable.Instance */\n.monokai .vm { color: #F8F8F2 } /* Name.Variable.Magic */\n.monokai .il { color: #AE81FF } /* Literal.Number.Integer.Long */',),{}), 'H1("Hi")\n
<h1 class="uk-h1 ">Hi</h1>\n\n
\n',),{})),(div((style(('pre { line-height: 125%; }\ntd.linenos .normal { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }\nspan.linenos { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }\ntd.linenos .special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }\nspan.linenos.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }\n.monokai .hll { background-color: #49483e }\n.monokai { background: #272822; color: #F8F8F2 }\n.monokai .c { color: #959077 } /* Comment */\n.monokai .err { color: #ED007E; background-color: #1E0010 } /* Error */\n.monokai .esc { color: #F8F8F2 } /* Escape */\n.monokai .g { color: #F8F8F2 } /* Generic */\n.monokai .k { color: #66D9EF } /* Keyword */\n.monokai .l { color: #AE81FF } /* Literal */\n.monokai .n { color: #F8F8F2 } /* Name */\n.monokai .o { color: #FF4689 } /* Operator */\n.monokai .x { color: #F8F8F2 } /* Other */\n.monokai .p { color: #F8F8F2 } /* Punctuation */\n.monokai .ch { color: #959077 } /* Comment.Hashbang */\n.monokai .cm { color: #959077 } /* Comment.Multiline */\n.monokai .cp { color: #959077 } /* Comment.Preproc */\n.monokai .cpf { color: #959077 } /* Comment.PreprocFile */\n.monokai .c1 { color: #959077 } /* Comment.Single */\n.monokai .cs { color: #959077 } /* Comment.Special */\n.monokai .gd { color: #FF4689 } /* Generic.Deleted */\n.monokai .ge { color: #F8F8F2; font-style: italic } /* Generic.Emph */\n.monokai .ges { color: #F8F8F2; font-weight: bold; font-style: italic } /* Generic.EmphStrong */\n.monokai .gr { color: #F8F8F2 } /* Generic.Error */\n.monokai .gh { color: #F8F8F2 } /* Generic.Heading */\n.monokai .gi { color: #A6E22E } /* Generic.Inserted */\n.monokai .go { color: #66D9EF } /* Generic.Output */\n.monokai .gp { color: #FF4689; font-weight: bold } /* Generic.Prompt */\n.monokai .gs { color: #F8F8F2; font-weight: bold } /* Generic.Strong */\n.monokai .gu { color: #959077 } /* Generic.Subheading */\n.monokai .gt { color: #F8F8F2 } /* Generic.Traceback */\n.monokai .kc { color: #66D9EF } /* Keyword.Constant */\n.monokai .kd { color: #66D9EF } /* Keyword.Declaration */\n.monokai .kn { color: #FF4689 } /* Keyword.Namespace */\n.monokai .kp { color: #66D9EF } /* Keyword.Pseudo */\n.monokai .kr { color: #66D9EF } /* Keyword.Reserved */\n.monokai .kt { color: #66D9EF } /* Keyword.Type */\n.monokai .ld { color: #E6DB74 } /* Literal.Date */\n.monokai .m { color: #AE81FF } /* Literal.Number */\n.monokai .s { color: #E6DB74 } /* Literal.String */\n.monokai .na { color: #A6E22E } /* Name.Attribute */\n.monokai .nb { color: #F8F8F2 } /* Name.Builtin */\n.monokai .nc { color: #A6E22E } /* Name.Class */\n.monokai .no { color: #66D9EF } /* Name.Constant */\n.monokai .nd { color: #A6E22E } /* Name.Decorator */\n.monokai .ni { color: #F8F8F2 } /* Name.Entity */\n.monokai .ne { color: #A6E22E } /* Name.Exception */\n.monokai .nf { color: #A6E22E } /* Name.Function */\n.monokai .nl { color: #F8F8F2 } /* Name.Label */\n.monokai .nn { color: #F8F8F2 } /* Name.Namespace */\n.monokai .nx { color: #A6E22E } /* Name.Other */\n.monokai .py { color: #F8F8F2 } /* Name.Property */\n.monokai .nt { color: #FF4689 } /* Name.Tag */\n.monokai .nv { color: #F8F8F2 } /* Name.Variable */\n.monokai .ow { color: #FF4689 } /* Operator.Word */\n.monokai .pm { color: #F8F8F2 } /* Punctuation.Marker */\n.monokai .w { color: #F8F8F2 } /* Text.Whitespace */\n.monokai .mb { color: #AE81FF } /* Literal.Number.Bin */\n.monokai .mf { color: #AE81FF } /* Literal.Number.Float */\n.monokai .mh { color: #AE81FF } /* Literal.Number.Hex */\n.monokai .mi { color: #AE81FF } /* Literal.Number.Integer */\n.monokai .mo { color: #AE81FF } /* Literal.Number.Oct */\n.monokai .sa { color: #E6DB74 } /* Literal.String.Affix */\n.monokai .sb { color: #E6DB74 } /* Literal.String.Backtick */\n.monokai .sc { color: #E6DB74 } /* Literal.String.Char */\n.monokai .dl { color: #E6DB74 } /* Literal.String.Delimiter */\n.monokai .sd { color: #E6DB74 } /* Literal.String.Doc */\n.monokai .s2 { color: #E6DB74 } /* Literal.String.Double */\n.monokai .se { color: #AE81FF } /* Literal.String.Escape */\n.monokai .sh { color: #E6DB74 } /* Literal.String.Heredoc */\n.monokai .si { color: #E6DB74 } /* Literal.String.Interpol */\n.monokai .sx { color: #E6DB74 } /* Literal.String.Other */\n.monokai .sr { color: #E6DB74 } /* Literal.String.Regex */\n.monokai .s1 { color: #E6DB74 } /* Literal.String.Single */\n.monokai .ss { color: #E6DB74 } /* Literal.String.Symbol */\n.monokai .bp { color: #F8F8F2 } /* Name.Builtin.Pseudo */\n.monokai .fm { color: #A6E22E } /* Name.Function.Magic */\n.monokai .vc { color: #F8F8F2 } /* Name.Variable.Class */\n.monokai .vg { color: #F8F8F2 } /* Name.Variable.Global */\n.monokai .vi { color: #F8F8F2 } /* Name.Variable.Instance */\n.monokai .vm { color: #F8F8F2 } /* Name.Variable.Magic */\n.monokai .il { color: #AE81FF } /* Literal.Number.Integer.Long */',),{}), 'A("My Blog", href="https://audrey.feldroy.com")\n
<a href="https://audrey.feldroy.com">My Blog</a>\n
\n',),{}))]show(*L(nb.cells).map(StyledCell))
Troubleshooting MonsterUI on This Site
My first MonsterUI notebook isn't rendering correctly. Here I debug it.
from fasthtml.common import * from monsterui.all import *
Understand the Problem
MonsterUI Buttons and Links is the notebook with the problem.
Let's start with a subset of the problem: the H1 text "MonsterUI Buttons and Links" is showing up as normal text.
H1("Hi")
A("My Blog", href="https://audrey.feldroy.com")
Notebook Detail Page
#| export @rt("/nbs/{name}") def notebook(name:str): fpath = Path(f'nbs/{name}.ipynb') nb = read_nb(fpath) title = nb.cells[0].source.lstrip("# ") desc = nb.cells[1].source if "MonsterUI" in title: return ( Theme.slate.headers(), franken.Container( franken.H1(title), # Title franken.P(desc), # Desc *L(nb.cells[2:]).map(StyledCell), cls="space-y-5" ) ) return ( Style(':root {font-family: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", sans-serif; color-scheme: light dark;} body {background-color: light-dark(#ffffff, #1a1a1a); color: light-dark(#1a1a1a, #ffffff);} p {line-height: 1.5;}'), Div( H1(title), # Title P(desc), # Desc *L(nb.cells[2:]).map(StyledCell), cls="space-y-5" ) )
http://localhost:8000/nbs/2025-01-23-Troubleshooting-MonsterUI-on-This-Site
name = "2025-01-23-Troubleshooting-MonsterUI-on-This-Site" fpath = Path(f'{name}.ipynb') fpath.absolute()
Troubleshooting the Troubleshooting MonsterUI Notebook
def is_code_cell(c): return c.cell_type == "code" cells = L(read_nb(nb_paths[1]).cells).filter(is_code_cell) cells
Hi
\n', '\n', '```'], 'text/plain': ["h1(('Hi',),{'class': 'uk-h1 '})"]}, 'execution_count': 3, 'metadata': {}, 'output_type': 'execute_result'}], 'source': 'H1("Hi")', 'idx_': 5},{'cell_type': 'code', 'execution_count': 4, 'id': 'b86c1d3c', 'metadata': {}, 'outputs': [{'data': {'text/markdown': ['```html\n', 'My Blog\n', '```'], 'text/plain': ["a(('My Blog',),{'href': 'https://audrey.feldroy.com'})"]}, 'execution_count': 4, 'metadata': {}, 'output_type': 'execute_result'}], 'source': 'A("My Blog", href="https://audrey.feldroy.com")', 'idx_': 6}]cells[1]
{ 'cell_type': 'code',
'execution_count': 3,
'id': 'cb344dfb',
'idx_': 5,
'metadata': {},
'outputs': [ { 'data': { 'text/markdown': [ '```html\n',
'<h1 class="uk-h1 ">Hi</h1>\n',
'\n',
'```'],
'text/plain': ["h1(('Hi',),{'class': 'uk-h1 '})"]},
'execution_count': 3,
'metadata': {},
'output_type': 'execute_result'}],
'source': 'H1("Hi")'}
{'cell_type': 'code',
'execution_count': 3,
'id': 'cb344dfb',
'metadata': {},
'outputs': [{'data': {'text/markdown': ['```html\n',
'Hi
\n', '\n', '```'], 'text/plain': ["h1(('Hi',),{'class': 'uk-h1 '})"]}, 'execution_count': 3, 'metadata': {}, 'output_type': 'execute_result'}], 'source': 'H1("Hi")', 'idx_': 5}cells[1].outputs[0].data
{ 'text/markdown': ['```html\n', '<h1 class="uk-h1 ">Hi</h1>\n', '\n', '```'],
'text/plain': ["h1(('Hi',),{'class': 'uk-h1 '})"]}
{'text/markdown': ['```html\n', 'Hi
\n', '\n', '```'], 'text/plain': ["h1(('Hi',),{'class': 'uk-h1 '})"]}Troubleshooting the Cosine Similarity Notebook
def is_code_cell(c): return c.cell_type == "code" cells = L(read_nb(nb_paths[9]).cells).filter(is_code_cell) cells[0]
{ 'cell_type': 'code',
'execution_count': 7,
'id': '06004824',
'idx_': 6,
'metadata': {},
'outputs': [ { 'data': { 'text/latex': [ '$$\\text{cos}(\\theta) = '
'\\frac{\\mathbf{A} \\cdot '
'\\mathbf{B}}{\\|\\mathbf{A}\\| '
'\\|\\mathbf{B}\\|}$$\n'],
'text/plain': [ '<IPython.core.display.Latex '
'object>']},
'metadata': {},
'output_type': 'display_data'}],
'source': '%%latex\n'
'$$\\text{cos}(\\theta) = \\frac{\\mathbf{A} \\cdot '
'\\mathbf{B}}{\\|\\mathbf{A}\\| \\|\\mathbf{B}\\|}$$'}
{'cell_type': 'code',
'execution_count': 7,
'id': '06004824',
'metadata': {},
'outputs': [{'data': {'text/latex': ['$$\\text{cos}(\\theta) = \\frac{\\mathbf{A} \\cdot \\mathbf{B}}{\\|\\mathbf{A}\\| \\|\\mathbf{B}\\|}$$\n'],
'text/plain': ['Rendering Code Outputs With render_code_output
cells = L(read_nb(nb_paths[1]).cells).filter(is_code_cell) cells[1]
{ 'cell_type': 'code',
'execution_count': 3,
'id': 'cb344dfb',
'idx_': 5,
'metadata': {},
'outputs': [ { 'data': { 'text/markdown': [ '```html\n',
'<h1 class="uk-h1 ">Hi</h1>\n',
'\n',
'```'],
'text/plain': ["h1(('Hi',),{'class': 'uk-h1 '})"]},
'execution_count': 3,
'metadata': {},
'output_type': 'execute_result'}],
'source': 'H1("Hi")'}
{'cell_type': 'code',
'execution_count': 3,
'id': 'cb344dfb',
'metadata': {},
'outputs': [{'data': {'text/markdown': ['```html\n',
'Hi
\n', '\n', '```'], 'text/plain': ["h1(('Hi',),{'class': 'uk-h1 '})"]}, 'execution_count': 3, 'metadata': {}, 'output_type': 'execute_result'}], 'source': 'H1("Hi")', 'idx_': 5}render_code_output(cells[1])
<footer><pre><code class="language-html"><h1 class="uk-h1 ">Hi</h1>
</code></pre>
</footer>
footer(('<h1 class="uk-h1 ">Hi</h1>\n\n
\n',),{})# show(*L(read_nb(nb_paths[4]).cells).map(StyledCell))
Serve
#| export serve()
server.stop()
Export
To export this notebook as arg-blog-fasthtml's main.py:
nb_export 2025-01-23-This-Site-Is-Now-Powered-by-This-Notebook.ipynb
mv main.py ..
© 2024-2025 Audrey M. Roy Greenfeld