A native Reflex component wrapping Knight Lab TimelineJS for interactive storytelling timelines in pure Python.
Project description
reflex-knightlab-timeline
- Source: https://github.com/ecrespo/reflex-knightlab-timeline
- PyPI: https://pypi.org/project/reflex-knightlab-timeline/
- Issues: https://github.com/ecrespo/reflex-knightlab-timeline/issues
A native Reflex component that wraps Knight Lab TimelineJS so you can build interactive, storytelling timelines in pure Python — no HTML, no iframe, no hand-written JavaScript.
It was built by migrating the certifications timeline from the reflex_resume
project (which used an iframe → static timeline.html → fetch(timeline.json))
into a reusable, reactive, version-pinned component.
import reflex as rx
from reflex_knightlab_timeline import timeline, TimelineData, Event, Text, TLDate
DATA = TimelineData(events=[
Event(start_date=TLDate(2024, 12, 14),
text=Text("Claude Code in Action", "Anthropic Academy")),
Event(start_date=TLDate(2023, 11, 22),
text=Text("Data Scientist with Python", "Datacamp")),
])
def index() -> rx.Component:
return timeline(data=DATA, height="600px")
app = rx.App()
app.add_page(index)
Why native instead of an iframe?
| iframe (before) | native component (this package) |
|---|---|
| Isolated from app state | Wired into Reflex state via events (on_change, …) |
| Tied to static files/routes | Reusable, pip install-able |
| Untyped JSON edited by hand | Typed Python builders + validation |
| Loads TimelineJS from a CDN at runtime | npm @knight-lab/timelinejs@3.9.11, reproducible |
Install
pip install reflex-knightlab-timeline
# or, from this repo:
pip install -e .
Reflex installs the underlying npm package (@knight-lab/timelinejs@3.9.11)
automatically on first run.
Usage
Data: three ways
from reflex_knightlab_timeline import (
timeline, TimelineData, Event, Slide, Era, TLDate, Text, Media, Background,
TimelineOptions, load_timeline_data,
)
# 1) Typed builders
data = TimelineData(
title=Slide(text=Text("My Journey")),
events=[Event(start_date=TLDate(2024, 12, 14),
text=Text("A cert", "Description"),
media=Media(url="https://...", credit="Coursera"))],
eras=[Era(TLDate(2018), TLDate(2024), Text("Career"))],
scale="human",
)
# 2) A raw dict (the TimelineJS JSON format)
data = {"events": [{"start_date": {"year": "2024"}, "text": {"headline": "A"}}]}
# 3) Load an existing timeline.json (e.g. migrated from reflex_resume)
data = load_timeline_data("assets/timeline.json")
Options (all TimelineJS options supported)
opts = TimelineOptions(
timenav_position="bottom", # "top" | "bottom"
timenav_height=200,
scale_factor=2,
initial_zoom=2,
hash_bookmark=False,
default_bg_color={"r": 255, "g": 255, "b": 255},
language="es",
theme="dark", # "dark" | "contrast" | custom CSS url
)
timeline(data=data, options=opts, height="700px")
Events → Python
class State(rx.State):
current: str = ""
@rx.event
def on_slide(self, unique_id: str):
self.current = unique_id
timeline(data=data, on_change=State.on_slide)
Supported events: on_change, on_loaded, on_dataloaded, on_nav_next,
on_nav_previous, on_zoom_in, on_zoom_out, on_back_to_start.
TimelineJS needs an explicitly sized container —
widthdefaults to"100%"andheightto"600px"; override as needed.
Demo
cd timeline_demo
reflex run
The demo renders (1) a timeline authored in Python, and (2) the 178-certification
timeline migrated 1:1 from reflex_resume, with live on_change updating state.
Development & tests (TDD)
This package was built test-first. The data layer is pure Python (no Reflex needed); the component contract tests require Reflex.
pip install -e ".[dev]"
pytest # 43 tests
Project layout
custom_components/reflex_knightlab_timeline/
models.py # typed TimelineJS data builders
options.py # all TimelineJS presentation options
timeline.py # the native rx.Component (ref + useEffect wrapper)
timeline_demo/ # Reflex demo app (parity with reflex_resume)
tests/ # pytest suite
specs/ # Spec-Driven Design artifacts (PRD, Tech, Data, API, Plan, Migration)
See specs/ for the full design, and specs/migration/iframe-to-native.md for
how to swap the old iframe in reflex_resume.
Credits
- TimelineJS3 © Northwestern University Knight Lab (MPL/own license — see their repo).
- Built on Reflex.
License
MIT — see LICENSE.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file reflex_knightlab_timeline-0.1.1.tar.gz.
File metadata
- Download URL: reflex_knightlab_timeline-0.1.1.tar.gz
- Upload date:
- Size: 16.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7c821920c4d4606a726273308f44689d27bf9ed5315f66b7c4befceb393daca5
|
|
| MD5 |
131ddf3b3afcb31ae28658541102c0e4
|
|
| BLAKE2b-256 |
d454913ecd667b2ed40737ccc3b40ae579e416dfd55a8e9b6ef76232f3cba227
|
File details
Details for the file reflex_knightlab_timeline-0.1.1-py3-none-any.whl.
File metadata
- Download URL: reflex_knightlab_timeline-0.1.1-py3-none-any.whl
- Upload date:
- Size: 12.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e1a4e4c2157fadd5afda53e492861a8aefafbfc95f3256f7f1d82b00d13110b8
|
|
| MD5 |
2ddc96c1bcd7b32b681a16ed0a4a30c6
|
|
| BLAKE2b-256 |
fbd79f6b3c62d809f09babaf64f05896a2aa60d5e67143668ed7629db549cf80
|