<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Kais</title>
    <description>The latest articles on DEV Community by Kais (@kais_sraieb).</description>
    <link>https://dev.to/kais_sraieb</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1976482%2Fd4bec8b1-6bd8-465a-a57a-062402d5e5fa.png</url>
      <title>DEV Community: Kais</title>
      <link>https://dev.to/kais_sraieb</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/kais_sraieb"/>
    <language>en</language>
    <item>
      <title>Stop Hardcoding Layouts in Vue — Use Route Meta Like a Pro</title>
      <dc:creator>Kais</dc:creator>
      <pubDate>Sun, 19 Apr 2026 23:32:23 +0000</pubDate>
      <link>https://dev.to/kais_sraieb/stop-hardcoding-layouts-in-vue-use-route-meta-like-a-pro-49on</link>
      <guid>https://dev.to/kais_sraieb/stop-hardcoding-layouts-in-vue-use-route-meta-like-a-pro-49on</guid>
      <description>&lt;p&gt;If you're still switching layouts manually in your Vue app… you're doing it wrong.&lt;/p&gt;

&lt;p&gt;Most people, especially beginners, end up writing messy logic just to handle different layouts like admin vs user. It works… but it scales like garbage.&lt;/p&gt;

&lt;p&gt;Let me show you a cleaner, scalable way.&lt;/p&gt;




&lt;p&gt;The Problem&lt;/p&gt;

&lt;p&gt;You have multiple layouts:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Admin dashboard&lt;/li&gt;
&lt;li&gt;User dashboard&lt;/li&gt;
&lt;li&gt;Public pages&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And you end up doing this:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&lt;br&gt;
&amp;lt;template&amp;gt;&lt;br&gt;
  &amp;lt;AdminLayout v-if="isAdmin"&amp;gt;&lt;br&gt;
    &amp;lt;Dashboard /&amp;gt;&lt;br&gt;
  &amp;lt;/AdminLayout&amp;gt;&lt;br&gt;
  &amp;lt;UserLayout v-else&amp;gt;&lt;br&gt;
    &amp;lt;Dashboard /&amp;gt;&lt;br&gt;
  &amp;lt;/UserLayout&amp;gt;&lt;br&gt;
&amp;lt;/template&amp;gt;&lt;br&gt;
&lt;/code&gt;&lt;br&gt;
This is bad.&lt;/p&gt;

&lt;p&gt;Why?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Logic mixed with UI&lt;/li&gt;
&lt;li&gt;Not reusable&lt;/li&gt;
&lt;li&gt;Becomes a nightmare when app grows&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;The Right Way: Use Route Meta&lt;/p&gt;

&lt;p&gt;Vue Router already gives you everything you need.&lt;/p&gt;

&lt;p&gt;Define layouts directly in your routes:&lt;br&gt;
&lt;code&gt;&lt;br&gt;
const routes = [&lt;br&gt;
  {&lt;br&gt;
    path: "/admin",&lt;br&gt;
    component: () =&amp;gt; import("@/pages/AdminDashboard.vue"),&lt;br&gt;
    meta: { layout: "admin", role: "admin" }&lt;br&gt;
  },&lt;br&gt;
  {&lt;br&gt;
    path: "/",&lt;br&gt;
    component: () =&amp;gt; import("@/pages/Home.vue"),&lt;br&gt;
    meta: { layout: "default" }&lt;br&gt;
  }&lt;br&gt;
];&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Now your routes control:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Which layout to use&lt;/li&gt;
&lt;li&gt;Who can access it&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Clean and centralized.&lt;/p&gt;




&lt;p&gt;Dynamic Layout System&lt;/p&gt;

&lt;p&gt;Create a layout switcher in your main App.vue:&lt;br&gt;
`&lt;/p&gt;

&lt;p&gt;import { useRoute } from "vue-router";&lt;br&gt;
import DefaultLayout from "@/layouts/DefaultLayout.vue";&lt;br&gt;
import AdminLayout from "@/layouts/AdminLayout.vue";&lt;/p&gt;

&lt;p&gt;const route = useRoute();&lt;/p&gt;

&lt;p&gt;const layouts = {&lt;br&gt;
  default: DefaultLayout,&lt;br&gt;
  admin: AdminLayout&lt;br&gt;
};&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&lt;br&gt;
&lt;/code&gt;&lt;br&gt;
&lt;br&gt;
  &lt;br&gt;
    &lt;br&gt;
  &lt;br&gt;
&lt;br&gt;
`&lt;br&gt;
Boom.&lt;/p&gt;

&lt;p&gt;Now layouts change automatically based on the route.&lt;/p&gt;

&lt;p&gt;No more messy conditions.&lt;/p&gt;




&lt;p&gt;Role-Based Access (Bonus)&lt;/p&gt;

&lt;p&gt;You can also protect routes using navigation guards:&lt;br&gt;
`&lt;br&gt;
router.beforeEach((to, from, next) =&amp;gt; {&lt;br&gt;
  const user = getUser(); // your auth logic&lt;/p&gt;

&lt;p&gt;if (to.meta.role &amp;amp;&amp;amp; user.role !== to.meta.role) {&lt;br&gt;
    return next("/unauthorized");&lt;br&gt;
  }&lt;/p&gt;

&lt;p&gt;next();&lt;br&gt;
});&lt;br&gt;
`&lt;br&gt;
Now your app:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Controls UI (layout)&lt;/li&gt;
&lt;li&gt;Controls access (role)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All from the same place.&lt;/p&gt;




&lt;p&gt;Why This Is Better&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Scalable architecture&lt;/li&gt;
&lt;li&gt;Clean separation of concerns&lt;/li&gt;
&lt;li&gt;Easy to extend (add new layouts anytime)&lt;/li&gt;
&lt;li&gt;Works perfectly with large apps&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;Go Further&lt;/p&gt;

&lt;p&gt;If you want to level up:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Lazy load layouts&lt;/li&gt;
&lt;li&gt;Add nested layouts&lt;/li&gt;
&lt;li&gt;Support multiple roles (admin, editor, user)&lt;/li&gt;
&lt;li&gt;Combine with state management (Pinia)&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;Final Thoughts&lt;/p&gt;

&lt;p&gt;Vue doesn’t force you into a structure — but that’s also why many devs build messy apps.&lt;/p&gt;

&lt;p&gt;Using route meta for layouts is one of those small decisions that makes a huge difference when your project grows.&lt;/p&gt;

&lt;p&gt;If you're serious about building clean Vue apps… start doing this now.&lt;/p&gt;

</description>
      <category>architecture</category>
      <category>javascript</category>
      <category>tutorial</category>
      <category>vue</category>
    </item>
  </channel>
</rss>
