npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

ical-browser

v0.2.2

Published

A library for generating iCalendar (ICS) files in Node.js and the browser, supporting events, todos, journals, alarms, and timezones.

Downloads

1,440

Readme

ical-browser

ical-browser is a lightweight TypeScript iCalendar writer for apps that need a simple "Add to calendar" or "Download invite" button.

https://codepen.io/qertis/full/RweggQJ

Features

  • Works in the browser and Node.js
  • TypeScript-first API
  • Generates .ics calendar text
  • Browser File helper for downloads
  • Supports common iCalendar components
  • Supports text escaping and line folding where implemented
  • Lightweight writer-only design

Installation

npm install ical-browser

Quick start: Add to calendar button

import ICalendar, { VEvent } from 'ical-browser'

const calendar = new ICalendar()
calendar.addEvent(new VEvent({
  uid: '[email protected]',
  summary: 'Project meeting',
  description: 'Weekly project sync',
  start: new Date('2026-07-01T10:00:00Z'),
  end: new Date('2026-07-01T11:00:00Z'),
}))

const file = calendar.download('project-meeting.ics')
const url = URL.createObjectURL(file)
const link = document.createElement('a')
link.href = url
link.download = file.name
link.click()
URL.revokeObjectURL(url)

download(...) creates a text/calendar .ics File. In the browser, use it with URL.createObjectURL(...) to trigger a download.

Browser usage

import ICalendar, { VEvent } from 'ical-browser'

function downloadInvite() {
  const calendar = new ICalendar()
  calendar.addEvent(new VEvent({
    uid: '[email protected]',
    summary: 'Product demo',
    description: 'Live product walkthrough',
    start: new Date('2026-07-01T15:00:00Z'),
    end: new Date('2026-07-01T16:00:00Z'),
  }))

  const file = calendar.download('product-demo.ics')
  const url = URL.createObjectURL(file)
  const link = document.createElement('a')
  link.href = url
  link.download = file.name
  link.click()
  URL.revokeObjectURL(url)
}

Node.js usage

import { writeFileSync } from 'node:fs'
import ICalendar, { VEvent } from 'ical-browser'

const calendar = new ICalendar()
calendar.addEvent(new VEvent({
  uid: '[email protected]',
  summary: 'Node.js generated event',
  start: new Date('2026-07-01T10:00:00Z'),
  end: new Date('2026-07-01T11:00:00Z'),
}))

writeFileSync('calendar.ics', calendar.ics)

In Node.js, use calendar.ics and write the string to a file or HTTP response.

Supported components

| Component | Class | Status | Notes | |---|---|---:|---| | VCALENDAR | ICalendar | Supported | Root calendar component | | VEVENT | VEvent | Supported | Calendar events | | VTODO | VTodo | Supported | Todo items | | VJOURNAL | VJournal | Supported | Journal entries | | VTIMEZONE | VTimezone | Supported | Timezone definitions with standard/daylight blocks | | VALARM | VAlarm | Supported | Nested alarms for events and todos | | VFREEBUSY | VFreeBusy | Supported | Serializes known free/busy periods | | VAVAILABILITY | VAvailability, VAvailable | Supported | Serializes availability blocks |

Examples

Event

import ICalendar, { VEvent } from 'ical-browser'

const calendar = new ICalendar()
const event = new VEvent({
  uid: '[email protected]',
  summary: 'Team meeting',
  description: 'Discuss project status',
  start: new Date('2026-07-01T10:00:00Z'),
  end: new Date('2026-07-01T11:00:00Z'),
})

calendar.addEvent(event)

Todo

import ICalendar, { VTodo } from 'ical-browser'

const calendar = new ICalendar()
const todo = new VTodo({
  uid: '[email protected]',
  summary: 'Prepare report',
  description: 'Prepare monthly report',
  due: new Date('2026-07-01T09:00:00Z'),
})

calendar.addTodo(todo)

Journal

import ICalendar, { VJournal } from 'ical-browser'

const calendar = new ICalendar()
const journal = new VJournal({
  uid: '[email protected]',
  summary: 'Daily note',
  description: 'Project notes',
  start: new Date('2026-07-01T09:00:00Z'),
})

calendar.addJournal(journal)

Timezone

import ICalendar, { VTimezone } from 'ical-browser'

const calendar = new ICalendar()
const timezone = new VTimezone({ tzid: 'Europe/Berlin' })

timezone.addStandard({
  start: new Date('2026-10-25T03:00:00Z'),
  tzOffsetFrom: '+0200',
  tzOffsetTo: '+0100',
  tzname: 'CET',
})
timezone.addDaylight({
  start: new Date('2026-03-29T02:00:00Z'),
  tzOffsetFrom: '+0100',
  tzOffsetTo: '+0200',
  tzname: 'CEST',
})

calendar.addTimezone(timezone)

Use startTz and endTz on events when you want TZID date-time properties:

const event = new VEvent({
  uid: '[email protected]',
  summary: 'Berlin meeting',
  start: new Date('2026-07-01T10:00:00Z'),
  startTz: 'Europe/Berlin',
  end: new Date('2026-07-01T11:00:00Z'),
  endTz: 'Europe/Berlin',
})

Alarm

import { VAlarm, VEvent } from 'ical-browser'

const event = new VEvent({
  uid: '[email protected]',
  summary: 'Meeting',
  start: new Date('2026-07-01T10:00:00Z'),
  end: new Date('2026-07-01T11:00:00Z'),
})

event.addAlarm(new VAlarm({
  action: 'DISPLAY',
  trigger: '-PT15M',
  description: 'Meeting starts in 15 minutes',
}))

VALARM is serialized inside components that support alarms. It is not a top-level VCALENDAR component. Events and todos support addAlarm(...).

Supported alarm actions are DISPLAY, AUDIO, and EMAIL. DURATION and REPEAT must be provided together when an alarm repeats.

Free/busy

import ICalendar, { VFreeBusy } from 'ical-browser'

const calendar = new ICalendar()
const freeBusy = new VFreeBusy({
  uid: '[email protected]',
  organizer: 'mailto:[email protected]',
  freeBusy: [
    {
      start: new Date('2026-07-01T09:00:00Z'),
      end: new Date('2026-07-01T11:00:00Z'),
      type: 'BUSY',
    },
  ],
})

calendar.addFreeBusy(freeBusy)

Availability

import ICalendar, { VAvailability, VAvailable } from 'ical-browser'

const calendar = new ICalendar()
const availability = new VAvailability({
  uid: '[email protected]',
  summary: 'Working hours',
  busyType: 'BUSY-UNAVAILABLE',
})

availability.addAvailable(new VAvailable({
  uid: '[email protected]',
  start: new Date('2026-07-06T09:00:00Z'),
  end: new Date('2026-07-06T17:00:00Z'),
  summary: 'Monday working hours',
}))

calendar.addAvailability(availability)

Timezone notes

Use UTC dates when possible.

Timezone handling is one of the most compatibility-sensitive parts of iCalendar. When exporting local times, make sure your calendar includes the required timezone information and test the generated .ics file in target calendar clients.

The event API supports startTz and endTz for TZID parameters. Their IANA timezone definitions are added to the calendar automatically. VTimezone can still be added with addStandard(...) and addDaylight(...) when a custom definition is required.

Compatibility notes

Generated .ics files should be tested in the calendar clients you support, such as Google Calendar, Apple Calendar, Outlook, and Thunderbird.

Calendar clients may interpret advanced iCalendar features differently.

What this library does not do

ical-browser is a writer, not a calendar engine.

It does not:

  • parse .ics files;
  • calculate available time slots;
  • expand recurring events;
  • merge busy intervals;
  • query external calendars;
  • provide CalDAV integration;
  • send emails;
  • execute alarms;
  • show notifications;
  • resolve booking conflicts.

Development

npm install
npm run build
npm test

License

Copyright (c) Denis Baskovsky under the MIT license.