diff --git a/docs/en-gb/_nav.json b/docs/en-gb/_nav.json
index 399b846..c810b93 100644
--- a/docs/en-gb/_nav.json
+++ b/docs/en-gb/_nav.json
@@ -1,4 +1,9 @@
[
+ {
+ "text": "projects",
+ "link": "/projects/",
+ "activeMatch": "/projects/"
+ },
{
"text": "blogs",
"link": "/blogs/",
diff --git a/docs/en-gb/projects/calendar-toolbox/api.md b/docs/en-gb/projects/calendar-toolbox/api.md
new file mode 100644
index 0000000..f1da780
--- /dev/null
+++ b/docs/en-gb/projects/calendar-toolbox/api.md
@@ -0,0 +1,390 @@
+---
+title: Calendar Toolbox API
+---
+
+## Package Overview
+
+The library is organised under the base package `com.onixbyte.calendar` with the following structure:
+
+| Package | Description |
+|--------------------------------------------|--------------------------------------------|
+| `com.onixbyte.calendar` | Root calendar object |
+| `com.onixbyte.calendar.component` | iCalendar components (VEVENT, VTODO, etc.) |
+| `com.onixbyte.calendar.component.property` | Component-level properties |
+| `com.onixbyte.calendar.property` | Calendar-level properties |
+| `com.onixbyte.calendar.parameter` | iCalendar property parameters |
+| `com.onixbyte.calendar.recurrence` | Recurrence rule types |
+| `com.onixbyte.calendar.value` | Value types |
+| `com.onixbyte.calendar.util` | Formatting utilities |
+
+---
+
+## Calendar
+
+The top-level object representing an iCalendar (RFC 5545) VCALENDAR container.
+
+```java
+Calendar calendar = Calendar.builder()
+ .withCalendarScale(...)
+ .withMethod(...)
+ .withProductIdentifier(...)
+ .withVersion(...)
+ .withOwner(...)
+ .withPrimaryCalendar(...)
+ .withPublishedTTL(...)
+ .withCalendarDescription(...)
+ .withCalendarName(...)
+ .withCalendarId(...)
+ .withCustomProperties(...)
+ .withComponents(event, todo, ...)
+ .build();
+
+String icsContent = calendar.formatted();
+```
+
+### Calendar Properties
+
+All calendar-level properties live in `com.onixbyte.calendar.property` and implement `CalendarProperty`.
+
+| Class | iCalendar Property | Description |
+|--------------------------|----------------------|-------------------------------------------|
+| `CalendarScale` | `CALSCALE` | Calendar system (e.g., GREGORIAN) |
+| `Method` | `METHOD` | iCalendar method (e.g., PUBLISH, REQUEST) |
+| `ProductIdentifier` | `PRODID` | Product identifier of the calendar |
+| `Version` | `VERSION` | iCalendar version (e.g., 2.0) |
+| `Owner` | `X-OWNER` | Owner of the calendar |
+| `PrimaryCalendar` | `X-PRIMARY-CALENDAR` | Whether this is a primary calendar |
+| `PublishedTTL` | `X-PUBLISHED-TTL` | Time-to-live for published calendar |
+| `CalendarDescription` | `X-CALENDAR-DESC` | Calendar description |
+| `CalendarName` | `X-CALENDAR-NAME` | Calendar name |
+| `CalendarId` | `X-CALENDAR-ID` | Calendar identifier |
+| `CustomCalendarProperty` | `X-*` | Custom calendar properties |
+
+Custom properties are created using a builder:
+
+```java
+var customProp = CustomCalendarProperty.builder()
+ .withParameters(...)
+ .build("X-MY-PROPERTY", "my-value");
+```
+
+> Note: Custom property names **must** start with `X-`.
+
+---
+
+## Components
+
+Components represent the core entities in an iCalendar object. Each component implements `CalendarComponent` and is rendered between `BEGIN:TYPE` and `END:TYPE` delimiters.
+
+### Event (VEVENT)
+
+Represents a scheduled event.
+
+```java
+Event event = Event.builder()
+ .withDateTimeStamp(dtstamp) // required
+ .withUniqueIdentifier(uid) // required
+ .withDateTimeStart(dtstart)
+ .withDateTimeEnd(dtend) // mutually exclusive with duration
+ .withDuration(duration) // mutually exclusive with dtend
+ .withSummary(summary)
+ .withDescription(description)
+ .withClassification(classification)
+ .withDateTimeCreated(dateTimeCreated)
+ .withGeographicPosition(geoPos)
+ .withLastModified(lastModified)
+ .withLocation(location)
+ .withOrganiser(organiser)
+ .withPriority(priority)
+ .withSequenceNumber(seqNumber)
+ .withStatus(status)
+ .withTimeTransparency(transparency)
+ .withUniformResourceLocator(url)
+ .withRecurrenceId(recurrenceId)
+ .withRecurrenceRule(rrule)
+ .withAttachments(attachments)
+ .withAttendees(attendees)
+ .withCategories(categories)
+ .withComments(comments)
+ .withContacts(contacts)
+ .withExceptionDateTimes(exDates)
+ .withRequestStatuses(statuses)
+ .withRelated(related)
+ .withResources(resources)
+ .withRecurrenceDateTimes(rDates)
+ .build();
+```
+
+### Todo (VTODO)
+
+Represents a to-do item or task.
+
+```java
+Todo todo = Todo.builder()
+ .withDateTimeStamp(dtstamp) // required
+ .withUniqueIdentifier(uid) // required
+ .withSummary(summary)
+ .withDateTimeStart(dtstart)
+ .withDateTimeDue(due) // mutually exclusive with duration
+ .withDuration(duration) // mutually exclusive with due
+ .withDateTimeCompleted(completed)
+ .withPercentComplete(percent)
+ .withClassification(classification)
+ .withDateTimeCreated(created)
+ .withDescription(description)
+ .withGeographicPosition(geoPos)
+ .withLastModified(lastModified)
+ .withLocation(location)
+ .withOrganiser(organiser)
+ .withPriority(priority)
+ .withSequenceNumber(seq)
+ .withStatus(status)
+ .withRecurrenceId(recurId)
+ .withRecurrenceRule(rrule)
+ .withUniformResourceLocator(url)
+ .withAttachments(attachments)
+ .withAttendees(attendees)
+ .withCategories(categories)
+ .withComments(comments)
+ .withContacts(contacts)
+ .withExceptionDateTimes(exDates)
+ .withRequestStatuses(statuses)
+ .withRelatedToList(related)
+ .withResources(resources)
+ .withRecurrenceDateTimes(rDates)
+ .build();
+```
+
+### Journal (VJOURNAL)
+
+Represents a journal entry or diary note.
+
+```java
+Journal journal = Journal.builder()
+ .withDateTimeStamp(dtstamp) // required
+ .withUniqueIdentifier(uid) // required
+ .withSummary(summary)
+ .withClassification(classification)
+ .withDateTimeCreated(created)
+ .withDateTimeStart(dtstart)
+ .withLastModified(lastModified)
+ .withOrganiser(organiser)
+ .withRecurrenceId(recurId)
+ .withSequenceNumber(seq)
+ .withStatus(status)
+ .withUniformResourceLocator(url)
+ .withRecurrenceRule(rrule)
+ .withAttachments(attachments)
+ .withAttendees(attendees)
+ .withCategories(categories)
+ .withComments(comments)
+ .withContacts(contacts)
+ .withDescriptions(descriptions)
+ .withExceptionDateTimes(exDates)
+ .withRelatedToList(related)
+ .withRecurrenceDate(rDates)
+ .withRequestStatuses(statuses)
+ .build();
+```
+
+### FreeBusy (VFREEBUSY)
+
+Represents free/busy time information.
+
+```java
+FreeBusy freeBusy = FreeBusy.builder()
+ .withDateTimeStamp(dtstamp) // required
+ .withUniqueIdentifier(uid) // required
+ .withContact(contact)
+ .withDateTimeStart(dtstart)
+ .withDateTimeEnd(dtend)
+ .withOrganiser(organiser)
+ .withUniformResourceLocator(url)
+ .withAttendees(attendees)
+ .withComments(comments)
+ .withFreeBusyTimes(freeBusyTimes)
+ .withRequestStatuses(statuses)
+ .build();
+```
+
+### TimeZone (VTIMEZONE)
+
+Defines time zone rules including standard and daylight saving time transitions.
+
+```java
+TimeZone timezone = TimeZone.builder()
+ .withTimeZoneIdentifier(tzId)
+ .withLastModified(lastModified)
+ .withTimeZoneUrl(tzUrl)
+ .withTimeZoneProperties(standardProp, daylightProp)
+ .build();
+```
+
+Time zone properties define the actual transition rules:
+
+```java
+TimeZoneProperty standard = TimeZoneProperty.builder()
+ .withDateTimeStart(dtstart)
+ .withTimeZoneOffsetTo(offsetTo)
+ .withTimeZoneOffsetFrom(offsetFrom)
+ .withRecurrenceRule(rrule)
+ .withTimeZoneNames(tzName)
+ .buildStandard(); // or buildDaylight()
+
+TimeZoneProperty daylight = TimeZoneProperty.builder()
+ .withDateTimeStart(dtstart)
+ .withTimeZoneOffsetTo(offsetTo)
+ .withTimeZoneOffsetFrom(offsetFrom)
+ .buildDaylight();
+```
+
+### Alarm (VALARM)
+
+Defines alarm/reminder notifications. Three alarm types are supported:
+
+```java
+// Audio alarm
+Alarm audioAlarm = Alarm.builder()
+ .withTrigger(trigger)
+ .withDuration(duration)
+ .withRepeatCount(repeatCount)
+ .withAttachments(audioAttachment)
+ .buildAudio();
+
+// Display alarm
+Alarm displayAlarm = Alarm.builder()
+ .withTrigger(trigger)
+ .withDescription(description) // required
+ .withDuration(duration)
+ .withRepeatCount(repeatCount)
+ .buildDisplay();
+
+// Email alarm
+Alarm emailAlarm = Alarm.builder()
+ .withTrigger(trigger)
+ .withDescription(description) // required
+ .withSummary(summary) // required
+ .withAttendees(attendees) // required
+ .withDuration(duration)
+ .withRepeatCount(repeatCount)
+ .buildEmail();
+```
+
+---
+
+## Component Properties
+
+Component properties live in `com.onixbyte.calendar.component.property` and implement `ComponentProperty`.
+
+| Class | iCalendar Property | Description |
+|---------------------------|--------------------|----------------------------------------------------------|
+| `Action` | `ACTION` | Alarm action type (AUDIO, DISPLAY, EMAIL) |
+| `Attachment` | `ATTACH` | Document attachment |
+| `Attendee` | `ATTENDEE` | Event/task attendee |
+| `Categories` | `CATEGORIES` | Categories or tags |
+| `Classification` | `CLASS` | Access classification (PUBLIC, PRIVATE, CONFIDENTIAL) |
+| `Comment` | `COMMENT` | Comment |
+| `Contact` | `CONTACT` | Contact information |
+| `DateTimeCompleted` | `COMPLETED` | Completion date-time |
+| `DateTimeCreated` | `CREATED` | Creation date-time |
+| `DateTimeDue` | `DUE` | Due date-time |
+| `DateTimeEnd` | `DTEND` | End date-time |
+| `DateTimeStamp` | `DTSTAMP` | Date-time stamp |
+| `DateTimeStart` | `DTSTART` | Start date-time |
+| `Description` | `DESCRIPTION` | Description |
+| `ExceptionDateTimes` | `EXDATE` | Exception date-times |
+| `FreeBusyTime` | `FREEBUSY` | Free/busy time periods |
+| `GeographicPosition` | `GEO` | Geographic position (lat/long) |
+| `LastModified` | `LAST-MODIFIED` | Last modified date-time |
+| `Location` | `LOCATION` | Location |
+| `Organiser` | `ORGANIZER` | Event organiser |
+| `PercentComplete` | `PERCENT-COMPLETE` | Completion percentage |
+| `Priority` | `PRIORITY` | Priority level |
+| `RecurrenceDateTimes` | `RDATE` | Recurrence date-times |
+| `RecurrenceId` | `RECURRENCE-ID` | Recurrence instance identifier |
+| `RecurrenceRule` | `RRULE` | Recurrence rule |
+| `RelatedTo` | `RELATED-TO` | Related component reference |
+| `RepeatCount` | `REPEAT` | Alarm repeat count |
+| `RequestStatus` | `REQUEST-STATUS` | Request status |
+| `Resources` | `RESOURCES` | Resources |
+| `SequenceNumber` | `SEQUENCE` | Sequence number (revision) |
+| `Status` | `STATUS` | Component status (TENTATIVE, CONFIRMED, CANCELLED, etc.) |
+| `Summary` | `SUMMARY` | Title or summary |
+| `TimeTransparency` | `TRANSP` | Time transparency (OPAQUE, TRANSPARENT) |
+| `TimeZoneIdentifier` | `TZID` | Time zone identifier |
+| `TimeZoneName` | `TZNAME` | Time zone name |
+| `TimeZoneOffsetFrom` | `TZOFFSETFROM` | Time zone offset from UTC |
+| `TimeZoneOffsetTo` | `TZOFFSETTO` | Time zone offset to UTC |
+| `TimeZoneUrl` | `TZURL` | Time zone URL |
+| `Trigger` | `TRIGGER` | Alarm trigger |
+| `UniformResourceLocator` | `URL` | Associated URL |
+| `UniqueIdentifier` | `UID` | Unique identifier |
+| `CustomComponentProperty` | `X-*` | Custom component properties |
+
+---
+
+## Parameters
+
+Parameters in `com.onixbyte.calendar.parameter` provide additional qualifiers on component properties.
+
+| Class | iCalendar Parameter | Description |
+|-------------------------------|---------------------|--------------------------------------------------------|
+| `AlarmTriggerRelationship` | `RELATED` | Trigger relationship (START, END) |
+| `AlternateTextRepresentation` | `ALTREP` | Alternate text URI |
+| `CalendarUserType` | `CUTYPE` | Calendar user type (INDIVIDUAL, GROUP, RESOURCE, etc.) |
+| `CommonName` | `CN` | Common name |
+| `Delegatees` | `DELEGATED-TO` | Delegatees |
+| `Delegators` | `DELEGATED-FROM` | Delegators |
+| `DirectoryEntryReference` | `DIR` | Directory entry URI |
+| `FormatType` | `FMTTYPE` | Format type (MIME type) |
+| `FreeBusyTimeType` | `FBTYPE` | Free/busy time type |
+| `InlineEncoding` | `ENCODING` | Inline encoding (BASE64) |
+| `Language` | `LANGUAGE` | Language |
+| `Membership` | `MEMBER` | Group membership |
+| `ParticipationRole` | `ROLE` | Participation role (CHAIR, REQ-PARTICIPANT, etc.) |
+| `ParticipationStatus` | `PARTSTAT` | Participation status (ACCEPTED, DECLINED, etc.) |
+| `RecurrenceIdentifierRange` | `RANGE` | Recurrence range (THISANDPRIOR, THISANDFUTURE) |
+| `RelationshipType` | `RELTYPE` | Relationship type (PARENT, CHILD, SIBLING) |
+| `RsvpExpectation` | `RSVP` | RSVP expectation (TRUE, FALSE) |
+| `SentBy` | `SENT-BY` | Sent by |
+| `TimeZoneIdentifier` | `TZID` | Time zone identifier |
+| `ValueDataType` | `VALUE` | Value data type (DATE, DATE-TIME, etc.) |
+
+---
+
+## Recurrence Types
+
+Located in `com.onixbyte.calendar.recurrence`.
+
+| Class | Description |
+|--------------|---------------------------------------------------------------------------|
+| `Frequency` | Frequency constants (DAILY, WEEKLY, MONTHLY, YEARLY) for recurrence rules |
+| `WeekdayNum` | Weekday number for recurrence rules (e.g., 2nd Monday) |
+
+---
+
+## Value Types
+
+Located in `com.onixbyte.calendar.value`.
+
+| Class | Description |
+|---------------------|------------------------------------------------|
+| `FreeBusyTimeValue` | Represents free/busy time value |
+| `PeriodOfTime` | Represents a period of time with start and end |
+| `PropertyValue` | Base value type for properties |
+| `UtcOffset` | UTC offset value (e.g., `-05:00`, `+01:00`) |
+
+---
+
+## Formatted Output
+
+All components and properties provide a `formatted()` method that returns an iCalendar-compliant string representation. The `Calendar.formatted()` method produces a complete `.ics` output wrapped in `BEGIN:VCALENDAR`/`END:VCALENDAR`.
+
+```java
+String ics = calendar.formatted();
+// BEGIN:VCALENDAR
+// CALSCALE:GREGORIAN
+// METHOD:PUBLISH
+// ...
+// END:VCALENDAR
+```
diff --git a/docs/en-gb/projects/calendar-toolbox/index.mdx b/docs/en-gb/projects/calendar-toolbox/index.mdx
new file mode 100644
index 0000000..b878f9d
--- /dev/null
+++ b/docs/en-gb/projects/calendar-toolbox/index.mdx
@@ -0,0 +1,109 @@
+---
+title: Calendar Toolbox
+---
+
+import { Tabs, Tab } from "@rspress/core/theme"
+
+## Introduction
+
+Calendar Toolbox is a Java library designed to simplify the creation of `.ics` files, adhering to the iCalendar specification (RFC 5545). This library provides developers with a straightforward API to generate calendar events that can be imported into popular calendar applications such as Microsoft Outlook, Google Calendar, and Apple Calendar.
+
+With Calendar Toolbox, you can effortlessly create, customise, and export calendar event files programmatically, enabling integration of calendar functionalities into your Java applications with minimal effort.
+
+## Features
+
+- **Full RFC 5545 Compliance** — Supports standard iCalendar components including VEVENT, VTODO, VJOURNAL, VFREEBUSY, VTIMEZONE, and VALARM.
+- **Fluent Builder Pattern** — All components and properties use builder pattern for readable and intuitive construction.
+- **Type-Safe Properties** — Strongly typed properties and parameters ensure correctness at compile time.
+- **Custom Extensions** — Support for custom `X-` properties at both calendar and component level.
+- **Lightweight** — Zero external dependencies for core functionality.
+
+## Installation
+
+
+
+ ```groovy title="build.gradle"
+ dependencies {
+ implementation 'com.onixbyte:calendar-toolbox:1.1.0'
+ }
+ ```
+
+
+ ```kotlin title="build.gradle.kts"
+ dependencies {
+ implementation("com.onixbyte:calendar-toolbox:1.1.0")
+ }
+ ```
+
+
+ ```xml title="pom.xml"
+
+
+ com.onixbyte
+ calendar-toolbox
+ 1.1.0
+
+
+ ```
+
+
+
+## Quick Start
+
+```java
+import com.onixbyte.calendar.Calendar;
+import com.onixbyte.calendar.component.Event;
+import com.onixbyte.calendar.component.property.*;
+import com.onixbyte.calendar.property.*;
+
+import java.time.LocalDateTime;
+import java.time.ZoneOffset;
+import java.time.ZonedDateTime;
+
+public class CalendarExample {
+
+ public static void main(String[] args) {
+ // Create required date-time properties
+ var now = ZonedDateTime.now(ZoneOffset.UTC);
+ var dtstamp = DateTimeStamp.of(now);
+ var uid = UniqueIdentifier.of("meeting-001@example.com");
+ var dtstart = DateTimeStart.of(
+ LocalDateTime.of(2025, 8, 15, 9, 0),
+ "America/New_York"
+ );
+ var dtend = DateTimeEnd.of(
+ LocalDateTime.of(2025, 8, 15, 10, 0),
+ "America/New_York"
+ );
+ var summary = Summary.of("Team Standup");
+ var description = Description.of("Daily team standup meeting.");
+
+ // Build the event
+ var event = Event.builder()
+ .withDateTimeStamp(dtstamp)
+ .withUniqueIdentifier(uid)
+ .withDateTimeStart(dtstart)
+ .withDateTimeEnd(dtend)
+ .withSummary(summary)
+ .withDescription(description)
+ .build();
+
+ // Build the calendar and output .ics content
+ var calendar = Calendar.builder()
+ .withCalendarScale(CalendarScale.of("GREGORIAN"))
+ .withMethod(Method.of("PUBLISH"))
+ .withProductIdentifier(ProductIdentifier.of("-//OnixByte//Calendar Toolbox//EN"))
+ .withVersion(Version.of("2.0"))
+ .withComponents(event)
+ .build();
+
+ System.out.println(calendar.formatted());
+ }
+}
+```
+
+This produces an `.ics` string that can be saved to a file or sent via email.
+
+## License
+
+Calendar Toolbox is open-source software released under the MIT License.
diff --git a/docs/en-gb/projects/index.md b/docs/en-gb/projects/index.md
new file mode 100644
index 0000000..32ed832
--- /dev/null
+++ b/docs/en-gb/projects/index.md
@@ -0,0 +1,5 @@
+---
+title: Projects
+---
+
+Explore awesome projects developed by OnixByte.
\ No newline at end of file
diff --git a/docs/zh-hans/_nav.json b/docs/zh-hans/_nav.json
index 399b846..c810b93 100644
--- a/docs/zh-hans/_nav.json
+++ b/docs/zh-hans/_nav.json
@@ -1,4 +1,9 @@
[
+ {
+ "text": "projects",
+ "link": "/projects/",
+ "activeMatch": "/projects/"
+ },
{
"text": "blogs",
"link": "/blogs/",
diff --git a/docs/zh-hans/projects/calendar-toolbox/api.md b/docs/zh-hans/projects/calendar-toolbox/api.md
new file mode 100644
index 0000000..76184d0
--- /dev/null
+++ b/docs/zh-hans/projects/calendar-toolbox/api.md
@@ -0,0 +1,390 @@
+---
+title: Calendar Toolbox API
+---
+
+## 包结构概览
+
+库的代码组织在基础包 `com.onixbyte.calendar` 下,结构如下:
+
+| 包 | 描述 |
+|---|---|
+| `com.onixbyte.calendar` | 根日历对象 |
+| `com.onixbyte.calendar.component` | iCalendar 组件(VEVENT、VTODO 等) |
+| `com.onixbyte.calendar.component.property` | 组件级属性 |
+| `com.onixbyte.calendar.property` | 日历级属性 |
+| `com.onixbyte.calendar.parameter` | iCalendar 属性参数 |
+| `com.onixbyte.calendar.recurrence` | 重复规则类型 |
+| `com.onixbyte.calendar.value` | 值类型 |
+| `com.onixbyte.calendar.util` | 格式化工具类 |
+
+---
+
+## Calendar
+
+表示 iCalendar(RFC 5545)VCALENDAR 容器的顶层对象。
+
+```java
+Calendar calendar = Calendar.builder()
+ .withCalendarScale(...)
+ .withMethod(...)
+ .withProductIdentifier(...)
+ .withVersion(...)
+ .withOwner(...)
+ .withPrimaryCalendar(...)
+ .withPublishedTTL(...)
+ .withCalendarDescription(...)
+ .withCalendarName(...)
+ .withCalendarId(...)
+ .withCustomProperties(...)
+ .withComponents(event, todo, ...)
+ .build();
+
+String icsContent = calendar.formatted();
+```
+
+### 日历属性
+
+所有日历级属性位于 `com.onixbyte.calendar.property`,实现 `CalendarProperty` 接口。
+
+| 类 | iCalendar 属性 | 描述 |
+|---|---|---|
+| `CalendarScale` | `CALSCALE` | 日历系统(例如 GREGORIAN) |
+| `Method` | `METHOD` | iCalendar 方法(例如 PUBLISH、REQUEST) |
+| `ProductIdentifier` | `PRODID` | 日历的产品标识符 |
+| `Version` | `VERSION` | iCalendar 版本(例如 2.0) |
+| `Owner` | `X-OWNER` | 日历所有者 |
+| `PrimaryCalendar` | `X-PRIMARY-CALENDAR` | 是否为主日历 |
+| `PublishedTTL` | `X-PUBLISHED-TTL` | 已发布日历的生存时间 |
+| `CalendarDescription` | `X-CALENDAR-DESC` | 日历描述 |
+| `CalendarName` | `X-CALENDAR-NAME` | 日历名称 |
+| `CalendarId` | `X-CALENDAR-ID` | 日历标识符 |
+| `CustomCalendarProperty` | `X-*` | 自定义日历属性 |
+
+自定义属性使用 Builder 创建:
+
+```java
+var customProp = CustomCalendarProperty.builder()
+ .withParameters(...)
+ .build("X-MY-PROPERTY", "my-value");
+```
+
+> 注意:自定义属性名称**必须**以 `X-` 开头。
+
+---
+
+## 组件
+
+组件是 iCalendar 对象的核心实体。每个组件实现 `CalendarComponent` 接口,并在 `BEGIN:TYPE` 和 `END:TYPE` 定界符之间渲染。
+
+### Event(VEVENT)
+
+表示一个预定的活动/事件。
+
+```java
+Event event = Event.builder()
+ .withDateTimeStamp(dtstamp) // 必需
+ .withUniqueIdentifier(uid) // 必需
+ .withDateTimeStart(dtstart)
+ .withDateTimeEnd(dtend) // 与 duration 互斥
+ .withDuration(duration) // 与 dtend 互斥
+ .withSummary(summary)
+ .withDescription(description)
+ .withClassification(classification)
+ .withDateTimeCreated(dateTimeCreated)
+ .withGeographicPosition(geoPos)
+ .withLastModified(lastModified)
+ .withLocation(location)
+ .withOrganiser(organiser)
+ .withPriority(priority)
+ .withSequenceNumber(seqNumber)
+ .withStatus(status)
+ .withTimeTransparency(transparency)
+ .withUniformResourceLocator(url)
+ .withRecurrenceId(recurrenceId)
+ .withRecurrenceRule(rrule)
+ .withAttachments(attachments)
+ .withAttendees(attendees)
+ .withCategories(categories)
+ .withComments(comments)
+ .withContacts(contacts)
+ .withExceptionDateTimes(exDates)
+ .withRequestStatuses(statuses)
+ .withRelated(related)
+ .withResources(resources)
+ .withRecurrenceDateTimes(rDates)
+ .build();
+```
+
+### Todo(VTODO)
+
+表示待办事项或任务。
+
+```java
+Todo todo = Todo.builder()
+ .withDateTimeStamp(dtstamp) // 必需
+ .withUniqueIdentifier(uid) // 必需
+ .withSummary(summary)
+ .withDateTimeStart(dtstart)
+ .withDateTimeDue(due) // 与 duration 互斥
+ .withDuration(duration) // 与 due 互斥
+ .withDateTimeCompleted(completed)
+ .withPercentComplete(percent)
+ .withClassification(classification)
+ .withDateTimeCreated(created)
+ .withDescription(description)
+ .withGeographicPosition(geoPos)
+ .withLastModified(lastModified)
+ .withLocation(location)
+ .withOrganiser(organiser)
+ .withPriority(priority)
+ .withSequenceNumber(seq)
+ .withStatus(status)
+ .withRecurrenceId(recurId)
+ .withRecurrenceRule(rrule)
+ .withUniformResourceLocator(url)
+ .withAttachments(attachments)
+ .withAttendees(attendees)
+ .withCategories(categories)
+ .withComments(comments)
+ .withContacts(contacts)
+ .withExceptionDateTimes(exDates)
+ .withRequestStatuses(statuses)
+ .withRelatedToList(related)
+ .withResources(resources)
+ .withRecurrenceDateTimes(rDates)
+ .build();
+```
+
+### Journal(VJOURNAL)
+
+表示日记条目或笔记。
+
+```java
+Journal journal = Journal.builder()
+ .withDateTimeStamp(dtstamp) // 必需
+ .withUniqueIdentifier(uid) // 必需
+ .withSummary(summary)
+ .withClassification(classification)
+ .withDateTimeCreated(created)
+ .withDateTimeStart(dtstart)
+ .withLastModified(lastModified)
+ .withOrganiser(organiser)
+ .withRecurrenceId(recurId)
+ .withSequenceNumber(seq)
+ .withStatus(status)
+ .withUniformResourceLocator(url)
+ .withRecurrenceRule(rrule)
+ .withAttachments(attachments)
+ .withAttendees(attendees)
+ .withCategories(categories)
+ .withComments(comments)
+ .withContacts(contacts)
+ .withDescriptions(descriptions)
+ .withExceptionDateTimes(exDates)
+ .withRelatedToList(related)
+ .withRecurrenceDate(rDates)
+ .withRequestStatuses(statuses)
+ .build();
+```
+
+### FreeBusy(VFREEBUSY)
+
+表示空闲/忙碌时间信息。
+
+```java
+FreeBusy freeBusy = FreeBusy.builder()
+ .withDateTimeStamp(dtstamp) // 必需
+ .withUniqueIdentifier(uid) // 必需
+ .withContact(contact)
+ .withDateTimeStart(dtstart)
+ .withDateTimeEnd(dtend)
+ .withOrganiser(organiser)
+ .withUniformResourceLocator(url)
+ .withAttendees(attendees)
+ .withComments(comments)
+ .withFreeBusyTimes(freeBusyTimes)
+ .withRequestStatuses(statuses)
+ .build();
+```
+
+### TimeZone(VTIMEZONE)
+
+定义时区规则,包括标准时间和夏令时转换。
+
+```java
+TimeZone timezone = TimeZone.builder()
+ .withTimeZoneIdentifier(tzId)
+ .withLastModified(lastModified)
+ .withTimeZoneUrl(tzUrl)
+ .withTimeZoneProperties(standardProp, daylightProp)
+ .build();
+```
+
+时区属性定义实际的转换规则:
+
+```java
+TimeZoneProperty standard = TimeZoneProperty.builder()
+ .withDateTimeStart(dtstart)
+ .withTimeZoneOffsetTo(offsetTo)
+ .withTimeZoneOffsetFrom(offsetFrom)
+ .withRecurrenceRule(rrule)
+ .withTimeZoneNames(tzName)
+ .buildStandard(); // 或 buildDaylight()
+
+TimeZoneProperty daylight = TimeZoneProperty.builder()
+ .withDateTimeStart(dtstart)
+ .withTimeZoneOffsetTo(offsetTo)
+ .withTimeZoneOffsetFrom(offsetFrom)
+ .buildDaylight();
+```
+
+### Alarm(VALARM)
+
+定义闹钟/提醒通知。支持三种闹钟类型:
+
+```java
+// 音频闹钟
+Alarm audioAlarm = Alarm.builder()
+ .withTrigger(trigger)
+ .withDuration(duration)
+ .withRepeatCount(repeatCount)
+ .withAttachments(audioAttachment)
+ .buildAudio();
+
+// 显示闹钟
+Alarm displayAlarm = Alarm.builder()
+ .withTrigger(trigger)
+ .withDescription(description) // 必需
+ .withDuration(duration)
+ .withRepeatCount(repeatCount)
+ .buildDisplay();
+
+// 邮件闹钟
+Alarm emailAlarm = Alarm.builder()
+ .withTrigger(trigger)
+ .withDescription(description) // 必需
+ .withSummary(summary) // 必需
+ .withAttendees(attendees) // 必需
+ .withDuration(duration)
+ .withRepeatCount(repeatCount)
+ .buildEmail();
+```
+
+---
+
+## 组件属性
+
+组件属性位于 `com.onixbyte.calendar.component.property`,实现 `ComponentProperty` 接口。
+
+| 类 | iCalendar 属性 | 描述 |
+|---|---|---|
+| `Action` | `ACTION` | 闹钟操作类型(AUDIO、DISPLAY、EMAIL) |
+| `Attachment` | `ATTACH` | 文档附件 |
+| `Attendee` | `ATTENDEE` | 事件/任务参与者 |
+| `Categories` | `CATEGORIES` | 类别或标签 |
+| `Classification` | `CLASS` | 访问分类(PUBLIC、PRIVATE、CONFIDENTIAL) |
+| `Comment` | `COMMENT` | 评论 |
+| `Contact` | `CONTACT` | 联系信息 |
+| `DateTimeCompleted` | `COMPLETED` | 完成日期时间 |
+| `DateTimeCreated` | `CREATED` | 创建日期时间 |
+| `DateTimeDue` | `DUE` | 截止日期时间 |
+| `DateTimeEnd` | `DTEND` | 结束日期时间 |
+| `DateTimeStamp` | `DTSTAMP` | 日期时间戳 |
+| `DateTimeStart` | `DTSTART` | 开始日期时间 |
+| `Description` | `DESCRIPTION` | 描述 |
+| `ExceptionDateTimes` | `EXDATE` | 例外日期时间 |
+| `FreeBusyTime` | `FREEBUSY` | 空闲/忙碌时间段 |
+| `GeographicPosition` | `GEO` | 地理位置(纬度/经度) |
+| `LastModified` | `LAST-MODIFIED` | 最后修改日期时间 |
+| `Location` | `LOCATION` | 地点 |
+| `Organiser` | `ORGANIZER` | 组织者 |
+| `PercentComplete` | `PERCENT-COMPLETE` | 完成百分比 |
+| `Priority` | `PRIORITY` | 优先级 |
+| `RecurrenceDateTimes` | `RDATE` | 重复日期时间 |
+| `RecurrenceId` | `RECURRENCE-ID` | 重复实例标识符 |
+| `RecurrenceRule` | `RRULE` | 重复规则 |
+| `RelatedTo` | `RELATED-TO` | 相关组件引用 |
+| `RepeatCount` | `REPEAT` | 闹钟重复次数 |
+| `RequestStatus` | `REQUEST-STATUS` | 请求状态 |
+| `Resources` | `RESOURCES` | 资源 |
+| `SequenceNumber` | `SEQUENCE` | 序列号(修订版本) |
+| `Status` | `STATUS` | 组件状态(TENTATIVE、CONFIRMED、CANCELLED 等) |
+| `Summary` | `SUMMARY` | 标题或摘要 |
+| `TimeTransparency` | `TRANSP` | 时间透明度(OPAQUE、TRANSPARENT) |
+| `TimeZoneIdentifier` | `TZID` | 时区标识符 |
+| `TimeZoneName` | `TZNAME` | 时区名称 |
+| `TimeZoneOffsetFrom` | `TZOFFSETFROM` | 相对于 UTC 的时区偏移(原) |
+| `TimeZoneOffsetTo` | `TZOFFSETTO` | 相对于 UTC 的时区偏移(目标) |
+| `TimeZoneUrl` | `TZURL` | 时区 URL |
+| `Trigger` | `TRIGGER` | 闹钟触发器 |
+| `UniformResourceLocator` | `URL` | 关联 URL |
+| `UniqueIdentifier` | `UID` | 唯一标识符 |
+| `CustomComponentProperty` | `X-*` | 自定义组件属性 |
+
+---
+
+## 参数
+
+参数位于 `com.onixbyte.calendar.parameter`,为组件属性提供额外限定。
+
+| 类 | iCalendar 参数 | 描述 |
+|---|---|---|
+| `AlarmTriggerRelationship` | `RELATED` | 触发器关联(START、END) |
+| `AlternateTextRepresentation` | `ALTREP` | 替代文本 URI |
+| `CalendarUserType` | `CUTYPE` | 日历用户类型(INDIVIDUAL、GROUP、RESOURCE 等) |
+| `CommonName` | `CN` | 通用名称 |
+| `Delegatees` | `DELEGATED-TO` | 受托人 |
+| `Delegators` | `DELEGATED-FROM` | 委托人 |
+| `DirectoryEntryReference` | `DIR` | 目录条目 URI |
+| `FormatType` | `FMTTYPE` | 格式类型(MIME 类型) |
+| `FreeBusyTimeType` | `FBTYPE` | 空闲/忙碌时间类型 |
+| `InlineEncoding` | `ENCODING` | 内联编码(BASE64) |
+| `Language` | `LANGUAGE` | 语言 |
+| `Membership` | `MEMBER` | 组成员 |
+| `ParticipationRole` | `ROLE` | 参与角色(CHAIR、REQ-PARTICIPANT 等) |
+| `ParticipationStatus` | `PARTSTAT` | 参与状态(ACCEPTED、DECLINED 等) |
+| `RecurrenceIdentifierRange` | `RANGE` | 重复范围(THISANDPRIOR、THISANDFUTURE) |
+| `RelationshipType` | `RELTYPE` | 关系类型(PARENT、CHILD、SIBLING) |
+| `RsvpExpectation` | `RSVP` | RSVP 期望(TRUE、FALSE) |
+| `SentBy` | `SENT-BY` | 发送者 |
+| `TimeZoneIdentifier` | `TZID` | 时区标识符 |
+| `ValueDataType` | `VALUE` | 值数据类型(DATE、DATE-TIME 等) |
+
+---
+
+## 递归类型
+
+位于 `com.onixbyte.calendar.recurrence`。
+
+| 类 | 描述 |
+|---|---|
+| `Frequency` | 重复频率常量(DAILY、WEEKLY、MONTHLY、YEARLY),用于重复规则 |
+| `WeekdayNum` | 重复规则的星期序号(例如第 2 个星期一) |
+
+---
+
+## 值类型
+
+位于 `com.onixbyte.calendar.value`。
+
+| 类 | 描述 |
+|---|---|
+| `FreeBusyTimeValue` | 表示空闲/忙碌时间值 |
+| `PeriodOfTime` | 表示一个时间段,包含开始和结束 |
+| `PropertyValue` | 属性的基础值类型 |
+| `UtcOffset` | UTC 偏移值(例如 `-05:00`、`+01:00`) |
+
+---
+
+## 格式化输出
+
+所有组件和属性都提供 `formatted()` 方法,返回符合 iCalendar 规范的字符串。`Calendar.formatted()` 方法生成完整的 `.ics` 输出,包含 `BEGIN:VCALENDAR`/`END:VCALENDAR`。
+
+```java
+String ics = calendar.formatted();
+// BEGIN:VCALENDAR
+// CALSCALE:GREGORIAN
+// METHOD:PUBLISH
+// ...
+// END:VCALENDAR
+```
diff --git a/docs/zh-hans/projects/calendar-toolbox/index.mdx b/docs/zh-hans/projects/calendar-toolbox/index.mdx
new file mode 100644
index 0000000..fde362d
--- /dev/null
+++ b/docs/zh-hans/projects/calendar-toolbox/index.mdx
@@ -0,0 +1,109 @@
+---
+title: Calendar Toolbox
+---
+
+import { Tabs, Tab } from "@rspress/core/theme"
+
+## 介绍
+
+Calendar Toolbox 是一个 Java 库,旨在简化遵循 iCalendar 规范(RFC 5545)的 `.ics` 文件的创建。该库为开发者提供了简洁的 API,可生成能够导入到 Microsoft Outlook、Google Calendar 和 Apple Calendar 等主流日历应用程序中的日历事件。
+
+通过 Calendar Toolbox,您可以以编程方式轻松创建、定制和导出日历事件文件,从而以最少的代价将日历功能集成到您的 Java 应用中。
+
+## 特性
+
+- **完整 RFC 5545 兼容** — 支持 VEVENT、VTODO、VJOURNAL、VFREEBUSY、VTIMEZONE 和 VALARM 等标准 iCalendar 组件。
+- **流式 Builder 模式** — 所有组件和属性均使用 Builder 模式,构建过程可读性强且直观。
+- **类型安全属性** — 强类型的属性和参数确保编译期正确性。
+- **自定义扩展** — 支持日历级和组件级的自定义 `X-` 属性。
+- **轻量级** — 核心功能零外部依赖。
+
+## 安装
+
+
+
+ ```groovy title="build.gradle"
+ dependencies {
+ implementation 'com.onixbyte:calendar-toolbox:1.1.0'
+ }
+ ```
+
+
+ ```kotlin title="build.gradle.kts"
+ dependencies {
+ implementation("com.onixbyte:calendar-toolbox:1.1.0")
+ }
+ ```
+
+
+ ```xml title="pom.xml"
+
+
+ com.onixbyte
+ calendar-toolbox
+ 1.1.0
+
+
+ ```
+
+
+
+## 快速开始
+
+```java
+import com.onixbyte.calendar.Calendar;
+import com.onixbyte.calendar.component.Event;
+import com.onixbyte.calendar.component.property.*;
+import com.onixbyte.calendar.property.*;
+
+import java.time.LocalDateTime;
+import java.time.ZoneOffset;
+import java.time.ZonedDateTime;
+
+public class CalendarExample {
+
+ public static void main(String[] args) {
+ // 创建所需的日期时间属性
+ var now = ZonedDateTime.now(ZoneOffset.UTC);
+ var dtstamp = DateTimeStamp.of(now);
+ var uid = UniqueIdentifier.of("meeting-001@example.com");
+ var dtstart = DateTimeStart.of(
+ LocalDateTime.of(2025, 8, 15, 9, 0),
+ "America/New_York"
+ );
+ var dtend = DateTimeEnd.of(
+ LocalDateTime.of(2025, 8, 15, 10, 0),
+ "America/New_York"
+ );
+ var summary = Summary.of("Team Standup");
+ var description = Description.of("Daily team standup meeting.");
+
+ // 构建事件
+ var event = Event.builder()
+ .withDateTimeStamp(dtstamp)
+ .withUniqueIdentifier(uid)
+ .withDateTimeStart(dtstart)
+ .withDateTimeEnd(dtend)
+ .withSummary(summary)
+ .withDescription(description)
+ .build();
+
+ // 构建日历并输出 .ics 内容
+ var calendar = Calendar.builder()
+ .withCalendarScale(CalendarScale.of("GREGORIAN"))
+ .withMethod(Method.of("PUBLISH"))
+ .withProductIdentifier(ProductIdentifier.of("-//OnixByte//Calendar Toolbox//EN"))
+ .withVersion(Version.of("2.0"))
+ .withComponents(event)
+ .build();
+
+ System.out.println(calendar.formatted());
+ }
+}
+```
+
+上述代码会生成一个 `.ics` 格式的字符串,可以保存为文件或通过邮件发送。
+
+## 许可证
+
+Calendar Toolbox 是采用 MIT 许可证发布的开源软件。
diff --git a/docs/zh-hans/projects/index.md b/docs/zh-hans/projects/index.md
new file mode 100644
index 0000000..de4ab44
--- /dev/null
+++ b/docs/zh-hans/projects/index.md
@@ -0,0 +1,5 @@
+---
+title: 项目
+---
+
+探索由 OnixByte 开发的开源项目。
\ No newline at end of file
diff --git a/i18n.json b/i18n.json
index 949eb2f..de46ba9 100644
--- a/i18n.json
+++ b/i18n.json
@@ -118,5 +118,9 @@
"notifications": {
"en-gb": "Notifications",
"zh-hans": "通知"
+ },
+ "projects": {
+ "en-gb": "Projects",
+ "zh-hans": "项目"
}
}