Skip to content

Named Routes

Named routes allow you to reference routes by a name rather than their URL pattern. This is particularly useful for generating URLs in your application, especially when routes contain parameters or have complex path structures.

Defining Named Routes

To define a named route, add a name parameter when defining the route:

typescript
import { Router } from 'bun-router'

const router = new Router()

// Define a named route
router.get('/users/{id}', getUserHandler, 'users.show')

In this example, 'users.show' is the name assigned to the route.

Generating URLs for Named Routes

Once you've defined named routes, you can generate URLs for them using the route method:

typescript
// Generate a URL for the 'users.show' route
const url = router.route('users.show', { id: '123' })
// Result: '/users/123'

The second parameter to route is an object containing any parameters needed to build the complete URL.

Benefit of Named Routes

Named routes provide several benefits:

  1. Decouple URL Generation from URL Structure: If you change the URL pattern of a route, all URL generation still works as long as the route name remains the same.

  2. Centralized URL Management: By using named routes, you ensure consistent URL generation throughout your application.

  3. Improved Readability: Route names can make the code more understandable by conveying the purpose of the route.

  4. Less Error-Prone: No need to remember complex URL patterns or worry about properly encoding parameters.

Naming Conventions

It's a good practice to adopt a consistent naming convention for your routes:

  • Use dot notation to indicate hierarchies (e.g., users.show, users.edit)
  • Use noun-based names for resource routes
  • Use verb-action combinations for specific operations

Common naming patterns include:

Route PurposeExample Name
List resourcesusers.index
Show a resourceusers.show
Create formusers.create
Store a resourceusers.store
Edit formusers.edit
Update a resourceusers.update
Delete a resourceusers.destroy

Named Routes with Multiple Parameters

For routes with multiple parameters, provide all necessary parameters when generating the URL:

typescript
router.get('/posts/{postId}/comments/{commentId}', getCommentHandler, 'comments.show')

// Generate URL with multiple parameters
const url = router.route('comments.show', {
  postId: '42',
  commentId: '7'
})
// Result: '/posts/42/comments/7'

Named Routes with Query Parameters

You can also include query parameters when generating URLs:

typescript
// Generate URL with route parameters and query parameters
const url = router.route('users.index', {}, {
  page: '2',
  sort: 'name',
  order: 'asc'
})
// Result: '/users?page=2&sort=name&order=asc'

// With both route parameters and query parameters
const url = router.route('users.posts', { userId: '123' }, { recent: 'true' })
// Result: '/users/123/posts?recent=true'

Named Routes in Route Groups

When using route groups, you can prefix route names for all routes in the group:

typescript
router.group({
  prefix: '/admin',
  as: 'admin.',
}, () => {
  // These routes will be named with the 'admin.' prefix
  router.get('/dashboard', getDashboardHandler, 'dashboard') // Named 'admin.dashboard'
  router.get('/users', getUsersHandler, 'users') // Named 'admin.users'
  router.get('/users/{id}', getUserHandler, 'users.show') // Named 'admin.users.show'
})

// Generate URLs using the prefixed route names
const dashboardUrl = router.route('admin.dashboard') // '/admin/dashboard'
const usersUrl = router.route('admin.users') // '/admin/users'
const userUrl = router.route('admin.users.show', { id: '123' }) // '/admin/users/123'

Absolute URLs

By default, route generates relative URLs. To generate absolute URLs, configure a base URL in your router:

typescript
// During router initialization
const router = new Router({
  baseUrl: 'https://example.com',
})

// Or update it later
router.setBaseUrl('https://example.com')

// Now route() will generate absolute URLs
const url = router.route('users.show', { id: '123' })
// Result: 'https://example.com/users/123'

Practical Example: Blog Application

Here's a more comprehensive example showing how named routes can be used in a blog application:

typescript
import { Router } from 'bun-router'

const router = new Router()

// Public routes
router.get('/', getHomeHandler, 'home')
router.get('/about', getAboutHandler, 'about')
router.get('/contact', getContactHandler, 'contact')

// Blog routes
router.group({
  prefix: '/blog',
  as: 'blog.',
}, () => {
  router.get('/', getBlogIndexHandler, 'index')
  router.get('/{slug}', getBlogPostHandler, 'show')
  router.get('/category/{category}', getCategoryHandler, 'category')
  router.get('/author/{author}', getAuthorHandler, 'author')
})

// Admin routes
router.group({
  prefix: '/admin',
  as: 'admin.',
  middleware: [authMiddleware()],
}, () => {
  router.get('/dashboard', getDashboardHandler, 'dashboard')

  // Admin blog management
  router.group({
    prefix: '/blog',
    as: 'blog.',
  }, () => {
    router.get('/', getAdminBlogIndexHandler, 'index')
    router.get('/create', getCreatePostHandler, 'create')
    router.post('/store', storePostHandler, 'store')
    router.get('/{id}/edit', getEditPostHandler, 'edit')
    router.put('/{id}', updatePostHandler, 'update')
    router.delete('/{id}', deletePostHandler, 'destroy')
  })
})

// Generate URLs in your application
function generateLinks() {
  return {
    home: router.route('home'),
    about: router.route('about'),
    contact: router.route('contact'),
    blog: router.route('blog.index'),
    recentPost: router.route('blog.show', { slug: 'latest-news' }),
    techCategory: router.route('blog.category', { category: 'technology' }),
    adminDashboard: router.route('admin.dashboard'),
    editPost: router.route('admin.blog.edit', { id: '42' }),
  }
}

Using Named Routes in Templates

Named routes are particularly useful when generating links in HTML templates:

typescript
// Controller function
async function getBlogIndexHandler(req) {
  const posts = await fetchPosts()

  const html = `
    <h1>Blog Posts</h1>
    <ul>
      ${posts.map(post => `
        <li>
          <a href="${router.route('blog.show', { slug: post.slug })}">
            ${post.title}
          </a>
          <small>By <a href="${router.route('blog.author', { author: post.author })}">
            ${post.authorName}
          </a></small>
        </li>
      `).join('')}
    </ul>
    <a href="${router.route('home')}">Back to Home</a>
  `

  return new Response(html, {
    headers: { 'Content-Type': 'text/html' }
  })
}

Best Practices

When working with named routes:

  1. Be Consistent: Establish and follow a naming convention for all routes.

  2. Use Hierarchical Names: Use dot notation to represent relationships between routes.

  3. Keep Names Meaningful: Choose names that clearly indicate the route's purpose.

  4. Documentation: Document your route names for team members to reference.

  5. Avoid Collisions: Ensure each route has a unique name to prevent unexpected behavior.

Next Steps

Now that you understand named routes, check out these related topics:

Released under the MIT License.