
Mira el video si prefieres:
Remix nos ofrece varias maneras para administrar las rutas de nuestra aplicación web. Podemos crear segmentos directamente en el nombre del archivo así como definir parámetros directamente. Pero Remix no nos forzará a utilizar solo una manera de crear nuestras rutas y organizar nuestros archivos, pues si estamos mas acostumbrados a emplear carpetas o folders para agrupar nuestros archivos que trabajan junto con nuestras rutas, siempre podemos utilizar el archivo route.tsx
. Pero eso no es todo, en caso de que prefiramos salir por completo de este pattern de emplear archivos para definir rutas y preferimos definirlas todas en un solo lugar como en un archivo JSON o incluso al estilo RubyOnRails, también podremos definirlas directamente en nuestro archivo de configuración de Vite. ⚡️
Pero, si con todo lo anterior aún prefieres una manera personalizada o la clásica de anidar manualmente rutas como lo hacías con react-router-dom
, ¡no hay problema! La comunidad de Remix nos tiene cubiertos con una serie de bibliotecas que nos permitirán personalizar a placer.
Remix prefiere que nosotros mismos, los programadores web, podamos decidir cómo queremos trabajar sin obligarnos a adaptarnos al framework como lo hacen otros muchos; Remix se adaptará a nuestra manera de trabajar. Tal vez por eso, por las muchas opciones a veces resulte difícil comprender sus rutas por completo. 🫂
Por eso en este video te voy a explicar:
- Cómo funcionan las rutas por defecto en la última versión de Remix
- Cómo emplear carpetas para crear tus rutas, como en otros frameworks
- Cómo podemos combinar estos dos patterns para que trabajen juntos
- Cómo usar los layouts y cómo salirse de ellos
También te voy a mostrar código de los ejemplos para que te quede todo bien claro. 🤟🏼
Bueno, ya está, no perdamos el tiempo en tiktok y vamos a dominar las rutas en Remix 😜 🤓
Rutas básicas
No existe la mejor manera de hacerlo, todo depende (casi siempre) del proyecto y su tamaño. Si un proyecto debe crecer mucho y mantener miles de rutas o más, puede que sea mejor organizar con carpetas, pero si el proyecto no será enorme, bueno las flat-routes
vendrán mejor. Remix nos ofrece las flat-routes
como la opción por default.
app/ ├── routes/ │ ├── _index.tsx │ ├── blissmo.tsx │ └── nuevos-cursos.jsx └── root.tsx
Todo comienza con una sola ruta (igual que con react-router-dom
), el archivo root.tsx
es la entrada a todo nuestro árbol de rutas, mismas que serán archivos con terminación jsx
o tsx
y vivirán dentro de la carpeta routes. Todas las rutas que coloquemos ahí responderán a segmentos después de la raíz: /blissmo
o /nuevos-cursos
. ✅
Delimitadores
podemos ponernos creativos con el nombre de nuestras rutas si queremos agregar más segmentos como: /nuevos-cursos/cursos-octubre
, para agregar segmentos nuevos en el nombre pero que a la vez pertenezcan a la misma ruta solo necesitamos agregar un punto en el nombre del archivo:
app/ ├── routes/ │ ├── _index.tsx │ ├── blissmo.tsx │ └── nuevos-cursos.cursos-octubre.jsx └── root.tsx
Así, puedes crear todos los segmentos que necesites. 🎉
Más adelante vamos a hablar también de cómo con el punto podemos anidar rutas independientes: sé paciente. 😉
👀 Seguro notaste a
_index.tsx
, este archivo es especial pues es la ruta por default o home y existe para administrarla el index del archivoroot.tsx
en la misma carpeta routes.
Segmentos dinámicos
Claro que, cuando trabajamos en una aplicación, siempre necesitaremos cargar datos, y para eso regularmente necesitamos saber qué datos, o de quién o de qué cosa. Si es un curso: ¿cuál curso? Si es un usuario: ¿Qué usuario? O si es una lista de cosas ¿Qué modelo de la base de datos enlistaremos? Bueno, para eso son los segmentos dinámicos.
app/ ├── routes/ │ ├── _index.tsx │ ├── blissmo.tsx │ ├── cursos.tsx │ └── cursos.$slug.tsx └── root.tsx
En este ejemplo, podemos ver que existen dos rutas con el segmento cursos en su nombre, pero uno tiene un signo de pesitos: $
esto significa que esta parte del nombre, este segmento es un valor y que querremos usarlo dentro de nuestro código. 🤯
Cuando escribamos dentro de nuestro archivo de ruta nuestro código web, podremos usar este valor $slug directamente en nuestro loader:
export async function loader({ params, }: LoaderFunctionArgs) { return db.cursos.findUnique({ where:{ slug: params.slug } }); }
Tener este poder a la mano simplifica enormemente la adquisición de los datos así como promueve la independencia de nuestras rutas que no necesitan recibir nada especial desde las rutas anteriores ¡así es, no necesitas guardar chingo de datitos desordenados en el localStorage
! Además, así podemos compartir links a nuestra aplicación web con todo y el dato a cargar ¿genial no? 🤩
👀 Estos segmentos dinámicos pueden ser más de uno.
cursos.$slug.$date
y todos vivirán dentro de params en el mismo nivel:params.slug
yparams.date
.
Todavía te voy a explicar cómo funcionan las rutas anidadas y los layouts, pero antes vamos a ver una forma muy popular que Remix también soporta.
Rutas por carpeta
Si vienes de otros frameworks más opinionated, seguro estás acostumbrado(a) a crear un montón de archivos nomás pa echar andar una sola ruta. Aunque para mi este no es mi pattern preferido, no voy a negar que es uno de los más populares y que puede escalar mucho. Por eso Remix también lo soporta. 💿
Las reglas aquí son: definir el nombre del segmento como el nombre de la carpeta y necesitamos un archivo para escribir nuestro código, los loaders, actions y demás, colocaremos un archivo dentro de la carpeta siempre con el nombre de route.tsx
. Esas son las únicas reglas, ahora podemos poner ahí mismo, dentro de la carpeta, cualquier cantidad de archivos que necesitemos, otros componentes o utilidades del backend y/o del front end. ¿Cool ah? 😮
app/ ├── routes/ │ ├── cursos/ │ │ ├── footer.tsx │ │ ├── primary-nav.tsx │ │ └── route.tsx │ ├── cursos.$slug.$date/ │ │ ├── calendar.tsx │ │ ├── route.tsx │ │ └── data-utils.server.ts │ └── blissmo.tsx └── root.tsx
Como puedes darte cuenta a simple, vista: la cantidad de archivos y anidamiento puede ser una carga cognitiva cada que se busca una ruta, pero también, una vez que se encuentra la carpeta de la ruta se puede tener todo en un mismo lugar, esto ayuda con el orden y la velocidad del mantenimiento en grandes proyectos. Pero, lo mejor para mí es que estas dos forma de trabajar no son excluyentes entre sí, es decir que podemos combinar esta forma de trabajar si fuere necesario.
👀 Estas formas diferentes de trabajar obedecen a un mismo intento por resolver un problema conocido como file organization fatigue. Como sabes, los developers JS siempre estamos fatigados 😅
Ahora sí, Rutas anidadas
Bueno, ahora que hemos definido las dos maneras más comunes de trabajar con rutas en Remix, vamos a profundizar un poco en la anidación de estas rutas y sus layouts que es algo que también se llega a prestar a confusión. 🧐
Aquí hay dos palabras que tenemos que entender a profundidad: Anidación (nesting) y disociación o desacoplar (decoupling).
La primera nos recuerda lo que hemos hecho siempre con React Router de poner rutas como children de otras rutas.
<Route path="/cursos"> <Route path="ofertas" /> </Route>
Pero en el caso de Remix, como todo esto será administrado por el servidor, podemos simplemente indicar la anidación con el punto: .
.
app/ ├── routes/ │ ├── _index.tsx │ ├── blissmo.tsx │ ├── cursos._index.tsx │ ├── cursos.$slug.tsx │ ├── cursos.populares.tsx │ └── cursos.tsx └── root.tsx
En este ejemplo, todas las rutas que comienzan con la palabra cursos
terminarán siendo children de app/routes/cursos.tsx
.
Ahora, el renderizado de estas rutas hijas sucederá a través de un componente que Remix nos provee y que se llama <Outlet/>
.
import { Outlet } from "@remix-run/react"; export const Page = ()=>{ return ( <> <h1>Pagina padre</h1> <p>Aquí se renderizarán las páginas hijas:</p> <Outlet /> </> ) }
Puedes imaginar esto de manera más simple como que la ruta padre siempre se renderizará y las rutas hijas cambiarán según coincidan: cursos/react19
, cursos/rust
.
👀 El componente
<Outlet />
soporta un prop llamado context que nos permite compartir cualquier dato necesario desde el padre fácilmente. 🥳
Esto resulta sumamente útil para disociar o desacoplar muchas rutas hijas que compartirán un mismo layout padre, así se vuelve mucho más fácil mantenerlas. ✅
¿Qué pasa si no necesito anidar pero si quiero el nombre en el segmento?
Hay ocaciones en las que se quiere conservar el nombre del segmento como parte de la ruta final, algo así: cursos/react19/promo
, pero no se necesita la anidación pues, por ejemplo: se quiere crear una landing page independiente que se renderice sin la ruta padre. 🫠
Para estos casos Remix tiene una maravillosa solución.
Podemos escapar del anidamiento sin perder el nombre del segmento solo añadiendo un guion bajo al final del nombre del segmento o layout del que queremos escapar.
app/ ├── routes/ │ ├── _index.tsx │ ├── blissmo.tsx │ ├── cursos._index.tsx │ ├── cursos.$slug.tsx │ ├── cursos.populares.tsx │ ├── cursos_.$slug.promo.tsx │ └── cursos.tsx └── root.tsx
Esto nos permitirá hacer match con la ruta cursos/react19/promo
pero ya no estaremos atados al layout de cursos.tsx
. 😳
Entonces, esta página ahora comparte el nombre en la ruta pero tiene como layout a root.tsx
directamente. 🤓 ¿Fácil no?
👀 Remix cargará todos los datos de todas las rutas anidadas en paralelo, lo que optimiza las cargas de nuestra app y evita la carga secuencial típica de un SPA.
¿Y si necesito todo lo contrario, osea compartir el layout pero sin segmentos en la ruta?
En ese caso nos estaríamos refiriendo a las Pathless Routes o rutas sin segmentos. Estas aunque son poco comunes, podemos crearlas con la misma estrategia del guion bajo pero en este caso en vez de al final, al principio:
app/ ├── routes/ │ ├── _profile.payments.tsx │ ├── _profile.basic-profile.tsx │ ├── _profile.tsx │ ├── _index.tsx │ ├── cursos.$slug.tsx │ └── cursos.tsx └── root.tsx
En este caso queremos que las rutas sean /payments
y /basic-profile
pero que las dos compartan el layout que hemos creado en _profile.tsx
. Así evitaremos repetirnos mientras conservamos la independencia de los segmentos. 😍
👀 No olvides agregar tu componente <Outlet /> dentro del JSX de
_profile.tsx
para que todo renderice correcto.
¡Uy! Yo creo que hemos aprendido mucho sobre las rutas de Remix y lo versátiles que son. Espero que esto te haya sido de ayuda si estás migrandote desde otro framework o si tu deseo es sacarle todo el jugo a los patterns más modernos para aplicaciones web. Dejaremos los temas más avanzados para un siguiente video, donde profundizaremos en los segmentos opcionales, los caracteres especiales y las rutas Splat, no olvides suscribirte para no perderte nada.
Abrazo. Bliss. 🤓
Enlaces relacionados

Intro express a Typescript
Checa este otro Post
