Development environment
Prerequisites
- .NET 10 SDK — every plugin csproj targets
net10.0(<TargetFramework>net10.0</TargetFramework>). - EF Core CLI tools (
dotnet-ef) — for plugins with aDbContext(Schulware, OdaOrg). Install/update withdotnet tool install --global dotnet-ef(ordotnet tool update). See migrations.md. - Kiota — only needed to regenerate the Schulware API client. See setup/kiota-client.md.
- A running SchulyBackend with PostgreSQL to load and test a plugin end-to-end.
The abstractions dependency
Schuly.Plugin.Abstractions is a NuGet PackageReference, not a project reference:
<PackageReference Include="Schuly.Plugin.Abstractions" Version="0.2.*" />
It supplies ISchulyPlugin, IPluginBackgroundTask, IPluginUserContext, IPluginLogin,
and PluginServiceContext. Backend-provided types such as IPluginVault
(Schuly.Infrastructure.Vault) are resolved at runtime from the host's DI container — the
host registers each plugin's isolated vault keyed by the plugin's Name.
How a plugin is structured
A plugin is a class library exposing one ISchulyPlugin implementation (the composition root,
slim like an ASP.NET Program.cs). The richer plugins keep HTTP routes in Controllers/
(discovered as an MVC ApplicationPart) rather than mapping them in ConfigureEndpoints, and
split sync logic across small scoped services driven by a single IPluginBackgroundTask.
See adding-a-plugin.md for the full lifecycle.
Building a plugin
# Restore + build a single plugin
dotnet build src/Schuly.Plugin.Schulware/Schuly.Plugin.Schulware.csproj -c Release
# Produce the loadable output (DLL + non-host dependencies) — same command CI uses
dotnet publish src/Schuly.Plugin.Schulware/Schuly.Plugin.Schulware.csproj -c Release -o ./out
Each plugin also has a .slnx solution file for opening it standalone in an IDE.
Running a plugin against a live backend
The backend's plugin host loads plugin DLLs from its plugins/ directory (/app/plugins/ in
the container) and reads each plugin's YAML config from its plugins-config directory.
- Bring up SchulyBackend + Postgres (see the backend's README).
dotnet publishthe plugin (above) and copy the plugin DLL plus its third-party dependency DLLs into the backend'splugins/folder. Host-shared assemblies (ASP.NET Core, EF Core, Npgsql, the abstractions, Schuly host assemblies) are already provided by the backend — only true third-party deps (e.g. Kiota, AngleSharp) need to ship alongside the plugin.- Drop the plugin's runtime config as
Schuly.Plugin.<Name>.ymlinto the backend's plugins-config directory. For Schulware this must contain at leastSchulwareApi.BaseUrl—ConfigureServicesthrows and refuses to load otherwise (seesrc/Schuly.Plugin.Schulware/config.ymlfor the schema). - Restart the backend. On startup the host calls
ConfigureServices→ConfigureEndpoints→MigrateAsync(which runsdb.Database.MigrateAsync()to create/upgrade the plugin's dedicated Postgres database), then schedules anyIPluginBackgroundTaskon itsInterval.
For real distribution (downloading prebuilt DLLs via curl) see
setup/distribution.md.