Docs

App Examples

App Examples Small examples for Enfyra App extensions and external SSR apps. Extension Data Load Rows With useApi <script setup> const { data, execute } = useApi("/post", { query: { fields: "id,title", limit: 10 } }) onMounted(() => execute()) </script> Create Row <script setup>

App Examples

Small examples for Enfyra App extensions and external SSR apps.

Extension Data

Load Rows With useApi

<script setup>
const { data, execute } = useApi("/post", {
  query: { fields: "id,title", limit: 10 }
})

onMounted(() => execute())
</script>

Create Row

<script setup>
const title = ref("")
const toast = useToast()

async function save() {
  await $fetch("/api/post", {
    method: "POST",
    body: { title: title.value }
  })
  toast.add({ title: "Saved" })
}
</script>

Show Current User

<script setup>
const { me, fetchUser } = useAuth()

onMounted(() => fetchUser())
</script>

<template>
  <p>{{ me?.email }}</p>
</template>

Extension Shell

Register Page Header

<script setup>
const { registerPageHeader } = usePageHeaderRegistry()

registerPageHeader({
  title: "Posts",
  description: "Manage content",
  leadingIcon: "",
  variant: "minimal"
})
</script>

Register Header Action

<script setup>
const { register: registerHeaderActions } = useHeaderActionRegistry()

registerHeaderActions({
  id: "refresh-posts",
  label: "Refresh",
  icon: "",
  color: "neutral",
  variant: "soft",
  onClick: () => refresh()
})
</script>

Register Menu And Account Notifications

<script setup>
const unread = ref(0)
const count = computed(() => unread.value > 0 ? String(unread.value) : null)

const { register: registerAccountPanel } = useAccountPanelRegistry()
registerAccountPanel({
  id: "notifications",
  label: "Notifications",
  icon: computed(() => unread.value > 0 ? "" : ""),
  count,
  badgeColor: "error",
  order: 20
})

const { register: registerMenuNotification } = useMenuNotificationRegistry()
watchEffect(() => {
  registerMenuNotification({
    id: "notifications-menu",
    target: { path: "/notifications" },
    value: count.value,
    color: unread.value > 0 ? "error" : "neutral",
    title: "Unread notifications"
  })
})
</script>

Gate A Button By Permission

<template>
  <PermissionGate :condition="{ and: [{ route: '/post', methods: ['POST'] }] }">
    <UButton type="button">Create</UButton>
  </PermissionGate>
</template>

Extension Forms

Use FormEditor

<template>
  <FormEditor
    table-name="post"
    :record="record"
    :includes="['title', 'status']"
  />
</template>

Open A Modal

<template>
  <UButton type="button" @click="open = true">Open</UButton>
  <CommonModal
    v-model:open="open"
    :cancel-action="{ label: 'Close', tone: 'neutral', onClick: () => (open = false) }"
  >
    <template #body>Modal content</template>
  </CommonModal>
</template>

<script setup>
const open = ref(false)
</script>

SSR App Proxy

Nuxt Proxy

export default defineNuxtConfig({
  routeRules: {
    "/enfyra/**": {
      proxy: `${process.env.API_URL}/**`
    }
  }
})

Password Login

await $fetch("/enfyra/login", {
  method: "POST",
  body: { email, password }
})

Fetch Current User

const user = await $fetch("/enfyra/me")

Logout

await $fetch("/enfyra/logout", {
  method: "POST"
})

SSR Realtime

Socket.IO Client

import { io } from "socket.io-client"

const socket = io("/chat", {
  path: "/socket.io",
  withCredentials: true,
  transports: ["polling"],
  upgrade: false
})

Listen For Event

socket.on("chat:message", (payload) => {
  messages.value.push(payload.message)
})

Send Event

socket.emit("chat:message", {
  conversationId,
  text
})