# Nested routes with navigation on page load?

**URL:** <https://discourse.elm-lang.org/t/nested-routes-with-navigation-on-page-load/5775>\
**Category:** Learn\
**Created:** [May 14, 2020, 3:14am UTC](https://discourse.elm-lang.org/t/nested-routes-with-navigation-on-page-load/5775 "2020-05-14T03:14:19Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![nathanbraun](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/nathanbraun/32/3834_2.png) [@nathanbraun](https://discourse.elm-lang.org/u/nathanbraun)\
**Post date:** [May 14, 2020, 3:14am UTC](https://discourse.elm-lang.org/t/nested-routes-with-navigation-on-page-load/5775/1 "2020-05-14T03:14:19Z")

</div>

Hi there, in the Elm guide, there’s a section on URL parsing where Evan goes through some examples of nested routes.

```auto
-- /blog/42
-- /blog/123
-- /blog/mosaic

```

I’m wondering how to get my app (in development and also production) to load blog/42 if I start there initially (e.g. type in localhost:8000/blog/42 or [www.mysite.com/blog/42](http://www.mysite.com/blog/42) in the navigation bar).

What DOES work:

1. I can do an initial load on a non nested route like /blog. Note this requires the --pushstate option on elm-live, which is what I’m using for development.

2. I can also click and navigate to /blog/42 by initially loading the home page and clicking a link to it. I.e. it’s the when I start at localhost:8000/blog/42 or [www.example.com/blog/42](http://www.example.com/blog/42) where I run into problems.

Looking at my console, it appears my server (elm-live here) is looking for my static content (index.html and elm.js) inside the ./blog directory in my project. That directory doesn’t exist, and so I get an error.

Anyone have any suggestions or ways to get around this?

Please let me know if anything is not clear and I’d be happy to clarify more, thank you!

Nate

---

<div class="post-metadata">

**Author:** ![joelq](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/joelq/32/445_2.png) [@joelq](https://discourse.elm-lang.org/u/joelq)\
**Post date:** [May 14, 2020, 3:45am UTC](https://discourse.elm-lang.org/t/nested-routes-with-navigation-on-page-load/5775/2 "2020-05-14T03:45:48Z")

</div>

This is a classic problem when trying to serve SPAs. You want the server to route all paths to `index.html` and let the client side app do the actual routing… How you achieve this depends on what server you are using. In general you can google for _“spa routing [your server here]”_. Below are a few examples:

## Production

If you’re using **nginx** to serve your site you could add this following configuration line (taken from [this article](https://www.serverlab.ca/tutorials/linux/web-servers-linux/how-to-configure-nginx-for-angular-and-reactjs/)) to your `nginx.conf`:

```auto
try_files $uri $uri/ /index.html?$args;

```

If you’re deploying your application to a service like [Netlify](https://www.netlify.com/), you’ll need to add a configuration (taken from [their docs](https://docs.netlify.com/routing/redirects/rewrites-proxies/#history-pushstate-and-single-page-apps) to your `_redirects` file that looks like:

```auto
/* /index.html 200

```

## Development

You’ll want to make sure your development server is handling the same. Some local servers do this by default. Looking through the [elm-live docs](https://www.elm-live.com/#pushstate), it looks like the `--pushstate` option you found is designed to deal with exactly this situation. Good find! 🙌

---

<div class="post-metadata">

**Author:** ![nathanbraun](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/nathanbraun/32/3834_2.png) [@nathanbraun](https://discourse.elm-lang.org/u/nathanbraun)\
**Post date:** [May 14, 2020, 3:52am UTC](https://discourse.elm-lang.org/t/nested-routes-with-navigation-on-page-load/5775/3 "2020-05-14T03:52:01Z")

</div>

Thanks, I haven’t actually tried nginx nested routes (/blog/42) yet, hopefully that works.

The issue with elm-live is while `--pushstate` sends

`localhost:8000/blog` to the main index.html as expected. It does NOT send:

`localhost:8000/blog/42` to the main index.html. Instead it sends it to `./blog/index.html`, which doesn’t exist and I get an error.

I’m not married to elm-live though. While live reloading is nice, I’d much rather have this work. Do you (or anyone) know of a development server that can handle nested routes deeper than one level? What do you use?

EDIT: Thinking about this now, I haven’t actually set up both the `/blog` AND `/blog/42` routes at the same time. I just did `/blog`, verified it worked, then modified it to be blog then an int (e.g. `/blog/42` ) which didn’t work. Maybe it would work if I included them both? That is, `/blog/42` would reroute to just `/blog`, which would reroute to the main `index.html`?.

Will test it out, happy to hear other thoughts in the meantime.

---

<div class="post-metadata">

**Author:** ![joelq](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/joelq/32/445_2.png) [@joelq](https://discourse.elm-lang.org/u/joelq)\
**Post date:** [May 14, 2020, 4:05am UTC](https://discourse.elm-lang.org/t/nested-routes-with-navigation-on-page-load/5775/4 "2020-05-14T04:05:07Z")

</div>

Hmmm, I’m not super familiar with elm-live but I’m sure it can handle this situation, that’s the whole purpose of the flag. The docs mention this plays with a `--start-page` flag. I wonder if you have to set that to the root index? Something like `--pushstate --start-page=/index.html` perhaps?

On my own projects, I usually use [Parcel](https://parceljs.org/). You can see how I use it my [elm game jam project](https://github.com/JoelQ/ecosystem). Of particular interest, [this commit](https://github.com/JoelQ/ecosystem/commit/f050bcc02550d22436bdb85166b19590e2f69f79) does all the setup. Unfortunately the project is not an SPA so you can’t see your problem in action. However, I just checked a private app I have that’s an SPA and it has the same setup and doesn’t seem to do anything special. IIRC Parcel supports this out of the box.

---

<div class="post-metadata">

**Author:** ![RyanNHG](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/ryannhg/32/5162_2.png) [@RyanNHG](https://discourse.elm-lang.org/u/RyanNHG)\
**Post date:** [May 14, 2020, 5:52am UTC](https://discourse.elm-lang.org/t/nested-routes-with-navigation-on-page-load/5775/6 "2020-05-14T05:52:21Z")

</div>

Hey @nathanbraun

This is the project structure I use with `elm-live`:

```auto
elm.json
src/
- Main.elm
public/
- index.html
- style.css

```

If you run this command:

```auto
elm-live src/Main.elm -u -d public -- --output=public/dist/app.js

```

The index.html file can access any assets within the public folder. But make sure to use “/style.css” and “/dist/app.js”, instead of “./style.css” or “style.css”.

Using relative paths for assets without the leading slash will cause sub routes to look for files in the wrong place!

Also make sure to call `Elm.Main.init` from either a script tag within index.html or by including another script in the public folder.

As for production, I use netlify and provide a netlify.toml to redirect all requests to public/index.html

Hope this helps!

_Edit:_ Here’s a link with an example in case the explanation was confusing:

> **[ryannhg/elm-spa](https://github.com/ryannhg/elm-spa/tree/a9f0df576b4836eec2418c5e1c03fab919ae8817/cli/projects/new)**
>
> single page apps made easy. Contribute to ryannhg/elm-spa development by creating an account on GitHub.

---

<div class="post-metadata">

**Author:** ![dmy](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/dmy/32/702_2.png) [@dmy](https://discourse.elm-lang.org/u/dmy)\
**Post date:** [May 14, 2020, 6:38am UTC](https://discourse.elm-lang.org/t/nested-routes-with-navigation-on-page-load/5775/7 "2020-05-14T06:38:29Z")

</div>

`elm-live src/Main.elm -u -- --output=elm.js` definitely works whatever the number of path segments in your URL if you have an `./index.html` file.

**You most likely forgot the slash before `elm.js`** in `<script src="/elm.js"></script>` in your `index.html`.

If you use `<script src="elm.js"></script>` instead without the slash, it will try to load the javascript file relatively to the current directory, which is `./blog/` when loading `localhost:8000/blog/42`, therefore trying to load `./blog/elm.js`. This is the expected behavior with any server.

---

<div class="post-metadata">

**Author:** ![nathanbraun](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/nathanbraun/32/3834_2.png) [@nathanbraun](https://discourse.elm-lang.org/u/nathanbraun)\
**Post date:** [May 14, 2020, 1:01pm UTC](https://discourse.elm-lang.org/t/nested-routes-with-navigation-on-page-load/5775/8 "2020-05-14T13:01:17Z")

</div>

Thank you @dmy and @RyanNHG, changing it to `/elm.js` worked. And appreciate the example Ryan. Thanks all for all the help!

---

<div class="post-metadata">

**Author:** ![razze](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/razze/32/1650_2.png) [@razze](https://discourse.elm-lang.org/u/razze)\
**Post date:** [May 14, 2020, 5:19pm UTC](https://discourse.elm-lang.org/t/nested-routes-with-navigation-on-page-load/5775/9 "2020-05-14T17:19:20Z")

</div>

Reminder, that naming your bundle `elm.js` will confuse windows in some circumstances. Be save and use something else, that doesn’t shadow an executable. (`elm` in this case)

---

<div class="post-metadata">

**Author:** ![system](https://canada1.discourse-cdn.com/flex035/uploads/elm_lang/original/1X/50a05e53677a2c3b47776d7abd0f113eb50193a1.png) [@system](https://discourse.elm-lang.org/u/system)\
**Post date:** [May 24, 2020, 5:19pm UTC](https://discourse.elm-lang.org/t/nested-routes-with-navigation-on-page-load/5775/10 "2020-05-24T17:19:20Z")

</div>

This topic was automatically closed 10 days after the last reply. New replies are no longer allowed.
