No description
  • C# 68.1%
  • TypeScript 29.5%
  • CSS 1.8%
  • JavaScript 0.4%
  • PowerShell 0.2%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
Mobius 8c843b18e9 Merge remote-tracking branch 'origin/main' into codex/sa-378-catalogue-shell-sync
# Conflicts:
#	StuffApp.Core/GraphQL/SourceOperationsGraphQl.cs
#	StuffApp.Core/Importing/ConfiguredContentImportService.cs
2026-11-13 15:53:20 -08:00
deploy Remove earlier import configurations; archive them in docs 2026-11-13 18:37:00 +00:00
docs Merge remote-tracking branch 'origin/main' into codex/sa-378-catalogue-shell-sync 2026-11-13 15:53:20 -08:00
scripts Streamline agent guidance and script task verification and publication 2026-11-06 15:43:24 -08:00
StuffApp.Cli SA-300: Source connections replace Content Source Systems and file rows 2026-10-31 08:01:30 +00:00
StuffApp.ComicImports SA-343, SA-345: scans, import profiles and vocabulary move to Sources 2026-11-06 23:10:03 +00:00
StuffApp.ComicImports.Tests Implement two-page comic reading 2026-11-05 14:31:10 -08:00
StuffApp.Core Merge remote-tracking branch 'origin/main' into codex/sa-378-catalogue-shell-sync 2026-11-13 15:53:20 -08:00
StuffApp.Core.Abstractions Merge remote-tracking branch 'origin/main' into codex/sa-378-catalogue-shell-sync 2026-11-13 15:53:20 -08:00
StuffApp.Core.Tests Merge remote-tracking branch 'origin/main' into codex/sa-378-catalogue-shell-sync 2026-11-13 15:53:20 -08:00
StuffApp.Plugin.Albums SA-297: Albums hold Images and Videos in a chosen order 2026-11-07 00:06:15 -08:00
StuffApp.Plugin.Artists SA-293 add personal profile Source relationships 2026-10-30 19:19:51 -07:00
StuffApp.Plugin.Audio Sources tab: Role among the Browser controls, no subsection panel; opt-in Random; + Add buttons 2026-11-13 19:08:47 +00:00
StuffApp.Plugin.AudioVisualizer.FrequencyBars Add plugin-supplied audio visualizers 2026-10-23 10:20:38 -07:00
StuffApp.Plugin.Characters SA-278: Record merge for any Entity that declares it 2026-11-07 00:17:53 -08:00
StuffApp.Plugin.Collections SA-272: Gallery type as a Zip galleries setting 2026-11-07 00:11:45 -08:00
StuffApp.Plugin.Comics Make archives child File System Sources (SA-325, SA-326) 2026-11-06 18:37:51 +00:00
StuffApp.Plugin.Comikey Interface names: I{X} for records, I{X}Provider for backing systems 2026-10-31 16:08:38 -07:00
StuffApp.Plugin.Directors SA-173 share Identity role plugin frontend 2026-10-30 11:52:14 -07:00
StuffApp.Plugin.Favorites Base StuffApp.Web and plugin UIs on shared skin tokens 2026-10-10 17:02:52 -07:00
StuffApp.Plugin.Groups SA-173 share Identity role plugin frontend 2026-10-30 11:52:14 -07:00
StuffApp.Plugin.Identities SA-278: Record merge for any Entity that declares it 2026-11-07 00:17:53 -08:00
StuffApp.Plugin.ImageRelationships Implement SA-295 personal Image relationships 2026-11-03 23:13:39 -08:00
StuffApp.Plugin.Images Sources tab: Role among the Browser controls, no subsection panel; opt-in Random; + Add buttons 2026-11-13 19:08:47 +00:00
StuffApp.Plugin.JsonApi JSON API Source provider for a comic server (SA-383) 2026-11-13 23:01:31 +00:00
StuffApp.Plugin.LibraryStats Count Content Entities in the Library Stats example (SA-120) 2026-10-16 23:08:38 -07:00
StuffApp.Plugin.Lists Editors: keep the hidden Enter-to-save button out of the layout 2026-11-09 02:35:34 +00:00
StuffApp.Plugin.OCount SA-369: Navigation Modes choose which Entities cross-Entity features show on 2026-11-09 00:36:52 +00:00
StuffApp.Plugin.Organized Base StuffApp.Web and plugin UIs on shared skin tokens 2026-10-10 17:02:52 -07:00
StuffApp.Plugin.People SA-292 add personal Identity roles 2026-10-30 12:06:09 -07:00
StuffApp.Plugin.Performers Editors: keep the hidden Enter-to-save button out of the layout 2026-11-09 02:35:34 +00:00
StuffApp.Plugin.Pets Editors end with their actions; Tags are chips 2026-11-09 02:31:35 +00:00
StuffApp.Plugin.Photographers SA-292 add personal Identity roles 2026-10-30 12:06:09 -07:00
StuffApp.Plugin.Playlists Editors: keep the hidden Enter-to-save button out of the layout 2026-11-09 02:35:34 +00:00
StuffApp.Plugin.Ratings Base StuffApp.Web and plugin UIs on shared skin tokens 2026-10-10 17:02:52 -07:00
StuffApp.Plugin.Releases Implement personal video records and segments (SA-296) 2026-11-04 10:46:29 -08:00
StuffApp.Plugin.Renta Interface names: I{X} for records, I{X}Provider for backing systems 2026-10-31 16:08:38 -07:00
StuffApp.Plugin.Skin.Light SA-123: add plugin-supplied skins 2026-10-23 13:57:03 -07:00
StuffApp.Plugin.Sources Merge remote-tracking branch 'origin/main' into codex/sa-378-catalogue-shell-sync 2026-11-13 15:53:20 -08:00
StuffApp.Plugin.StashInstance Implement content availability shell foundation (SA-376) 2026-11-12 19:43:31 -08:00
StuffApp.Plugin.Tapas Interface names: I{X} for records, I{X}Provider for backing systems 2026-10-31 16:08:38 -07:00
StuffApp.Plugin.Text Sources tab: Role among the Browser controls, no subsection panel; opt-in Random; + Add buttons 2026-11-13 19:08:47 +00:00
StuffApp.Plugin.Universes SA-278: Record merge for any Entity that declares it 2026-11-07 00:17:53 -08:00
StuffApp.Plugin.VideoRelationships Implement personal video records and segments (SA-296) 2026-11-04 10:46:29 -08:00
StuffApp.Plugin.Videos Videos keep Random record: personal-video declares randomRecord 2026-11-13 11:33:01 -08:00
StuffApp.Plugin.Works SA-278: Record merge for any Entity that declares it 2026-11-07 00:17:53 -08:00
StuffApp.PluginSdk Signal adaptive panel width explicitly 2026-11-09 23:13:30 -08:00
StuffApp.PluginSigner Consolidate content pipelines and signed Stash plugins 2026-10-05 17:01:26 -07:00
StuffApp.Web Merge remote-tracking branch 'origin/main' into cleaners-decorators-browsers 2026-11-13 15:21:21 -08:00
.gitattributes Add a Docker deploy bundle for the Comics alpha 2026-10-17 15:18:22 -07:00
.gitignore Load a gitignored appsettings.local.json so alpha keeps its database 2026-10-11 15:43:47 -07:00
AGENTS.md Rework Settings Navigation Modes panels and add UI standards 2026-11-13 17:43:35 +00:00
compose.yaml Fix PostgreSQL 18 development volume mount 2026-10-28 00:01:24 -07:00
global.json Build Images browser prototype 2026-09-29 17:43:35 -07:00
README.md SA-312: archive the Stash plugins and code paths 2026-10-30 18:02:37 +00:00
StuffApp.slnx Move O count out of Core into the O count plugin (SA-274) 2026-11-01 21:31:51 +00:00

StuffApp

StuffApp is an early, plugin-oriented media application prototype. The current milestone provides a .NET 10 Kestrel and GraphQL backend, PostgreSQL persistence, a React application shell with a core Browser, and external declarative Images, Videos, and Albums plugins. Plugins supply frontend Entity classes and Big Grid tile renderers; the host owns storage, querying, server-side sorting, pagination, relationships, and view selection.

Prerequisites

  • .NET SDK 10.0.400 (selected by global.json)
  • PostgreSQL 18, or Docker with Compose
  • pnpm 12
  • FFmpeg and ffprobe for Video and Audio metadata and generated posters

The repository's default development connection is Host=localhost;Port=5432;Database=stuffapp;Username=stuffapp;Password=stuffapp. Override it with the ConnectionStrings__StuffApp environment variable when needed.

To run StuffApp on a Linux server with Docker instead, build a deploy bundle with scripts\Build-DeployBundle.ps1; see deploy/README.md.

Start the prototype

Build the external Images plugin:

pnpm --dir StuffApp.Plugin.Images install
pnpm --dir StuffApp.Plugin.Images build
pnpm --dir StuffApp.Plugin.Videos install
pnpm --dir StuffApp.Plugin.Videos build
pnpm --dir StuffApp.Plugin.Audio install
pnpm --dir StuffApp.Plugin.Audio build
pnpm --dir StuffApp.Plugin.AudioVisualizer.FrequencyBars install
pnpm --dir StuffApp.Plugin.AudioVisualizer.FrequencyBars build
pnpm --dir StuffApp.Plugin.Text install
pnpm --dir StuffApp.Plugin.Text build
pnpm --dir StuffApp.Plugin.Albums install
pnpm --dir StuffApp.Plugin.Albums build

The Source and comic plugins build the same way: StuffApp.Plugin.Sources, Identities, Works, Artists, Groups, Universes, Characters, and Comics. Comics depends on its Identity family plugins, so install those together. See Sources for the abstract Source foundation. The Stash plugins and Studio Scenes are archived until the personal library model is built; see Archived Stash code.

Start PostgreSQL:

docker compose up -d

Register the built plugin outputs once in PostgreSQL. Folders can be absolute or relative to StuffApp.Core:

INSERT INTO installed_plugins (id, folder_path, enabled, created_at, updated_at)
VALUES (
  'stuffapp.content.images',
  'C:\Projects\StuffApp\StuffApp.Plugin.Images\dist',
  TRUE,
  CURRENT_TIMESTAMP,
  CURRENT_TIMESTAMP
)
ON CONFLICT (id) DO UPDATE
SET folder_path = EXCLUDED.folder_path,
    enabled = EXCLUDED.enabled,
    updated_at = EXCLUDED.updated_at;

INSERT INTO installed_plugins (id, folder_path, enabled, created_at, updated_at)
VALUES (
  'stuffapp.content.videos',
  'C:\Projects\StuffApp\StuffApp.Plugin.Videos\dist',
  TRUE,
  CURRENT_TIMESTAMP,
  CURRENT_TIMESTAMP
)
ON CONFLICT (id) DO UPDATE
SET folder_path = EXCLUDED.folder_path,
    enabled = EXCLUDED.enabled,
    updated_at = EXCLUDED.updated_at;

INSERT INTO installed_plugins (id, folder_path, enabled, created_at, updated_at)
VALUES
  ('stuffapp.content.audio', 'C:\Projects\StuffApp\StuffApp.Plugin.Audio\dist', TRUE, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP),
  ('stuffapp.content.text', 'C:\Projects\StuffApp\StuffApp.Plugin.Text\dist', TRUE, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP),
  ('stuffapp.audio-visualizer.frequency-bars', 'C:\Projects\StuffApp\StuffApp.Plugin.AudioVisualizer.FrequencyBars\dist', TRUE, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP)
ON CONFLICT (id) DO UPDATE
SET folder_path = EXCLUDED.folder_path,
    enabled = EXCLUDED.enabled,
    updated_at = EXCLUDED.updated_at;

INSERT INTO installed_plugins (id, folder_path, enabled, created_at, updated_at)
VALUES (
  'stuffapp.albums',
  'C:\Projects\StuffApp\StuffApp.Plugin.Albums\dist',
  TRUE,
  CURRENT_TIMESTAMP,
  CURRENT_TIMESTAMP
)
ON CONFLICT (id) DO UPDATE
SET folder_path = EXCLUDED.folder_path,
    enabled = EXCLUDED.enabled,
    updated_at = EXCLUDED.updated_at;

In separate terminals, start the API and web application:

dotnet run --project StuffApp.Core
pnpm --dir StuffApp.Web dev

The web UI is available at http://localhost:5173; Vite proxies GraphQL and content requests to Kestrel at http://localhost:5087. To run a second instance beside it, set STUFFAPP_WEB_PORT and STUFFAPP_API_URL (for example 5174 and http://127.0.0.1:5088) before starting Vite.

Add explicit images

The prototype deliberately has no filesystem scanner. Register only paths you choose:

dotnet run --project StuffApp.Cli -- add-image "C:\path\to\first.jpg" "C:\path\to\second.png"

Each new Content record receives a UUIDv7. The browser obtains metadata through GraphQL and image bytes through /content/{uuid}; filesystem paths are not returned to the frontend.

Verify

dotnet restore StuffApp.slnx
dotnet build StuffApp.slnx --no-restore
dotnet test StuffApp.slnx --no-build
pnpm --dir StuffApp.Web test -- --run
pnpm --dir StuffApp.Web build
pnpm --dir StuffApp.Plugin.Images test
pnpm --dir StuffApp.Plugin.Images build
pnpm --dir StuffApp.Plugin.Videos test
pnpm --dir StuffApp.Plugin.Videos build
pnpm --dir StuffApp.Plugin.Audio test
pnpm --dir StuffApp.Plugin.Audio build
pnpm --dir StuffApp.Plugin.AudioVisualizer.FrequencyBars test
pnpm --dir StuffApp.Plugin.AudioVisualizer.FrequencyBars build
pnpm --dir StuffApp.Plugin.Text test
pnpm --dir StuffApp.Plugin.Text build
pnpm --dir StuffApp.Plugin.Albums test
pnpm --dir StuffApp.Plugin.Albums build

Architecture and milestone decisions are recorded in docs/.