Added prominent warnings in multiple locations to prevent accidental database migrations that would break Impress 2020: README.md: - Added critical warning in "OpenNeo ID Database" section - Highlighted that Impress 2020 directly accesses both databases - Added warning in "Deployment" section about schema compatibility - Linked to detailed documentation docs/impress-2020-dependencies.md: - Clarified both databases are directly accessed by Impress 2020 - Added new "Database Consolidation Blocker" section - Documented that consolidation migration is ready but blocked - Provided options to unblock (retire I2020 or coordinated deployment) This ensures future developers (including future me!) are aware of this critical dependency before proposing database schema changes. Related: feature/consolidate-auth-database branch contains a ready-to-go database consolidation, but it's blocked on Impress 2020 retirement. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
164 lines
7.9 KiB
Markdown
164 lines
7.9 KiB
Markdown
<img src="https://i.imgur.com/mZ2FCfX.png" width="200" height="200" alt="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 databases**: Primary database (`openneo_impress`) + legacy auth database (`openneo_id`)
|
|
- **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](./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](./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 # Multi-database setup (main + openneo_id)
|
|
└── environments/
|
|
└── *.rb # Env-specific config (incl. impress_2020_origin)
|
|
```
|
|
|
|
**Documentation:**
|
|
- [docs/customization-architecture.md](./docs/customization-architecture.md) - Deep dive into data model & rendering
|
|
- [docs/impress-2020-dependencies.md](./docs/impress-2020-dependencies.md) - What still depends on Impress 2020 service
|
|
|
|
**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 (two databases: `openneo_impress`, `openneo_id`)
|
|
- **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](https://lebron-values.netlify.app))
|
|
- **Impress 2020**: GraphQL for some outfit data, image generation service (being phased out)
|
|
|
|
## Development Notes
|
|
|
|
### OpenNeo ID Database
|
|
|
|
The `openneo_id` database is a legacy from when authentication was a separate service ("OpenNeo ID") meant to unify auth across multiple OpenNeo projects. DTI was the only project that succeeded, so the apps were merged—but the database split remains for now.
|
|
|
|
**Implications**:
|
|
- Rails is configured for multi-database mode
|
|
- User auth models live in `auth_user.rb` and connect to `openneo_id`
|
|
- **⚠️ CRITICAL**: Impress 2020 also directly accesses both `openneo_impress` and `openneo_id` databases via SQL
|
|
- **Database migrations affecting these schemas must consider Impress 2020's direct access**
|
|
- See [docs/impress-2020-dependencies.md](./docs/impress-2020-dependencies.md) for full details on this dependency
|
|
|
|
### 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)
|
|
- **Shared databases**: Both services directly access the same MySQL databases over the network
|
|
- `openneo_impress` - Main application data
|
|
- `openneo_id` - Authentication data
|
|
- ⚠️ **Any database schema changes must be compatible with both services**
|
|
|
|
---
|
|
|
|
**Project maintained by [@matchu](https://github.com/matchu)** • **[OpenNeo.net](https://openneo.net)**
|