### Start development servers: cargo run, caddy run, yarn turbo run Source: https://docs.ryot.io/contributing Run these three commands in separate terminals to start the backend, Caddy reverse proxy, and frontend development server. The frontend is then available at http://localhost:8000. ```bash cargo run ``` ```bash caddy run --config 'ci/Caddyfile' ``` ```bash yarn turbo run dev --filter=@ryot/frontend ``` -------------------------------- ### Kubernetes Helm installation Source: https://docs.ryot.io/deployment Installs the Ryot Helm chart from the GitHub Container Registry with required security and configuration settings. ```bash helm install ryot oci://ghcr.io/ignisda/charts/ryot \ --set secret.adminAccessToken.value="$(openssl rand -hex 16)" \ --set postgres.auth.password="$(openssl rand -hex 16)" \ --set config.frontendUrl="https://ryot.your-domain.com" ``` -------------------------------- ### Start PostgreSQL with Docker Source: https://docs.ryot.io/contributing Run a PostgreSQL 18 Alpine container with the credentials and database name expected by the project's DATABASE_URL. Exposes port 5432 on localhost. ```bash docker run -e POSTGRES_PASSWORD=postgres -e POSTGRES_USER=postgres -e POSTGRES_DB=postgres -p 5432:5432 postgres:18-alpine ``` -------------------------------- ### Dokku deployment script Source: https://docs.ryot.io/deployment A bash script to automate Ryot server setup on Dokku using the Ghcr image. Requires sudo privileges and an existing global domain configuration. ```bash #!/usr/bin/env bash set -euo pipefail if [ "$EUID" -ne 0 ] then echo "Please run as root" exit fi IMAGE_NAME="ignisda/ryot" APPNAME="" read -rp "Enter the name of the app: " APPNAME # check if app name is empty if [ -z "$APPNAME" ]; then echo "App name empty. Using default name: ryot" APPNAME="ryot" fi # pull the latest image docker rmi -f "$IMAGE_NAME" || true docker pull "$IMAGE_NAME:latest" image_sha="$(docker inspect --format={{ '"{{index .RepoDigests 0}}"' }} $IMAGE_NAME)" echo "Calculated image sha: $image_sha" if dokku apps:exists $APPNAME; then dokku git:from-image $APPNAME $image_sha || echo "Already on latest" exit 0 fi dokku apps:create "$APPNAME" dokku postgres:create "$APPNAME-service" dokku postgres:link "$APPNAME-service" "$APPNAME" # check if required dokku plugin exists if ! dokku plugin:list | grep letsencrypt; then dokku plugin:install https://github.com/dokku/dokku-letsencrypt.git fi dokku domains:add $APPNAME $APPNAME."$(cat /home/dokku/VHOST)" dokku letsencrypt:enable "$APPNAME" dokku git:from-image "$APPNAME" "$image_sha" ``` -------------------------------- ### Docker Compose image update for v4 Source: https://docs.ryot.io/migration Example configuration change for the docker-compose file to upgrade to the latest RYOT version. ```yaml image: "ignisda/ryot:latest" ``` -------------------------------- ### Sink integration webhook URL format Source: https://docs.ryot.io/integrations/overview Webhook URL format for sink integrations. The first line shows the generic pattern with placeholders, and the second line is a concrete example. Keep these URLs private to prevent abuse. ```txt https:///_i/ https://app.ryot.io/_i/int_a6cGGXEq6KOI # example ``` -------------------------------- ### Create environment file with APP_VERSION, UNKEY_ROOT_KEY, DATABASE_URL Source: https://docs.ryot.io/contributing Create this environment file in the repository root. APP_VERSION is set to v10.0.2, UNKEY_ROOT_KEY is a dummy value, and DATABASE_URL points to the local PostgreSQL instance. ```bash APP_VERSION=v10.0.2 UNKEY_ROOT_KEY=dummy-root-key DATABASE_URL=postgres://postgres:postgres@localhost:5432/postgres ``` -------------------------------- ### Fly deployment: Launch application Source: https://docs.ryot.io/deployment Deploys the application using the fly.toml configuration file. ```bash flyctl launch ``` -------------------------------- ### Fly deployment: Create database Source: https://docs.ryot.io/deployment Initial step to create a new postgres database for the Ryot instance on Fly. ```bash flyctl postgres create ryot-db ``` -------------------------------- ### Fly deployment: Attach database Source: https://docs.ryot.io/deployment Connects the previously created postgres database to the Ryot application. ```bash fly postgres attach --app ryot ryot-db ``` -------------------------------- ### Run final v1 release for migrations Source: https://docs.ryot.io/migration Run the last v1 release of the server to perform all necessary migrations before upgrading. ```bash $ docker run --volume ./ryot/data:/data ignisda/ryot:v1.22.1 ``` -------------------------------- ### Deploy Ryot with Docker Compose Source: https://docs.ryot.io/ Use this docker-compose.yml file to set up the Ryot service and its required PostgreSQL database. Ensure you replace the placeholder values for FRONTEND_URL, DATABASE_URL, and SERVER_ADMIN_ACCESS_TOKEN. ```yaml services: ryot-db: image: postgres:18-alpine # at-least version 15 is required restart: unless-stopped container_name: ryot-db volumes: - postgres_storage:/var/lib/postgresql environment: - TZ=Europe/Amsterdam - POSTGRES_DB=postgres - POSTGRES_USER=postgres - POSTGRES_PASSWORD=postgres ryot: image: ignisda/ryot:v10 # or ghcr.io/ignisda/ryot:v10 pull_policy: always container_name: ryot restart: unless-stopped ports: - "8000:8000" environment: - TZ=Europe/Amsterdam - FRONTEND_URL=https://ryot.your-domain.com # IP address is fine too - DATABASE_URL=postgres://postgres:postgres@ryot-db:5432/postgres # REQUIRED - SERVER_ADMIN_ACCESS_TOKEN=28ebb3ae554fa9867ba0 # REQUIRED: set to a long random string volumes: postgres_storage: ``` -------------------------------- ### Set Spotify environment variables Source: https://docs.ryot.io/guides/music Configure the Spotify Client ID and Client Secret as environment variables for your Ryot instance. ```bash MUSIC_SPOTIFY_CLIENT_ID=your_client_id_here MUSIC_SPOTIFY_CLIENT_SECRET=your_client_secret_here ``` -------------------------------- ### Convert local user to OIDC user with SQL Source: https://docs.ryot.io/guides/authentication SQL commands to convert a local user to an OIDC user. First, delete the newly created OIDC user (identified by its oidc_issuer_id) using DELETE FROM "user" WHERE id = 'usr_v5aGOC9UzrId';. Then update the old local user's record with the OIDC issuer ID and set password to NULL using UPDATE "user" SET oidc_issuer_id = '104798859970005336426', password = NULL WHERE id = 'usr_ujrD0pCeKc1Y';. Run these in the database via docker exec -u postgres -it ryot-db psql. ```sql DELETE FROM "user" WHERE id = 'usr_v5aGOC9UzrId'; ``` ```sql UPDATE "user" SET oidc_issuer_id = '104798859970005336426', password = NULL WHERE id = 'usr_ujrD0pCeKc1Y'; ``` -------------------------------- ### Fly deployment: Configure secrets Source: https://docs.ryot.io/deployment Sets instance configuration secrets, such as S3 storage URLs. ```bash fly secrets set FILE_STORAGE_S3_URL='https://play.min.io:9000' ``` -------------------------------- ### Insert seaql_migrations for v3 to v4 upgrade Source: https://docs.ryot.io/migration SQL statements to populate the seaql_migrations table during the upgrade process from v3 to v4. ```sql INSERT INTO seaql_migrations (version, applied_at) VALUES ('m20230410_create_metadata', 1684693316); INSERT INTO seaql_migrations (version, applied_at) VALUES ('m20230413_create_person', 1684693316); INSERT INTO seaql_migrations (version, applied_at) VALUES ('m20230417_create_user', 1684693316); INSERT INTO seaql_migrations (version, applied_at) VALUES ('m20230419_create_seen', 1684693316); INSERT INTO seaql_migrations (version, applied_at) VALUES ('m20230501_create_metadata_group', 1697640078); INSERT INTO seaql_migrations (version, applied_at) VALUES ('m20230502_create_genre', 1684693316); INSERT INTO seaql_migrations (version, applied_at) VALUES ('m20230504_create_collection', 1684693316); INSERT INTO seaql_migrations (version, applied_at) VALUES ('m20230505_create_review', 1684693316); INSERT INTO seaql_migrations (version, applied_at) VALUES ('m20230509_create_import_report', 1684693316); INSERT INTO seaql_migrations (version, applied_at) VALUES ('m20230622_create_exercise', 1697640078); INSERT INTO seaql_migrations (version, applied_at) VALUES ('m20230804_create_user_measurement', 1697640078); INSERT INTO seaql_migrations (version, applied_at) VALUES ('m20230819_create_workout', 1697640078); INSERT INTO seaql_migrations (version, applied_at) VALUES ('m20230901_create_partial_metadata', 1697640078); INSERT INTO seaql_migrations (version, applied_at) VALUES ('m20230912_create_calendar_event', 1697640078); INSERT INTO seaql_migrations (version, applied_at) VALUES ('m20231003_create_partial_metadata_to_person', 1697640078); INSERT INTO seaql_migrations (version, applied_at) VALUES ('m20231016_create_collection_to_entity', 1697640078); INSERT INTO seaql_migrations (version, applied_at) VALUES ('m20231017_create_user_to_entity', 1697640078); ``` -------------------------------- ### Enable Ryot Pro Features Source: https://docs.ryot.io/ Add the SERVER_PRO_KEY environment variable to your existing ryot service configuration in docker-compose.yml to enable Pro features. ```diff ryot: environment: + - SERVER_PRO_KEY= ``` -------------------------------- ### Configure OIDC environment variables Source: https://docs.ryot.io/guides/authentication Environment variables required to configure OpenID Connect (OIDC) authentication for Ryot. Set SERVER_OIDC_CLIENT_ID, SERVER_OIDC_CLIENT_SECRET, and SERVER_OIDC_ISSUER_URL; FRONTEND_URL is the instance URL. Optional variables include FRONTEND_OIDC_BUTTON_LABEL and RUST_LOG for debugging. After setting these, restart the instance to see the 'Continue with OpenID Connect' button. ```bash FRONTEND_URL=https://app.ryot.io # The URL of your Ryot instance SERVER_OIDC_CLIENT_ID=******** SERVER_OIDC_CLIENT_SECRET=******** SERVER_OIDC_ISSUER_URL=https://accounts.google.com # The URL of your OIDC provider (might end with trailing slash) # Below are optional FRONTEND_OIDC_BUTTON_LABEL=Use Google RUST_LOG=ryot=debug # To debug why OIDC authentication is failing ``` -------------------------------- ### Reset and populate seaql_migrations for v2 to v3 upgrade Source: https://docs.ryot.io/migration SQL commands to clear existing migrations and re-insert the required migration history for the v2 to v3 upgrade. ```sql DELETE FROM seaql_migrations; INSERT INTO seaql_migrations (version, applied_at) VALUES ('m20230410_create_metadata', 1684693316); INSERT INTO seaql_migrations (version, applied_at) VALUES ('m20230413_create_person', 1684693316); INSERT INTO seaql_migrations (version, applied_at) VALUES ('m20230417_create_user', 1684693316); INSERT INTO seaql_migrations (version, applied_at) VALUES ('m20230419_create_seen', 1684693316); INSERT INTO seaql_migrations (version, applied_at) VALUES ('m20230502_create_genre', 1684693316); INSERT INTO seaql_migrations (version, applied_at) VALUES ('m20230505_create_review', 1684693316); INSERT INTO seaql_migrations (version, applied_at) VALUES ('m20230507_create_collection', 1684693316); INSERT INTO seaql_migrations (version, applied_at) VALUES ('m20230509_create_import_report', 1684693316); INSERT INTO seaql_migrations (version, applied_at) VALUES ('m20230622_create_exercise', 1697640078); INSERT INTO seaql_migrations (version, applied_at) VALUES ('m20230804_create_user_measurement', 1697640078); INSERT INTO seaql_migrations (version, applied_at) VALUES ('m20230819_create_workout', 1697640078); INSERT INTO seaql_migrations (version, applied_at) VALUES ('m20230901_create_metadata_group', 1697640078); INSERT INTO seaql_migrations (version, applied_at) VALUES ('m20230901_create_partial_metadata', 1697640078); INSERT INTO seaql_migrations (version, applied_at) VALUES ('m20230912_create_calendar_event', 1697640078); INSERT INTO seaql_migrations (version, applied_at) VALUES ('m20231003_create_partial_metadata_to_person', 1697640078); INSERT INTO seaql_migrations (version, applied_at) VALUES ('m20231016_create_collection_to_entity', 1697640078); INSERT INTO seaql_migrations (version, applied_at) VALUES ('m20231017_create_user_to_entity', 1697640078); ``` -------------------------------- ### Configure Ryot for Cloudflare R2 with environment variables Source: https://docs.ryot.io/guides/file-storage Set these environment variables on your Ryot instance to use Cloudflare R2 for file storage and exporting. Replace with your Cloudflare account ID and use the actual values for your bucket name and API credentials. FILE_STORAGE_S3_REGION is optional; some clients require a region, so use "auto" for R2. ```sh FILE_STORAGE_S3_BUCKET_NAME=ryot-storage FILE_STORAGE_S3_ACCESS_KEY_ID=your-access-key-id FILE_STORAGE_S3_SECRET_ACCESS_KEY=your-secret-access-key FILE_STORAGE_S3_URL=https://.r2.cloudflarestorage.com FILE_STORAGE_S3_REGION=auto # optional: some clients require a region; use "auto" for R2 ``` -------------------------------- ### Export and restore the entire database with pg_dump and pg_restore Source: https://docs.ryot.io/exporting Use these commands to export and restore the entire Ryot database. The first command dumps the database to a file, and the second restores it from that file. Both commands require the ryot-db container to be running. ```bash docker exec -u postgres -i ryot-db pg_dump -Fc --no-acl --no-owner > /tmp/ryot.file.sql ``` ```bash docker exec -u postgres -i ryot-db pg_restore -U postgres -d postgres < /tmp/ryot.file.sql ``` -------------------------------- ### WorkoutSummary Interface Source: https://docs.ryot.io/exporting Represents the overall summary of a workout, containing exercises, focused metrics, and total values. ```typescript export interface WorkoutSummary { exercises: WorkoutSummaryExercise[]; focused: WorkoutFocusedSummary; total: WorkoutOrExerciseTotals | null; } ``` -------------------------------- ### Workout Summary Interfaces Source: https://docs.ryot.io/exporting Interfaces for summarizing exercises, equipment, force, and level focus within a workout. ```typescript /** The summary about an exercise done in a workout. */ export interface WorkoutSummaryExercise { best_set: WorkoutSetRecord | null; id: string; /** @default 'reps_and_weight' */ lot: ExerciseLot | null; num_sets: number; /** * @default 'metric' * @type {'metric' | 'imperial'} */ unit_system: UserUnitSystem; } export type ExerciseEquipment = 'bands' | 'cable' | 'other' | 'barbell' | 'machine' | 'body_only' | 'dumbbell' | 'foam_roll' | 'ez_curl_bar' | 'kettlebells' | 'exercise_ball' | 'medicine_ball'; export interface WorkoutEquipmentFocusedSummary { /** * @default 'barbell' * @type {'bands' | 'cable' | 'other' | 'barbell' | 'machine' | 'body_only' | 'dumbbell' | 'foam_roll' | 'ez_curl_bar' | 'kettlebells' | 'exercise_ball' | 'medicine_ball'} */ equipment: ExerciseEquipment; exercises: number[]; } export type ExerciseForce = 'pull' | 'push' | 'static'; export interface WorkoutForceFocusedSummary { exercises: number[]; /** * @default 'pull' * @type {'pull' | 'push' | 'static'} */ force: ExerciseForce; } export type ExerciseLevel = 'beginner' | 'expert' | 'intermediate'; export interface WorkoutLevelFocusedSummary { exercises: number[]; /** * @default 'beginner' * @type {'beginner' | 'expert' | 'intermediate'} */ level: ExerciseLevel; } ``` -------------------------------- ### Set Hardcover API key environment variable Source: https://docs.ryot.io/guides/books Set this environment variable to enable Hardcover book tracking in Ryot. The API key expires after a year or on January 1st, so you will need to renew it accordingly. ```bash BOOKS_HARDCOVER_API_KEY=Bearer eyJhbGciOiJIUzI1NiIsCJ9.5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36Pw5c ``` -------------------------------- ### WorkoutFocusedSummary Interface Source: https://docs.ryot.io/exporting Aggregates various focused summary types including equipment, forces, levels, lots, and muscles. ```typescript export interface WorkoutFocusedSummary { equipments: WorkoutEquipmentFocusedSummary[]; forces: WorkoutForceFocusedSummary[]; levels: WorkoutLevelFocusedSummary[]; lots: WorkoutLotFocusedSummary[]; muscles: WorkoutMuscleFocusedSummary[]; } ``` -------------------------------- ### ImportOrExportMetadataItem interface Source: https://docs.ryot.io/exporting Defines a media item for import/export, including collections, identifier, lot, reviews, seen history, source, and source_id. The lot defaults to 'book' and source defaults to 'custom'. ```typescript export interface ImportOrExportMetadataItem { /** The collections this entity was added to. */ collections: CollectionToEntityDetails[]; /** The provider identifier. For eg: TMDB-ID, Openlibrary ID and so on. */ identifier: string; /** * The type of media. * * @default 'book' * @type {'book' | 'show' | 'movie' | 'anime' | 'manga' | 'music' | 'podcast' | 'audio_book' | 'video_game' | 'comic_book' | 'visual_novel'} */ lot: MediaLot; /** The review history for the user. */ reviews: ImportOrExportItemRating[]; /** The seen history for the user. */ seen_history: ImportOrExportMetadataItemSeen[]; /** * The source of media. * * @default 'custom' * @type {'igdb' | 'tmdb' | 'tvdb' | 'vndb' | 'custom' | 'metron' | 'itunes' | 'anilist' | 'audible' | 'spotify' | 'music_brainz' | 'giant_bomb' | 'hardcover' | 'myanimelist' | 'listennotes' | 'google_books' | 'openlibrary' | 'manga_updates' | 'youtube_music'} */ source: MediaSource; /** An string to help identify it in the original source. */ source_id: string; } ``` -------------------------------- ### Workout Interface Source: https://docs.ryot.io/exporting Represents a completed workout by the user, including timing, metrics, and summary data. ```typescript /** A workout that was completed by the user. */ export interface Workout { calories_burnt: string | null; duration: number; end_time: string; id: string; information: WorkoutInformation; name: string; repeated_from: string | null; start_time: string; summary: WorkoutSummary; template_id: string | null; } ``` -------------------------------- ### WorkoutMuscleFocusedSummary Interface Source: https://docs.ryot.io/exporting Defines the structure for a workout summary focused on specific muscle groups. ```typescript export interface WorkoutMuscleFocusedSummary { exercises: number[]; /** * @default 'abdominals' * @type {'lats' | 'neck' | 'traps' | 'chest' | 'biceps' | 'calves' | 'glutes' | 'triceps' | 'forearms' | 'abductors' | 'adductors' | 'lower_back' | 'shoulders' | 'abdominals' | 'hamstrings' | 'middle_back' | 'quadriceps'} */ muscle: ExerciseMuscle; } ``` -------------------------------- ### Workout Set Statistics and Records Source: https://docs.ryot.io/exporting Interfaces for tracking individual set statistics, totals, and records. ```typescript /** Details about the statistics of the set performed. */ export interface WorkoutSetStatistic { distance: string | null; duration: string | null; one_rm: string | null; pace: string | null; reps: string | null; volume: string | null; weight: string | null; } export interface WorkoutSetTotals { weight: string | null; } /** Details about the set performed. */ export interface WorkoutSetRecord { confirmed_at: string | null; /** * @default 'normal' * @type {'drop' | 'normal' | 'warm_up' | 'failure'} */ lot: SetLot; note: string | null; personal_bests: WorkoutSetPersonalBest[] | null; rest_time: number | null; rest_timer_started_at: string | null; rpe: number | null; statistic: WorkoutSetStatistic; totals: WorkoutSetTotals | null; } ``` -------------------------------- ### WorkoutLotFocusedSummary Interface Source: https://docs.ryot.io/exporting Defines the structure for a workout summary focused on exercise lots, including a list of exercise IDs and the specific exercise lot type. ```typescript export interface WorkoutLotFocusedSummary { exercises: number[]; /** * @default 'reps_and_weight' * @type {'reps' | 'duration' | 'reps_and_weight' | 'reps_and_duration' | 'distance_and_duration' | 'reps_and_duration_and_distance'} */ lot: ExerciseLot; } ``` -------------------------------- ### ProcessedExercise and WorkoutInformation Interfaces Source: https://docs.ryot.io/exporting Defines the structure for processed exercises and complete workout information. ```typescript export type UserUnitSystem = 'metric' | 'imperial'; /** An exercise that has been processed and committed to the database. */ export interface ProcessedExercise { assets: EntityAssets | null; id: string; /** * @default 'reps_and_weight' * @type {'reps' | 'duration' | 'reps_and_weight' | 'reps_and_duration' | 'distance_and_duration' | 'reps_and_duration_and_distance'} */ lot: ExerciseLot; notes: string[]; sets: WorkoutSetRecord[]; total: WorkoutOrExerciseTotals | null; /** * @default 'metric' * @type {'metric' | 'imperial'} */ unit_system: UserUnitSystem; } export interface WorkoutSupersetsInformation { /** A color that will be displayed on the frontend. */ color: string; /** The identifier of all the exercises which are in the same superset */ exercises: number[]; } /** Information about a workout done. */ export interface WorkoutInformation { assets: EntityAssets | null; comment: string | null; exercises: ProcessedExercise[]; supersets: WorkoutSupersetsInformation[]; } ``` -------------------------------- ### MediaLot and SeenState type aliases Source: https://docs.ryot.io/exporting Defines the MediaLot union type for supported media types and the SeenState union type for viewing states. MediaLot includes book, show, movie, anime, manga, music, podcast, audio_book, video_game, comic_book, and visual_novel. SeenState includes dropped, on_a_hold, completed, and in_progress. ```typescript export type MediaLot = 'book' | 'show' | 'movie' | 'anime' | 'manga' | 'music' | 'podcast' | 'audio_book' | 'video_game' | 'comic_book' | 'visual_novel'; export type SeenState = 'dropped' | 'on_a_hold' | 'completed' | 'in_progress'; ``` -------------------------------- ### Workout and Exercise Totals Source: https://docs.ryot.io/exporting Defines the summary totals for a workout or exercise. ```typescript /** The totals of a workout and the different bests achieved. */ export interface WorkoutOrExerciseTotals { distance: string; duration: string; /** The number of personal bests achieved. */ personal_bests_achieved: number; reps: string; /** The total seconds that were logged in the rest timer. */ rest_time?: number; weight: string; } ``` -------------------------------- ### WorkoutTemplate Interface Source: https://docs.ryot.io/exporting Defines the structure of a workout template, including metadata and summary information. ```typescript export interface WorkoutTemplate { created_on: string; id: string; information: WorkoutInformation; name: string; summary: WorkoutSummary; } ``` -------------------------------- ### Manually update seaql_migrations table Source: https://docs.ryot.io/migration Execute these SQL commands to update the migration history in the database before upgrading to the public v2 release. ```sql DELETE FROM seaql_migrations; INSERT INTO seaql_migrations (version, applied_at) VALUES ('m20230410_create_metadata', 1684693316); INSERT INTO seaql_migrations (version, applied_at) VALUES ('m20230412_create_creator', 1684693316); INSERT INTO seaql_migrations (version, applied_at) VALUES ('m20230417_create_user', 1684693316); INSERT INTO seaql_migrations (version, applied_at) VALUES ('m20230419_create_seen', 1684693316); INSERT INTO seaql_migrations (version, applied_at) VALUES ('m20230502_create_genre', 1684693316); INSERT INTO seaql_migrations (version, applied_at) VALUES ('m20230505_create_review', 1684693316); INSERT INTO seaql_migrations (version, applied_at) VALUES ('m20230507_create_collection', 1684693316); INSERT INTO seaql_migrations (version, applied_at) VALUES ('m20230509_create_import_report', 1684693316); ``` -------------------------------- ### CompleteExport Interface Source: https://docs.ryot.io/exporting The root interface for a complete user data export, containing collections, exercises, measurements, metadata, people, templates, and workouts. ```typescript /** Complete export of the user. */ export interface CompleteExport { /** Data about user's collections. */ collections: CollectionItem[] | null; /** Data about user's exercises. */ exercises: ImportOrExportExerciseItem[] | null; /** Data about user's measurements. */ measurements: UserMeasurement[] | null; /** Data about user's media. */ metadata: ImportOrExportMetadataItem[] | null; /** Data about user's media groups. */ metadata_groups: ImportOrExportMetadataGroupItem[] | null; /** Data about user's people. */ people: ImportOrExportPersonItem[] | null; /** Data about user's workout templates. */ workout_templates: ImportOrExportWorkoutTemplateItem[] | null; /** Data about user's workouts. */ workouts: ImportOrExportWorkoutItem[] | null; } ``` -------------------------------- ### Exercise and Set Type Definitions Source: https://docs.ryot.io/exporting Defines the categories for exercises, sets, and personal bests. ```typescript /** The different types of exercises that can be done. */ export type ExerciseLot = 'reps' | 'duration' | 'reps_and_weight' | 'reps_and_duration' | 'distance_and_duration' | 'reps_and_duration_and_distance'; /** The types of set (mostly characterized by exertion level). */ export type SetLot = 'drop' | 'normal' | 'warm_up' | 'failure'; /** The different types of personal bests that can be achieved on a set. */ export type WorkoutSetPersonalBest = 'time' | 'pace' | 'reps' | 'one_rm' | 'volume' | 'weight' | 'distance'; ``` -------------------------------- ### ImportOrExportMetadataItemSeen interface Source: https://docs.ryot.io/exporting Defines a specific instance when an entity was seen, including optional episode/chapter numbers, timestamps, progress, providers, and state. The state defaults to 'completed' if not provided. ```typescript export interface ImportOrExportMetadataItemSeen { /** If for an anime, the episode which was seen. */ anime_episode_number: number | null; /** The timestamp when finished watching. */ ended_on: string | null; /** If for a manga, the chapter which was seen. */ manga_chapter_number: string | null; /** If for a manga, the volume which was seen. */ manga_volume_number: number | null; /** The amount of time (in seconds) spent consuming the item manually. */ manual_time_spent: string | null; /** If for a podcast, the episode which was seen. */ podcast_episode_number: number | null; /** The progress of media done. If none, it is considered as done. */ progress: string | null; /** The providers this item was consumed on. */ providers_consumed_on: string[] | null; /** If for a show, the episode which was seen. */ show_episode_number: number | null; /** If for a show, the season which was seen. */ show_season_number: number | null; /** The timestamp when started watching. */ started_on: string | null; /** * The state of the media item. * * @default 'completed' */ state: SeenState | null; } ``` -------------------------------- ### ImportOrExportWorkoutTemplateItem Interface Source: https://docs.ryot.io/exporting Wraps a workout template with collection details for import or export purposes. ```typescript export interface ImportOrExportWorkoutTemplateItem { collections: CollectionToEntityDetails[]; details: WorkoutTemplate; } ``` -------------------------------- ### CORS configuration for Cloudflare R2 bucket Source: https://docs.ryot.io/guides/file-storage Add this CORS policy to your R2 bucket to allow your Ryot instance to upload files directly from the browser. Adjust the origins to match your Ryot instance URLs. The policy permits PUT requests with the content-type header. ```json [ { "AllowedOrigins": [ "https://app.ryot.io", "https://pro.ryot.io" ], "AllowedMethods": [ "PUT" ], "AllowedHeaders": [ "content-type" ] } ] ``` -------------------------------- ### PersonSourceSpecifics interface Source: https://docs.ryot.io/exporting Defines provider-specific flags for a person, indicating whether they are a studio, company, or publisher on various platforms. ```typescript export interface PersonSourceSpecifics { is_anilist_studio: boolean | null; is_giant_bomb_company: boolean | null; is_hardcover_publisher: boolean | null; is_tmdb_company: boolean | null; is_tvdb_company: boolean | null; } ``` -------------------------------- ### ImportOrExportMetadataGroupItem interface Source: https://docs.ryot.io/exporting Defines a media group item for import/export, similar to ImportOrExportMetadataItem but with a title field for the group name. Includes collections, identifier, lot, reviews, source, and title. ```typescript export interface ImportOrExportMetadataGroupItem { /** The collections this entity was added to. */ collections: CollectionToEntityDetails[]; /** The provider identifier. For eg: TMDB-ID, Openlibrary ID and so on. */ identifier: string; /** * The type of media. * * @default 'book' * @type {'book' | 'show' | 'movie' | 'anime' | 'manga' | 'music' | 'podcast' | 'audio_book' | 'video_game' | 'comic_book' | 'visual_novel'} */ lot: MediaLot; /** The review history for the user. */ reviews: ImportOrExportItemRating[]; /** * The source of media. * * @default 'custom' * @type {'igdb' | 'tmdb' | 'tvdb' | 'vndb' | 'custom' | 'metron' | 'itunes' | 'anilist' | 'audible' | 'spotify' | 'music_brainz' | 'giant_bomb' | 'hardcover' | 'myanimelist' | 'listennotes' | 'google_books' | 'openlibrary' | 'manga_updates' | 'youtube_music'} */ source: MediaSource; /** Name of the group. */ title: string; } ``` -------------------------------- ### ImportOrExportWorkoutItem Interface Source: https://docs.ryot.io/exporting Wraps a workout entity with collection details for import or export operations. ```typescript /** Details about a specific exercise item that needs to be exported. */ export interface ImportOrExportWorkoutItem { /** The collections this entity was added to. */ collections: CollectionToEntityDetails[]; /** The details of the workout. */ details: Workout; } ``` -------------------------------- ### User measurement type definitions Source: https://docs.ryot.io/exporting Defines interfaces for user measurement statistics, information, and the measurement export structure. Includes comment, name, timestamp, and asset/statistics fields. ```typescript export interface UserMeasurementStatistic { name: string; value: string; } /** The actual statistics that were logged in a user measurement. */ export interface UserMeasurementInformation { assets: EntityAssets; statistics: UserMeasurementStatistic[]; } /** An export of a measurement taken at a point in time. */ export interface UserMeasurement { /** Any comment associated entered by the user. */ comment: string | null; /** The contents of the actual measurement. */ information: UserMeasurementInformation; /** The name given to this measurement by the user. */ name: string | null; /** The date and time this measurement was made. */ timestamp: string; } ``` -------------------------------- ### ImportOrExportPersonItem Interface Source: https://docs.ryot.io/exporting Defines the structure for a creator item, including collections, provider identifiers, and source-specific data. ```typescript /** Details about a specific creator item that needs to be exported. */ export interface ImportOrExportPersonItem { /** The collections this entity was added to. */ collections: CollectionToEntityDetails[]; /** The provider identifier. */ identifier: string; /** The name of the creator. */ name: string; /** The review history for the user. */ reviews: ImportOrExportItemRating[]; /** * The source of data. * * @default 'custom' * @type {'igdb' | 'tmdb' | 'tvdb' | 'vndb' | 'custom' | 'metron' | 'itunes' | 'anilist' | 'audible' | 'spotify' | 'music_brainz' | 'giant_bomb' | 'hardcover' | 'myanimelist' | 'listennotes' | 'google_books' | 'openlibrary' | 'manga_updates' | 'youtube_music'} */ source: MediaSource; /** The source specific data. */ source_specifics: PersonSourceSpecifics | null; } ``` -------------------------------- ### MediaSource type alias Source: https://docs.ryot.io/exporting Defines the MediaSource union type for all supported data providers, including IGDB, TMDB, TVDB, VNDB, custom, and many others. ```typescript export type MediaSource = 'igdb' | 'tmdb' | 'tvdb' | 'vndb' | 'custom' | 'metron' | 'itunes' | 'anilist' | 'audible' | 'spotify' | 'music_brainz' | 'giant_bomb' | 'hardcover' | 'myanimelist' | 'listennotes' | 'google_books' | 'openlibrary' | 'manga_updates' | 'youtube_music'; ``` -------------------------------- ### ExerciseMuscle Type Source: https://docs.ryot.io/exporting A union type representing all possible muscle groups that can be targeted in a workout. ```typescript export type ExerciseMuscle = 'lats' | 'neck' | 'traps' | 'chest' | 'biceps' | 'calves' | 'glutes' | 'triceps' | 'forearms' | 'abductors' | 'adductors' | 'lower_back' | 'shoulders' | 'abdominals' | 'hamstrings' | 'middle_back' | 'quadriceps'; ``` -------------------------------- ### CompleteExport TypeScript type definitions Source: https://docs.ryot.io/exporting TypeScript type definitions for the CompleteExport schema, automatically generated by schematic. These interfaces describe the structure of exported data, including collections, reviews, ratings, and entity assets. Use these types when working with the JSON export format. ```ts // Automatically generated by schematic. DO NOT MODIFY! /* eslint-disable */ export interface StringIdAndNamedObject { id: string; name: string; } export interface UserToCollectionExtraInformation { is_hidden: boolean | null; } export interface CollectionItemCollaboratorInformation { collaborator: StringIdAndNamedObject; extra_information: UserToCollectionExtraInformation | null; } export type CollectionExtraInformationLot = 'date' | 'number' | 'string' | 'boolean' | 'date-time' | 'string-array'; export interface CollectionExtraInformation { default_value: string | null; description: string; /** * @default 'string' * @type {'date' | 'number' | 'string' | 'boolean' | 'date-time' | 'string-array'} */ lot: CollectionExtraInformationLot; name: string; possible_values: string[] | null; required: boolean | null; } export interface CollectionItem { collaborators: CollectionItemCollaboratorInformation[]; count: number; creator: StringIdAndNamedObject; description: string | null; id: string; information_template: CollectionExtraInformation[] | null; is_default: boolean; name: string; } export interface CollectionToEntityDetails { collection_id: string; collection_name: string; created_on: string; creator_user_id: string; information: unknown | null; last_updated_on: string; /** The rank of this entity in the collection. This is ignored during importing. */ rank?: string; } /** Comments left in replies to posted reviews. */ export interface ImportOrExportItemReviewComment { created_on: string; id: string; /** The user ids of all those who liked it. */ liked_by: string[]; text: string; user: StringIdAndNamedObject; } export type Visibility = 'public' | 'private'; /** Review data associated to a rating. */ export interface ImportOrExportItemReview { /** The date the review was posted. */ date: string | null; /** Whether to mark the review as a spoiler. Defaults to false. */ spoiler: boolean | null; /** Actual text for the review. */ text: string | null; /** * The visibility set by the user. * * @default 'public' */ visibility: Visibility | null; } /** A rating given to an entity. */ export interface ImportOrExportItemRating { /** If for an anime, the episode for which this review was for. */ anime_episode_number: number | null; /** The comments attached to this review. */ comments: ImportOrExportItemReviewComment[] | null; /** If for a manga, the chapter for which this review was for. */ manga_chapter_number: string | null; /** If for a podcast, the episode for which this review was for. */ podcast_episode_number: number | null; /** The score of the review. */ rating: string | null; /** Data about the review. */ review: ImportOrExportItemReview | null; /** If for a show, the episode for which this review was for. */ show_episode_number: number | null; /** If for a show, the season for which this review was for. */ show_season_number: number | null; } /** Details about a specific exercise item that needs to be exported. */ export interface ImportOrExportExerciseItem { /** The collections this entity was added to. */ collections: CollectionToEntityDetails[]; /** The unique identifier of the exercise. */ id: string; /** The name of the exercise. */ name: string; /** The review history for the user. */ reviews: ImportOrExportItemRating[]; } export type EntityRemoteVideoSource = 'youtube' | 'dailymotion'; /** The data that a remote video can have. */ export interface EntityRemoteVideo { /** * @default 'youtube' * @type {'youtube' | 'dailymotion'} */ source: EntityRemoteVideoSource; url: string; } /** The assets related to an entity. */ export interface EntityAssets { /** The urls of the remote images. */ remote_images: string[]; /** The urls of the remote videos. */ remote_videos: EntityRemoteVideo[]; /** The keys of the S3 images. */ s3_images: string[]; /** The keys of the S3 videos. */ s3_videos: string[]; } ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.