Building your application

Routing

Edit this page

Routing serves as a key component to web applications. Within SolidStart, there are two types:

  • UI routes — define the user interface in your app
  • API routes — define the serverless functions in your app

To read more about API routes, see the API Routes section.


Creating new routes

SolidStart uses file based routing which is a way of defining your routes by creating files and folders in your project. This includes your pages and API routes.

SolidStart traverses your routes directory, collects all of the routes, and then makes them accessible using the <FileRoutes />. This component will only include your UI routes, and not your API routes. Rather than manually defining each Route inside a Router component, <FileRoutes /> will generate the routes for you based on the file system.

Because <FileRoutes /> returns a routing config object, you can use it with the router of your choice. In this example we use solid-router:

app.tsx
import { Suspense } from "solid-js";
import { Router } from "@solidjs/router";
import { FileRoutes } from "@solidjs/start/router";
export default function App() {
return (
<Router root={props => <Suspense>{props.children}</Suspense>}>
<FileRoutes />
</Router>
);
}

This will generate a route for each file in the routes directory and its subdirectories.

This means that all you have to do is create a file in your routes folder and SolidStart takes care of everything else needed to make that route available to visit in your application!


File based routing

Each file in the routes directory is treated as a route. To create a new route or page in your application, simply create a new file in the routes directory. The file name will be the URL path for the route:

  • example.com/blog/routes/blog.tsx
  • example.com/contact/routes/contact.tsx
  • example.com/directions/routes/directions.tsx

Nested routes

If you need nested routes, you can create a directory with the name of the preceding route segment, and create new files in that directory:

  • example.com/blog/article-1/routes/blog/article-1.tsx
  • example.com/work/job-1/routes/work/job-1.tsx

When a file is named index, it will be rendered when there are no additional URL route segments being requested for a matching directory:

  • example.com/routes/index.tsx
  • example.com/socials/routes/socials/index.tsx

For a route to be rendered as a page, it should default export a component. This component represents the content that will be rendered when users visit the page:

export default function Index() {
return <div>Welcome to my site!</div>;
}

Renaming Index

By default, the component that is rendered for a route comes from the default export of the index.tsx file in each folder. However, this can make it difficult to find the correct index.tsx file when searching, since there will be multiple files with that name.

To avoid this, you can rename the index.tsx file to the name of the folder it is in and it will be rendered as the default export for that route:

|-- routes/ // example.com
|-- blog/
|-- article-1.tsx // example.com/blog/article-1
|-- article-2.tsx
|-- work/
|-- job-1.tsx // example.com/work/job-1
|-- job-2.tsx
|-- socials/
|-- socials.tsx // example.com/socials

Escaping nested routes

When you have a path that is nested but wish for it to have a separate Layout, you can escape the nested route by applying a name between ( ). This will allow you to create a new route that is not nested under the previous route:

|-- routes/
|-- users/
|-- index.tsx
|-- projects.tsx
|-- users(details)/
|-- [id].tsx

Additionally, you can incorporate nested layouts of their own:

|-- routes/
|-- users.tsx
|-- users(details).tsx
|-- users/
|-- index.tsx
|-- projects.tsx
|-- users(details)/
|-- [id].tsx

Dynamic routes

Dynamic routes are routes that can match any value for one segment of the route. When your URL path contains a dynamic segment, square brackets ([]) are used to define the dynamic segment:

  • example.com/users/:id/routes/users/[id].tsx
  • example.com/users/:id/:name/routes/users/[id]/[name].tsx
  • example.com/*missing/routes/[...missing].tsx

This allows you to create a single route that can match any value for that segment of the URL path. For example, /users/1 and /users/2 are both valid routes and rather than defining separate routes for each user, you can use a dynamic route to match any value for the id segment.

|-- routes/
|-- users/
|-- [id].tsx

For example, using solid-router, you could use the useParams hook to match the dynamic segment:

routes/users/[id].tsx
import { useParams } from "@solidjs/router";
export default function UserPage() {
const params = useParams();
return <div>User {params.id}</div>;
}

Optional parameter

If you have optional parameters in your route, you can use the double square brackets ([[id]]) to define the dynamic segment. This will match any number of segments, including none.

|-- routes/
|-- users/
|-- [[id]].tsx

In this case, some pages that could be matched include:

  • /users
  • /users/1
  • /users/1/2

Catch-all routes

Catch-all routes are a special type of dynamic route that can match any number of segments. They are defined using square brackets with ... before the label for the route (e.g. [...post]).

|-- routes/
|-- blog/
|-- index.tsx
|-- [...post].tsx

The value of the catch-all route will be an array of strings, where each string is a segment of the URL path that matched the catch-all route. For example, with the route [...post], the value of post will be a property on the params object that is returned by the useParams hook. It will be a string with the value of the dynamic segment.

routes/blog/[...post].tsx
import { useParams } from "@solidjs/router";
export default function BlogPage() {
const params = useParams();
return <div>Blog {params.post}</div>;
}

Route groups

Using route groups, you can organize your routes in a way that makes sense for your application, without affecting the URL structure. Since file-based routing is based on the file system, it can be difficult to organize your routes in a way that makes sense for your application.

In SolidStart, route groups are defined by using parenthesis (()) surrounding the folder name:

|-- routes/
|-- (static)
|-- about-us // example.com/about-us
|-- index.tsx
|-- contact-us // example.com/contact-us
|-- index.tsx

Additional route config

SolidStart offers a way to add additional route configuration outside of the file system. Since SolidStart supports the use of other routers, you can use the route export to provided by <FileRoutes /> to define the route configuration for the router of your choice.

import type { RouteSectionProps, RouteDefinition } from "@solidjs/router";
export const route = {
load() {
// define load function
}
} satisfies RouteDefinition
export default function UsersLayout(props: RouteSectionProps) {
return (
<div>
<h1>Users</h1>
{props.children}
</div>
);
}
Report an issue with this page