A modern and customizable calendar package for Vue 3 / Nuxt 3, born from the need to simplify complex scheduling components. This is a community package, not officially maintained by the Nuxt team.

I originally built an admin dashboard for sports coaching sessions, and the calendar component I created manually was quite complex for me to maintain. That's when I decided to create my first Nuxt module to make this reusable and easier to manage. This module is the result of that journey - a clean, modular calendar solution that can be easily integrated into any Nuxt 3 project.
- ✨ Easy imports - Import components and composables directly
- 🎨 Themes - Light, dark and automatic theme support
- 🌍 Internationalization - Complete locale support
- 📱 Responsive - Adapted for mobile and tablets
- ⚡ Performance - Optimized with Vue 3 and Composition API
- 🎯 TypeScript - Complete TypeScript support
- 🔧 Configurable - Flexible configuration options
- 📅 Events - Complete event management
- 🏃♂️ Sports Coaching Ready - Perfect for scheduling sports sessions
- 📊 Admin Dashboard - Built with admin interfaces in mind
A modern, customizable calendar package for Vue 3 / Nuxt 3. Includes typed composables and ready-to-use components, per-component light/dark theming, and reservation helpers (details + add modals).
npm install nuxt-calendar-module
Add the stylesheet once (Nuxt example):
// nuxt.config.ts
export default defineNuxtConfig({
css: ['nuxt-calendar-module/runtime/assets/calendar.css']
})
Or import globally:
// app entry or app.vue
import 'nuxt-calendar-module/runtime/assets/calendar.css'
Render a reservation calendar in minutes.
<template>
<CalendarComponent
:locale="'en-US'"
:timezone="'Europe/Paris'"
:theme="'light'"
:reservations="reservations"
@reservation-click="onReservationClick"
@new-reservation="onNewReservation"
/>
</template>
<script setup lang="ts">
import { ref } from 'vue'
import 'nuxt-calendar-module/runtime/assets/calendar.css'
import CalendarComponent from 'nuxt-calendar-module/runtime/components/CalendarComponent.vue'
const reservations = ref([
{ id: '1', title: 'Client Session', start_date: '2025-08-04T14:00:00+02:00', end_date: '2025-08-04T15:00:00+02:00', duration: 60 }
])
function onReservationClick(reservation: any) {}
function onNewReservation(reservation: any) { reservations.value.push(reservation) }
</script>
Import from nuxt-calendar-module/runtime/components
.
CalendarComponent.vue
: High-level reservation calendar (recommended)Calendar.vue
: Table-based reservation calendarSimpleCalendar.vue
: Monthly events gridBaseCalendar.vue
: Slot-based base calendarReservationModal.vue
: Read-only modal with reservation detailsAddReservationModal.vue
: Form modal (single-day; start/end time; duration auto-computed)
reservations?: Reservation[]
working-hours?: { morning: number[]; afternoon: number[] }
locale?: string
(defaultfr-FR
)timezone?: string
(defaultEurope/Paris
)theme?: 'light' | 'dark' | 'auto'
(scoped, see theming)
reservation-click
(reservation)view-change
(view: 'day' | 'week', date: Date)date-change
(date: Date)new-reservation
(reservation)reservations-updated
(reservations: Reservation[])
Details modal:
<ReservationModal :visible="open" :reservation="current" :locale="'en-US'" @close="open=false" />
Add modal:
<AddReservationModal :visible="addOpen" @close="addOpen=false" @submit="onCreate" />
onCreate
receives { id, title, start_date, end_date, duration, amount?, phone? }
.
Import from nuxt-calendar-module/runtime/composables
.
// Generic calendar
const { currentYear, monthName, selectedDate, calendarDates, goToNextMonth, goToPreviousMonth, addEvent } =
useCalendar({ locale: 'en-US' })
// Reservation calendar
const r = useReservationCalendar({ locale: 'en-US', timezone: 'Europe/Paris' })
r.addReservation({ id: 'r1', title: 'Call', start_date: new Date().toISOString(), end_date: new Date(Date.now()+3600000).toISOString(), duration: 60 })
The calendar theme is scoped to the component root via data-theme
and will not affect the rest of the page.
theme="light"
(default palette)- background: gray-50; borders: gray-950 at 20%; text: gray-950
theme="dark"
(inverse palette)- background: near black; borders: light at 20%; text: gray-50
theme="auto"
follows OS preference
Switch live:
<CalendarComponent :theme="currentTheme" />
export interface Reservation {
id: string | number
title: string
start_date: string
end_date: string
duration: number
amount?: number
phone?: string
}
npm install
npm run build
cd playground && npm run dev
npm run test
Manual:
npm version patch -m "chore(release): v%s"
git push origin main --tags
npm publish --access public
GitHub Actions: push a tag vX.Y.Z
after adding NPM_TOKEN
in repo settings → Secrets → Actions.