Jellystat Documentation

repository·main·Indexed 25 days ago

https://github.com/cyfershepard/jellystat

An open-source statistics application for Jellyfin and Emby that provides monitoring for sessions, libraries, users, and watch history. It features a Node.js backend, React frontend, and PostgreSQL database. The application includes a Swagger-documented API with endpoints for synchronization, statistics, and backups, and supports deployment via Docker and Docker Compose.

Tokens
4.4K
Snippets
10
Records
21
Agent score
82%

What's inside Jellystat

  1. Set up Jellystat for local development

    main

    To run Jellystat locally for development, follow these steps:

    1. Clone the repository from Git.
    2. Configure your environment variables (see Environmental Variables below).
    3. Install dependencies: npm install.
    4. Build local files: npm run build.

    To run the application, use one of the following commands:

    • Run only the backend Node.js server: npm run start-server
    • Run only the frontend React UI: npm run start-client
    • Run both backend and frontend simultaneously: npm run start-app
    npm install
    npm run build
    npm run start-app
  2. Configure Jellystat using Docker secrets

    main

    If you are using Docker Compose or Docker Swarm, you can load environment variable values from files by prefixing the variable name with FILE__. This is useful for managing sensitive information like passwords via Docker secrets.

    For example, setting FILE__MYVAR: /run/secrets/MYSECRETFILE will result in the environment variable MYVAR containing the contents of /run/secrets/MYSECRETFILE.

    jellystat:
      environment:
        FILE__MYVAR: /run/secrets/MYSECRETFILE
  3. WebSocket task listeners and toast notifications

    main

    Jellystat uses a WebSocket connection (socket) to listen for specific background tasks and provide real-time feedback via toast notifications. The application listens for the following task names:

    • PlaybackSyncTask
    • PartialSyncTask
    • FullSyncTask
    • BackupTask
    • TaskError
    • GeneralAlert

    Message Types and Behavior

    When a message is received via these tasks, the application reacts based on the message.type:

    Message TypeActionToast Type
    StartCreates a new toastinfo
    SuccessCreates a new toast (if no active toast) or updates existingsuccess
    ErrorCreates a new toast (if no active toast) or updates existingerror
    UpdateUpdates the existing toast with new contentinfo

    To ensure clean-up, the application removes these listeners when the component unmounts.

  4. How Jellystat manages application lifecycle and routing

    main

    The Jellystat application uses a state-driven lifecycle to determine which view to render based on the backend configuration state (setupState), the presence of a configuration object, and the existence of an authentication token in localStorage.

    Lifecycle States

    • State 0 (Unconfigured): Renders the Signup page. The app checks /auth/isConfigured to determine the current state.
    • State 1 (Setup Required): Renders the Setup page.
    • State 2 (Configured):
      • If no token is present: Renders the Login page.
      • If a token is present: Renders the main application interface including the Navbar and the routes defined in the routes configuration.

    Error Handling

    If the application fails to connect to the backend, it renders an ErrorPage with the message: "Error: Unable to connect to Jellystat Backend".

  5. Initialize Jellystat frontend with i18n and React

    main

    The Jellystat frontend entrypoint initializes internationalization (i18n) using i18next before mounting the React application.

    Internationalization Configuration

    • Fallback Language: en-GB
    • Backend: Uses i18next-http-backend to load translation files from ${baseUrl}/locales/{{lng}}/{{ns}}.json.
    • Language Detection: Detects language via a priority order: cookie, localStorage, sessionStorage, navigator, htmlTag, querystring, path, and subdomain. It caches the detected language in cookie.
    • Interpolation: escapeValue is set to false.

    Application Mounting

    Once i18n is initialized, the application is rendered into the DOM element with ID root using the following structure:

    1. React.StrictMode for development checks.
    2. Suspense with a <Loading /> component as the fallback during lazy loading.
    3. BrowserRouter using baseUrl as the basename to ensure correct routing relative to the deployment path.
    4. The <App /> component as the root of the application.
    i18n
      .use(Backend)
      .use(LanguageDetector)
      .use(initReactI18next)
      .init({
        fallbackLng: "en-GB",
        debug: false,
        backend: {
          loadPath: `${baseUrl}/locales/{{lng}}/{{ns}}.json`,
        },
        detection: {
          order: ["cookie", "localStorage", "sessionStorage", "navigator", "htmlTag", "querystring", "path", "subdomain"],
          cache: ["cookie"],
        },
        interpolation: {
          escapeValue: false,
        },
      })
      .then(() => {
        createRoot(document.getElementById("root")).render(
          <React.StrictMode>
            <Suspense fallback={<Loading />}>
              <BrowserRouter basename={baseUrl}>
                <App />
              </BrowserRouter>
            </Suspense>
          </React.StrictMode>
        );
      });
  6. Deploy Jellystat using Docker Compose

    main

    You can deploy Jellystat and its required PostgreSQL database using the provided docker-compose.yml configuration. The setup includes a jellystat service for the application and a jellystat-db service running postgres:18.1. The application service depends on the database being healthy before starting.

    version: '3'
    
    services:
      jellystat-db:
        image: postgres:18.1
        shm_size: '1gb'
        container_name: jellystat-db
        restart: unless-stopped
        logging:
          driver: "json-file"
          options:
            max-file: "5"
            max-size: "10m"
        environment:
          POSTGRES_USER: postgres
          POSTGRES_PASSWORD: mypassword
        volumes:
          - postgres-data:/var/lib/postgresql
        healthcheck:
          test:
            - CMD-SHELL
            - pg_isready --dbname=postgres --username=postgres
          interval: 10s
          timeout: 5s
          retries: 5
    
      jellystat:
        image: cyfershepard/jellystat:latest
        container_name: jellystat
        restart: unless-stopped
        logging:
          driver: "json-file"
          options:
            max-file: "5"
            max-size: "10m"
        environment:
          POSTGRES_USER: postgres
          POSTGRES_PASSWORD: mypassword
          POSTGRES_IP: jellystat-db
          POSTGRES_PORT: 5432
          JWT_SECRET: "my-secret-jwt-key"
          TZ: mytimezone
        volumes:
          - jellystat-backup-data:/app/backend/backup-data
        ports:
          - "3000:3000"
        depends_on:
          jellystat-db:
            condition: service_healthy
        healthcheck:
          test: wget --no-verbose --tries=1 --spider http://localhost:3000/auth/isConfigured || exit 1
          interval: 60s
          timeout: 30s
          retries: 5
          start_period: 30s
    
    networks:
      default:
    
    volumes:
      postgres-data:
      jellystat-backup-data:
  7. Configure Jellystat Environment Variables

    main

    Jellystat relies on several environment variables for its operation. The server requires JWT_SECRET to be defined; if it is missing, the process will exit with an error.

    Key environment variables include:

    • JWT_SECRET: Required. Used for verifying JSON Web Tokens.
    • JS_LISTEN_IP: The IP address the server listens on (defaults to 0.0.0.0).
    • JS_BASE_URL: Sets a base path for the application (e.g., /jellystat). If provided, the server will redirect the root URL to this base name and strip it from incoming request URLs to handle routing.
    • POSTGRES_USER: Database user (defaults to postgres).
    • POSTGRES_ROLE: Database role (defaults to the value of POSTGRES_USER).
  8. Use FILE__ prefix to load secrets from files

    main

    Jellystat's entrypoint script supports loading sensitive configuration (secrets) from files using environment variables prefixed with FILE__.

    When the container starts, the script looks for any environment variable starting with FILE__. It treats the value of that variable as a path to a file. It then reads the contents of that file and exports them as a new environment variable with the FILE__ prefix removed.

    Example Behavior: If you set FILE__DATABASE_PASSWORD=/run/secrets/db_pass, the script will read the content of /run/secrets/db_pass and export it as DATABASE_PASSWORD.

    Constraints:

    • The file specified in the FILE__ variable must exist; otherwise, the container will exit with an error.
    • If the resulting variable name (without the prefix) is already set in the environment, a warning will be printed to stdout, and the existing value will be overwritten by the file's content.