├── .gitignore ├── cabal.project.local ├── Setup.hs ├── miso-app.cabal ├── web └── Main.hs ├── README.md ├── LICENSE └── default.nix /.gitignore: -------------------------------------------------------------------------------- 1 | .stack* 2 | dist-* 3 | result 4 | -------------------------------------------------------------------------------- /cabal.project.local: -------------------------------------------------------------------------------- 1 | compiler: ghcjs 2 | 3 | -------------------------------------------------------------------------------- /Setup.hs: -------------------------------------------------------------------------------- 1 | import Distribution.Simple 2 | main = defaultMain 3 | -------------------------------------------------------------------------------- /miso-app.cabal: -------------------------------------------------------------------------------- 1 | cabal-version: >=1.10 2 | name: miso-app 3 | version: 0.1.0.0 4 | synopsis: Miso Start Template 5 | -- description: 6 | -- bug-reports: 7 | license: BSD3 8 | license-file: LICENSE 9 | author: Alejandro Serrano 10 | maintainer: trupill@gmail.com 11 | -- copyright: 12 | category: Language 13 | build-type: Simple 14 | 15 | executable miso-app 16 | if !impl(ghcjs) 17 | buildable: False 18 | main-is: Main.hs 19 | ghcjs-options: -dedupe 20 | build-depends: base >=4.12 && <5, 21 | text, aeson, 22 | microlens, microlens-mtl, microlens-th, 23 | miso, servant-client-ghcjs 24 | hs-source-dirs: web 25 | default-language: Haskell2010 -------------------------------------------------------------------------------- /web/Main.hs: -------------------------------------------------------------------------------- 1 | {-# language NamedFieldPuns #-} 2 | {-# language OverloadedStrings #-} 3 | {-# language RecordWildCards #-} 4 | 5 | module Main where 6 | 7 | import Miso 8 | import Miso.String (MisoString) 9 | 10 | main :: IO () 11 | main = startApp App { .. } 12 | where 13 | initialAction = None 14 | model = Model { } 15 | update = updateModel 16 | view = viewModel 17 | events = defaultEvents 18 | subs = [] 19 | mountPoint = Nothing 20 | logLevel = Off 21 | 22 | data Model 23 | = Model { } 24 | deriving (Show, Eq) 25 | 26 | data Action 27 | = None 28 | deriving (Show, Eq) 29 | 30 | updateModel :: Action -> Model -> Effect Action Model 31 | updateModel _ m = noEff m 32 | 33 | bootstrapUrl :: MisoString 34 | bootstrapUrl = "https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css" 35 | 36 | viewModel :: Model -> View Action 37 | viewModel Model { } 38 | = div_ [] 39 | [ text "Hello from Miso!" 40 | , link_ [ rel_ "stylesheet" 41 | , href_ bootstrapUrl ] 42 | ] -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # [Miso](https://haskell-miso.org/) Start Template 2 | 3 | Copy the files and start hacking your Miso app! 4 | 5 | ## Prepare the build 6 | 7 | 1. [Install Nix](https://nixos.org/download.html) 8 | * If you are using macOS 10.15 or newer, check the [specific instructions](https://nixos.org/manual/nix/stable/#sect-macos-installation) 9 | 2. Optionally set up a binary cache: 10 | 1. [Install Cachix](https://docs.cachix.org/installation.html#installation): `nix-env -iA cachix -f https://cachix.org/api/v1/install` 11 | 2. Use the Miso cache: `cachix use miso-haskell` 12 | 13 | ## Build and run the project 14 | 15 | ```sh 16 | nix-build 17 | open ./result/bin/miso-app.jsexe/index.html 18 | ``` 19 | 20 | ## Build the project in a nix-shell 21 | 22 | ```sh 23 | nix-shell -A env 24 | cabal build 25 | open `find dist-newstyle/ -name index.html` 26 | ``` 27 | 28 | ## Update dependencies 29 | 30 | The `default.nix` file has a couple of lines which indicate the "state of the world" for the build system: 31 | - The version of Miso you are going to use, usually from Git; 32 | - A Hackage snapshot, which can be updated by taking the latest version from [`all-cabal-hashes`](https://github.com/commercialhaskell/all-cabal-hashes). 33 | 34 | The example also shows how you can re-wire the Hackage information to make some packages use a different version from the latest (`servant` in our case), and how to bring a package from a GitHub repository. 35 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2020, Alejandro Serrano 2 | 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | 8 | * Redistributions of source code must retain the above copyright 9 | notice, this list of conditions and the following disclaimer. 10 | 11 | * Redistributions in binary form must reproduce the above 12 | copyright notice, this list of conditions and the following 13 | disclaimer in the documentation and/or other materials provided 14 | with the distribution. 15 | 16 | * Neither the name of Alejandro Serrano nor the names of other 17 | contributors may be used to endorse or promote products derived 18 | from this software without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 23 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 24 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 25 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 26 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 30 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 | -------------------------------------------------------------------------------- /default.nix: -------------------------------------------------------------------------------- 1 | let 2 | # Pin the Miso repository to a particular commit, import the expression, and 3 | # retrieve the nixpkgs package set it provides. 4 | # 5 | # Last updated: 4 September 2020 6 | pkgs = ( 7 | import ( 8 | builtins.fetchTarball { 9 | url = "https://github.com/dmjio/miso/archive/bb230192164f0532660aadb4175460740abfa2a2.tar.gz"; 10 | sha256 = "0q44lxzz8pp89ccaiw3iwczha8x2rxjwmgzkxj8cxm97ymsm0diy"; 11 | } 12 | ) {} 13 | ).pkgs; 14 | 15 | # Construct a complete Haskell package set by overlaying the base package set 16 | # from nixpkgs with various packages from external sources. 17 | haskellPackages = pkgs.haskell.packages.ghcjs.override ( 18 | oldArgs: { 19 | # Ensure that we have an up-to-date Hackage snapshot. 20 | # 21 | # Last updated: 4 September 2020. 22 | all-cabal-hashes = pkgs.fetchurl { 23 | url = "https://github.com/commercialhaskell/all-cabal-hashes/archive/117622c10bf41f70548af023366ad82eab9835e3.tar.gz"; 24 | sha256 = "15zpi7x1iqkjk4dscm0z9xxshl58nmdi3sxgn8w3x86wbz03k1wv"; 25 | }; 26 | 27 | # Override/extend the base package set. 28 | overrides = pkgs.lib.composeExtensions (oldArgs.overrides or (_: _: {})) ( 29 | hself: hsuper: { 30 | servant = pkgs.haskell.lib.dontCheck ( 31 | hself.callHackage "servant" "0.16" {} 32 | ); 33 | servant-client-core = pkgs.haskell.lib.dontCheck ( 34 | hself.callHackage "servant-client-core" "0.16" {} 35 | ); 36 | servant-client-ghcjs = 37 | let 38 | src = 39 | pkgs.fetchFromGitHub { 40 | owner = "haskell-servant"; 41 | repo = "servant"; 42 | rev = "v0.16"; 43 | sha256 = "0dyn50gidzbgyq9yvqijnysai9hwd3srqvk8f8rykh09l375xb9j"; 44 | } + "/servant-client-ghcjs"; 45 | in 46 | pkgs.haskell.lib.doJailbreak ( 47 | hself.callCabal2nix "servant-client-ghcjs" src {} 48 | ); 49 | } 50 | ); 51 | } 52 | ); 53 | in 54 | 55 | haskellPackages.developPackage { 56 | # cf. https://nix.dev/anti-patterns/language.html#reproducability-referencing-top-level-directory-with 57 | root = builtins.path { 58 | path = ./.; 59 | name = "miso-project"; 60 | }; 61 | name = "miso-app"; 62 | } 63 | --------------------------------------------------------------------------------