SDK & Export API

Vue 3 Integration

Last updated June 4, 2026

Vue 3 Integration

Import the Vue adapter from @rankhiker/sdk/vue (Vue 3 only).

Browser baseUrl note

Vue components run in the browser, so pin the www host to keep the API key header from being dropped across the apex-to-www redirect:

ts
{ apiKey: '...', baseUrl: 'https://rankhiker.com' }

Plugin (app level)

Register once with app.use, passing either a client or a config:

ts
import { createApp } from 'vue';
import { rankHikerPlugin } from '@rankhiker/sdk/vue';
import App from './App.vue';

createApp(App) .use(rankHikerPlugin, { config: { apiKey: import.meta.env.VITE_RANKHIKER_API_KEY, baseUrl: 'https://rankhiker.com', }, }) .mount('#app');

provideRankHiker (component level)

Call inside setup() to provide a client to descendants. Pass a pre-built RankHikerClient or a config object:

ts
import { provideRankHiker } from '@rankhiker/sdk/vue';

provideRankHiker({ apiKey: import.meta.env.VITE_RANKHIKER_API_KEY, baseUrl: 'https://rankhiker.com', });

useRankHikerClient

Returns the provided client. Throws if neither the plugin nor provideRankHiker supplied one above the component.

ts
import { useRankHikerClient } from '@rankhiker/sdk/vue';

const client = useRankHikerClient();

useArticles

Returns reactive refs { data, loading, error, refetch }.

The params argument may be a plain object (treated as static), or a ref, computed, or getter for reactivity. To refetch when a value changes, pass a getter:

ts
import { ref } from 'vue';
import { useArticles } from '@rankhiker/sdk/vue';

const workspaceId = ref('665abc...');

// Getter form: refetches whenever workspaceId changes const { data, loading, error, refetch } = useArticles(() => ({ workspaceId: workspaceId.value, limit: 10, }));

useArticle

Returns reactive refs { data, loading, error }. The slug may be a ref or getter, and the fetch is skipped while the slug is nullish:

ts
import { useArticle } from '@rankhiker/sdk/vue';

const { data, loading, error } = useArticle(() => route.params.slug as string);

BlogList

An unstyled list of articles. Props:

PropTypeNotes
paramsListArticlesParamsFilter params for the API call.
classstringClass on the grid container.
cardClassstringClass on each card.
hrefForPost(post) => stringSlug to URL mapping. Defaults to /blog/{slug}.
Slots: card (scoped, receives { post }), loading, empty, and error (scoped, receives { error }).
vue
<script setup lang="ts">
import { BlogList } from '@rankhiker/sdk/vue';
</script>

<template> <BlogList :params="{ limit: 12 }" class="blog-grid" card-class="blog-card"> <template #card="{ post }"> <a :href="/blog/${post.slug}"> <h3>{{ post.title }}</h3> <p>{{ post.excerpt }}</p> </a> </template> <template #empty> <p>No posts yet.</p> </template> <template #error="{ error }"> <p>{{ error.message }}</p> </template> </BlogList> </template>

BlogPost

Renders a single article by slug. The body HTML is rendered via innerHTML. Props:

PropTypeNotes
slugstringRequired. Article slug.
classstringClass on the article wrapper.
Slots: loading, notFound, error (scoped, { error }), and the default slot (scoped, { post }) to fully take over rendering.
vue
<script setup lang="ts">
import { BlogPost } from '@rankhiker/sdk/vue';

defineProps<{ slug: string }>(); </script>

<template> <BlogPost :slug="slug" class="prose"> <template #notFound> <p>That post does not exist.</p> </template> </BlogPost> </template>

Take over rendering with the default slot:

vue
<BlogPost :slug="slug">
  <template #default="{ post }">
    <article>
      <h1>{{ post.title }}</h1>
      <p>{{ post.wordCount }} words</p>
      <div v-html="post.content" />
    </article>
  </template>
</BlogPost>

A full SFC blog (list and detail)

vue
<script setup lang="ts">
import { ref } from 'vue';
import { provideRankHiker, BlogList, BlogPost } from '@rankhiker/sdk/vue';

provideRankHiker({ apiKey: import.meta.env.VITE_RANKHIKER_API_KEY, baseUrl: 'https://rankhiker.com', });

const slug = ref<string | null>(null); </script>

<template> <BlogPost v-if="slug" :slug="slug"> <template #default="{ post }"> <button @click="slug = null">Back</button> <h1>{{ post.title }}</h1> <div v-html="post.content" /> </template> </BlogPost>

<BlogList v-else :params="{ limit: 12 }"> <template #card="{ post }"> <button @click="slug = post.slug">{{ post.title }}</button> </template> </BlogList> </template>

Was this article helpful?