diff --git a/ChangeLog.md b/ChangeLog.md
--- a/ChangeLog.md
+++ b/ChangeLog.md
@@ -1,5 +1,13 @@
 # Revision history for hanabi-dealer
 
+	## 0.6.0.0 -- 2020-02-08
+
+	* introduce the observation (or audience) mode
+
+	* rename the command names from server and client to hanabib and hanabif respectively.
+
+	* Flag jsaddle builds hanabiq that is quickly-built executable including the functionalities of both hanabib and hanabif (but it is not stable.)
+
 	## 0.5.0.0 -- 2020-02-05
 
 	* implement possibility marks which represent what colors and what numbers are possible for each card
diff --git a/Game/Hanabi.hs b/Game/Hanabi.hs
--- a/Game/Hanabi.hs
+++ b/Game/Hanabi.hs
@@ -6,6 +6,8 @@
               -- * Datatypes
               -- ** The Class of Strategies
               Strategies, Strategy(..), StrategyDict(..), mkSD, DynamicStrategy, mkDS, mkDS', Verbose(..), STDIO, stdio, Blind, ViaHandles(..), Verbosity(..), verbose,
+              -- ** Audience
+              Peeker, peek,
               -- ** The Game Specification
               GameSpec(..), defaultGS, Rule(..), defaultRule, isRuleValid, colors,
               -- ** The Game State and Interaction History
@@ -17,7 +19,7 @@
               isCritical, isUseless, bestPossibleRank, achievedRank, isPlayable, isHinted,
               isMoreObviouslyUseless, isObviouslyUseless, isDefinitelyUseless, isMoreObviouslyPlayable, isObviouslyPlayable, isDefinitelyPlayable, obviousChopss, definiteChopss, isDoubleDrop,
               -- ** Minor ones
-              what'sUp, what'sUp1, ithPlayer, recentEvents, prettyPI, ithPlayerFromTheLast, view, replaceNth, shuffle, showPossibilities, showColorPossibilities, showNumberPossibilities) where
+              what'sUp, what'sUp1, ithPlayer, recentEvents, prettyPI, prettySt, ithPlayerFromTheLast, view, replaceNth, shuffle, showPossibilities, showColorPossibilities, showNumberPossibilities) where
 -- module Hanabi where
 import qualified Data.IntMap as IM
 import System.Random
@@ -414,7 +416,7 @@
 --  (where 1<n<10) starts selfplay with youselves:D
 selfplay gs
      = do g <- newStdGen
-          ((finalSituation,_),_) <- start gs [stdio] g
+          ((finalSituation,_),_) <- start gs [] [stdio] g
           putStrLn $ prettyEndGame finalSituation
 
 -- | 'prettyEndGame' can be used to pretty print the final situation.
@@ -430,15 +432,20 @@
                      len2 =len `div` 2
                  in reverse (drop len2 ys) ++ xs ++ drop (len - len2) ys
 
+type Peeker m = State -> m ()
+peek :: Peeker IO
+peek = putStrLn . prettySt ithPlayerFromTheLast
+
 -- | 'start' creates and runs a game. This is just the composition of 'createGame' and 'run'.
 start :: (RandomGen g, Monad m, Strategies ps m) =>
-       GameSpec -> ps -> g -> m (((EndGame, [State], [Move]), ps), g)
-start gs players gen = let
+       GameSpec -> [Peeker m] -> ps -> g -> m (((EndGame, [State], [Move]), ps), g)
+start gs audience players gen = let
                          (st, g) = createGame gs gen
-                       in fmap (\e -> (e,g)) $ run [st] [] players
-run :: (Monad m, Strategies ps m) => [State] -> [Move] -> ps -> m ((EndGame, [State], [Move]), ps)
-run states moves players = do ((mbeg, sts, mvs), ps) <- runARound (\sts@(st:_) mvs -> let myOffset = turn (publicState st) in broadcast (zipWith rotate [-myOffset, 1-myOffset ..] sts) mvs players (myOffset `mod` numPlayers (gameSpec $ publicState st)) >> return ()) states moves players
-                              case mbeg of Nothing -> run sts mvs ps
+                       in fmap (\e -> (e,g)) $ run audience [st] [] players
+run :: (Monad m, Strategies ps m) => [Peeker m] -> [State] -> [Move] -> ps -> m ((EndGame, [State], [Move]), ps)
+run audience states moves players = do
+                              ((mbeg, sts, mvs), ps) <- runARound (\sts@(st:_) mvs -> let myOffset = turn (publicState st) in mapM_ ($ st) audience >> broadcast (zipWith rotate [-myOffset, 1-myOffset ..] sts) mvs players (myOffset `mod` numPlayers (gameSpec $ publicState st)) >> return ()) states moves players
+                              case mbeg of Nothing -> run audience sts mvs ps
                                            Just eg -> return ((eg, sts, mvs), ps)
 
 -- | The 'Strategy' class is exactly the interface that
diff --git a/Game/Hanabi/Backend.lhs b/Game/Hanabi/Backend.lhs
--- a/Game/Hanabi/Backend.lhs
+++ b/Game/Hanabi/Backend.lhs
@@ -4,7 +4,11 @@
 --
 
 -- x #define SNAP
-module Game.Hanabi.Backend(server, Options(..), defaultOptions, module Game.Hanabi) where
+module Game.Hanabi.Backend(server,
+#ifdef WARP
+                           hanabiApp,
+#endif
+                           Options(..), defaultOptions, module Game.Hanabi) where
 
 import Game.Hanabi hiding (main)
 import Game.Hanabi.Msg
@@ -50,7 +54,7 @@
 # ifdef WARP
 import Network.Wai.Handler.WebSockets
 import Network.Wai.Handler.Warp as Warp
-import Network.Wai(responseLBS)
+import Network.Wai(Application, responseLBS)
 import Network.HTTP.Types(status400)
 # endif
 #endif
@@ -95,24 +99,25 @@
     hPutStrLn stderr $ "hanabi-dealer server " ++ version options
     beginCT <- getCurrentTime
     hPutStrLn stderr ("started at " ++ show beginCT)
-#ifdef TFRANDOM
-    g <- newTFGen
+#ifdef WARP
+    app <- hanabiApp options $ \_ resp -> resp $ responseLBS status400 [] "Not a WebSocket request."
+    Warp.run (port options) app
 #else
-    g <- newStdGen
-#endif
-
-    mv <- newMVar (IntMap.empty::IntMap.IntMap ([MVar ViaWebSocket], MVar (Maybe (EndGame,[State],[Move]))))
-    let params = Params{gen = g, mvTIDToMVH = mv, versionString = version options, gsConstructorMap = Map.fromList $ strategies options, conn = error "Game.Hanabi.Backend.server: should not happen"}
-#ifdef SNAP
+    params <- mkParams options
+# ifdef SNAP
     httpServe (setPort (port options) defaultConfig) $ runWebSocketsSnap $ loop params
-#else
-# ifdef WARP
-    Warp.run (port options) $ websocketsOr defaultConnectionOptions (loop params) $ \_ resp -> resp $ responseLBS status400 [] "Not a WebSocket request."
 # else
     runServer "127.0.0.1" (port options) $ loop params
 # endif
 #endif
 
+#ifdef WARP
+hanabiApp :: Options -> Application -> IO Application
+hanabiApp options fallbackApp = do
+    params <- mkParams options
+    return $ websocketsOr defaultConnectionOptions (loop params) fallbackApp
+#endif
+
 data Params g = Params{gen :: g,
                        mvTIDToMVH :: MVar (IntMap.IntMap ([MVar ViaWebSocket], MVar (Maybe (EndGame,[State],[Move])))),
                        conn :: Connection,
@@ -120,6 +125,18 @@
                        gsConstructorMap :: Map.Map String (IO (DynamicStrategy IO))
                       }
 
+#ifdef TFRANDOM
+mkParams :: Options -> IO (Params TFGen)
+mkParams options = do
+    g <- newTFGen
+#else
+mkParams :: Options -> IO (Params StdGen)
+mkParams options = do
+    g <- newStdGen
+#endif
+    mv <- newMVar (IntMap.empty::IntMap.IntMap ([MVar ViaWebSocket], MVar (Maybe (EndGame,[State],[Move]))))
+    return Params{gen = g, mvTIDToMVH = mv, versionString = version options, gsConstructorMap = Map.fromList $ strategies options, conn = error "Game.Hanabi.Backend.server: should not happen"}
+
 -- Well, this is not a loop any longer....
 loop :: RandomGen g =>
         Params g -> PendingConnection -> IO ()
@@ -136,7 +153,7 @@
 # endif
                  let p = params{gen = g, conn = c}
 #endif
-                 withPingThread c 30 (return ()) $ fmap (const ()) $ answerHIO p
+                 withPingThread c 25 (return ()) $ fmap (const ()) $ answerHIO p
 
 
 endecodeX Nothing     = endecode
@@ -172,6 +189,8 @@
     observe (v:_) (m:_) vh = liftIO $ sendTextData (connection vh) $ endecodeX (verbVWS vh) $ WhatsUp1 v m
 
 
+watch conn mbVerb st = sendTextData conn $ endecodeX mbVerb $ Watch st
+
 answerHIO :: RandomGen g => Params g -> IO ()
 answerHIO params = do
   available Nothing (mvTIDToMVH params) (conn params)
@@ -200,13 +219,13 @@
 interpret mbVerb inp params
   = let sender :: String -> IO ()
         sender = sendTextData (conn params) . endecodeX mbVerb . Str
-        createR creater args = case reads args of [(rule,rest)] | isRuleValid rule -> create creater rule rest
-                                                  _             -> create creater defaultRule args
-        create :: Maybe Int -> Rule -> String -> IO ()
-        create from rule args =
+        createR observe creater args = case reads args of [(rule,rest)] | isRuleValid rule -> create observe creater rule rest
+                                                          _             -> create observe creater defaultRule args
+        create :: Bool -> Maybe Int -> Rule -> String -> IO ()
+        create observe from rule args =
                               case wordsBy (==',') args of
                                 is | numAllies > 0 -> if numAllies >= 9
-                                                      then sender "Too many teemmates!\n"
+                                                      then sender "Too many teammates!\n"
                                                       else case dropWhile (\s -> isWS s || s `Map.member` gsConstructorMap params) is of
                                                              alg:_ -> sender $ "Algorithm " ++ shows (maximum is) " not implemented yet.\n"
                                                              []    -> do
@@ -224,11 +243,13 @@
                                                                    constructor _     algIx = fromJust $ Map.lookup algIx $ gsConstructorMap params
                                                                ixSs <- sequence $ zipWith constructor [0..] is
                                                                sender "starting the game\n"
-                                                               let playerList = mkDS "via WebSocket" (VWS (conn params) mbVerb sendFullHistoryInFact) : ixSs
+                                                               let playerList | observe = ixSs
+                                                                              |otherwise= mkDS "via WebSocket" (VWS (conn params) mbVerb sendFullHistoryInFact) : ixSs
                                                                    (playOrder,g) = case from of Just n  -> (dr++tk, gen params)
                                                                                                    where (tk,dr) = splitAt n playerList
                                                                                                 Nothing -> shuffle playerList $ gen params
-                                                               eithFinalSituation <- try $ start (GS (succ numAllies) rule) playOrder g
+                                                               eithFinalSituation <- try $ if observe then start (GS numAllies rule)        [watch (conn params) mbVerb] playOrder g
+                                                                                                      else start (GS (succ numAllies) rule) []                           playOrder g
                                                                finalSituation <- case eithFinalSituation of
                                                                                    Left e -> do hPutStrLn stderr $ displayException (e::SomeException)
                                                                                                 return Nothing
@@ -240,10 +261,12 @@
                                 _  -> sender "The arguments of the `create' command could not be parsed."
     in case lex inp of
         [("version", _)]   -> sender $ "hanabi-dealer server " ++ versionString params
-        [("create", args)] -> createR (Just 0) args
-        [("from",   args)] -> case reads args of [(n, ars)] -> createR (Just n) ars
+        [("create", args)] -> createR False (Just 0) args
+        [("from",   args)] -> case reads args of [(n, ars)] -> createR False (Just n) ars
                                                  _          -> sender "Parse error. The player number expected."
-        [("shuffle",args)] -> createR Nothing args
+        [("observe",args)] -> case reads args of [(n, ars)] -> createR True (Just n) ars
+                                                 _          -> createR True Nothing args
+        [("shuffle",args)] -> createR False Nothing args
         [("available", s)] | all isSpace s -> when (isJust mbVerb) $ available mbVerb (mvTIDToMVH params) (conn params)
         [("attend", arg)] -> case reads arg of
                                [(gid, s)] | all isSpace s -> do tidToMVH <- readMVar $ mvTIDToMVH params
diff --git a/Game/Hanabi/Client.hs b/Game/Hanabi/Client.hs
--- a/Game/Hanabi/Client.hs
+++ b/Game/Hanabi/Client.hs
@@ -3,7 +3,11 @@
 {-# LANGUAGE OverloadedStrings          #-}
 {-# LANGUAGE ExtendedDefaultRules       #-}
 {-# LANGUAGE CPP                        #-}
-module Game.Hanabi.Client(client, Game.Hanabi.Msg.Options(..), Game.Hanabi.Msg.defaultOptions, mkDS) where
+module Game.Hanabi.Client(client,
+#if !defined ghcjs_HOST_OS && !defined IOS
+      clientApp,
+#endif
+      Game.Hanabi.Msg.Options(..), Game.Hanabi.Msg.defaultOptions, mkDS) where
 
 import Game.Hanabi hiding (main, rule)
 import qualified Game.Hanabi(rule)
@@ -22,24 +26,45 @@
 import           Miso.String  (MisoString)
 import qualified Miso.String  as S
 
-#ifdef IOS
+#ifdef ghcjs_HOST_OS
+client :: Game.Hanabi.Msg.Options -> IO ()
+client options = clientJSM options
+#else
+# ifdef IOS
 import Language.Javascript.JSaddle.WKWebView as JSaddle
 
-runApp :: JSM () -> IO ()
-runApp = JSaddle.run
-#else
-import Language.Javascript.JSaddle.Warp as JSaddle
+client :: Game.Hanabi.Msg.Options -> IO ()
+client options = JSaddle.run $ clientJSM options
+# else
+import Language.Javascript.JSaddle.WebSockets
+import Network.Wai.Handler.Warp
+import Network.Wai
+import Network.WebSockets(defaultConnectionOptions)
 
-runApp :: JSM () -> IO ()
-runApp = JSaddle.run 8080 -- 8720
-#endif
+{- This doesn't work.
+client :: Game.Hanabi.Msg.Options -> IO ()
+client options = runSettings (setPort 8080 (setTimeout 3600 defaultSettings)) $ clientApp options    -- Maybe the port number should be taken from options, and it should be correctly set.
+clientApp :: Game.Hanabi.Msg.Options -> Application
+clientApp options request respond = do
+    app <- jsmToApp $ clientJSM options
+    app request respond
+-}
 
+client :: Game.Hanabi.Msg.Options -> IO ()
+client options = runSettings (setPort 8080 (setTimeout 3600 defaultSettings)) =<< clientApp options    -- Maybe the port number should be taken from options, and it should be correctly set.
+clientApp :: Game.Hanabi.Msg.Options -> IO Application
+clientApp = jsmToApp . clientJSM
+
+jsmToApp :: JSM () -> IO Application
+jsmToApp f = jsaddleOr defaultConnectionOptions (f >> syncPoint) jsaddleApp
+# endif
+#endif
 -- Miso's implementation of WebSockets uses global IORef.
 -- https://github.com/dmjio/miso/blob/master/frontend-src/Miso/Subscription/WebSocket.hs
 
-client :: Game.Hanabi.Msg.Options -> IO ()
-client options = runApp $ startApp App{
-    model  = Model{tboxval = Message "available", players = ["via WebSocket"], from = Just 0, rule = defaultRule, received = [], fullHistory = False, showVerbosity = False, verbosity = verbose},
+clientJSM :: Game.Hanabi.Msg.Options -> JSM ()
+clientJSM options = startApp App{
+    model  = Model{tboxval = Message "available", players = ["via WebSocket"], from = Just 0, rule = defaultRule, received = [], fullHistory = False, showVerbosity = False, verbosity = verbose, play = True},
     update = updateModel,
     view   = appView strNames $ version options,
     subs   = [ websocketSub uri protocols HandleWebSocket ],
@@ -77,6 +102,8 @@
 updateModel (UpdateVerbosity v) model = noEff model{verbosity = v}
 updateModel Toggle            model = noEff model{fullHistory = not $ fullHistory model}
 updateModel ToggleVerbosity   model = noEff model{showVerbosity = not $ showVerbosity model}
+updateModel TogglePlay        model | play model && length (players model) < 2 = noEff model{play = False, players = "via WebSocket" : players model}
+                                    | otherwise                                = noEff model{play = not $ play model}
 #ifdef DEBUG
 updateModel (HandleWebSocket act) model = noEff model{received = Str (show act) : received model }
 #endif
@@ -100,6 +127,7 @@
   | UpdateVerbosity Verbosity
   | Toggle
   | ToggleVerbosity
+  | TogglePlay
   | Id
 
 data Model = Model {
@@ -111,6 +139,7 @@
   , fullHistory :: Bool
   , showVerbosity :: Bool
   , verbosity :: Verbosity
+  , play :: Bool
   } deriving (Show, Eq)
 
 lenShownHistory = 10
@@ -187,6 +216,7 @@
 renderMsg _ verb _ (WhatsUp1     p  m)  = renderWhatsUp1 verb p m
 renderMsg _ _    _ (PrettyEndGame Nothing)     = pre_ [] [ text $ S.pack $ prettyMbEndGame Nothing]
 renderMsg _ verb _ (PrettyEndGame (Just tup))  = renderEndGame verb tup -- pre_ [] [ text $ S.pack $ prettyEndGame tup]
+renderMsg _ verb _ (Watch st)           = renderSt verb ithPlayerFromTheLast st
 renderMsg strategies _    mdl (PrettyAvailable games)
   = div_ [style_ $ M.fromList [("overflow","auto")]] [
       hr_ [],
@@ -203,9 +233,10 @@
              label_ [for_ "shuffle"] [text "shuffle on startup"]
                                   ] :
 --             table_ [solid] $
-                         [ tr_ [] [td_ [solid] [x], td_ [] [input_ [type_ "radio", id_ iD, onClick (From $ Just n), checked_ $ from mdl == Just n],
-                                                            label_ [for_ iD] [text "Turn 0"]]]
-                         | (n,x) <- zip [0..] $ text "You" : reverse (zipWith (renderPlayer strategies) [0..] (players mdl))
+                         [ tr_ [] [td_ [solid] [x], td_ [] (if n>=0 then [input_ [type_ "radio", id_ iD, onClick (From $ Just n), checked_ $ from mdl == Just n],
+                                                                          label_ [for_ iD] [text "Turn 0"]]
+                                                                    else [])]
+                         | (n,x) <- zip [if play mdl then 0 else -1 ..] $ you : reverse (zipWith (renderPlayer strategies) [0..] (players mdl))
                          , let iD = S.pack $ "radio"++show n ]
 -- x                       ++ [tr_ [] [td_ [] [], td_ [] [input_ [type_ "radio", id_ "shuffle", onClick (From Nothing), checked_ $ from mdl == Nothing],
 --                                                        label_ [for_ "shuffle"] [text "shuffle the player list before the game"]]]]
@@ -234,10 +265,16 @@
                    mkTR "funPlayerHand"                                 (\n -> (rule mdl){funPlayerHand=n})  funPlayerHand
                  ],
 
-             button_ [onClick $ SendMessage $ Message $ S.pack $ (case from mdl of Just n -> "from " ++ shows n " "
-                                                                                   Nothing-> "shuffle ") ++ show (rule mdl) ++ concat (intersperse "," $ map S.unpack $ reverse $ players mdl)] [text $ S.pack "create a game"]
+             button_ [onClick $ SendMessage $ Message $ S.pack $ (case from mdl of Just n  | play mdl  -> "from " ++ shows n " "
+                                                                                           | otherwise -> "observe " ++ shows n " "
+                                                                                   Nothing | play mdl  -> "shuffle "
+                                                                                           | otherwise -> "observe ") ++ show (rule mdl) ++ concat (intersperse "," $ map S.unpack $ reverse $ players mdl)] [text $ S.pack "create a game"]
       ]
    ]
+    where you =  span_[][
+              input_ [ type_ "checkbox", id_ "you", onClick TogglePlay, checked_ $ play mdl]
+            , label_ [for_ "you"] [if play mdl then text "You" else s_ [] [text "You"]]
+            ]
 renderPlayer :: [MisoString] -> Int -> MisoString -> View Action
 --renderPlayer _ i p = text p
 renderPlayer strategies i p = dropdown strategies (UpdatePlayer i) p
diff --git a/Game/Hanabi/Msg.hs b/Game/Hanabi/Msg.hs
--- a/Game/Hanabi/Msg.hs
+++ b/Game/Hanabi/Msg.hs
@@ -33,12 +33,13 @@
 #endif
 
 -- WhatsUp and WhatsUp1 should be minimized after better clients are implemented. 効率上はminimizeすべきだが、テスト目的ではとりあえずこのままの方がやりやすい。
-data Msg = Str String | WhatsUp String [PrivateView] [Move] | WhatsUp1 PrivateView Move | PrettyEndGame (Maybe (EndGame, [State], [Move])) | PrettyAvailable [(Int, (Int, Int))] deriving (Show, Read, Eq, Generic)
+data Msg = Str String | WhatsUp String [PrivateView] [Move] | WhatsUp1 PrivateView Move | PrettyEndGame (Maybe (EndGame, [State], [Move])) | Watch State | PrettyAvailable [(Int, (Int, Int))] deriving (Show, Read, Eq, Generic)
 prettyMsg :: Verbosity -> Msg -> String
 prettyMsg _    (Str xs)        = xs
 prettyMsg verb (WhatsUp name ps ms) = what'sUp  verb name ps ms
 prettyMsg verb (WhatsUp1     p  m)  = what'sUp1 verb      p  m
 prettyMsg _    (PrettyEndGame tup)  = prettyMbEndGame tup
+prettyMsg _    (Watch st)           = prettySt ithPlayerFromTheLast st
 prettyMsg _    (PrettyAvailable available) = unlines $ map prettyAvailableGame available
 prettyMbEndGame Nothing    = "Game ended abnormally, possibly by connection failure.\n"
 prettyMbEndGame (Just tup) = prettyEndGame tup
diff --git a/Game/Hanabi/Strategies/SimpleStrategy.hs b/Game/Hanabi/Strategies/SimpleStrategy.hs
--- a/Game/Hanabi/Strategies/SimpleStrategy.hs
+++ b/Game/Hanabi/Strategies/SimpleStrategy.hs
@@ -30,6 +30,6 @@
 sndOf3 (_,b,_) = b
 
 main = do g <- newStdGen
---          ((eg,_),_) <- start defaultGS ([S],[stdio]) g -- Play it with standard I/O (human player).
-          ((eg,_),_) <- start defaultGS [S,S] g -- Play it with itself.
+--          ((eg,_),_) <- start defaultGS [] ([S],[stdio]) g -- Play it with standard I/O (human player).
+          ((eg,_),_) <- start defaultGS [peek] [S,S] g -- Play it with itself.
           putStrLn $ prettyEndGame eg
diff --git a/all.hs b/all.hs
new file mode 100644
--- /dev/null
+++ b/all.hs
@@ -0,0 +1,34 @@
+{-# LANGUAGE OverloadedStrings, CPP #-}
+import Network.Wai
+import Network.HTTP.Types
+import Network.Wai.Handler.Warp (run)
+
+import Game.Hanabi.Client(clientApp)
+import Game.Hanabi.Backend(hanabiApp, mkDS)
+import Game.Hanabi.Msg(defaultOptions, Options(..))
+
+import Game.Hanabi.Strategies.SimpleStrategy hiding (main)
+
+main = do putStrLn "localhost:8080"  -- Seemingly other port than 8080 does not work.
+          let opt = defaultOptions{version="hanabi-dealer quickbuilt server", strategies=strs}
+          capp <- clientApp opt
+          bapp <- hanabiApp opt $ \_ resp -> resp $ responseLBS status400 [("Content-Type", "text/plain")] "400 Not a WebSocket request."
+          run 8080 $ route capp bapp
+route :: Application -> Application -> Application
+route capp bapp request respond = case rawPathInfo request of
+    "/ws/" -> bapp request respond
+    _      -> capp request respond
+--    _      -> respond $ responseLBS status404 [("Content-Type", "text/plain")] "404 Not found"
+
+{-
+import Game.Hanabi.Client(client)
+
+-- main = client defaultOptions{strategies=strs, version="foo"}
+main = do capp <- clientApp defaultOptions{strategies=strs, version="foo"}
+          run 8080 capp
+-}
+-- strs :: [(String, IO (DynamicStrategy IO))]
+strs = [
+     ("Stupid example strategy", return $ mkDS "Stupid example strategy" $ S)
+ -- x , ("Sontakki", return $ mkDS "Sontakki" (Sontakki emptyDefault))
+  ]
diff --git a/hanabi-dealer.cabal b/hanabi-dealer.cabal
--- a/hanabi-dealer.cabal
+++ b/hanabi-dealer.cabal
@@ -10,7 +10,7 @@
 -- PVP summary:      +-+------- breaking API changes
 --                   | | +----- non-breaking API additions
 --                   | | | +--- code changes with no API change
-version:             0.5.0.0
+version:             0.6.0.0
 
 -- A short (one-line) description of the package.
 synopsis:            Hanabi card game
@@ -73,11 +73,18 @@
   Description: Use template-haskell just for obtaining the compilation time.
   Default:     True
 Flag jsaddle
-  Description: Build the client with JSaddle even when compiling with GHC.
+--   Description: Build the client with JSaddle even when compiling with GHC.
+--                (Package miso must have been built with --flags="jsaddle".)
+--   Default:     False
+-- Flag all
+  Description: Quickbuild all-in-one server, using JSaddle.
                (Package miso must have been built with --flags="jsaddle".)
   Default:     False
 
 library
+ if flag(jsaddle)
+  buildable: False
+ else
   -- Modules exported by the library.
   exposed-modules:     Game.Hanabi
 
@@ -97,7 +104,8 @@
   -- Base language which the package is written in.
   default-language:    Haskell2010
 
-  if impl(ghcjs) || flag(jsaddle) || flag(server)
+  if impl(ghcjs) || flag(server)
+--                       || flag(jsaddle)
     exposed-modules:     Game.Hanabi.VersionInfo
     other-modules:       Game.Hanabi.Msg
     -- cpp-options:      -DCABAL
@@ -120,16 +128,34 @@
       if flag(WARP)
         build-depends:       wai-websockets, warp, wai, http-types
         cpp-options:         -DWARP
-  if impl(ghcjs) || flag(jsaddle)
+  if impl(ghcjs)
+--                || flag(jsaddle)
       exposed-modules:     Game.Hanabi.Client
       ghcjs-options:      -dedupe -O
       build-depends:      base >=4.12 && <4.13, jsaddle-warp >=0.9, aeson, miso, time >=1.6
       if flag(official)
         cpp-options:  -DURI="ws://133.54.228.39:8720"
+--  if flag(jsaddle)
+--      build-depends:      warp, wai, websockets
 
-executable server
+executable hanabiq
+  main-is: all.hs
+  other-modules: Game.Hanabi, Game.Hanabi.Msg, Game.Hanabi.Backend, Game.Hanabi.Client, Game.Hanabi.Strategies.SimpleStrategy
+--  if !flag(all)
+  if !flag(jsaddle)
+    buildable: False
+  else
+    ghc-options: -O0 -rtsopts
+    cpp-options: -DURI="ws://localhost:8080/ws/" -DWARP
+    build-depends: base >=4.12 && <4.13, containers >=0.5, random >=1.1, jsaddle-warp >=0.9, aeson, miso, websockets >=0.12 && <0.13, network >=2.6 && <3.2, hashable >=1.3, time >=1.6 && <1.9, text >=1.2, utf8-string, wai-websockets, warp, wai, http-types
+    if flag(TFRANDOM)
+      build-depends: tf-random
+      cpp-options: -DTFRANDOM
+    default-language: Haskell2010
+
+executable hanabib
   main-is:       server.hs
-  other-modules: Game.Hanabi.Backend, Game.Hanabi.Msg, Game.Hanabi.VersionInfo, Game.Hanabi.Strategies.SimpleStrategy
+  other-modules: Game.Hanabi.Strategies.SimpleStrategy
   if impl(ghcjs) || !flag(server)
     buildable: False
   else
@@ -151,10 +177,11 @@
         build-depends:       wai-websockets, warp, wai, http-types
         cpp-options:         -DWARP
 
-executable client
+executable hanabif
   main-is:       client.hs
-  other-modules: Game.Hanabi.Msg, Game.Hanabi.Client, Game.Hanabi.VersionInfo, Game.Hanabi.Strategies.SimpleStrategy
-  if !impl(ghcjs) && !flag(jsaddle)
+  other-modules: Game.Hanabi.Strategies.SimpleStrategy
+  if !impl(ghcjs)
+--                 && !flag(jsaddle)
     buildable: False
   else
     ghcjs-options:      -dedupe -O
@@ -165,3 +192,5 @@
       cpp-options:  -DURI="ws://133.54.228.39:8720"
     if flag(TH)
       build-depends: template-haskell
+--    if flag(jsaddle)
+--      build-depends:      warp, wai, websockets
