In Vue Router 5 file routing, what does adding src/pages/posts.vue beside a posts/ folder change, and how do you keep a page out of it?
answer
- same name, file and folder
- the file becomes the parent
- children need a RouterView
- a dot instead of a slash
- parentheses leave the URL alone
basics
~20 sA .vue file with the same name as a folder becomes the parent route, and the folder's pages render inside its RouterView. To add /posts/new outside that layout, name the file posts.new.vue; the dot becomes a slash without nesting.
solid answer
~40 sIn Vue Router 5 file-based routing, a `.vue` file beside a folder **of the same name** turns into a parent route: `posts.vue` gets the path `/posts`, and `posts/index.vue` and `posts/[slug].vue` become its children, rendered inside the `<RouterView>` that `posts.vue` must contain. Without `posts.vue` the folder only groups the children under `/posts`, with no shared component. To put a page under the same URL prefix without the layout, use a dot in the file name: `src/pages/posts.new.vue` becomes a separate `/posts/new` route. Folders in parentheses, such as `(admin)/`, group files without adding a URL segment, and a `@name` suffix like `[email protected]` fills a named view.
code
vue · 13 lines<!-- src/pages/posts.vue: the layout for /posts and /posts/:slug -->
<script setup lang="ts">
import PostsSidebar from '@/components/PostsSidebar.vue'
</script>
<template>
<div class="posts-layout">
<PostsSidebar />
<main>
<RouterView />
</main>
</div>
</template>go deeper
Remember the rule: a file with the same name as a folder becomes the parent, and the folder's pages appear inside its RouterView.
Explain the generated records: a parent with children, a component-less parent when the file is missing, and how a dot, a parenthesised group or an @name suffix changes the result.
Show you can spot accidental nesting and missing outlets in review, and choose between a same-name layout, a dot-named sibling and a route group for a real page.
Discuss how the folder tree becomes the UI hierarchy, so a layout change is a file move that every team touching that folder has to agree on.
## Nesting comes from a file beside a folder In Vue Router 5 file-based routing, a **nested route** is a parent route whose component renders a child route inside its own `<RouterView>`. The plugin creates one whenever a `.vue` file sits next to a folder **with the same name**. For a blog that wants a shared posts sidebar, the files are `src/pages/posts.vue`, `src/pages/posts/index.vue` and `src/pages/posts/[slug].vue`, and the plugin generates, in effect: ```ts const routes = [ { path: '/posts', component: () => import('src/pages/posts.vue'), children: [ { path: '', component: () => import('src/pages/posts/index.vue') }, { path: ':slug', component: () => import('src/pages/posts/[slug].vue') }, ], }, ] ``` The parent `posts.vue` is the **layout**: it renders the sidebar once and places a `<RouterView />` where the list or the article goes. How the router fills that outlet and keeps the parent mounted while children change is ordinary nested-view behaviour; the file layout only decides which record is the parent. ## What each arrangement produces | Files in `src/pages` | Result | |---|---| | `posts/index.vue`, `posts/[slug].vue` only | a `/posts` record **without a component**; the children render in the outlet one level up | | plus `posts.vue` | `posts.vue` becomes the parent component; both pages render inside its `<RouterView>` | | plus `posts.new.vue` | a separate top-level `/posts/new` route, **not** inside `posts.vue` | | `(admin)/drafts.vue` | `/drafts`; the group folder adds nothing to the URL | | `[email protected]` beside `index.vue` | one `/` route with a `default` and an `aside` view | ## Escaping the layout with a dot Sometimes a page needs the URL prefix but not the UI. A post editor at `/posts/new` should be full-screen, not squeezed next to the posts sidebar. Putting it at `posts/new.vue` would nest it inside `posts.vue`. Naming it `src/pages/posts.new.vue` instead makes the plugin turn the `.` into a `/` and emit a sibling route at `/posts/new`. This is controlled by `pathParser.dotNesting`, which defaults to `true`. ## Route groups and named views - **Route groups.** A folder whose name is wrapped in parentheses, such as `src/pages/(admin)/`, organises files without changing URLs: `(admin)/drafts.vue` is served at `/drafts`. A page file can also be a group, as in `admin/(dashboard).vue`, which acts as the `index.vue` of `admin`. - **Named views.** Appending `@` and a name to a page, as in `[email protected]`, registers that component as the `aside` view of the same route. A plain `index.vue` is the `default` view, so you never need `[email protected]`. - **Params in folder names.** A layout can sit on a dynamic segment too: `posts/[slug].vue` beside a `posts/[slug]/` folder makes the article page the parent of, say, `posts/[slug]/comments.vue`. ## Names in a nested layout Names follow file paths here too, and the layout and its index page get **different** names, which matters once navigation is typed: - `posts.vue` (the layout) is named `/posts`. - `posts/index.vue` (the list) is named `/posts/`, with a trailing slash, because `index` contributes an empty segment. - `posts/[slug].vue` (the article) is named `/posts/[slug]`. - `posts.new.vue` (the full-screen editor) is named after its file, `/posts.new`, even though its URL is `/posts/new`. A link that should open the list therefore targets `/posts/`, the child, rather than the layout's name. ## Choosing the right tool | Goal | Use | |---|---| | Shared chrome for a group of URLs | a same-name file beside the folder | | Same URL prefix, different chrome | a dot in the file name | | Tidy folders, unchanged URLs | a parenthesised route group | | Two components on one route | `@name` view files | ## Mistakes worth catching in review 1. **The layout has no `<RouterView>`.** The parent renders, the URL changes, and the child pages never appear. The fix is in the layout's template, not in the file names. 2. **A page nested by accident.** Adding `posts/new.vue` when a `posts.vue` exists silently puts the editor inside the posts layout. 3. **Expecting the group name in the URL.** `(admin)/drafts.vue` is `/drafts`, not `/admin/drafts`; use a plain `admin/` folder when the segment belongs in the URL. 4. **Assuming a layout needs registration.** There is nothing to register: the same-name file is the whole convention, and deleting it removes the shared component.
- What happens if you delete posts.vue but keep the posts/ folder?The plugin still emits a `/posts` record with the folder's pages as children, but the record has no component. The children then render in the `<RouterView>` one level up, usually the app's root outlet, so the URLs stay the same and only the shared sidebar disappears.
- How do you give the home page a second view, such as an aside?Add `src/pages/[email protected]` next to `index.vue`. The plugin generates one `/` route whose components are `default` and `aside`, and the app shell renders the second one with a `<RouterView name="aside" />`.
saying these in an interview costs you the question
- A layout must be registered in the router config before children nest in it.
- posts/new.vue stays outside posts.vue as long as it is a separate file.
- (admin)/drafts.vue is served at /admin/drafts.
- Deleting posts.vue breaks the /posts URLs of its children.
- The parent layout renders its children automatically, without a RouterView.