- Issue created by @fago
- 🇺🇸United States glynster
In our example, we used the Drupal Tabs already integrated within Nuxt. For most cases with our development, this setup meets the client’s needs, with the exception of providing a way to return to the backend and log out.
Here is the code we generated:
<script setup lang="ts"> import type { TabsProps } from '~/types' const props = defineProps<TabsProps>() const config = useRuntimeConfig() const siteApi = config.public.api // Function to format local task links const getLocalTaskLinks = () => { return props.tabs.primary.map((tab) => ({ label: tab.label, to: tab.label === 'View' ? tab.url : `${siteApi}${tab.url}`, icon: filterIconByLabel(tab.label), })) } // Custom function to filter icons based on tab labels const filterIconByLabel = (label: string) => { switch (label) { case 'View': return 'i-heroicons-eye' case 'Edit': return 'i-heroicons-pencil' case 'Delete': return 'i-heroicons-trash' case 'Revisions': return 'i-heroicons-document-duplicate' case 'Export': return 'i-heroicons-arrow-up-tray' case 'API': return 'i-heroicons-code-bracket' default: return null } } let links = [] if (props.tabs.primary && props.tabs.primary.length > 0) { links = [ [ { label: 'Drupal CMS', icon: 'i-heroicons-home', to: `${siteApi}/admin/content`, }, ], [...getLocalTaskLinks()], [ { label: 'Log out', icon: 'i-heroicons-arrow-left-start-on-rectangle', to: `${siteApi}/user/logout`, }, ], ] } else { links = [ [ { label: 'Drupal CMS', icon: 'i-heroicons-home', to: `${siteApi}/admin/content`, }, ], [ { label: 'Log out', icon: 'i-heroicons-arrow-left-start-on-rectangle', to: `${siteApi}/user/logout`, }, ], ] } </script> <template> <div class="admin-links md:px-auto sticky top-0 z-20 w-full bg-zinc-200 bg-opacity-70 px-4 px-8 text-black shadow shadow-gray-300 backdrop-blur-md dark:bg-gray-800 dark:text-white dark:shadow-gray-700" > <UHorizontalNavigation :links="links" :ui="{ base: 'text-xs', }" /> </div> </template> <style lang="css"> .admin-links { .truncate { @apply hidden md:block; } } </style>
There are a few key points to note:
- The Drupal Tabs were relative, so we had to force the API environment to recognize the root.
- We added some extra links, as having access to the API is incredibly helpful for debugging and checking things. This has been invaluable.
- We included a link back to Drupal—specifically, for us, this is at admin/content.
- We are also using Nuxt UI, as we've migrated away from Bootstrap in favor of Tailwind.
- On the Drupal side, we added additional routing for the API call:
custom_builder.routing.yml custom.ce_api: path: '/ce-api/node/{node}' defaults: _controller: '\Drupal\custom\Controller\LocalApiController::nodeExtraSettings' _title: 'API' requirements: _permission: 'access content' options: parameters: node: type: 'entity:node'
I believe incorporating this link into the default Lupus setup will be a game-changer for developers.
- 🇦🇹Austria fago Vienna
Thanks for sharing, this seems awesome!
I wonder how we can facilitate creating, sharing and re-using solutions like this.
If we could manage to work-in necessary backend solutions to be available by default or configurable, we could also package the frontend parts up as sort of theme/component you add. So we could have a couple of add-ons like this available for people to install and use depending on preference. Like a collection of themes you use for starting.
What about providing this as a nuxt-layer? What do you think? Would you be interested in re-shaping it to make it re-usable for multiple sites?
I don't think we should depend on nuxt-ui and tailwind by default, they are great, but we should enable people to make their choices. So things like that should better be optional add-ons, which we then can opt to use for new sites, demos etc.
- 🇺🇸United States glynster
I really like this idea! Starting with a basic Nuxt version sounds great, and allowing features to be configurable within nuxt.config adds flexibility for those who want to enable them. Nuxt UI/Tailwind is a solid choice—it stays within the Nuxt ecosystem and provides a strong foundation for development. But as you mentioned, it’s important for devs to pick the tools that best suit their project.
What are your thoughts on collaboration? I assume we could handle most of this on GitHub?
- 🇦🇹Austria fago Vienna
> What are your thoughts on collaboration? I assume we could handle most of this on GitHub?
Yes, agreed. Since Drupal Gitlab makes all code gplv2+ it's not a good choice for frontend stuff atm, anyway Github seems natural for that, so I think it's fine to go with it atm! We could make some github topic like lupus-decoupled-nuxt-layer and link them from the project page / website?
- 🇺🇸United States glynster
@fago, here is what I have generated for a Nuxt layer:
https://github.com/StirStudios/stir_nuxt_base
At the moment, it is suited to our project needs, though it may include more than necessary. Here’s what it does currently:
- Wraps Lupus CE and other checks into a composable.
- Checks for user roles and session, returning an admin editing menu. I didn’t see the need to include the full Drupal admin menu—just the editing tabs.
- Adds a Vite hook so Nuxt dev tools work locally with DDEV.
- Nuxt 4 compatibility.
- Smooth scroll.
- Page transition.
- Turnstile for forms (currently webform, with CSRF token fetching).
- Robots.
- Sitemap (we generated an API on the Drupal end).
- Nuxt UI (as the base for ease of theming).
- Heavily integrated with Paragraphs, as you’ll see.
This is my first time working with layers, and it made sense to start with Nuxt 4 compatibility. The webform is quite flexible, allowing for many options, and basic validation is handled via Nuxt UI and Yup. I’ve also implemented basic theming for user login forms, though there’s less flexibility since we don’t have the same control over theming as we do with webforms.