diff --git a/README.md b/README.md
index 945410e8c2ea5ac2cff9c605f748c75574446217..1645fe1342a78b9e80201593aff0898f605d3210 100644
--- a/README.md
+++ b/README.md
@@ -2,159 +2,4 @@
 
 This is a library that provides building blocks for cs-214 webapps.
 
-### Example
-
-This example shows a simple counter webapp built using the `webapp-lib`.
-
-An example webapp is implemented in 4 parts:
-
-#### Counter Model (types)
-
-Those include the definition of state, events and view.
-
-```scala
-package apps.counter
-
-case class CounterView(value: Int)
-
-case class CounterState(value: Int)
-
-enum CounterEvent:
-  case Increment
-```
-
-#### Counter wire
-
-The serialization and deserialization of the events and view.
-
-```scala
-package apps.counter
-
-import cs214.webapp.*
-import cs214.webapp.DecodingException
-
-import scala.util.{Failure, Success, Try}
-
-object CounterWire extends AppWire[CounterEvent, CounterView]:
-  import CounterEvent.*
-  import CounterView.*
-  import ujson.*
-
-  override object eventFormat extends WireFormat[CounterEvent]:
-    override def encode(event: CounterEvent): Value =
-      event match
-        case Increment =>
-          Obj("type" -> "Increment")
-
-    override def decode(js: Value): Try[CounterEvent] =
-      Try:
-        js("type").str match
-          case "Increment" =>
-            Increment
-          case _ =>
-            throw DecodingException(f"Invalid counter event $js")
-
-  override object viewFormat extends WireFormat[CounterView]:
-    override def encode(v: CounterView): Value =
-      Obj("value" -> v.value)
-
-    override def decode(js: Value): Try[CounterView] =
-      Try:
-        CounterView(js("value").num.toInt)
-```
-
-#### Counter logic
-
-The logic of the counter -- a transition system that updates the state based on the events and can project a state into a view.
-
-```scala
-package apps.counter
-
-import cs214.webapp.*
-import cs214.webapp.server.{StateMachine}
-import scala.util.{Failure, Success, Try}
-
-class CounterLogic extends StateMachine[CounterEvent, CounterState, CounterView]:
-  import Action.*
-
-  override val appInfo: AppInfo = AppInfo(
-    id = "counter",
-    name = "Counter",
-    description = "A simple counter app that increments a counter by one.",
-    year = 2024
-  )
-
-  override val wire = CounterWire
-
-  override def init(clients: Seq[UserId]): CounterState = CounterState(0)
-
-  override def transition(state: CounterState)(userId: UserId, event: CounterEvent): Try[Seq[Action[CounterState]]] =
-    Try:
-      event match
-        case CounterEvent.Increment =>
-          Seq(Render(CounterState(state.value + 1)))
-
-  override def project(state: CounterState)(userId: UserId): CounterView =
-    CounterView(state.value)
-```
-
-#### Counter UI
-
-The UI representation of the counter view.
-
-```scala
-package apps.counter
-
-import apps.counter.*
-import cs214.webapp.*
-import cs214.webapp.client.*
-import cs214.webapp.client.graphics.{HTMLAttribute, TextClientAppInstance}
-import org.scalajs.dom
-import scalatags.JsDom.all.*
-
-import scala.scalajs.js.annotation.JSExportTopLevel
-
-@JSExportTopLevel("counter")
-object CounterClientApp extends WSClientApp:
-  def appId: String = "counter"
-
-  def uiId: UIId = "counter"
-
-  def init(userId: UserId, sendMessage: ujson.Value => Unit, target: dom.Element): ClientAppInstance =
-    CounterClientAppInstance(userId, sendMessage, target)
-
-class CounterClientAppInstance(userId: UserId, sendMessage: ujson.Value => Unit, target: dom.Element)
-    extends TextClientAppInstance[CounterEvent, CounterView](userId, sendMessage, target):
-
-  override val wire = CounterWire
-
-  override def handleTextInput(view: CounterView, text: String): Option[CounterEvent] = text match
-    case "increment" | "i" => Some(CounterEvent.Increment)
-    case _                 => None
-
-  override def renderView(userId: UserId, view: CounterView): Vector[TextSegment] =
-    Vector(
-      TextSegment(text = "Counter\n", modifiers = cls := "bold"),
-      TextSegment("Click the number to increment it!\n"),
-      TextSegment(
-        view.value.toString,
-        onMouseEvent = {
-          case MouseEvent.Click(_) => sendEvent(CounterEvent.Increment)
-          case _                   => ()
-        },
-        modifiers = cls := "bold clickable huge"
-      )
-    )
-
-  override def css: String =
-    """|.bold {
-       |  font-weight: bold;
-       |}
-       |.clickable {
-       |  cursor: pointer;
-       |}
-       |.huge {
-       |  font-size: 2em;
-       |}
-       |""".stripMargin
-```
+For a minimal example on how to use the library see the [`counter` example](https://cs-214.epfl.ch/labs/webapp-examples-2d859dd07e39/counter.html)