an open-source education platform

Your class material — online and interactive

Teachers! Put your explanations, demos, quizzes, diagrams, exercises, and exams all in one place: Your very own website!

Beautiful math

Basic:

x=b±b24ac2ax = \frac{-b \pm \sqrt{b^2 - 4ac}}{2a}

Or more involved:

ex2dx=π\int_{-\infty}^{\infty} e^{-x^2}\,dx = \sqrt{\pi}

Visual callouts

Discuss!

In pairs, discuss X.

Solution

Here you'd explain your solution, maybe with a video?

Collaborate

Teachers can co-author skripts or fork anyone's published material under CC-BY-SA (credit the author, share alike).

Privacy

Teachers can see students' progress or exams on Eduskript - but the mapping to real student IDs is done locally on the teacher's device. We only store anonymized IDs of students.

Annotate like on paper!

You can highlight, sure...

Ease your burden with AI

Eduskript has a built-in AI agent that can write, edit, and adapt your content. Need an exam based on the material you taught? Our agent is aware of your materials and writes matching exercises!

Eduskript supports MCP, which means it natively integrates even with online AI chats such as claude.ai and chatgpt.com.

An epic in-browser coding experience with Python, JavaScript and SQL

Write, run, and experiment with code directly in the browser. With multi-file support, auto-testing and confetti included! 🎊🥳🎊

Exercise

Draw a 3-step stairs made of three 30×30 squares with line colors red, yellow, green.

Press "Run" and "Check".

PythonLoading editor…
# Solution by student 👇️
import turtle
t = turtle.Turtle()

for square in ["red", "orange", "green"]:
    t.color(square)
    for side in range(6):
        t.forward(30)
        t.left(90)
    t.left(180)
Exercise

A more involved example using a public API to plot all earthquakes M ≥ 4 of the last 7 days.

Press "Run".

PythonLoading editor…
from pyodide.http import pyfetch
import matplotlib.pyplot as plt

print("🌍 Setting up earthquake visualization...")

QUAKE_URL = "https://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/all_week.geojson"
LAND_URL  = "https://raw.githubusercontent.com/nvkelso/natural-earth-vector/master/geojson/ne_110m_land.geojson"
PLATE_URL = "https://raw.githubusercontent.com/fraxen/tectonicplates/master/GeoJSON/PB2002_boundaries.json"

print("📡 Fetching earthquake data (last 7 days)...")
quakes = await (await pyfetch(QUAKE_URL)).json()

print("🗺️  Fetching landmass and tectonic plate data...")
land   = await (await pyfetch(LAND_URL)).json()
plates = await (await pyfetch(PLATE_URL)).json()

strong = [f for f in quakes["features"]
          if f["properties"]["mag"] is not None and f["properties"]["mag"] >= 4.0]

print(f"🔍 Found {len(strong)} strong earthquakes (M ≥ 4)...")

lons  = [f["geometry"]["coordinates"][0] for f in strong]
lats  = [f["geometry"]["coordinates"][1] for f in strong]
mags  = [f["properties"]["mag"]          for f in strong]
sizes = [10 * (m ** 2) for m in mags]

fig, ax = plt.subplots(figsize=(13, 6.5))
ax.set_facecolor("#cfe0eb")

print("🎨 Drawing landmasses...")
# --- Layer 1: Landmasses ---
for feature in land["features"]:
    geom = feature["geometry"]
    polygons = [geom["coordinates"]] if geom["type"] == "Polygon" else geom["coordinates"]
    for poly in polygons:
        outer = poly[0]
        ax.fill([c[0] for c in outer], [c[1] for c in outer],
                facecolor="#e8d9b0", edgecolor="#a89870", linewidth=0.4)

print("📐 Drawing plate boundaries...")
# --- Layer 2: Plate boundaries ---
for feature in plates["features"]:
    coords = feature["geometry"]["coordinates"]
    ax.plot([c[0] for c in coords], [c[1] for c in coords],
            color="#444", linewidth=0.8, alpha=0.7)

print("💥 Plotting earthquake locations...")
# --- Layer 3: Earthquakes ---
ax.scatter(lons, lats, s=sizes, color="#d63031",
           alpha=0.7, edgecolor="black", linewidth=0.3)

ax.set_xlim(-180, 180)
ax.set_ylim(-90, 90)
ax.set_aspect("equal")
ax.set_title(f"Earthquakes (M ≥ 4) and plate boundaries — last 7 days ({len(strong)} quakes)")
ax.set_xlabel("Longitude")
ax.set_ylabel("Latitude")

print("✅ Done! Displaying plot...")
plt.show()

Create your own interactive components with AI

Need a custom widget for your lesson? Describe it to an AI agent and ship it as a plugin.

Below is a Dijkstra shortest-path visualizer I built for my computer science class.

Press Play ▶️

Loading plugin...

And here's a tool that lets students design and encode their own EAN-13 barcode.

Press "Play demo"

Loading plugin...

Your own SQLite databases in the browser

Execute queries against actual data, and see results and feedback instantly!

Exercise

Query the Top-10 most danceable genres in the spotify.db database. Select name from the genres table and calculate the average danceability of its songs as avg_danceability.

Press Run.

SQLLoading editor…
--- Student answer:
SELECT g.name AS genre,
       ROUND(AVG(t.danceability), 3) AS avg_danceability
FROM genres g
JOIN track_genres tg ON g.genre_id = tg.genre_id
JOIN tracks t        ON tg.track_id = t.track_id
GROUP BY g.name
ORDER BY avg_danceability DESC
LIMIT 10;

One Markdown document

No cumbersome block structure, but one document per lesson in easy Markdown syntax. Just write.

See it in action

informatikgarten.ch — a complete computer science curriculum built on Eduskript, featuring programming with Python and turtle, encoding a barcode, SQL databases, networking, cryptography lessons, and more.