Wikipedia, as it happens
Every dot is a live edit to English Wikipedia. Time runs left to right. The big plot puts character gains above zero and losses below; the four small multiples keep size as volume and use green for adds, red for removals.
Choose which edits to follow
The edit stream
Shape of the current window
Raw edits remain available for inspection while Semiotic derives temporal volume, magnitude density, and signed character flow.
Edit volume
10-second bins · stacked by editor class
Magnitude density
Time × absolute character change · cell color is count
Net character flow
Signed character change summed into 10-second intervals
Latest matching edits
Select a row to hold its detail above, or open the revision on Wikipedia.
Overview and drilldown
The overview uses double encodings (fill plus outline) so actor classes survive dense overlap. The small multiples share the same time and magnitude extents, making activity and outliers comparable without asking color to do two jobs at once. That way you can see clusters across different Wikipedia editor types while still seeing patterns specific to admins or anons.
Administrators need a second lookup
Recent-change events identify bots and expose editor names, but do not include local user groups. Registered names are therefore resolved in cached batches against Wikipedia's users API; members of the sysop group move into the administrator series when that lookup returns.
One event buffer
The EventSource keeps one React-side control buffer, then the charts mirror the filtered window through Semiotic's imperative push, update, and remove API. Semiotic handles temporal windows, canvas rendering, binning, heatmap aggregation, axes, hover hit-testing, and per-datum swarm styles.
const stream = new EventSource( "https://stream.wikimedia.org/v2/stream/recentchange" ) const swarmRef = useRef(null) stream.onmessage = ({ data }) => { const change = JSON.parse(data) if (change.server_name !== "en.wikipedia.org") return if (!["edit", "new"].includes(change.type)) return const delta = (change.length?.new ?? 0) - (change.length?.old ?? 0) setEdits(current => [...current, { id: change.meta.id, time: Date.parse(change.meta.dt), magnitude: Math.abs(delta), delta, group: classifyEditor(change) }].slice(-600)) } useSyncedPushData(swarmRef, visibleEdits, { id: "id" }) <RealtimeSwarmChart ref={swarmRef} timeAccessor="time" valueAccessor="delta" yScaleType="symlog" categoryAccessor="group" colors={groupColors} pointStyle={edit => ({ stroke: actorStyles[edit.group].stroke, strokeWidth: actorStyles[edit.group].strokeWidth, r: edit.minor ? 3 : 4 })} pointIdAccessor="id" enableHover />Live data fromWikimedia EventStreams. This example filters the global recent-change stream to edit and new-page events fromen.wikipedia.org. Stream data may contain user-provided page titles and edit summaries.