DayFlow: A Featherweight Calendar That Punches Above Its Weight
If you have ever tried to build a calendar UI from scratch, you know the pain. Between date math, overlapping event layout, drag-and-drop rescheduling, and responsive multi-day rendering, it is one of the most deceptively difficult UI challenges in frontend development. DayFlow exists so you never have to do that again.
@dayflow/core is a lightweight, plugin-driven calendar toolkit that renders Google Calendar and Apple Calendar-style scheduling interfaces. Originally a React-only library, it has since grown into a framework-agnostic engine powered by Preact under the hood, with thin adapters for React, Vue 3, Svelte 5, and Angular. The React adapter lives in @dayflow/react, and together they weigh in at a remarkably compact ~3KB gzipped for the core engine.
What You Get Out of the Box
DayFlow ships with a rich set of calendar views and interactions that cover the vast majority of scheduling use cases:
- Day, Week, and Month views with intelligent event stacking and overlap detection
- Year Canvas for a bird's-eye overview of event distribution across an entire year
- Fixed Week Year View for continuous scrollable long-term planning
- Dark mode support built in
- Virtual scrolling for handling large event datasets without breaking a sweat
- Import/export of .ics files for interoperability with standard calendar formats
- SSR support for Next.js and other server-rendering frameworks
- Full TypeScript type definitions throughout
As of v3.1.0, features like drag-and-drop, keyboard shortcuts, localization, and the sidebar have been extracted into independent plugins, keeping the core lean and letting you install only what you need.
Getting Started
To use DayFlow with React, install the core engine, the React adapter, and Tailwind CSS (which is required for styling):
npm install @dayflow/core @dayflow/react lucide-react
npm install -D tailwindcss @tailwindcss/postcss autoprefixer
Or with yarn:
yarn add @dayflow/core @dayflow/react lucide-react
yarn add -D tailwindcss @tailwindcss/postcss autoprefixer
You will also want the plugins that match your needs:
npm install @dayflow/plugin-drag @dayflow/plugin-keyboard-shortcuts
npm install @dayflow/plugin-localization @dayflow/plugin-sidebar
Your First Calendar in Five Minutes
Rendering a Week View
The core API revolves around two pieces: the useCalendarApp hook for state management and the DayFlowCalendar component for rendering. Here is the simplest useful calendar you can build:
import { useCalendarApp, DayFlowCalendar, createWeekView, createMonthView, createEvent } from '@dayflow/core';
import '@dayflow/core/dist/styles.css';
function ScheduleBoard() {
const events = [
createEvent({
id: 'evt-1',
title: 'Sprint Planning',
start: new Date(2026, 1, 23, 10, 0),
end: new Date(2026, 1, 23, 11, 30),
}),
createEvent({
id: 'evt-2',
title: 'Design Review',
start: new Date(2026, 1, 25, 14, 0),
end: new Date(2026, 1, 25, 15, 0),
}),
];
const calendar = useCalendarApp({
views: [createWeekView(), createMonthView()],
events,
initialDate: new Date(),
defaultView: 'week',
});
return (
<div style={{ height: '90vh' }}>
<DayFlowCalendar calendar={calendar} />
</div>
);
}
export default ScheduleBoard;
The createEvent helper builds properly typed event objects. The useCalendarApp hook accepts an array of view configurations, your initial event data, a starting date, and which view to display first. Wrap DayFlowCalendar in a container with a defined height and you are done.
Switching Between Views
Because you passed both createWeekView() and createMonthView() into the views array, DayFlow automatically renders a view switcher. Users can toggle between week and month layouts without any additional code. Adding the day view is just as simple:
import { createDayView, createWeekView, createMonthView } from '@dayflow/core';
const calendar = useCalendarApp({
views: [createDayView(), createWeekView(), createMonthView()],
events,
initialDate: new Date(),
defaultView: 'week',
});
The Year at a Glance
One of DayFlow's more distinctive features is the Year Canvas view, which shows an entire year of event distribution in a compact visual format. There is also a Fixed Week mode for continuous scrollable planning:
import { createYearView } from '@dayflow/core';
const calendar = useCalendarApp({
views: [
createWeekView(),
createMonthView(),
createYearView({
mode: 'year-canvas',
showTimedEventsInYearView: true,
}),
],
events,
initialDate: new Date(),
defaultView: 'month',
});
Setting mode to 'fixed-week' switches to the continuous grid layout, which is particularly useful for project planning and resource allocation scenarios.
Taking It Further
Adding Drag-and-Drop
Since v3.1.0, drag-and-drop lives in its own plugin. Install @dayflow/plugin-drag and register it in your calendar configuration:
import { useCalendarApp, DayFlowCalendar, createWeekView, createEvent } from '@dayflow/core';
import { createDragPlugin } from '@dayflow/plugin-drag';
import '@dayflow/core/dist/styles.css';
function InteractiveCalendar() {
const dragPlugin = createDragPlugin();
const calendar = useCalendarApp({
views: [createWeekView()],
plugins: [dragPlugin],
events: [
createEvent({
id: 'meeting-1',
title: 'Team Standup',
start: new Date(2026, 1, 23, 9, 0),
end: new Date(2026, 1, 23, 9, 30),
}),
],
initialDate: new Date(),
defaultView: 'week',
});
return (
<div style={{ height: '90vh' }}>
<DayFlowCalendar calendar={calendar} />
</div>
);
}
With the drag plugin active, users can move events between time slots and days, resize events by dragging their edges, and create new events by clicking and dragging on empty time slots. The plugin provides real-time visual feedback during all interactions.
Keyboard Navigation and Localization
The plugin architecture extends to keyboard shortcuts and multi-language support. Stack as many plugins as you need:
import { createDragPlugin } from '@dayflow/plugin-drag';
import { createKeyboardShortcutsPlugin } from '@dayflow/plugin-keyboard-shortcuts';
import { createLocalizationPlugin } from '@dayflow/plugin-localization';
const calendar = useCalendarApp({
views: [createWeekView(), createMonthView()],
plugins: [
createDragPlugin(),
createKeyboardShortcutsPlugin(),
createLocalizationPlugin({ locale: 'ja' }),
],
events: myEvents,
initialDate: new Date(),
defaultView: 'week',
});
The localization plugin currently supports English, Japanese, Chinese, German, French, Spanish, and Korean. Each plugin receives the calendar instance during installation and can hook into lifecycle events, modify behavior, and add new functionality without bloating the core.
Listening for Visible Range Changes
When building integrations that fetch events from a backend, you will want to know when the visible date range changes so you can load the right data. The onVisibleRangeChange callback handles this:
const calendar = useCalendarApp({
views: [createWeekView(), createMonthView()],
events: [],
initialDate: new Date(),
defaultView: 'week',
onVisibleRangeChange: (range, reason) => {
console.log(`Range changed to ${range.start} - ${range.end}`);
console.log(`Reason: ${reason}`); // 'scroll' or 'navigation'
fetchEventsForRange(range.start, range.end);
},
});
The reason parameter tells you whether the change was triggered by scrolling or by explicit navigation (clicking next/previous), which can be useful for debouncing or loading strategies.
A Note on the CSS Layer Gotcha
If your application already uses Tailwind CSS with a custom theme, be aware that DayFlow's CSS bundle ships its own copy of Tailwind along with theme variables defined outside of CSS @layer declarations. This can cause DayFlow's theme to override your own. The recommended workaround is to wrap the import in a CSS layer:
@import url("@dayflow/core/dist/styles.css") layer(dayflow);
@import 'tailwindcss';
This ensures the cascade resolves in your favor while still giving DayFlow the styles it needs.
Conclusion
DayFlow is one of those libraries that makes you wonder why calendar components ever had to be so heavy. Its ~3KB gzipped core, plugin-driven architecture, and framework-agnostic design make it a compelling choice for teams that want Google Calendar-level interactivity without the bundle weight that usually comes with it. The Year Canvas view and virtual scrolling are genuine differentiators that set it apart from more established alternatives.
The library is still young and evolving fast, so expect the API to shift as it matures. But if you are starting a new project that needs scheduling UI and you value modularity and performance, DayFlow is well worth a look. Install the core, pick your plugins, and let the events flow.