Shojiku 0.2.0

dotnet add package Shojiku --version 0.2.0
                    
NuGet\Install-Package Shojiku -Version 0.2.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Shojiku" Version="0.2.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Shojiku" Version="0.2.0" />
                    
Directory.Packages.props
<PackageReference Include="Shojiku" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Shojiku --version 0.2.0
                    
#r "nuget: Shojiku, 0.2.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Shojiku@0.2.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Shojiku&version=0.2.0
                    
Install as a Cake Addin
#tool nuget:?package=Shojiku&version=0.2.0
                    
Install as a Cake Tool

Shojiku for .NET

.NET bindings for Shojiku — a document engine that turns a YAML template plus your data into a deterministic PDF.

Install

dotnet add package Shojiku

The engine binary ships as a runtime-identifier-specific asset inside the package, so there is no build step on the supported platforms (Linux and macOS on x64 and arm64, Windows on x64) and no native dependency to deploy alongside your application.

Usage

using Shojiku;

using var client = new ShojikuClient(templates: "App/Templates");

var result = await client.GenerateAsync("receipt_ja", new {
    customer = new { name = "Yamada Shoji K.K." },
    items = new[] { new { name = "Consulting", qty = 1, price = 120000 } },
});

if (result.Success)
    await result.Artifact!.WriteAsync("receipt.pdf");
else
    foreach (var d in result.Failure!.Diagnostics) logger.LogWarning(d.Message);

Signing is a separate step over the rendered document:

var signed = await result.Artifact!.SignAsync(new LocalPem(key: "signer.key", cert: "signer.crt"));
if (signed.Success)
    await signed.Artifact!.WriteAsync("receipt-signed.pdf");

Nothing throws in the normal flow: every operation returns a result you query — Success, the artifact, and the engine's diagnostics (an overflowing box, an unknown field). A failure carries a trace: which step failed, and its structured cause, so it is data you log and inspect rather than an exception you catch.

Every operation has a blocking form beside the …Async one, so a console application is not pushed through .GetAwaiter().GetResult().

The template root can also come from the SHOJIKU_TEMPLATE_ROOT environment variable (useful for system-wide installs); template names are identifiers, never paths. An explicit templates: beats that variable; SHOJIKU_LIBRARY is the deliberate exception and beats an explicit library:, because where the engine lives is a deployment decision.

Signing with a key this process never holds

When the private key lives in a cloud KMS, an HSM or a smartcard, use ExternalSigner instead. Shojiku hands out the bytes a signature has to cover; your code signs them wherever the key is and hands the signature back, so the key never enters your application:

var provider = new ExternalSigner(
    toBeSigned => kms.Sign(keyId, toBeSigned),
    Algorithm.EcdsaP256Sha256,
    cert: "signer.crt");
var signed = await artifact.SignAsync(provider);

The call site does not change — which provider you pass is the only difference, and a provider registered by name works the same way under a strict client. This package ships no cloud client of its own: the callback is whichever client your application already uses.

Two details worth getting right. The bytes you are handed are the CMS signed attributes, not the document's digest — a service that signs a digest must hash these bytes with SHA-256 itself. And the signature is that operation's raw output: PKCS#1 v1.5 bytes for rsa-pkcs1-sha256, an ASN.1 DER sequence for ecdsa-p256-sha256, which is what AWS KMS and Google Cloud KMS both return unchanged.

A failure inside your own code is not swallowed into a failed result: an outage at your key service is not a fact about the document.

Requirements

.NET 10 or newer.

Documentation

License

Licensed under any of Apache-2.0, MIT, or BSD-3-Clause, at your option.

Product Compatible and additional computed target framework versions.
.NET net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
  • net10.0

    • No dependencies.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
0.2.0 64 8/8/2026
0.1.0 107 8/1/2026