Catalog Metadata
The supporting metadata that classifies and describes the catalog: genres, moods, labels, contributor roles, image variants and the GeoNames-backed places dataset. These models are shared across Albums, Artists and Tracks.
1 Genre
A musical genre. Genres form a two-level hierarchy via the
ParentSlug self-link, and attach to both
Tracks (track_genres)
and Artists
(artist_genres) as many-to-many relations.
public class Genre : BaseModel
{
public required string Slug { get; set; }
public string? ParentSlug { get; set; }
public bool IsActive { get; set; } = true;
public int DisplayOrder { get; set; }
}
| Field | Type | Description |
|---|---|---|
Id |
Guid |
Primary key. Inherited from BaseModel. |
Slug |
string · required · ≤60 |
Stable, unique machine identifier (e.g. lo-fi-hip-hop).
The human-readable name is resolved per-locale via i18n —
genres do not store a display name.
|
ParentSlug |
string? · ≤60 |
Slug of the parent genre, or null for a top-level
genre. Indexed. Builds the genre tree.
|
IsActive |
bool · default true |
Whether the genre is selectable. Indexed; lets a genre be retired without deleting history. |
DisplayOrder |
int |
Sort order in pickers and listings. Indexed. |
Table: genres. Slug is uniquely indexed.
2 Mood
A curated, editorial mood tag — distinct from the continuous mood
scores computed by the audio enricher (see
TrackAudioFeatures).
Moods attach to Tracks (track_moods) and Albums
(album_moods).
public class Mood : BaseModel
{
public required string Slug { get; set; }
public bool IsActive { get; set; } = true;
public int DisplayOrder { get; set; }
}
| Field | Type | Description |
|---|---|---|
Id |
Guid |
Primary key. Inherited from BaseModel. |
Slug |
string · required · ≤60 |
Unique machine identifier (e.g. chill, energetic). Display name resolved via i18n. |
IsActive |
bool · default true |
Whether the mood is selectable. Indexed. |
DisplayOrder |
int |
Sort order in pickers and listings. Indexed. |
Table: moods. Slug is uniquely indexed. Unlike Genre, Mood has no hierarchy.
3 Label
A record label. An Album may
reference a Label via Album.LabelId.
| Field | Type | Description |
|---|---|---|
Id |
Guid |
Primary key. Inherited from BaseModel. |
Name |
string · required · ≤160 |
The label's canonical name. |
DisplayName |
string? · ≤160 |
Optional alternative name for display. |
Type |
LabelType enum |
Kind of label. Default SelfReleased. Indexed. |
OwnerUserId / Owner |
Guid? + User? |
The user who owns the label. OnDelete = SetNull. Indexed. |
Country |
string? · ≤2 |
ISO 3166-1 alpha-2 country code. |
WebsiteUrl |
string? · ≤500 |
The label's website. |
LogoUrl |
string? · ≤500 |
URL of the label's logo. |
IsSystemDefault |
bool |
Marks the single system-default label (used for self-released
albums with no explicit label). A unique filtered index allows
only one row with this set to true.
|
LabelType
| Value | Int | Meaning |
|---|---|---|
SelfReleased | 0 | The artist released it themselves. Default. |
Indie | 1 | An independent label. |
Major | 2 | A major label. |
Virtual | 3 | A virtual / AI-native label. |
4 ContributorRole
The shared role catalog used by both
TrackContributor
and AlbumContributor.
Values are grouped by numeric range so a category can be queried
arithmetically — Role / 100 yields the category number
(e.g. 500 / 100 == 5 → all production roles).
Performance · 300+
| Value | Int | Value | Int |
|---|---|---|---|
MainArtist | 300 | Instrumentalist | 305 |
FeaturedArtist | 301 | Soloist | 306 |
Vocalist | 302 | GroupMember | 307 |
LeadVocalist | 303 | Conductor | 308 |
BackgroundVocalist | 304 | Orchestra | 309 |
Writing · 400+
| Value | Int | Value | Int |
|---|---|---|---|
Composer | 400 | Arranger | 403 |
Lyricist | 401 | Adapter | 404 |
ComposerLyricist | 402 |
Production · 500+
| Value | Int | Value | Int |
|---|---|---|---|
Producer | 500 | VocalProducer | 503 |
ExecutiveProducer | 501 | Remixer | 504 |
StudioProducer | 502 |
Engineering · 600+
| Value | Int | Value | Int |
|---|---|---|---|
RecordingEngineer | 600 | AudioEngineer | 603 |
MixingEngineer | 601 | ProgrammingEngineer | 604 |
MasteringEngineer | 602 |
Business · 700+
| Value | Int | Meaning |
|---|---|---|
Publisher | 700 | The publishing entity. |
AandR | 702 | Artists & Repertoire. |
5 Images
Album and Artist artwork is stored as a set of pre-resized variants.
Both AlbumImage and
ArtistImage implement the
shared IImageVariantRecord interface, so the same
rendering and source-set logic works for either.
public interface IImageVariantRecord
{
ImageVariant Variant { get; }
ImageSize Size { get; }
string ObjectKey { get; }
bool IsPrimary { get; }
}
ImageVariant
The crop/shape of an image variant.
| Value | Int | Meaning |
|---|---|---|
Square | 0 | 1:1 crop — covers, avatars. |
Banner | 1 | Wide banner crop — page headers. |
Hero | 2 | Large hero crop — feature sections. |
Portrait | 3 | Tall portrait crop. |
ImageSize
The resolution tier of an image variant.
| Value | Int | Meaning |
|---|---|---|
Thumb | 0 | Smallest — list thumbnails. |
Small | 1 | Small cards. |
Medium | 2 | Default detail size. |
Large | 3 | Large hero/detail rendering. |
Original | 4 | The original uploaded resolution. |
Both image tables carry a unique filtered index
(ix_album_images_primary_unique /
ix_artist_images_primary_unique) that allows at most
one row with IsPrimary = true per
(parentId, Variant, Size). See
docs/image-format-strategy.md for the generation and
format strategy.
6 Places & Geography
The places dataset provides structured geography for artist origin
(Artist.OriginStateId / OriginCityId). It is
backed by GeoNames: the primary keys are GeoNames
geonameId values, stable across dataset refreshes. These
three models do not inherit BaseModel —
they use a long primary key.
PlaceState
A state / province / region — backed by GeoNames admin1 entries
(e.g. BR.27 = São Paulo, US.CA =
California).
| Field | Type | Description |
|---|---|---|
Id | long | Primary key — the GeoNames geonameId. |
CountryCode | string · required | ISO 3166-1 alpha-2 country code. |
ExternalCode | string · required | GeoNames admin1 code (e.g. "27", "CA"). |
Name | string · required | The state name. |
AsciiName | string · required | ASCII-only variant of Name, used for fuzzy search. |
Cities | ICollection<PlaceCity> | The cities within the state. |
PlaceCity
A city — backed by GeoNames cities1000 entries
(population ≥ 1000).
| Field | Type | Description |
|---|---|---|
Id | long | Primary key — the GeoNames geonameId. |
CountryCode | string · required | ISO 3166-1 alpha-2 country code. |
StateId / State | long? + nav | FK to the parent PlaceState. Null when GeoNames has no admin1 mapping. |
Name | string · required | The city name. |
AsciiName | string · required | ASCII-only variant of Name, used for fuzzy search. |
Population | long | City population (from GeoNames). |
Latitude / Longitude | decimal? | Geographic coordinates. |
Timezone | string? | IANA timezone identifier. |
PlaceTranslation
A localized name for a place (state or city). Because states and
cities share the same GeoNames geonameId space,
PlaceId references either places_states.id
or places_cities.id — there is no hard FK.
| Field | Type | Description |
|---|---|---|
PlaceId | long | The geonameId of the state or city being translated. |
Locale | string · required | One of the 5 supported locales: en-US, pt-BR, pt-PT, es-ES, es-419. |
Name | string · required | The localized place name. |
IsPreferred | bool | Marks the preferred translation for the locale when several exist. |