Integrations
Skylite UX is designed to integrate with various external and self-hosted services. This section covers how to set up and configure integrations for development.
We use the Docker Outside of Docker dev container feature for easier development.
Integration Development
For Self-Hosted Integrations:
- Create a new folder in
Skylite-UX/.devcontainer/integrations/ - Create a Docker Compose file for the new service you are integrating (see Docker Compose for Integrations)
- Spin up the Docker container
- Generate an API key for the service (if applicable)
For External Integrations:
- Obtain API credentials or OAuth credentials for the external service (if applicable)
Code Implementation (All Integration Types):
- Add a new folder in
Skylite-UX/app/integrations/(e.g.,app/integrations/myService/) - Create your client-side integration file (e.g.,
myServiceShoppingLists.ts,myServiceCalendar.ts) - Add a new folder in
Skylite-UX/server/integrations/(e.g.,server/integrations/myService/) - Create your server-side service files (
client.ts,index.ts,types.ts, etc.) - (Optional) Add a new folder in
Skylite-UX/server/api/integrations/if you need proxy API endpoints - (Optional) Create API endpoint file(s) (e.g.,
[...path].tsfor proxy routes) if needed - Add your service in
Skylite-UX/app/integrations/integrationConfig.ts:- Import your service factory function(s) at the top of the file
- Add an entry to the
integrationConfigsarray with your integration configuration - Add your service factory to the
serviceFactoryMapobject using the key${type}:${service} - (Optional) Add field filter to the
fieldFiltersobject if needed for shopping integrations
- Restart the application to load the new integration configuration (the config is read at startup)
- Add the service in Skylite UX via Settings > Integrations > Add Integration (the integration will now appear in the list)
- Test and commit as defined in the Development Workflow
Integration Configuration
Docker Compose for Integrations
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
# .devcontainer/integrations/service/service-docker-compose.yml
services:
# Notes about the integration
# How to create API key, base URL, etc.
# Base URL: e.g. http://mealie:9000
mealie:
image: ghcr.io/mealie-recipes/mealie:latest
container_name: mealie
restart: always
ports:
- "9925:9000" # External port mapping
deploy:
resources:
limits:
memory: 1000M # Memory limit
volumes:
- mealie-data:/app/data/
environment:
# Set Backend ENV Variables Here
ALLOW_SIGNUP: false
PUID: 1000
PGID: 1000
TZ: America/Anchorage
# Make sure the service runs on the same network as the dev container
networks:
skylite-ux_devcontainer_default:
volumes:
mealie-data:
# Make sure the service runs on the same network as the dev container
networks:
skylite-ux_devcontainer_default:
external: true
Defining Your Integration in integrationConfig.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
// 1. Import your service factory function(s) at the top of integrationConfig.ts
import { createTandoorService, getTandoorFieldsForItem } from "./tandoor/tandoorShoppingLists";
// 2. Add your integration config entry to the integrationConfigs array
export const integrationConfigs: IntegrationConfig[] = [
{
type: "shopping", // calendar,todo,shopping,meal
service: "tandoor", // the name of the service you are integrating
settingsFields: [
// fields used for setting up the integration
{
key: "apiKey",
label: "API Key",
type: "password" as const,
placeholder: "Scope needs to be \"read write\"",
required: true,
description: "Your Tandoor API key for authentication"
},
{
key: "baseUrl",
label: "Base URL",
type: "url" as const,
placeholder: "http://your-tandoor-instance:port",
required: true,
description: "The base URL of your Tandoor instance"
}
],
capabilities: ["add_items", "edit_items"], // declare your capabilities
icon: "https://cdn.jsdelivr.net/gh/selfhst/icons/svg/tandoor-recipes.svg", // icon URL from selfh.st/icons
dialogFields: [
// fields used for dialog
{
key: "name",
label: "Item Name",
type: "text" as const,
placeholder: "Milk, Bread, Apples, etc.",
required: true,
canEdit: true,
},
{
key: "quantity",
label: "Quantity",
type: "number" as const,
min: 0,
canEdit: true,
},
{
key: "unit",
label: "Unit",
type: "text" as const,
placeholder: "Disabled for Tandoor",
canEdit: false,
},
],
// time in minutes to sync the integration
syncInterval: 5,
},
];
// 3. Add your service factory to the serviceFactoryMap object
const serviceFactoryMap = {
"calendar:iCal": createICalService, // existing entry
"calendar:google": createGoogleCalendarService, // existing entry
"shopping:mealie": createMealieService, // existing entry
"shopping:tandoor": createTandoorService, // Add your factory function here
} as const;
// 4. (Optional) Add field filter for shopping integrations
const fieldFilters = {
mealie: getMealieFieldsForItem,
tandoor: getTandoorFieldsForItem, // Add your field filter function here if needed
};
Troubleshooting Integrations
Common Issues
Authentication Errors
1
2
3
# Ensure service is on the same Docker network as dev container
# Ensure correct base URL
# Check token expiration
Data Sync Issues
1
2
3
4
# Check network connectivity
# Verify API endpoints
# Review error logs
# Test with minimal data set