Development Guide

Welcome to the Skylite UX development guide! This document will help you set up your development environment and understand the project structure.

Prerequisites

Before you begin, ensure you have the following installed:

Quick Start

# npm
npm run dev

Project Structure

Skylite-UX/
├── .devcontainer/           # Dev container configuration
│   └── integrations/        # Compose files to deploy integration containers
├── app/                     # Main application code
│   ├── assets/              # Static assets (CSS, images, etc.)
│   ├── components/          # Vue components
│   │   ├── calendar/        # Calendar-related components
│   │   ├── global/          # Global/shared components
│   │   ├── settings/        # Settings page components
│   │   ├── shopping/        # Shopping list components
│   │   └── todos/           # Todo list components
│   ├── composables/         # Vue composables
│   ├── integrations/        # External integration files
│   ├── lib/                 # Library configurations
│   ├── pages/               # Application pages (auto-routed)
│   ├── plugins/             # Nuxt plugins
│   ├── types/               # TypeScript type definitions
│   ├── utils/               # Utility functions
│   ├── app.config.ts        # App configuration
│   └── app.vue              # Root Vue component
├── prisma/                  # Database schema and migrations
│   ├── migrations/          # Database migration files
│   └── schema.prisma        # Prisma schema definition
├── public/                  # Public static assets
├── server/                  # Server-side code
│   ├── api/                 # API endpoints
│   │   ├── integrations/    # Integration API routes
│   │   ├── shopping-lists/  # Shopping list API routes
│   │   ├── todos/           # Todo API routes
│   │   └── users/           # User API routes
│   ├── integrations         # Integration service files
│   └── plugins/             # Server plugins
├── eslint.config.mjs        # ESLint configuration
├── LICENSE.md               # Project license
├── nuxt.config.ts           # Nuxt configuration
├── package.json             # Dependencies and scripts
├── README.md                # Project documentation
└── tsconfig.json            # TypeScript configuration

Development Workflow

1. Branch Strategy

2. Development Process

  1. Create a branch
    git checkout dev
    git pull origin dev
    git checkout -b feature/your-feature-name
  2. Make your changes
    • Write code following the style guide
    • Add tests for new features
    • Update documentation (if required)
  3. Test your changes
    npm run test
    npm run lint
    npm run type-check
  4. Commit your changes
    git add .
    git commit -m "feat: add new feature description"
  5. Push and create PR
    git push origin feature/your-feature-name
    # Create Pull Request to dev branch

3. Code Style

All linting rules are defined in eslint.config.mjs.

File Naming Conventions

The project uses a camelCase naming convention for all files with some exceptions such as API routes and docker compose files where kebab-case is the convention.

Vue & TypeScript Guidelines

Styling Guidelines

Code Quality

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

Adding New Features to Existing Self-Hosted Integrations

  1. Spin up the Docker container found in Skylite-UX/.devcontainer/integrations/
  2. Generate an API key for the service
  3. Add the service to Skylite in Settings > Integrations > Add Integration
  4. Make your changes, test, and commit as defined in the Development Workflow

Adding New Integrations

  1. Create a new folder in Skylite-UX/.devcontainer/integrations/
  2. Create a Docker Compose file for the new service you are integrating
  3. Add a new folder in Skylite-UX/app/integrations/
  4. Create your integration file
  5. Add a new folder in Skylite-UX/server/api/integrations
  6. Create your API endpoint file(s)
  7. Add a new folder in Skylite-UX/server/integrations
  8. Create your service files
  9. Add your service in Skylite-UX/app/integrations/integrationConfig.ts so it will be picked up when Skylite starts
  10. Spin up your Docker container
  11. Generate an API key
  12. Add the service to Skylite in Settings > Integrations > Add Integration
  13. Test and commit as defined in the Development Workflow

Integration Configuration

Docker Compose for Integrations

# .devcontainer/integrations/service/service-docker-compose.yml
version: '3.8'

services:
  # Comments about the integration
  # How to create API key, base URL, etc.
  # Base URL: 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

{
    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
    files: [
      // list your file paths for your integration
      "/integrations/tandoor/tandoorShoppingLists.ts", 
      "/server/api/integrations/tandoor/[...path].ts",
      "/server/integrations/tandoor/"
    ],
    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,
  },

Troubleshooting Integrations

Common Issues

Authentication Errors
# Ensure service is on the same Docker network as dev container
# Ensure correct base URL
# Check token expiration
Data Sync Issues
# Check network connectivity
# Verify API endpoints
# Review error logs
# Test with minimal data set

Testing

Skylite-UX uses @nuxt/test-utils for comprehensive testing support, including both unit and end-to-end tests.

Building

Development Build

npm run build:dev

Production Build

npm run build

Preview Production Build

npm run preview

Docker Build

# Build Docker image
docker build -t skylite-ux .

# Run Docker container
docker run -p 3000:3000 skylite-ux

Troubleshooting

Common Issues

Port Already in Use

# Find process using port 3000
lsof -i :3000

# Kill the process
kill -9 <PID>

Node Modules Issues

# Clear npm cache
npm cache clean --force

# Remove node_modules and reinstall
rm -rf node_modules package-lock.json
npm install

Docker Issues

# Clean up Docker containers
docker system prune -a

# Rebuild without cache
docker-compose build --no-cache

TypeScript Errors

# Check TypeScript configuration
npm run type-check

# Regenerate TypeScript types
npm run types:generate

Getting Help

Additional Resources