App Listings & Screenshots
AppListing — the central marketplace storefront entity linking a PluginDefinition to its commercial presence, plus AppScreenshot for the media gallery.
An AppListing is the storefront face of a Plugin. It carries everything a tenant sees in the catalog: name, tagline, icon, version, ratings, and install counts. Screenshots provide the visual gallery on the listing detail page.
AppListing Entity
The central entity of the Marketplace module. It connects a Plugin to its commercial presence including pricing, reviews, screenshots, and install metrics. AverageRating and ReviewCount are denormalized for query performance and recalculated whenever a review is added or updated.
| Field | Type | Description |
|---|---|---|
| Id | Guid | Primary key |
| PluginId | Guid | FK to the Plugin module's PluginDefinition this listing represents |
| DeveloperProfileId | Guid | FK to the developer who published this listing |
| Name | string | Display name of the application in the storefront |
| Tagline | string | Short tagline displayed below the app name (max 300 chars) |
| Description | string | Full rich-text description of the app's features and capabilities |
| IconUrl | string | URL to the app's icon image displayed in the catalog grid |
| Version | string | Semantic version string of the currently listed version (e.g. "1.2.0") |
| IsPublished | bool | Whether this listing is visible in the public storefront |
| IsFeatured | bool | Whether this listing is promoted in the featured/hero section |
| WithdrawalReason | string? | Reason provided when the listing was withdrawn (null if still active) |
| AverageRating | decimal | Denormalized average rating (1.0–5.0), recalculated on each review change |
| ReviewCount | int | Denormalized total number of user reviews |
| TotalInstalls | int | Cumulative number of installations across all tenants |
| ActiveInstalls | int | Number of tenants currently using (not uninstalled) this app |
Entity Source
public class AppListing : AuditableEntity<Guid>
{
public Guid PluginId { get; set; }
public Guid DeveloperProfileId { get; set; }
public string Name { get; set; } = string.Empty;
public string Tagline { get; set; } = string.Empty;
public string Description { get; set; } = string.Empty;
public string IconUrl { get; set; } = string.Empty;
public string Version { get; set; } = string.Empty;
public bool IsPublished { get; set; }
public bool IsFeatured { get; set; }
public string? WithdrawalReason { get; set; }
public decimal AverageRating { get; set; }
public int ReviewCount { get; set; }
public int TotalInstalls { get; set; }
public int ActiveInstalls { get; set; }
public virtual DeveloperProfile DeveloperProfile { get; set; } = default!;
public virtual AppPricing? Pricing { get; set; }
public virtual ICollection<AppCategoryMapping> CategoryMappings { get; set; } = new List<AppCategoryMapping>();
public virtual ICollection<AppScreenshot> Screenshots { get; set; } = new List<AppScreenshot>();
public virtual ICollection<AppReview> Reviews { get; set; } = new List<AppReview>();
public virtual ICollection<AppSubmission> Submissions { get; set; } = new List<AppSubmission>();
public virtual ICollection<AppPurchase> Purchases { get; set; } = new List<AppPurchase>();
public virtual ICollection<AppInstallCount> InstallCounts { get; set; } = new List<AppInstallCount>();
}AppScreenshot Entity
Represents a screenshot image for an app listing's detail page. Screenshots are ordered by SortOrder and displayed in a carousel on the storefront.
| Field | Type | Description |
|---|---|---|
| Id | Guid | Primary key |
| AppListingId | Guid | FK to the app listing this screenshot belongs to |
| ImageUrl | string | URL to the screenshot image file |
| Caption | string | Alt-text / caption displayed below the screenshot |
| SortOrder | int | Display order in the screenshot carousel (lower = first) |
Listing Status Lifecycle
An AppListing moves through several states from first draft to public visibility. The IsPublished flag controls storefront visibility; IsFeatured promotes a listing to the hero section.