I wanted to share a fun experiment I put together (with the help of AI, of course). I’ve wanted to try out PyScript for a while now, and I finally got around to testing it out in the context of an Anki note type. This example shows how you can add dynamic content to an Anki card using:
- PyScript on it’s own
- HTMX + PyScript
- Tailwind for styling
{{Front}}
<link rel="stylesheet" href="https://pyscript.net/releases/2024.10.1/core.css">
<script type="module" src="https://pyscript.net/releases/2024.10.1/core.js"></script>
<script src="https://cdn.tailwindcss.com"></script>
<script src="https://unpkg.com/htmx.org@1.9.2"></script>
<script type="py">
from pyscript import document
from pyscript.ffi import create_proxy
import js, json
# Fetch multiple cat facts in Python
async def fetch_multiple_facts(event):
# read & clamp user input
val = document.getElementById("limitInput").value
try:
n = int(val)
except:
n = 1
n = max(1, min(n, 10))
# fetch list of facts
res = await js.fetch(f"https://catfact.ninja/facts?limit={n}")
js_data = await res.json()
py_data = js_data.to_py()
# build HTML list
items = "".join(f"<li class='mb-2'>{f['fact']}</li>" for f in py_data["data"])
document.getElementById("pyFactsList").innerHTML = \
f"<ul class='list-disc list-inside'>{items}</ul>"
# htmx:afterSwap handler in Python
def on_htmx_swap(evt):
detail = evt.detail
if detail.target.id == "htmxFactsList":
try:
data = json.loads(detail.xhr.responseText)
items = "".join(f"<li class='mb-2'>{f['fact']}</li>" for f in data["data"])
detail.target.innerHTML = f"<ul class='list-disc list-inside'>{items}</ul>"
except Exception as e:
detail.target.innerText = "Error rendering facts"
print("htmx swap render error:", e)
# bind Python event‐handlers
btn_py = document.getElementById("pyBtn")
btn_py.addEventListener("click", create_proxy(fetch_multiple_facts))
# listen for all htmx swaps
js.document.addEventListener("htmx:afterSwap", create_proxy(on_htmx_swap))
</script>
<!-- === Input for number of facts === -->
<div class="p-4 bg-white rounded-lg shadow mb-4">
<label for="limitInput" class="block mb-1 font-semibold">Number of facts (1 – 10):</label>
<input
id="limitInput"
name="limit"
type="number"
min="1"
max="10"
value="3"
class="border border-gray-300 rounded px-3 py-2 w-20 focus:ring-2 focus:ring-blue-300"
/>
</div>
<!-- === Pure PyScript Example === -->
<div class="p-4 bg-gray-50 rounded-lg shadow mb-4">
<button
id="pyBtn"
class="px-4 py-2 bg-indigo-500 hover:bg-indigo-700 text-white font-bold rounded mb-2"
>
Get Cat Facts (PyScript)
</button>
<div id="pyFactsList" class="mt-3 text-gray-800">
Enter a number and click above…
</div>
</div>
<!-- === htmx + PyScript Example === -->
<div class="p-4 bg-pink-50 rounded-lg shadow">
<button
hx-get="https://catfact.ninja/facts"
hx-include="#limitInput"
hx-headers='{"Accept":"application/json"}'
hx-trigger="click"
hx-target="#htmxFactsList"
hx-swap="innerHTML"
class="px-4 py-2 bg-pink-500 hover:bg-pink-700 text-white font-bold rounded mb-2"
>
Get Cat Facts (htmx)
</button>
<div id="htmxFactsList" class="mt-3 text-gray-800">
Enter a number and click above…
</div>
</div>
Thought I’d share to see if anybody has other ideas about fun things to do with HTMX and/or PyScript.