Skip to content

feat: import Decent Espresso profiles via DecentConverter #328

@hessius

Description

@hessius

Summary

Port the DecentConverter logic from the met-community-profiles repository to enable importing Decent Espresso profiles into Meticulous format. This extends the existing "Import from URL" feature (#96) and addresses profile interoperability (#284).

Background

Decent Espresso is the most popular prosumer espresso platform with thousands of community-shared profiles. The MeticulousHome team built a DecentConverter (Vue component) that converts Decent .json profiles to Meticulous format. We should port this logic to our backend.

Behaviour

Import Flow

  1. User navigates to Profile Catalogue → Import
  2. Three import options:
    • From file (existing) — upload .json file
    • From URL (existing, Import from link #96) — paste any URL
    • From Decent (new) — paste a Decent profile URL or upload Decent .json
  3. For Decent import:
    • Backend detects Decent format (has author, beverage_type, steps[] with flow/pressure targets)
    • Runs DecentConverter logic to translate:
      • Decent steps[] → Meticulous stages[]
      • Decent flow/pressure targets → Meticulous dynamics
      • Decent exit_condition → Meticulous exit_triggers
      • Decent temperature → Meticulous temperature
      • Decent notes → Meticulous description
    • Shows preview of converted profile with stage visualization
    • User confirms → profile saved

Decent Profile Sources

  • Decent community links: https://visualizer.coffee/shots/... export URLs
  • Diaspora profiles: Various community forums share .json exports
  • Direct file upload: Users export from Decent tablet app

Conversion Details (from DecentConverter.vue)

Decent Meticulous
steps[].flow stages[].dynamics.points (flow type)
steps[].pressure stages[].dynamics.points (pressure type)
steps[].temperature stages[].temperature
steps[].exit.type == "pressure_over" exit_triggers[].type = "pressure"
steps[].exit.type == "flow_over" exit_triggers[].type = "flow"
steps[].seconds exit_triggers[].type = "time"
steps[].weight exit_triggers[].type = "weight"
author profile.author
title profile.name
notes profile.description

Edge Cases

  • Profiles with advanced Decent features (move-on conditions, limiter) → best-effort conversion with warning
  • Profiles with espresso_decline step type → map to declining pressure/flow dynamics
  • Invalid/corrupt files → clear error message with format guidance

Implementation

Backend

  1. New service: apps/server/services/decent_converter.py
    • detect_decent_format(data: dict) -> bool
    • convert_decent_to_meticulous(data: dict) -> dict
    • Port logic from DecentConverter.vue to Python
  2. Extend POST /api/import-from-url to auto-detect Decent format
  3. New endpoint: POST /api/convert-decent for direct file conversion
  4. Validate output against espresso-profile-schema

Frontend

  1. Add "Decent" import option in ProfileCatalogue import dialog
  2. Show conversion preview before saving
  3. Display warnings for unsupported Decent features
  4. i18n keys for all Decent-specific strings (6 locales)

Acceptance Criteria

  • Decent profiles auto-detected by format
  • Conversion produces valid Meticulous profiles (passes schema validation)
  • Temperature, flow, pressure, and weight targets correctly mapped
  • Exit conditions correctly translated
  • Preview shown before save
  • Edge cases handled with user-visible warnings
  • i18n for all 6 locales
  • Tests for converter with sample Decent profiles

References

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions