pindo-sms can be used directly in Vue components or extracted into a reusable composable. This page covers both patterns, plus a Nuxt.js server route example.
Installation
Options API
Instantiate PindoSMS in the data function so each component instance gets its own client, or create it outside the component for a shared instance:
import { PindoSMS } from 'pindo-sms';
export default {
name: 'App',
data() {
return {
pindoSMS: new PindoSMS(import.meta.env.VITE_PINDO_API_TOKEN),
status: '',
};
},
methods: {
async sendMessage() {
this.status = 'Sending...';
try {
await this.pindoSMS.sendSMS({
to: '+250781234567',
text: 'Hello from Vue!',
sender: 'MyApp',
});
this.status = 'SMS sent!';
} catch (error) {
console.error('Failed to send SMS:', error);
this.status = 'Failed to send SMS.';
}
},
},
};
Composition API
With the Composition API, create the client inside setup or at the module level:
App.vue (Composition API)
<script setup lang="ts">
import { ref } from 'vue';
import { PindoSMS, SMSPayload } from 'pindo-sms';
const pindo = new PindoSMS(import.meta.env.VITE_PINDO_API_TOKEN);
const status = ref('');
async function sendMessage() {
status.value = 'Sending...';
const payload: SMSPayload = {
to: '+250781234567',
text: 'Hello from Vue!',
sender: 'MyApp',
};
try {
await pindo.sendSMS(payload);
status.value = 'SMS sent!';
} catch (error) {
console.error('Failed to send SMS:', error);
status.value = 'Failed to send SMS.';
}
}
</script>
<template>
<button @click="sendMessage">Send SMS</button>
<p v-if="status">{{ status }}</p>
</template>
Composable
For larger applications, extract the SMS logic into a composable so multiple components can share it without duplicating code:
import { PindoSMS, SMSPayload } from 'pindo-sms';
const pindo = new PindoSMS(import.meta.env.VITE_PINDO_API_TOKEN);
export function usePindo() {
async function sendSMS(to: string, text: string, sender: string): Promise<any> {
const payload: SMSPayload = { to, text, sender };
return pindo.sendSMS(payload);
}
async function sendBulkSMS(
recipients: { phonenumber: string; name: string }[],
text: string,
sender: string,
): Promise<any> {
return pindo.sendBulkSMS({ recipients, text, sender });
}
return { sendSMS, sendBulkSMS };
}
Import and call usePindo in any component:
components/NotificationButton.vue
<script setup lang="ts">
import { usePindo } from '@/composables/usePindo';
const { sendSMS } = usePindo();
async function notify() {
await sendSMS('+250781234567', 'Your order is ready.', 'MyApp');
}
</script>
<template>
<button @click="notify">Notify customer</button>
</template>
Environment variables
Vite (and therefore Vue CLI projects using Vite) exposes variables prefixed with VITE_ to the client bundle:
VITE_PINDO_API_TOKEN=your_api_token_here
VITE_ variables are embedded in the client-side bundle and visible to anyone who inspects your JavaScript. Use this only for tokens that are acceptable to expose, or proxy SMS requests through a backend.
Nuxt.js server route
In a Nuxt 3 application, handle SMS sending in a server route so the token stays on the server:
Add the token to your environment
PINDO_API_TOKEN=your_api_token_here
Nuxt 3 reads .env automatically. Access server-only variables via useRuntimeConfig() in server routes.Configure runtimeConfig
export default defineNuxtConfig({
runtimeConfig: {
// Server-only — not exposed to the client
pindoApiToken: process.env.PINDO_API_TOKEN,
},
});
Create the server route
server/api/send-sms.post.ts
import { PindoSMS, SMSPayload } from 'pindo-sms';
export default defineEventHandler(async (event) => {
const config = useRuntimeConfig();
const pindo = new PindoSMS(config.pindoApiToken);
const body = await readBody<SMSPayload>(event);
const { to, text, sender } = body;
if (!to || !text || !sender) {
throw createError({ statusCode: 400, message: 'Missing required fields: to, text, sender' });
}
return pindo.sendSMS({ to, text, sender });
});
Call the route from a Vue component
<script setup lang="ts">
const status = ref('');
async function send() {
status.value = 'Sending...';
try {
await $fetch('/api/send-sms', {
method: 'POST',
body: { to: '+250781234567', text: 'Hello from Nuxt!', sender: 'MyApp' },
});
status.value = 'SMS sent!';
} catch {
status.value = 'Failed to send SMS.';
}
}
</script>
<template>
<button @click="send">Send SMS</button>
<p v-if="status">{{ status }}</p>
</template>
The Nuxt runtimeConfig.pindoApiToken field (without public.) is available only in server routes and Nitro handlers. It is never serialized into the client bundle.