diff --git a/public/assets/ytp/auths/driver-airtable-access-token.webp b/public/assets/ytp/auths/driver-airtable-access-token.webp
new file mode 100644
index 00000000..04a8e344
Binary files /dev/null and b/public/assets/ytp/auths/driver-airtable-access-token.webp differ
diff --git a/public/assets/ytp/sources/airtable-config.webp b/public/assets/ytp/sources/airtable-config.webp
new file mode 100644
index 00000000..28148e0d
Binary files /dev/null and b/public/assets/ytp/sources/airtable-config.webp differ
diff --git a/public/assets/ytp/sources/google-calendar-config.webp b/public/assets/ytp/sources/google-calendar-config.webp
new file mode 100644
index 00000000..11433c99
Binary files /dev/null and b/public/assets/ytp/sources/google-calendar-config.webp differ
diff --git a/public/assets/ytp/sources/google-photos-config.webp b/public/assets/ytp/sources/google-photos-config.webp
new file mode 100644
index 00000000..869e232c
Binary files /dev/null and b/public/assets/ytp/sources/google-photos-config.webp differ
diff --git a/src/assets/ytp-auth.afphoto b/src/assets/ytp-auth.afphoto
index 3c96c15d..036585fc 100644
Binary files a/src/assets/ytp-auth.afphoto and b/src/assets/ytp-auth.afphoto differ
diff --git a/src/assets/ytp-sources.afphoto b/src/assets/ytp-sources.afphoto
index 9eb2a21e..d93a63c6 100644
Binary files a/src/assets/ytp-sources.afphoto and b/src/assets/ytp-sources.afphoto differ
diff --git a/src/pages/essentials-for-yootheme-pro/addons/sources/nav.json b/src/pages/essentials-for-yootheme-pro/addons/sources/nav.json
index 5f427518..79a19e03 100644
--- a/src/pages/essentials-for-yootheme-pro/addons/sources/nav.json
+++ b/src/pages/essentials-for-yootheme-pro/addons/sources/nav.json
@@ -46,6 +46,10 @@
"title": "Database",
"href": "./providers/database"
},
+ {
+ "title": "Airtable",
+ "href": "./providers/airtable"
+ },
{
"title": "Google Sheet",
"href": "./providers/google-sheet"
@@ -105,6 +109,14 @@
{
"title": "Google Business Profile",
"href": "./providers/google-business-profile"
+ },
+ {
+ "title": "Google Calendar",
+ "href": "./providers/google-calendar"
+ },
+ {
+ "title": "Google Photos",
+ "href": "./providers/google-photos"
}
]
},
diff --git a/src/pages/essentials-for-yootheme-pro/addons/sources/providers/airtable.md b/src/pages/essentials-for-yootheme-pro/addons/sources/providers/airtable.md
new file mode 100644
index 00000000..fe23c566
--- /dev/null
+++ b/src/pages/essentials-for-yootheme-pro/addons/sources/providers/airtable.md
@@ -0,0 +1,69 @@
+---
+title: Airtable
+description: Content Source based on Airtable apps
+icon: '
+
+'
+---
+
+{% elementIcon draw=$markdoc.frontmatter.icon /%}
+
+{% $markdoc.frontmatter.description %}. {% .lead %}
+
+The Airtable Source feeds data from Airtable platform. Based on the [multi-instance](/essentials-for-yootheme-pro/addons/sources/multi-instance-sources/) source workflow it allows connecting to multiple accounts with different configurations.
+
+---
+
+## Settings
+
+The source settings determines the content structure, every time the instance is saved the structure will be regenerated.
+
+{% image %}
+
+{% /image %}
+
+| Setting | Description | Required |
+| ------- | ----------- | :------: |
+| **Account** | The Airtable Account which to authenticate with. | ✓ |
+| **Base** | The Airtable base which to retrieve the data from. | ✓ |
+| **Table** | The Airtable base table which data to create the source with. | ✓ |
+
+{% partial file="ytp-sources-common-settings.md" variables={name: "Airtable"} /%}
+
+---
+
+### Authentication
+
+Authentication is based on the Airtable Personal Access Token driven by the [Airtable Token Driver](/essentials-for-yootheme-pro/auth/drivers/airtable-access-token).
+
+{% image %}
+
+{% /image %}
+
+---
+
+## Content Queries
+
+For every source instance the following content queries will be made available as Dynamic Content option.
+
+### Record Query
+
+Fetches a single record from the Airtable base table and resolves to a dynamically generated list of record type based on the table schema.
+
+| Setting | Default | Description |
+| ------- | ------- | ----------- |
+| **Record ID** | | The ID of the record to query. |
+| **Cache** | `3600` | The duration in seconds before the cache is invalidated and the query re-executed. |
+
+---
+
+### Records Query
+
+Fetches a single record from the Airtable base table and resolves to a dynamically generated list of record type based on the table schema.
+
+| Setting | Default | Description |
+| ------- | ------- | ----------- |
+| **View** | | Optional table view to use instead of a raw query. |
+| **Start** | `1` | The offset applied to the query. |
+| **Quantity** | `20` | The limit applied to the query. |
+| **Cache** | `3600` | The duration in seconds before the cache is invalidated and the query re-executed. |
diff --git a/src/pages/essentials-for-yootheme-pro/addons/sources/providers/google-calendar.md b/src/pages/essentials-for-yootheme-pro/addons/sources/providers/google-calendar.md
new file mode 100644
index 00000000..16fdb1a1
--- /dev/null
+++ b/src/pages/essentials-for-yootheme-pro/addons/sources/providers/google-calendar.md
@@ -0,0 +1,168 @@
+---
+title: Google Calendar
+description: Content Source based on Google Calendar
+icon: '
+
+
+'
+---
+
+{% elementIcon draw=$markdoc.frontmatter.icon /%}
+
+{% $markdoc.frontmatter.description %}. {% .lead %}
+
+The Google Calendar source feeds data from the Google Calendar service. Based on the [multi-instance](/essentials-for-yootheme-pro/addons/sources/multi-instance-sources/) source workflow it allows connecting to multiple accounts with different configurations.
+
+---
+
+## Settings
+
+The source settings determines the content structure, every time the instance is saved the structure will be regenerated.
+
+{% image %}
+
+{% /image %}
+
+| Setting | Description | Required |
+| ------- | ----------- | :------: |
+| **Account** | The Google account which to authenticate with. | ✓ |
+| **Calendar** | The Google calendar which data to create the source with. | ✓ |
+
+{% partial file="ytp-sources-common-settings.md" variables={name: "Google Calendar"} /%}
+
+---
+
+### Authentication
+
+Authentication is based on the OAuth protocol driven by the [Google OAuth Driver](/essentials-for-yootheme-pro/auth/drivers/google-oauth).
+
+{% image %}
+
+{% /image %}
+
+---
+
+## Content Queries
+
+For every source instance the following content queries will be made available as Dynamic Content option.
+
+### Calendar Query
+
+Fetches the Calendar data resolving to a [Calendar Type](#calendar-type).
+
+| Setting | Default | Description |
+| ------- | ------- | ----------- |
+| **Cache** | `3600` | The duration in seconds before the cache is invalidated and the query re-executed. |
+
+---
+
+### Event Query
+
+Fetches a single event from the calendar and resolves to a [Event Type](#event-type).
+
+| Setting | Default | Description | Required |
+| ------- | ------- | ----------- | :------: |
+| **Event ID** | | The ID of the event to query. | ✓ |
+| **Cache** | `3600` | The duration in seconds before the cache is invalidated and the query re-executed. |
+
+---
+
+### Events Query
+
+Fetches events from the calendar and resolves to a list of [Event Type](#event-type).
+
+| Setting | Default | Description |
+| ------- | ------- | ----------- |
+| **Query** | | Optionaly filter matching terms in the summary, description, location, attendee\'s displayName and attendee\'s email fields. |
+| **Single Events Only** | | Whether to expand recurring events into instances and only return single one-off events and instances of recurring events, but not the underlying recurring events themselves. |
+| **Order By** | | The order by which to query the events, `Start Time (asc)` or `Updated (asc)`. |
+| **Quantity** | `250` | The maximum amount of events to query. |
+| **Time Min / Max** | | Lower and Upper bounds (exclusive) for an event\'s start or end time to filter by. |
+| **Cache** | `3600` | The duration in seconds before the cache is invalidated and the query re-executed. |
+
+---
+
+## Content Types
+
+The content types define the mapping options for the source content.
+
+### Calendar Type
+
+Defines the mapping options of a Calendar object.
+
+| Option | Description | Type | Filters |
+| ------ | ----------- | ---- | ------- |
+| **ID** | Unique identifier of the calendar. | `String` |
+| **Summary** | Title of the calendar. | `String` | `Limit` |
+| **Description** | Description of the calendar. | `String` | `Limit` |
+| **Location** | Geographic location of the event as free-form text. | `String` | `Limit` |
+| **Time Zone** | The calendars default time zone. | `String` |
+
+---
+
+### Event Type
+
+Defines the mapping options of an Event object.
+
+| Option | Description | Type | Filters |
+| ------ | ----------- | ---- | ------- |
+| **ID** | Opaque identifier of the event. | `String` |
+| **URL** | An absolute link to the event in the Google Calendar Web UI. | `String` |
+| **Type** | Specific type of the event, `default`, `outOfOffice`, `focusTime` or `workingLocation`. | `String` |
+| **Status** | Status of the event, `confirmed`, `tentative` or `cancelled`. - | `String` |
+| **Visibility** | Visibility of the event, `default`, `public`, `private`, or `confidential` | `String` |
+| **Summary** | Title of the event. | `String` | `Limit` |
+| **Description** | Description of the calendar. | `String` | `Limit` |
+| **Location** | Geographic location of the event as free-form text. | `String` | `Limit` |
+| **Start** | The (inclusive) start time of the event. For a recurring event, this is the start time of the first instance. | `String` | `Date` |
+| **End** | The (exclusive) end time of the event. For a recurring event, this is the end time of the first instance. | `String` | `Date` |
+| **Created** | Creation time of the event. | `String` | `Date` |
+| **Updated** | Last modification time of the event. | `String` | `Date` |
+| **Creator** | The creator of the event. | [Profile Type](#profile-type) |
+| **Organizer** | The organizer of the event. | [Profile Type](#profile-type) |
+| **Attendees** | The attendees of the event. | [Attendee Type](#attendee-type) |
+| **Attachments** | File attachments of the event. | [Attachment Type](#attachment-type) |
+
+---
+
+### Profile Type
+
+Defines the mapping options of a Profile object.
+
+| Option | Description | Type | Filters |
+| ------ | ----------- | ---- | ------- |
+| **ID** | Identifier of the profile. | `String` |
+| **Email** | The profile's email. | `String` |
+| **Name** | The profile's name. | `String` | `Limit` |
+
+---
+
+### Attendee Type
+
+Defines the mapping options of an Attendee object.
+
+| Option | Description | Type | Filters |
+| ------ | ----------- | ---- | ------- |
+| **ID** | Identifier of the attendee. | `String` |
+| **Email** | The attendee's email. | `String` |
+| **Name** | The attendee's name. | `String` | `Limit` |
+| **Comment** | The attendee's name. | `String` | `Limit` |
+| **Response Status** | The attendee's response status, `needsAction`, `declined`, `tentative` or `accepted`. | `String` |
+| **Is Organizer** | Whether the attendee is the organizer of the event. | `Boolean` |
+| **Is Resource** | Whether the attendee is a resource. | `Boolean` |
+| **Is Optional** | Whether this is an optional attendee. | `Boolean` |
+| **Additional Guests Count** | Number of additional guests. | `Int` |
+
+---
+
+### Attachment Type
+
+Defines the mapping options of an Attachment object.
+
+| Option | Description | Type | Filters |
+| ------ | ----------- | ---- | ------- |
+| **ID** | Identifier of the attached file. | `String` |
+| **Title** | Title of the attachment. | `String` | `Limit` |
+| **Mime Type** | Internet media type (MIME type) of the attachment. | `String` |
+| **File URL** | URL link to the attachment. | `String` |
+| **Icon URL** | URL link to the attachment's icon. | `String` |
diff --git a/src/pages/essentials-for-yootheme-pro/addons/sources/providers/google-photos.md b/src/pages/essentials-for-yootheme-pro/addons/sources/providers/google-photos.md
new file mode 100644
index 00000000..00609af8
--- /dev/null
+++ b/src/pages/essentials-for-yootheme-pro/addons/sources/providers/google-photos.md
@@ -0,0 +1,134 @@
+---
+title: Google Photos
+description: Content Source based on Google Photos media
+icon: '
+
+'
+---
+
+{% elementIcon draw=$markdoc.frontmatter.icon /%}
+
+{% $markdoc.frontmatter.description %}. {% .lead %}
+
+The Google Photos source feeds media from the Google Photos service. Based on the [multi-instance](/essentials-for-yootheme-pro/addons/sources/multi-instance-sources/) source workflow it allows connecting to multiple accounts with different configurations.
+
+---
+
+## Settings
+
+The source settings determines the content structure, every time the instance is saved the structure will be regenerated.
+
+{% image %}
+
+{% /image %}
+
+| Setting | Description | Required |
+| ------- | ----------- | :------: |
+| **Account** | The Google account which to authenticate with. | ✓ |
+
+{% partial file="ytp-sources-common-settings.md" variables={name: "Google Photos"} /%}
+
+---
+
+### Authentication
+
+Authentication is based on the OAuth protocol driven by the [Google OAuth Driver](/essentials-for-yootheme-pro/auth/drivers/google-oauth).
+
+{% image %}
+
+{% /image %}
+
+---
+
+## Content Queries
+
+For every source instance the following content queries will be made available as Dynamic Content option.
+
+### Album Query
+
+Fetches a single album resolving to a [Album Type](#album-type).
+
+| Setting | Default | Description |
+| ------- | ------- | ----------- |
+| **Album ID** | | The ID of the album to query. | ✓ |
+| **Cache** | `3600` | The duration in seconds before the cache is invalidated and the query re-executed. |
+
+---
+
+### Albums Query
+
+Fetches all albums from the library resolving to a list of [Album Type](#album-type).
+
+| Setting | Default | Description |
+| ------- | ------- | ----------- |
+| **Cache** | `3600` | The duration in seconds before the cache is invalidated and the query re-executed. |
+
+---
+
+### Album Media Query
+
+Fetches media from a single album resolving to a list of [Media Type](#media-type).
+
+| Setting | Default | Description |
+| ------- | ------- | ----------- |
+| **Album ID** | | The ID of the album to query. | ✓ |
+| **Page Size** | | The number of the page which to query. | ✓ |
+| **Cache** | `3600` | The duration in seconds before the cache is invalidated and the query re-executed. |
+
+---
+
+## Content Types
+
+The content types define the mapping options for the source content.
+
+### Album Type
+
+Defines the mapping options of an Album object.
+
+| Option | Description | Type | Filters |
+| ------ | ----------- | ---- | ------- |
+| **ID** | Unique identifier of the album. | `String` |
+| **Title** | Title of the album. | `String` | `Limit` |
+| **Cover Photo URL** | The album cover photo URL. | `String` |
+| **Total Media Count** | The album total amount of media. | `Int` |
+
+---
+
+### Media Type
+
+Defines the mapping options of a Media object.
+
+#### Media
+
+| Option | Description | Type | Filters |
+| ------ | ----------- | ---- | ------- |
+| **ID** | Opaque identifier of the media. | `String` |
+| **URL** | The path to the locally cached media file, with optionall arguments `Width` and `Height` . | `String` |
+| **Description** | Description of the media. This is shown to the user in the item's info section in the Google Photos app. | `String` | `Limit` |
+| **Filename** | Filename of the media. This is shown to the user in the item's info section in the Google Photos app. | `String` |
+| **MIME Type** | MIME type of the media. For example, `image/jpeg`. | `String` |
+
+#### Metadata
+
+| Option | Description | Type |
+| ------ | ----------- | ---- |
+| **Width** | Original width (in pixels) of the media. | `Int` |
+| **Height** | Original height (in pixels) of the media. | `Int` |
+| **Creation Time** | Time when the media was first created (not when it was uploaded to Google Photos). | `String` |
+| **Camera Brand** | Brand of the camera with which the photo was taken. | `String` |
+| **Camera Model** | Model of the camera with which the photo was taken. | `String` |
+
+#### Metadata (Video)
+
+| Option | Description | Type |
+| ------ | ----------- | ---- |
+| **Frame Rate** | Frame rate of the media in case is a video. | `Int` |
+
+#### Metadata (Photo)
+
+| Option | Description | Type |
+| ------ | ----------- | ---- |
+| **Camera ISO** | ISO of the camera with which the photo was taken. | `Int` |
+| **Focal Length** | Focal length of the camera lens with which the photo was taken. | `Int` |
+| **Aperture F** | Aperture f number of the camera lens with which the photo was taken. | `Int` |
+| **Exposure Time** | Exposure time of the camera aperture in seconds when the photo was taken. | `String` |
diff --git a/src/pages/essentials-for-yootheme-pro/auth/drivers/airtable-access-token.md b/src/pages/essentials-for-yootheme-pro/auth/drivers/airtable-access-token.md
new file mode 100644
index 00000000..0443cf0e
--- /dev/null
+++ b/src/pages/essentials-for-yootheme-pro/auth/drivers/airtable-access-token.md
@@ -0,0 +1,22 @@
+---
+title: Airtable Access Token
+description: A Driver for Airtable Personal Access Tokens
+icon: '
+
+'
+---
+
+{% elementIcon draw=$markdoc.frontmatter.icon /%}
+
+{% $markdoc.frontmatter.description %}. {% .lead %}
+
+The Airtable Access Token Driver manage Airtable Personal Access Tokens obtained through the [Airtable](https://airtable.com/create/tokens) dashboard.
+
+{% image %}
+
+{% /image %}
+
+| Setting | Description |
+| ------- | ----------- |
+| **Name** | The name that will identify this token. |
+| **Token** | The access token created at the Airtable Dashboard. |