-
+
+
+
@@ -9,14 +11,11 @@
diff --git a/src/composables/useStrapi.js b/src/composables/useStrapi.js
new file mode 100644
index 0000000..7ed3f96
--- /dev/null
+++ b/src/composables/useStrapi.js
@@ -0,0 +1,142 @@
+import { inject, ref } from 'vue'
+
+// Base composable to access the Strapi client
+const getStrapiClient = () => {
+ const client = inject('strapi')
+ if (!client)
+ throw new Error(
+ 'Strapi client not initialized. Did you install the plugin?',
+ )
+ return client
+}
+
+// Merge default and user options
+const mergeOptions = (userOptions = {}) => {
+ return { pLevel: '5', ...userOptions }
+}
+
+// Singleton instance for global data
+let globalInstance = null
+
+/**
+ * Use the global singleton data with caching
+ * This composable ensures the global data is only fetched once,
+ * even when called from multiple places
+ * @param {object} options - optional query options
+ */
+export const useStrapiGlobal = async (options = {}) => {
+ // Return existing instance if already fetched
+ if (globalInstance) {
+ return globalInstance
+ }
+
+ // Create new instance
+ const data = ref(null)
+ const loading = ref(true)
+ const error = ref(null)
+ const client = getStrapiClient()
+
+ // Store the instance before making the request
+ globalInstance = { data, loading, error }
+
+ try {
+ const response = await client
+ .single('global')
+ .find(mergeOptions(options))
+ data.value = response.data
+ } catch (err) {
+ error.value = err
+ console.error(err)
+ // Reset instance on error so it can be retried
+ globalInstance = null
+ } finally {
+ loading.value = false
+ }
+
+ return globalInstance
+}
+
+/**
+ * Reset the global singleton cache
+ * Useful for forcing a refetch of global data
+ */
+export const resetStrapiGlobal = () => {
+ globalInstance = null
+}
+
+/**
+ * Use a singleton content type
+ * @param {string} uid - Strapi singleton UID
+ * @param {object} options - optional query options
+ */
+export const useStrapiSingle = async (uid, options = {}) => {
+ const data = ref(null)
+ const loading = ref(true)
+ const error = ref(null)
+ const client = getStrapiClient()
+
+ try {
+ const response = await client.single(uid).find(mergeOptions(options))
+ data.value = response.data
+ } catch (err) {
+ error.value = err
+ console.error(err)
+ } finally {
+ loading.value = false
+ }
+
+ return { data, loading, error }
+}
+
+/**
+ * Use a single entry by ID
+ * @param {string} contentType
+ * @param {number|string} id
+ * @param {object} options - optional query options
+ */
+export const useStrapiOne = async (contentType, id, options = {}) => {
+ const data = ref(null)
+ const loading = ref(true)
+ const error = ref(null)
+ const client = getStrapiClient()
+
+ try {
+ const response = await client
+ .entity(contentType)
+ .findOne({ id, ...mergeOptions(options) })
+ data.value = response.data
+ } catch (err) {
+ error.value = err
+ console.error(err)
+ } finally {
+ loading.value = false
+ }
+
+ return { data, loading, error }
+}
+
+/**
+ * Use a collection of entries
+ * @param {string} contentType
+ * @param {object} options - optional query options
+ */
+export const useStrapiMany = async (contentType, options = {}) => {
+ const data = ref(null)
+ const loading = ref(true)
+ const error = ref(null)
+ const client = getStrapiClient()
+
+ try {
+ const response = await client
+ .entity(contentType)
+ .find(mergeOptions(options))
+ data.value = response.data
+ } catch (err) {
+ error.value = err
+ console.error(err)
+ } finally {
+ loading.value = false
+ }
+
+ return { data, loading, error }
+}
diff --git a/src/composables/useStrapiHead.js b/src/composables/useStrapiHead.js
new file mode 100644
index 0000000..0e40172
--- /dev/null
+++ b/src/composables/useStrapiHead.js
@@ -0,0 +1,24 @@
+import { computed } from 'vue'
+import { useSeoMeta } from '@unhead/vue'
+import { useStrapiGlobal } from '@/composables/useStrapi'
+
+export default (pageSeo) => {
+ const { data: globalData } = useStrapiGlobal()
+
+ const globalSeo = computed(() => globalData?.value?.seo)
+
+ const title = computed(() => {
+ return pageSeo?.title || globalSeo.value?.title || ''
+ })
+ const description = computed(() => {
+ return pageSeo?.description || globalSeo.value?.description || ''
+ })
+ const image = computed(() => {
+ return pageSeo?.image || globalSeo.value?.image
+ })
+
+ useSeoMeta({
+ title: title.value,
+ description: description.value,
+ })
+}
diff --git a/src/libs/strapi.js b/src/libs/strapi.js
deleted file mode 100644
index 27897d5..0000000
--- a/src/libs/strapi.js
+++ /dev/null
@@ -1,109 +0,0 @@
-import { strapi } from '@strapi/client'
-
-export const strapiClient = strapi({
- baseURL: 'https://cms.nicwands.com/api',
- auth: import.meta.env.VITE_STRAPI_API_TOKEN,
-})
-
-/**
- * Enhanced fetch function with preview support
- * @param {string} contentType - The Strapi content type (e.g., 'global', 'articles')
- * @param {object} options - Fetch options including preview settings
- * @param {boolean} options.isPreview - Whether this is a preview request
- * @param {string} options.status - Content status ('draft' or 'published')
- * @param {boolean} options.isSingle - Whether this is a single type or collection
- * @param {object} options.params - Additional query parameters
- * @returns {Promise} Strapi response
- */
-export const fetchWithPreview = async (contentType, options = {}) => {
- const {
- isPreview = false,
- status = 'published',
- isSingle = false,
- params = {},
- ...otherOptions
- } = options
-
- const queryParams = { ...params }
- const headers = {}
-
- // Add status parameter for draft content in preview mode
- if (isPreview && status) {
- queryParams.status = status
- }
-
- // Enable content source maps for Live Preview
- if (isPreview) {
- headers['strapi-encode-source-maps'] = 'true'
- }
-
- // Disable caching for preview requests
- if (isPreview) {
- headers['Cache-Control'] = 'no-cache'
- }
-
- try {
- if (isSingle) {
- const manager = strapiClient.single(contentType)
- return await manager.find(queryParams, { headers, ...otherOptions })
- } else {
- const manager = strapiClient.collection(contentType)
- return await manager.find(queryParams, { headers, ...otherOptions })
- }
- } catch (error) {
- console.error(`Error fetching ${contentType}:`, error)
- throw error
- }
-}
-
-/**
- * Fetch global content with preview support
- */
-export const getGlobal = async (previewOptions = {}) => {
- return await fetchWithPreview('global', {
- isSingle: true,
- ...previewOptions,
- })
-}
-
-/**
- * Fetch a collection item by slug with preview support
- */
-export const getBySlug = async (contentType, slug, previewOptions = {}) => {
- return await fetchWithPreview(contentType, {
- isSingle: false,
- params: {
- filters: { slug: { $eq: slug } },
- populate: '*',
- },
- ...previewOptions,
- })
-}
-
-/**
- * Fetch a single item by document ID (useful for preview)
- */
-export const getByDocumentId = async (
- contentType,
- documentId,
- previewOptions = {},
-) => {
- const { isSingle = false } = previewOptions
-
- if (isSingle) {
- return await fetchWithPreview(contentType, {
- isSingle: true,
- params: { documentId },
- ...previewOptions,
- })
- } else {
- return await fetchWithPreview(contentType, {
- isSingle: false,
- params: {
- filters: { documentId: { $eq: documentId } },
- populate: '*',
- },
- ...previewOptions,
- })
- }
-}
diff --git a/src/main.js b/src/main.js
index ac15ebb..cb3cec0 100644
--- a/src/main.js
+++ b/src/main.js
@@ -1,7 +1,9 @@
import './styles/main.scss'
import App from './App.vue'
import { ViteSSG } from 'vite-ssg/single-page'
+import strapi from './plugins/strapi'
export const createApp = ViteSSG(App, ({ app }) => {
// Plugins
+ app.use(strapi)
})
diff --git a/src/plugins/strapi.js b/src/plugins/strapi.js
new file mode 100644
index 0000000..54388e8
--- /dev/null
+++ b/src/plugins/strapi.js
@@ -0,0 +1,13 @@
+import { strapi } from '@strapi/client'
+
+export default {
+ install: (app) => {
+ const client = strapi({
+ baseURL: 'https://cms.nicwands.com/api',
+ auth: import.meta.env.VITE_STRAPI_API_TOKEN,
+ })
+
+ // Also provide
+ app.provide('strapi', client)
+ },
+}
diff --git a/src/styles/main.scss b/src/styles/main.scss
index acd9de1..d80dbe7 100644
--- a/src/styles/main.scss
+++ b/src/styles/main.scss
@@ -61,14 +61,6 @@ code {
@include code;
}
-/* DL styling */
-dl {
- grid-template-columns: desktop-vw(40px) 1fr;
- display: grid;
- align-items: center;
- padding-top: desktop-vw(8px);
-}
-
#app {
min-height: 100vh;
}