title: How can I do a simple elmish router?
body: <p>Sorry, but I'm a newbie with Fable and F#. I started a boilerplate from <a href="https://safe-stack.github.io/docs/quickstart/" rel="noreferrer">SAFE project</a>, and I created a SPA with two pages. However, all the logic is inside a single file. My question is. How can I implement a router putting each view in one file?</p>
  
  <p>I would something like that:</p>
  
  <pre><code>...
  Client
    |_Client.fs
    |_Pages
        |_ Home.fs
        |_ About.fs
  Server
    |_Server.fs
  ...
  </code></pre>
  
  <p>Below is my Client.fs file</p>
  
  <p><strong>src/Client/Client.fs</strong></p>
  
  <pre><code>(**
   - title: Navigation demo
   - tagline: The router sample ported from Elm
  *)
  module App
  
  open Fable.Core
  open Fable.Import
  open Elmish
  open Fable.Import.Browser
  open Fable.PowerPack
  open Elmish.Browser.Navigation
  open Elmish.Browser.UrlParser
  
  
  JsInterop.importAll "whatwg-fetch"
  
  // Types
  type Page = Home | Blog of int | Search of string
  
  type Model =
    { page : Page
      query : string
      cache : Map&lt;string,string list&gt; }
  
  let toHash =
      function
      | Blog id -&gt; "#blog/" + (string id)
      | _ -&gt; "#home"
  
  /// The URL is turned into a Page option.
  let pageParser : Parser&lt;Page-&gt;_,_&gt; =
    oneOf
      [ map Home (s "home")
        map Blog (s "blog" &lt;/&gt; i32) ]
  
  
  type Msg =
    | Query of string
    | Enter
    | FetchFailure of string*exn
    | FetchSuccess of string*(string list)
  
  
  type Place = { ``place name``: string; state: string; }
  
  (* If the URL is valid, we just update our model or issue a command.
  If it is not a valid URL, we modify the URL to whatever makes sense.
  *)
  let urlUpdate (result:Option&lt;Page&gt;) model =
    match result with
    | Some page -&gt;
        { model with page = page; query = "" }, []
  
    | None -&gt;
        Browser.console.error("Error parsing url")
        ( model, Navigation.modifyUrl (toHash model.page) )
  
  let init result =
    urlUpdate result { page = Home; query = ""; cache = Map.empty }
  
  
  (* A relatively normal update function. The only notable thing here is that we
  are commanding a new URL to be added to the browser history. This changes the
  address bar and lets us use the browser&amp;rsquo;s back button to go back to
  previous pages.
  *)
  let update msg model =
    match msg with
    | Query query -&gt;
        { model with query = query }, []
  
    | FetchFailure (query,_) -&gt;
        { model with cache = Map.add query [] model.cache }, []
  
    | FetchSuccess (query,locations) -&gt;
        { model with cache = Map.add query locations model.cache }, []
  
  
  // VIEW
  
  open Fable.Helpers.React
  open Fable.Helpers.React.Props
  
  
  let viewLink page description =
    a [ Style [ Padding "0 20px" ]
        Href (toHash page) ]
      [ str description]
  
  let internal centerStyle direction =
      Style [ Display "flex"
              FlexDirection direction
              AlignItems "center"
              unbox("justifyContent", "center")
              Padding "20px 0" ]
  
  let words size message =
    span [ Style [ unbox("fontSize", size |&gt; sprintf "%dpx") ] ] [ str message ]
  
  let internal onEnter msg dispatch =
      function
      | (ev:React.KeyboardEvent) when ev.keyCode = 13. -&gt;
          ev.preventDefault()
          dispatch msg
      | _ -&gt; ()
      |&gt; OnKeyDown
  
  let viewPage model dispatch =
    match model.page with
    | Home -&gt;
        [ words 60 "Welcome!"
          str "Play with the links and search bar above. (Press ENTER to trigger the zip code search.)" ]
  
    | Blog id -&gt;
        [ words 20 "This is blog post number"
          words 100 (string id) ]
  
  open Fable.Core.JsInterop
  
  let view model dispatch =
    div []
      [ div [ centerStyle "row" ]
          [ viewLink Home "Home"
            viewLink (Blog 42) "Cat Facts"
            viewLink (Blog 13) "Alligator Jokes"
            viewLink (Blog 26) "Workout Plan" ]
        hr []
        div [ centerStyle "column" ] (viewPage model dispatch)
      ]
  
  open Elmish.React
  open Elmish.Debug
  
  // App
  Program.mkProgram init update view
  |&gt; Program.toNavigable (parseHash pageParser) urlUpdate
  |&gt; Program.withReact "elmish-app"
  |&gt; Program.withDebugger
  |&gt; Program.run
  </code></pre>