# Introducing elm-pages v3 - full-stack Elm and scripts!

**URL:** https://discourse.elm-lang.org/t/introducing-elm-pages-v3-full-stack-elm-and-scripts/9185
**Category:** Show and Tell
**Created:** [June 14, 2023, 8:41pm UTC](https://discourse.elm-lang.org/t/introducing-elm-pages-v3-full-stack-elm-and-scripts/9185 "2023-06-14T20:41:33Z")
**Posts on this page:** 17
**Page:** 1

<div class="post-metadata">

### Author: ![dillonkearns](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/dillonkearns/32/1587_2.png) [@dillonkearns](https://discourse.elm-lang.org/u/dillonkearns)
#### Post date: [June 14, 2023, 8:41pm UTC](https://discourse.elm-lang.org/t/introducing-elm-pages-v3-full-stack-elm-and-scripts/9185/1 "2023-06-14T20:41:34Z")

</div>

Hello folks,

I’m very excited to share a project that I’ve been hard at work on for quite a while now. I hope you find it useful!

`elm-pages` v3 introduces two major new areas that open up a lot of new use cases: server-rendered routes, and scripts. You can read all about it in the announcement post here, and in the latest [Elm package docs](https://package.elm-lang.org/packages/dillonkearns/elm-pages/latest/) and [the v3 docs site](https://elm-pages.com/docs/).

> **[Introducing elm-pages v3](https://elm-pages.com/blog/introducing-v3/)**
>
> While elm-pages v2 was focused on static site generation, elm-pages v3 is a hybrid framework, giving you all the same static site generation features from v2, but with a whole new set of use cases opened up with server-rendered routes.

If you try it out, I’d love to hear from you! Also, feel free to join us in the `#elm-pages` Slack channel to ask questions or share what you build. Happy coding!

---

<div class="post-metadata">

### Author: ![Janiczek](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/janiczek/32/4516_2.png) [@Janiczek](https://discourse.elm-lang.org/u/Janiczek)
#### Post date: [June 15, 2023, 11:56am UTC](https://discourse.elm-lang.org/t/introducing-elm-pages-v3-full-stack-elm-and-scripts/9185/2 "2023-06-15T11:56:54Z")

</div>

Dillon, you have my unending admiration for finishing something so big 🙂

---

<div class="post-metadata">

### Author: ![uweg](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/uweg/32/2541_2.png) [@uweg](https://discourse.elm-lang.org/u/uweg)
#### Post date: [June 15, 2023, 12:36pm UTC](https://discourse.elm-lang.org/t/introducing-elm-pages-v3-full-stack-elm-and-scripts/9185/3 "2023-06-15T12:36:59Z")

</div>

Congratulations!

Out of curiosity: Are you doing this for a company or in your free time? (please feel free to not answer!)

---

<div class="post-metadata">

### Author: ![dillonkearns](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/dillonkearns/32/1587_2.png) [@dillonkearns](https://discourse.elm-lang.org/u/dillonkearns)
#### Post date: [June 15, 2023, 10:12pm UTC](https://discourse.elm-lang.org/t/introducing-elm-pages-v3-full-stack-elm-and-scripts/9185/4 "2023-06-15T22:12:43Z")

</div>

> [@Janiczek](#):
>
> Dillon, you have my unending admiration for finishing something so big 🙂

Thank you Martin! It was a real challenge to get everything to come together in this big release, I’m very relieved to ship it now. It was especially hard because the design of one part depended so much on everything else, so just shipping one small piece could end up with a local optimization in the design that results in a sub-optimal design for the overall framework. In the end, I just worked at it until I had removed all of the asterisks and felt that it was really nice to use. Several times that meant throwing a design away and starting it from scratch even. But I’m very grateful that I got to put in the time to make that happen!

> [@uweg](#):
>
> Out of curiosity: Are you doing this for a company or in your free time? (please feel free to not answer!)

Some amount of funding has come from [my GitHub sponsors](https://github.com/sponsors/dillonkearns/), who I’m really grateful to for their support. The GitHub sponsorship currently covers the amount I pay for monthly fees for hosting and editing Elm Radio episodes, however. A company has also been helping to sponsor my work, which has made a big difference to help support my time on this project, and the rest I’m funding from my own savings.

---

<div class="post-metadata">

### Author: ![kanishka](https://avatars.discourse-cdn.com/v4/letter/k/3e96dc/32.png) [@kanishka](https://discourse.elm-lang.org/u/kanishka)
#### Post date: [June 16, 2023, 3:20pm UTC](https://discourse.elm-lang.org/t/introducing-elm-pages-v3-full-stack-elm-and-scripts/9185/5 "2023-06-16T15:20:04Z")

</div>

This is going to be really cool. One less objection for anybody who says they want next.js features to adopt elm, should that become a demand.

* * *

OT: This triggered me reading again for some liveview alternative implemented in python (personal desire to combine sql\_alchemy with no api approach), which led me back to reactpy…Overall, I wonder if anybody will hesitate about running a node based server for elm-pages-v3 with backendtask, or if people will just embrace prisma et al. It definitely makes sense to start with node for MVP.

---

<div class="post-metadata">

### Author: ![dillonkearns](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/dillonkearns/32/1587_2.png) [@dillonkearns](https://discourse.elm-lang.org/u/dillonkearns)
#### Post date: [June 16, 2023, 4:25pm UTC](https://discourse.elm-lang.org/t/introducing-elm-pages-v3-full-stack-elm-and-scripts/9185/6 "2023-06-16T16:25:26Z")

</div>

> [@kanishka](#):
>
> Overall, I wonder if anybody will hesitate about running a node based server for elm-pages-v3 with backendtask, or if people will just embrace prisma et al. It definitely makes sense to start with node for MVP.

It’s not the MVP, that’s the architecture of elm-pages. At some point it might become less Node-specific and more pluggable with other JS runtimes like Deno, but the JavaScript Backend is a core design decision that’s not going away. Elm compiles down to JS, so a JS-based Backend is a good pairing for running Elm because it needs to execute the compiled Elm code and interop through JS (it’s using ports to communicate even though it builds some abstractions to do that in a more high-level way).

Keep in mind that you can run anything you want from NodeJS, including directly executing low-level C bindings. There are also some frameworks that make it easier to create bindings from NodeJS to Rust, for example. So lots of great options for writing the Custom BackendTask definitions in languages other than JavaScript. You could even compile Python, or an increasing number of backend languages, to WASM, and execute that natively from the Node backend. So the sky’s the limit with what you can interop with.

---

<div class="post-metadata">

### Author: ![Confidenceman02](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/confidenceman02/32/4396_2.png) [@Confidenceman02](https://discourse.elm-lang.org/u/Confidenceman02)
#### Post date: [June 18, 2023, 9:38am UTC](https://discourse.elm-lang.org/t/introducing-elm-pages-v3-full-stack-elm-and-scripts/9185/7 "2023-06-18T09:38:59Z")

</div>

Epic! This looks like it has been a wild amount of work.

I find all the server rendered stuff pretty mind bendy so I didn’t quite grok all of it through the documentation. Might take a few passes.

The `Model` declared in the examples, does this work like any typical model one might find in your standard Elm SPA? So I can provide non serialisable data like functions etc and that will work no problem?

---

<div class="post-metadata">

### Author: ![dillonkearns](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/dillonkearns/32/1587_2.png) [@dillonkearns](https://discourse.elm-lang.org/u/dillonkearns)
#### Post date: [June 18, 2023, 5:05pm UTC](https://discourse.elm-lang.org/t/introducing-elm-pages-v3-full-stack-elm-and-scripts/9185/8 "2023-06-18T17:05:01Z")

</div>

> [@Confidenceman02](#):
>
> I find all the server rendered stuff pretty mind bendy so I didn’t quite grok all of it through the documentation. Might take a few passes.

Yeah, it’s a lot to take in! I have a docs page on “The elm-pages Architecture” (TEPA? 🤔 ). It’s a wrapper around a regular Elm app, so the `init`/`update`/`Model` all works the same way. The `Model` is not serialized, so you can have any data types in there. Only `Data` and `ActionData` are serialized (the additions on top of the standard Elm Architecture).

So in a nutshell, an `elm-pages` app resolves `data` (and `action` if it’s a non-GET request) on the server. That data that was resolved on the Backend is then available when the Elm app hydrates. It’s exactly the same as if you have a regular Elm app with the pattern of passing in some initial data from the server as Flags to your app, just that it’s handled for you under the hood to make it more seamless and type-safe.

> **[The elm-pages Architecture | elm-pages docs](https://elm-pages.com/docs/architecture/)**
>
> Let's look at the lifecycle of a request in an elm-pages app.

I hope that’s helpful! Happy to answer more questions on the architecture, and feedback on how to improve the docs is very welcome.

---

<div class="post-metadata">

### Author: ![Brendan](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/brendan/32/5118_2.png) [@Brendan](https://discourse.elm-lang.org/u/Brendan)
#### Post date: [June 19, 2023, 12:22am UTC](https://discourse.elm-lang.org/t/introducing-elm-pages-v3-full-stack-elm-and-scripts/9185/9 "2023-06-19T00:22:48Z")

</div>

Congratulations Dillon! This is quite an achievement.

For those of us who have shipped a static site using V2, should we be upgrading? What does that upgrade path look like?

Thank you for all your hard work.

---

<div class="post-metadata">

### Author: ![Confidenceman02](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/confidenceman02/32/4396_2.png) [@Confidenceman02](https://discourse.elm-lang.org/u/Confidenceman02)
#### Post date: [June 19, 2023, 5:36am UTC](https://discourse.elm-lang.org/t/introducing-elm-pages-v3-full-stack-elm-and-scripts/9185/10 "2023-06-19T05:36:44Z")

</div>

That is excellent to hear.

I did read that document and where I got lost is that initial html that is sent from the server before hydration.

Is that HTML resolved by parsing the view function, building the HTML page and sending that?

---

<div class="post-metadata">

### Author: ![kanishka](https://avatars.discourse-cdn.com/v4/letter/k/3e96dc/32.png) [@kanishka](https://discourse.elm-lang.org/u/kanishka)
#### Post date: [June 20, 2023, 2:42pm UTC](https://discourse.elm-lang.org/t/introducing-elm-pages-v3-full-stack-elm-and-scripts/9185/11 "2023-06-20T14:42:03Z")

</div>

I don’t know v3 well, but I remember spending a while trying to really understand what happened under the hood of nextjs. IIRC, this section of react-static’s (react-static is a minimalist alternative to next) docs helped me understand a little better at that time - [GitHub - react-static/react-static: ⚛️ 🚀 A progressive static site generator for React.](https://github.com/react-static/react-static#how-does-it-work).

---

<div class="post-metadata">

### Author: ![dillonkearns](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/dillonkearns/32/1587_2.png) [@dillonkearns](https://discourse.elm-lang.org/u/dillonkearns)
#### Post date: [June 20, 2023, 5:09pm UTC](https://discourse.elm-lang.org/t/introducing-elm-pages-v3-full-stack-elm-and-scripts/9185/12 "2023-06-20T17:09:29Z")

</div>

> [@Brendan](#):
>
> For those of us who have shipped a static site using V2, should we be upgrading? What does that upgrade path look like?

Yes, I would definitely recommend upgrading to v3 for static sites as well! You’ll get to use Vite for your non-Elm assets (including in the dev server), and you’ll get the benefit of automatic serialization (no `OptimizedDecoder`s, and a more efficient binary format). Lots of other small improvements, and in general being on the latest version will be better for future updates.

For upgrading, I would recommend these steps:

- Use the `elm-pages init` command (or [`elm-pages-starter` repo](https://github.com/dillonkearns/elm-pages-starter)) to get the shell for a v3 app
- Copy any configuration over to the v3 shell and get the basic boilerplate working with no errors with your baseline configuration for your app ported over
- Modify the `script/src/AddRoute.elm` Script according to your conventions of your app (set it up to use the view library you use, like `elm-css`, etc., and if your site is all static routes then have it use [`Scaffold.Route.preRender`](https://package.elm-lang.org/packages/dillonkearns/elm-pages/latest/Scaffold-Route#preRender) instead of `serverRender`)
- Use `npx elm-pages run AddRoute <Module.Name>` to add each route, and make sure that your routing works the same as your v2 app
- Port your Route Modules’ `data` functions over one-by-one from your v2 code and get them compiling. If you have any non-serializable types (functions, or HTML), then those will need to be massaged into serializable types and then transformed into HTML or functions as needed from your `view` instead. You’ll also change `OptimizedDecoder` into a regular `Json.Decode.Decoder`, and rename `DataSource` to `BackendTask`, and add some `BackendTask.allowFatal` to migrate to the new `BackendTask` design.
- Finally, copy your `view`, `init`, etc. into each of those routes.

You could rearrange and tweak those steps, but hopefully that gives you a sense of what’s involved and how to tackle the upgrade. Feel free to share feedback on those steps if you find anything that’s missing or could be improved. Hope that’s helpful, and hope you enjoy v3!

---

<div class="post-metadata">

### Author: ![dillonkearns](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/dillonkearns/32/1587_2.png) [@dillonkearns](https://discourse.elm-lang.org/u/dillonkearns)
#### Post date: [June 20, 2023, 5:47pm UTC](https://discourse.elm-lang.org/t/introducing-elm-pages-v3-full-stack-elm-and-scripts/9185/13 "2023-06-20T17:47:45Z")

</div>

> [@Confidenceman02](#):
>
> where I got lost is that initial html that is sent from the server before hydration.
> 
> Is that HTML resolved by parsing the view function, building the HTML page and sending that?

Yes, what happens is that `elm-pages` takes the Route Modules that you define and it compiles two versions of your app. One that runs on the Backend (that will execute during your build step, or on the server for server-rendered Routes), and one that runs on the Frontend.

## Backend app

- Resolves `data` for the given URL (uses ports under the hood to communicate with NodeJS as needed to read files, etc.)
- Takes the resolved Route Module’s `Data` and calls the Route Module’s `init`. Throws away the `Effect`, it only needs the `Model`
- Calls the Route Module’s `view` function with the `Model` from `init` and the resolved `Data`
- Turns the return value of the Route Module’s `view` into the final HTML to be rendered using the `Shared.view` function, and adding the surrounding HTML for an `elm-pages` skeleton (`<script>` tags, `<style>` tags, etc.). It also includes a base64 encoded version of the binary encoded version of the Route Module’s `Data`.

## Frontend app

- The initial paint of the page is from the HTML (no JS/Elm) that was rendered out on the server as described above
- After the initial paint is all done, `elm-pages` passes in this serialized `data` in as an Elm Flag, then renders the Route Module for the given URL. This time, `init` is called and the `Effect` is not thrown away but is actually performed. However, `data` is not performed (it is only ever performed in the Backend, as the name `BackendTask` implies). `data` is already available through the Flags that `elm-pages` managed under the hood for us.
- Any subsequent page navigations will go and reach out to the Backend to resolve the `Data` for that URL. Since the rendered app is a single-page app (SPA), it does not do a full page load (no HTML is downloaded), instead it only downloads the binary serialized form of the Route Module’s `Data`. If it is a pre-rendered Route Module, then this is just loading a static file from a CDN. If it is a server-rendered route, then the server returns that binary content and resolves it at request-time.

Hope that is helpful! Let me know if there’s anything else that’s fuzzy about it. I would love to help demystify these things in the docs, so questions and pointers about which parts are unclear are very helpful!

---

<div class="post-metadata">

### Author: ![Brendan](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/brendan/32/5118_2.png) [@Brendan](https://discourse.elm-lang.org/u/Brendan)
#### Post date: [June 21, 2023, 2:21pm UTC](https://discourse.elm-lang.org/t/introducing-elm-pages-v3-full-stack-elm-and-scripts/9185/14 "2023-06-21T14:21:09Z")

</div>

That’s helpful, thank you! I’m looking forward to seeing how it has matured.

---

<div class="post-metadata">

### Author: ![kanishka](https://avatars.discourse-cdn.com/v4/letter/k/3e96dc/32.png) [@kanishka](https://discourse.elm-lang.org/u/kanishka)
#### Post date: [June 29, 2023, 7:22am UTC](https://discourse.elm-lang.org/t/introducing-elm-pages-v3-full-stack-elm-and-scripts/9185/15 "2023-06-29T07:22:57Z")

</div>

> So the sky’s the limit with what you can interop with.

What do you think the most popular Custom BackendTask language will be after js/ts? I started glancing at node + rust + wasm, after your prompting. I am guessing I can also find python and go examples.

---

<div class="post-metadata">

### Author: ![dillonkearns](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/dillonkearns/32/1587_2.png) [@dillonkearns](https://discourse.elm-lang.org/u/dillonkearns)
#### Post date: [July 4, 2023, 4:33pm UTC](https://discourse.elm-lang.org/t/introducing-elm-pages-v3-full-stack-elm-and-scripts/9185/16 "2023-07-04T16:33:15Z")

</div>

Node is quite general purpose, so I would frame it more as a tool to get JSON back-and-forth between `BackendTask.Custom.run` (through the Node definitions in `custom-backend-task.ts`) in an `elm-pages` app. However you get that JSON data is up to you.

> [@kanishka](#):
>
> What do you think the most popular Custom BackendTask language will be after js/ts? I

I imagine the vast majority of elm-pages users are using NodeJS, but again whatever you want to run in NodeJS that results in some JSON data will work, so it’s really up to you. I don’t see it as much of an `elm-pages`-specific question, it’s more of a question of nice ways to get JSON data into NodeJS. If you search on that topic you’ll find a lot more resources and tools to help with that, and whatever you come up with there will be an option for your `elm-pages` Custom BackendTask definitions.

---

<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: [July 14, 2023, 4:33pm UTC](https://discourse.elm-lang.org/t/introducing-elm-pages-v3-full-stack-elm-and-scripts/9185/17 "2023-07-14T16:33:26Z")

</div>

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