I've been poking at Remix as a SSR framework. It appeals because I agree with the philosophy: react focused, leaning into web standards, and with good developer UX.
But, similar to other convention-based frameworks, I quickly ran into a situation where I knew how to write the code but not how to implement it via convention.
The site I'm building with Remix shares a layout between the index and its sub-pages. Essentially the index /
route is the home, and shares its layout with any /subpage
.
Basically:
What Doesn't Work
Naively, I started building out a layout with this file structure:
routes/
└── index.tsx
└── subpage.tsx
But remix considers /subpage
a peer, of /
, even if the url reads like subpage
is a child of /
. And so the subpage route contains none of the shared layout defined in the index file.
So clearly the index.tsx
file is not the right place to put shared layout code. But where?
What Does Work
The remix documentation has two other concepts that compose to solve this problem, layout routes and pathless routes.
Layout Routes
A layout route is a file with the same name as a directory:
routes/
├── app
│ ├── index.tsx # <-- page rendered inside layout
│ └── subpage.tsx # <-- page rendered inside layout
├── app.tsx # <--- the layout file
└── index.tsx
But that alone doesn't solve my problem unless I want the entire app to exist at a nested route /app
(or whatever). I don't.
Pathless Routes
The second concept is the pathless route, which is any folder that starts with __
. This allows you to create nesting in the filesystem that isn't reflected in the url, for example:
routes/
├── app
│ ├── __admin
│ │ ├── admin-login.tsx # <-- renders at /app/admin-login
│ │ └── moderation.tsx # <-- renders at /app/moderation
│ ├── page1.tsx # <-- renders at /app/page1
│ └── page2.tsx # <-- renders at /app/page2
├── app.tsx
└── index.tsx # <-- renders at /
Combining the Two with Index Pages
Frankly, I didn't expect combining pathless and layout routes to work to work with index
pages, as index pages are usually a bit special in that they're usually expect to exist as files not directories. And especially not as directories starting with __
!
But--credit to remix--the rules here compose well with indexes just as well as they do with other pages and routes. Applying the rules above, I ended up with:
routes/
├── __index
│ ├── index.tsx
│ └── subpage.tsx
└── __index.tsx
Which renders exactly like you think it might:
Code
You can checkout code for the example above on Github.
Top comments (10)
Any reason you didn't use
root.tsx
?Simplified example above, but some of the other pages don't share that layout. Putting layout in the root was causing it to show up everywhere. I miss something?
@pckilgore Yes I'm in the same situation now. The login page has its own layout. Thanks for this tutorial!
@ryanflorence thanks for Remix. It's awesome!
@pckilgore Thank you for sharing, your tutorial saves my day, I spent more than an hour with this issue before finding your post.
Thanks @pckilgore. I've been looking for this for hours
It seems like this might not work on the new v2 routing. It keeps saying that you cannot use a path less on index. Do you know if that is the case?
For anyone still struggling with this with the new v2 routing. you CANNOT use
__index.index.tsx
you have to use something other than__index
in the v2 update. So just using something like__landing.index.tsx
would be a good replacement.Saved me a lot of trouble planning my routes, thanks !
For some reason browsing the docs I kept overlooking the part about using
__
before the name of a folder...Hello, I'm looking in the documentation for the part that talks about __ for routing but I can't find it, do you have a link? Thank you for your reply.
remix.run/docs/en/v1/guides/routin...