elm-pages 2.0 routing RFC #180
Replies: 4 comments 5 replies
-
For reference, I'll also share an experiment I explored which resulted in a dead end. Url Parser-based routing
page : Page MyCustomRouteType ...
type MyOpaqueRouteType = Thing1 Int | Thing2 String Hardcoding the route there is impossible. You'd have to refer to the type in that module because it's defined in the module itself. So no getting around the circular dependencies in that instance. The original conversation is at https://discord.com/channels/534524278847045633/727578237101932556/830632281869254667. |
Beta Was this translation helpful? Give feedback.
-
👋 Use case:I'd love to clarify my understanding against the existing example on the site - featuring "Sibelius" Right now:You might define:
You'd create
And then in the decoder for the This works well and great, and ALL pages are generated ahead of time. But it falls short - because you would need to definite a This RFC Is shooting for:Let's imagine I had access to an API of composer information, right now, there's now way to wrap that api with pages. So in the world, I might: create Now I don't need to have anthing inside of a Is that right?Assuming I understand properly, a question I have is:
A "feature request"
I ran into this when converting to elm-pages from another framework - which expected the files to be prefixed with the date of posting - ie This is kind of nice for the purposes of both filesystem alphabetization and organization AND compatibility with other frameworks. I think it would be great if elm-pages simply dropped numbers and special characters rather than exploding when hitting them. |
Beta Was this translation helpful? Give feedback.
-
Hey. Based on the Module name and matching routes, will it also provide support to create "root" routes like The use case would be when all content for the application lives in a CMS including page urls, it would be nice to be able to map all content to pages, therefore having support for something like:
I believe this could create a potential conflict in the case of someone creating a |
Beta Was this translation helpful? Give feedback.
-
I feel really good about this design and I'm looking forward for more details regarding the My comment here is almost a nitpick – why use Also – I really like the fact that |
Beta Was this translation helpful? Give feedback.
-
Summary
The current prototype uses a file-based router. Some sources of inspiration:
elm-spa
(and in particular the routing from the upcoming release [permalink])Module identifier limitations in Elm
NextJS uses the following conventions
pages/post/create.js
- Will match /post/createpages/post/[pid].js
- Will match /post/1, /post/abc, etc. But not /post/createpages/post/[...slug].js
- Will match /post/1/2, /post/a/b/c, etc. But not /post/create, /post/abcpages/post/[[...slug]].js
will match /post, /post/a, /post/a/b, and so on.The main difference between catch all and optional catch all routes is that with optional, the route without the parameter is also matched (/post in the example above).
The terms they use for those are:
pid
)A naming convention for
elm-pages
With
elm-pages
, we get nicely typedRouteParams
based on which of these we use. We have to use a different naming convention because Elm modules must start with a capital letter, followed by alphanumeric or_
characters.So these are the rules I'm imagining for
elm-pages
' file-based routing:elm-spa
uses that same convention)_
is a dynamic segment_
's is an optional dynamic segmentREST
(all-uppercase), then it matches a list of the rest parameters (all segments after)Page.Post.Slug_
/post/a
, but not/post
{ slug : String }
Page.Post.Slug__
/post/a
, AND/post
{ slug : Maybe String }
Page.Post.REST_
/post/a/b/c
, but not/post
{ slug : NonEmptyList String }
Page.Post.REST__
/post/a/b/c
AND/post
{ slug : Maybe (NonEmptyList String) }
Route Precedence
Unparameterized Routes will always match first. So between
Page.Post.Slug_
andPage.Post.Create
, the create page has no route params so it will always match andSlug_
will be overshadowed (not match) for that specific path.Similarly, I believe it makes sense for catch all routes to always match after a regular dynamic segment. So for example, for the path
/post/tag/elm
,Page.Post.Tag_.TagName_
would match, andPage.Post.REST_
would be overshadowed (not match).Index routes
In the current 2.0 alpha, the special route name
Index
is treated likeindex.html
is in web page routing.So
Page.Index
is the root route (/
). You can also currently doPage.Post.Index
, which would match/post
.In the latter case, this is redundant (you could simply use the module name
Page.Post
).Another way to approach this would be to use the top-level module name
Page
for this purpose. There is an elegance to this approach. The problem is that I'm currently using the module namePage
for the API for defining a Page Module. For example,This is a nice, simple name. But maybe we could come up with a different name so that we could eliminate the special rules for index routes and instead just use
Page
as the module name for the root route.RouteParam field normalization
If
RouteParams
has a field which cannot be turned directly into a valid Elm field name, it can either be normalized, or the framework could give an error.For example
Page.Post.Type_
Since
type
is a reserved word in Elm, then the field name would have to be modified to be valid:type alias RouteParams = { type_ : String }
Adding an underscore in these cases is sufficient for reserved words. I think it makes sense to just normalize them, since each route parameter should have a unique name so we shouldn't need to worry about collisions.
Leading numbers or special characters will result in an invalid Elm module name, so the Elm compiler will catch that problem before the framework has to deal with it.
Beta Was this translation helpful? Give feedback.
All reactions