This file is a solution-wide navigation guide for humans and coding agents working in NINA.sln. It complements the per-project ARCHITECTURE.md files and stays focused on boundaries that are backed up by the code.
For repository-wide contribution workflow, branch expectations, release-note updates, and general coding rules, also read CONTRIBUTING.md.
This guide covers the projects listed in NINA.sln.
NINA.Docsis a git submodule declared in.gitmodulesand points tohttps://github.com/isbeorn/nina.docs.git.- It is not part of the
NINA.slnproject architecture documented below. - If a code change also requires user-facing documentation updates, handle that separately in the
NINA.Docssubmodule /nina.docsrepository, following the documentation notes inCONTRIBUTING.md.
- Treat repository-local, versioned files as the system of record for future contributors and coding agents.
- Keep this file as a map. Put detailed subsystem guidance in the owning
ARCHITECTURE.md,CONTRIBUTING.md, or a focused checked-in reference. - If a review, bug, or repeated agent mistake reveals a durable rule, update the nearest doc, test, analyzer, script, or route map instead of relying on off-repo memory.
- Maintain the existing line-ending style of every touched file; default to CRLF for new files unless the target location dictates LF.
- Treat the root
.editorconfigas the canonical C# style source. It covers indentation, line endings, namespace style,usingplacement,varpreferences, naming, and selected analyzer severities. - Do not introduce new warnings casually. If an existing warning blocks a focused cleanup, keep the fix scoped and document any intentional deferral in the PR.
- For XAML, follow surrounding file style; no repo-wide XAML formatter configuration is checked in.
- Prefer modern C# supported by the target project. For new or refactored MVVM code, prefer
CommunityToolkit.Mvvmwhere it fits instead of expanding legacy relay-command patterns.
Read the project-local architecture doc before making non-trivial changes in that project:
NINA/ARCHITECTURE.mdNINA.Astrometry/ARCHITECTURE.mdNINA.Core/ARCHITECTURE.mdNINA.CustomControlLibrary/ARCHITECTURE.mdNINA.Equipment/ARCHITECTURE.mdNINA.Image/ARCHITECTURE.mdNINA.MGEN/ARCHITECTURE.mdNINA.Platesolving/ARCHITECTURE.mdNINA.Plugin/ARCHITECTURE.mdNINA.Profile/ARCHITECTURE.mdNINA.Sequencer/ARCHITECTURE.mdNINA.Sequencer.Generators/ARCHITECTURE.mdNINA.Setup/ARCHITECTURE.mdNINA.SetupBundle/ARCHITECTURE.mdNINA.Test/ARCHITECTURE.mdNINA.WPF.Base/ARCHITECTURE.md
Note: the solution project is named NINA.PlateSolving, but the folder on disk is NINA.Platesolving.
The solution has a clear layering pattern.
NINA.CoreShared utilities, logging, localization, enums, common models, SQLite EF context, and generated protobuf contracts.NINA.ProfilePersisted user profile and typed settings model.NINA.AstrometryAstronomy math, coordinate types, night/twilight calculations, catalog queries.
NINA.ImageImage model, file formats, analysis, star detection, rendering helpers.NINA.MGENStandalone MGEN2/MGEN3 transport/protocol library.NINA.EquipmentDevice abstractions and concrete ASCOM/Alpaca/native adapters.NINA.PlatesolvingPlate-solver integrations and orchestration.
NINA.CustomControlLibraryReusable custom WPF controls and themes.NINA.WPF.BaseShared mediators, dockable/view-model base classes, equipment UI support, sky survey subsystem.
NINA.PluginPlugin manifests, loading, installation, compatibility checks, MEF composition.NINA.SequencerAdvanced sequencer engine, entity model, serialization, target/template storage, expressions/symbols.NINA.Sequencer.GeneratorsRoslyn source generator used by sequencer expression-backed properties.
NINAExecutable WPF app, DI composition root, main shell, app-specific views/view models, runtime assets.NINA.SetupWiX MSI project.NINA.SetupBundleWiX Burn bootstrapper.NINA.TestNUnit test suite.
These are in NINA.sln and matter during dependency tracing, but they do not have ARCHITECTURE.md files from the previous documentation pass:
Accord.Imaging (NETStandard)nikoncswrapper
The executable startup path is code-driven:
NINA/App.xaml.csParses command-line options, initializes user settings, loads/selects the active profile, configures logging and notifications, and shows the main window.NINA/CompositionRoot.csBuilds the application service provider and eagerly resolves major view models/controllers.NINA/Utility/IoCBindings.csRegisters the DI graph withMicrosoft.Extensions.DependencyInjection.NINA/MainWindow.xaml(.cs)Hosts the shell.
If you are unsure where an app-wide service comes from, start with IoCBindings.cs.
IProfileServiceis the central runtime configuration service.- Typed settings live in
NINA.Profile, not in scattered ad hoc files. - A profile change can invalidate cached settings references; many components subscribe to
ProfileChangedfor that reason.
- The EF6/SQLite context lives in
NINA.Core.Database.NINADbContext. - The SQL files it consumes at runtime live under
NINA/Database. - A schema or initialization change usually touches both places.
- User-visible labels are generally backed by
NINA.Core.Locale.Loc. - Sequence/plugin metadata often passes label keys like
Lbl_*and resolves them at runtime. - For locale additions or label changes, edit only
NINA.Core/Locale/Locale.resx, which is the source resource file in the current solution layout. - Do not manually edit the other
Locale.<culture>.resxfiles; those are managed through Crowdin, as noted inCONTRIBUTING.md.
- Any third-party package addition, removal, or replacement requires a license metadata check before the change is complete.
- Keep both the in-app list in
NINA/View/About/ThirdPartyLicensesView.xamland the bundled text fileNINA/3rd-party-licenses.txtsynchronized with the actual dependency set. - Remove stale license entries when a package is no longer used.
- If a dependency offers multiple licenses and this project intentionally uses one of them, document the chosen license consistently in both places.
Runtime code expects files in the application output layout, especially under:
NINA/ExternalNINA/UtilityNINA/DatabaseNINA/Sequencer/Examples
If code starts depending on a new runtime file, the change is not complete until:
- the file is copied by
NINA.csproj - the installer packages it when necessary (
NINA.Setup)
The plugin and sequencer systems are tightly connected.
NINA.Plugin.PluginLoader:
- loads built-in sequencer/entity types first
- scans plugin DLLs from versioned folders under
%LOCALAPPDATA%\\NINA - composes sequence items, conditions, triggers, containers, dockable view models, pluggable behaviors, and equipment providers through MEF
- merges plugin resource dictionaries into the WPF application resources
The main app does not hard-code the final sequencer palette. Instead:
NINA.ViewModel.Sequencer.SequenceNavigationVMwaits for plugin loading, then buildsSequencerFactorySequencerFactoryexposes cloneable entity prototypes to the sequence editorNINA.Sequencer.Serialization.SequenceJsonConverterdeserializes through factory-backed creation converters
If you add a new sequence entity or extension point, check all of:
- the sequencer type itself
- MEF export metadata
- plugin loader composition
- serialization/clone behavior
Lower-level runtime code communicates upward through mediator interfaces rather than directly referencing concrete WPF view models.
Primary mediator implementations live in NINA.WPF.Base/Mediator.
The executable wires those mediators to concrete handlers through DI in NINA/Utility/IoCBindings.cs.
If a library project needs to trigger UI-side behavior, prefer an existing mediator or add a new interface/mediator pair in NINA.WPF.Base instead of reaching into NINA directly.
NINA.Astrometryalready depends on established astronomy libraries and models throughSOFAandNOVAS, andNINA.TestpreloadsSOFAlib.dllplusNOVAS31lib.dllduring test bootstrap.- For astronomical calculations and other mathematically sensitive code, prefer algorithms that can be traced to published scientific papers, standards, or official reference documentation for the underlying model instead of ad hoc derivations.
- Validate those changes with extensive automated tests in
NINA.Test, using reference values, edge cases, and regression coverage rather than only spot-checking results manually. - Existing tests already follow that pattern in places such as
NINA.Test/AstrometryTest/AstrometryTest.cs, which includes cases annotated as coming from documented SOFA values and other cited reference data.
- WPF-facing tests that instantiate
System.Windows.Application, depend onApplication.Current.Resources, or construct XAML-backed views should run STA and generally be[NonParallelizable]. - New file-writing tests should prefer isolated temp paths or injectable path providers over shared user locations such as
%LOCALAPPDATA%, unless the shared location is the behavior under test.
- Keep reusable logic out of
NINAwhen a lower library already owns that concern. - Keep UI shell composition out of
NINA.WPF.Base; that project provides shared infrastructure, not final app assembly. - Keep plugin runtime rules centralized in
NINA.Plugin; do not duplicate plugin scanning or manifest logic in app view models. - Keep runtime file layout expectations synchronized between code, build output, and installer authoring.
- If a boundary matters enough to document, consider whether a focused unit test, analyzer, or CI check can enforce it.
- For concrete owner and verification routing, use
.codex/skills/nina-repository/references/project-map.mdand.codex/skills/nina-repository/references/testing-map.md.