impress/README.md
Emi Matchu 9ba94f9f4b chore: document legacy openneo_id migrations and update references
This commit completes the database consolidation cleanup by documenting
the historical migrations and updating all references to reflect the
single-database architecture.

Changes:
- db/openneo_id_migrate/README.md: Created comprehensive documentation
  explaining the history of the separate database and why these migrations
  are preserved but no longer runnable
- db/openneo_id_schema.rb: Deleted (no longer needed)
- README.md: Updated to reflect single-database architecture
  - Removed mentions of "two databases"
  - Updated "OpenNeo ID Database" section to "Authentication Architecture"
  - Added reference to historical context in db/openneo_id_migrate/README.md
- deploy/setup.yml: Removed openneo_id database creation and privileges
  for future deployments
- db/migrate/20240401124200_increase_username_length.rb: Updated comment
  to note this was historically paired with an openneo_id migration

The codebase now fully reflects the consolidated single-database architecture.
The legacy migration files in db/openneo_id_migrate/ are preserved for
historical reference only.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-02 07:02:43 +00:00

7.7 KiB

Dress to Impress beach logo

Dress to Impress

Dress to Impress (DTI) is a tool for designing Neopets outfits. Load your pet, browse items, and see how they look together—all with a mobile-friendly interface!

Architecture Overview

DTI is a Rails application with a React-based outfit editor, backed by MySQL databases and a crowdsourced data collection system.

Core Components

  • Rails backend (Ruby 3.4, Rails 8.0): Serves web pages, API endpoints, and manages data
  • MySQL database: Single database (openneo_impress) containing all application and authentication data
  • React outfit editor: Embedded in app/javascript/wardrobe-2020/, provides the main customization UI
  • Modeling system: Crowdsources pet/item appearance data by fetching from Neopets APIs when users load their pets

The Impress 2020 Complication

In 2020, we started a NextJS rewrite ("Impress 2020") to modernize the frontend. We've since consolidated back into Rails, but Impress 2020 still provides essential services:

  • GraphQL API: Some outfit appearance data still loads via GraphQL (being migrated to Rails REST APIs)
  • Image generation: Runs a headless browser to render outfit thumbnails and convert HTML5 assets to PNGs

See docs/impress-2020-dependencies.md for migration status.

Key Concepts

Customization Data Model

The core data model powers outfit rendering and item compatibility. See docs/customization-architecture.md for details.

Quick summary:

  • body_id is the key compatibility constraint (not species or color directly)
  • Items have different swf_assets (visual layers) for different bodies
  • Restrictions are subtractive: start with all layers, hide some based on zone restrictions
  • Data is crowdsourced through "modeling" (users loading pets to contribute appearance data)

Modeling (Crowdsourced Data)

DTI doesn't pre-populate item/pet data. Instead:

  1. User loads a pet (via pet name lookup)
  2. DTI fetches appearance data from Neopets APIs (legacy Flash/AMF protocol)
  3. New SwfAsset records and relationships are created
  4. Over time, the database learns which items fit which pet bodies

This "self-sustaining" approach means the site stays up-to-date as Neopets releases new content, without manual data entry.

Directory Map

Key Application Files

app/
├── controllers/
│   ├── outfits_controller.rb       # Outfit editor + CRUD
│   ├── items_controller.rb         # Item search, pages, and JSON APIs
│   ├── pets_controller.rb          # Pet loading (triggers modeling)
│   └── closet_hangers_controller.rb # User item lists ("closets")
│
├── models/
│   ├── item.rb                     # Items + compatibility prediction logic
│   ├── pet_type.rb                 # Species+Color combinations (has body_id)
│   ├── pet_state.rb                # Visual variants (pose/gender/mood)
│   ├── swf_asset.rb                # Visual layers (biology/object)
│   ├── outfit.rb                   # Saved outfits + rendering logic (visible_layers)
│   ├── alt_style.rb                # Alternative pet appearances (Nostalgic, etc.)
│   └── pet/
│       └── modeling_snapshot.rb    # Processes Neopets API data into models
│
├── services/
│   ├── neopets/
│   │   ├── custom_pets.rb          # Neopets AMF/Flash API client (pet data)
│   │   ├── nc_mall.rb              # NC Mall item scraping
│   │   └── neopass.rb              # NeoPass OAuth integration
│   ├── neopets_media_archive.rb    # Local mirror of images.neopets.com
│   └── lebron_nc_values.rb         # NC item trading values (external API)
│
├── javascript/
│   ├── wardrobe-2020/              # React outfit editor (extracted from Impress 2020)
│   │   ├── loaders/                # REST API calls (migrated from GraphQL)
│   │   ├── WardrobePage/           # Main editor UI
│   │   └── components/             # Shared React components
│   └── application.js              # Rails asset pipeline entrypoint
│
└── views/
    ├── outfits/
    │   └── edit.html.haml          # Outfit editor page (loads React app)
    ├── items/
    │   └── show.html.haml          # Item detail page
    └── closet_hangers/
        └── index.html.haml         # User closet/item lists

Configuration & Docs

config/
├── routes.rb                       # All Rails routes
├── database.yml                    # Database configuration
└── environments/
    └── *.rb                        # Env-specific config (incl. impress_2020_origin)

Documentation:

Tests:

  • test/ - Test::Unit tests (privacy features)
  • spec/ - RSpec tests (models, services, integrations)
    • Coverage is focused on key areas: modeling, prediction logic, external APIs
    • Not comprehensive, but thorough for critical behaviors

Tech Stack

  • Backend: Ruby on Rails (Ruby 3.4, Rails 8.0)
  • Frontend: Mix of Rails views (Turbo/HAML) and React (for outfit editor)
  • Database: MySQL (openneo_impress)
  • Styling: CSS, Sass (moving toward modern Rails conventions)
  • External Integrations:
    • Neopets.com: Legacy Flash/AMF protocol for pet appearance data (modeling)
    • Neopets NC Mall: Web scraping for NC item availability/pricing
    • NeoPass: OAuth integration for Neopets account linking
    • Neopets Media Archive: Local filesystem mirror of images.neopets.com (never discards old files)
    • Lebron's NC Values: Third-party API for NC item trading values (lebron-values.netlify.app)
    • Impress 2020: GraphQL for some outfit data, image generation service (being phased out)

Development Notes

Authentication Architecture

Authentication data lives in the auth_users table (managed by the AuthUser model). This was historically in a separate openneo_id database (a legacy from when "OpenNeo ID" was envisioned as a service to unify auth across multiple OpenNeo projects). As of November 2025, the databases have been consolidated into a single database for simplicity.

User accounts are split across two related tables:

  • auth_users - Authentication data (passwords, email, OAuth connections) via Devise
  • users - Application data (points, closet settings, etc.)

These are linked via User.remote_idAuthUser.id. See db/openneo_id_migrate/README.md for the historical context.

Rails/React Hybrid

Most pages are traditional Rails views using Turbo for interactivity. The outfit editor (/outfits/new) is a full React app that:

  • Loads into a #wardrobe-2020-root div
  • Uses React Query for data fetching
  • Calls both Rails REST APIs (in loaders/) and Impress 2020 GraphQL (being migrated)

The goal is to simplify this over time—either consolidate into Rails+Turbo, or commit fully to React. For now, we're in a hybrid state.

Deployment

  • Main app: VPS running Rails (Puma, MySQL)
  • Impress 2020: Separate VPS in same datacenter (NextJS, GraphQL, headless browser for images)
  • Both services share the same MySQL database (Impress 2020 makes SQL calls over the network)

Project maintained by @matchuOpenNeo.net