diff --git a/app/box-socket.hs b/app/box-socket.hs
--- a/app/box-socket.hs
+++ b/app/box-socket.hs
@@ -1,8 +1,4 @@
-{-# LANGUAGE DataKinds #-}
-{-# LANGUAGE FlexibleContexts #-}
-{-# LANGUAGE FlexibleInstances #-}
 {-# LANGUAGE OverloadedStrings #-}
-{-# LANGUAGE ScopedTypeVariables #-}
 {-# OPTIONS_GHC -Wall #-}
 
 {-
diff --git a/box-socket.cabal b/box-socket.cabal
--- a/box-socket.cabal
+++ b/box-socket.cabal
@@ -1,6 +1,6 @@
 cabal-version: 3.0
 name: box-socket
-version: 0.5.2.0
+version: 0.5.2.1
 license: BSD-3-Clause
 license-file: LICENSE
 copyright: Tony Day (c) 2017
@@ -13,75 +13,96 @@
 description: Websockets built with the box library.
 build-type: Simple
 tested-with:
-    , GHC == 9.10.1
-    , GHC == 9.6.5
-    , GHC == 9.8.2
+  ghc ==9.6.7
+  ghc ==9.8.4
+  ghc ==9.10.2
+  ghc ==9.12.2
+
 extra-doc-files:
-    ChangeLog.md
-    readme.md
+  ChangeLog.md
+  readme.md
 
 source-repository head
-    type: git
-    location: https://github.com/tonyday567/box-socket
+  type: git
+  location: https://github.com/tonyday567/box-socket
 
 common ghc-options-exe-stanza
-    ghc-options:
-        -fforce-recomp
-        -funbox-strict-fields
-        -rtsopts
-        -threaded
-        -with-rtsopts=-N
+  ghc-options:
+    -fforce-recomp
+    -funbox-strict-fields
+    -rtsopts
+    -threaded
+    -with-rtsopts=-N
 
 common ghc-options-stanza
-    ghc-options:
-        -Wall
-        -Wcompat
-        -Widentities
-        -Wincomplete-record-updates
-        -Wincomplete-uni-patterns
-        -Wpartial-fields
-        -Wredundant-constraints
+  ghc-options:
+    -Wall
+    -Wcompat
+    -Widentities
+    -Wincomplete-record-updates
+    -Wincomplete-uni-patterns
+    -Wpartial-fields
+    -Wredundant-constraints
 
-common ghc2021-stanza
-    default-language: GHC2021
+common ghc2024-additions
+  default-extensions:
+    DataKinds
+    DerivingStrategies
+    DisambiguateRecordFields
+    ExplicitNamespaces
+    GADTs
+    LambdaCase
+    MonoLocalBinds
+    RoleAnnotations
 
+common ghc2024-stanza
+  if impl(ghc >=9.10)
+    default-language:
+      GHC2024
+  else
+    import: ghc2024-additions
+    default-language:
+      GHC2021
+
 library
-    import: ghc-options-stanza
-    import: ghc2021-stanza
-    hs-source-dirs: src
-    build-depends:
-        , async          >=2.2.3 && <2.3
-        , base           >=4.14 && <5
-        , box            >=0.9.3 && <0.10
-        , bytestring     >=0.11.3 && <0.13
-        , network-simple >=0.4 && <0.5
-        , profunctors    >=5.6 && <5.7
-        , text           >=1.2 && <2.2
-        , websockets     >=0.12 && <0.14
-    exposed-modules:
-        Box.Socket.Types
-        Box.TCP
-        Box.TCP.Example
-        Box.Websocket
-        Box.Websocket.Example
+  import: ghc-options-stanza
+  import: ghc2024-stanza
+  hs-source-dirs: src
+  build-depends:
+    async >=2.2.3 && <2.3,
+    base >=4.14 && <5,
+    box >=0.9.3 && <0.10,
+    bytestring >=0.11.3 && <0.13,
+    network-simple >=0.4 && <0.5,
+    profunctors >=5.6 && <5.7,
+    text >=1.2 && <2.2,
+    websockets >=0.12 && <0.14,
 
+  exposed-modules:
+    Box.Socket.Types
+    Box.TCP
+    Box.TCP.Example
+    Box.Websocket
+    Box.Websocket.Example
+
 executable box-socket
-    import: ghc-options-exe-stanza
-    import: ghc-options-stanza
-    import: ghc2021-stanza
-    main-is: box-socket.hs
-    hs-source-dirs: app
-    build-depends:
-        , base                 >=4.14 && <5
-        , box-socket
-        , optparse-applicative >=0.17 && <0.19
+  import: ghc-options-exe-stanza
+  import: ghc-options-stanza
+  import: ghc2024-stanza
+  main-is: box-socket.hs
+  hs-source-dirs: app
+  build-depends:
+    base >=4.14 && <5,
+    box-socket,
+    optparse-applicative >=0.17 && <0.20,
 
 test-suite doctests
-    import: ghc2021-stanza
-    main-is: doctests.hs
-    hs-source-dirs: test
-    build-depends:
-        , base             >=4.14 && <5
-        , doctest-parallel >=0.3 && <0.4
-    ghc-options: -threaded
-    type: exitcode-stdio-1.0
+  import: ghc2024-stanza
+  main-is: doctests.hs
+  hs-source-dirs: test
+  build-depends:
+    base >=4.14 && <5,
+    doctest-parallel >=0.3 && <0.5,
+
+  ghc-options: -threaded
+  type: exitcode-stdio-1.0
diff --git a/readme.md b/readme.md
--- a/readme.md
+++ b/readme.md
@@ -1,16 +1,8 @@
-
-# Table of Contents
-
-1.  [Usage](#org6c95983)
-2.  [Design](#org6cb8437)
-
-[![img](https://img.shields.io/hackage/v/box-socket.svg)](https://hackage.haskell.org/package/box) [![img](https://github.com/tonyday567/box-socket/workflows/haskell-ci/badge.svg)](https://github.com/tonyday567/box/actions?query=workflow%3Ahaskell-ci)
+[![img](https://img.shields.io/hackage/v/box-socket.svg)](https://hackage.haskell.org/package/box-socket) [![img](https://github.com/tonyday567/box-socket/actions/workflows/haskell-ci.yml/badge.svg)](https://github.com/tonyday567/box/actions/workflows/haskell-ci.yml)
 
 Socket API based on the box library, with websockets and TCP support.
 
 
-<a id="org6c95983"></a>
-
 # Usage
 
     :set -XOverloadedStrings
@@ -28,8 +20,6 @@
 
 See examples in Box.Websocket.Example and Box.TCP.Example for a variety of usage.
 
-
-<a id="org6cb8437"></a>
 
 # Design
 
diff --git a/src/Box/TCP/Example.hs b/src/Box/TCP/Example.hs
--- a/src/Box/TCP/Example.hs
+++ b/src/Box/TCP/Example.hs
@@ -66,7 +66,7 @@
 
 -- | "q" to close the client, reads and writes from std
 --
--- >>> clientIO
+-- >> clientIO
 -- *** Exception: Network.Socket.connect: <socket: ...>: does not exist (Connection refused)
 clientIO :: IO ()
 clientIO =
@@ -74,10 +74,10 @@
 
 -- | "q" to close a client socket down. Ctrl-c to close the server. Reads and writes from std.
 --
--- >>> a <- async serverIO
--- >>> serverIO
+-- >> a <- async serverIO
+-- >> serverIO
 -- *** Exception: Network.Socket.bind: resource busy (Address already in use)
 --
--- >>> cancel a
+-- >> cancel a
 serverIO :: IO ()
 serverIO = serverBox defaultTCPConfig (CloseAfter 0) (dimap decodeUtf8 encodeUtf8 (stdBox "q"))
diff --git a/src/Box/Websocket/Example.hs b/src/Box/Websocket/Example.hs
--- a/src/Box/Websocket/Example.hs
+++ b/src/Box/Websocket/Example.hs
@@ -67,18 +67,20 @@
 
 -- | "q" to close the client, reads and writes from std
 --
--- >>> clientIO
+-- >> clientIO
 -- *** Exception: Network.Socket.connect: <socket: ...>: does not exist (Connection refused)
+-- ...
 clientIO :: IO ()
 clientIO =
   clientBox defaultSocketConfig (CloseAfter 0) (stdBox "q")
 
 -- | "q" to close a client socket down. Ctrl-c to close the server. Reads and writes from std.
 --
--- >>> a <- async serverIO
--- >>> serverIO
+-- >> a <- async serverIO
+-- >> serverIO
 -- *** Exception: Network.Socket.bind: resource busy (Address already in use)
+-- ...
 --
--- >>> cancel a
+-- >> cancel a
 serverIO :: IO ()
 serverIO = serverBox defaultSocketConfig (CloseAfter 0) (stdBox "q")
