Writing a Package Manifest
A package manifest is a TOML file that defines a font package.
It tells foton what the package is called, where its downloadable sources are,
and which fonts from those sources should be installed.
Typical workflow
A practical workflow for authoring a package is:
- Write a manifest file
- Run
foton manifest checkon it - Install it locally with
foton install --manifest - Add it to a package registry if you want to publish it
Example manifest
name = "example-font"
version = "1.2.3"
description = "Example font family for UI and coding"
homepage = "https://example.com/example-font"
repository = "https://github.com/example/example-font"
license = "OFL-1.1"
[[sources]]
url = "https://example.com/downloads/example-font-1.2.3.zip"
hash = "sha256:0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"
[sources.contents]
type = "archive"
fonts = [
"example-font-1.2.3/ExampleFont-Regular.ttf",
"example-font-1.2.3/ExampleFont-Bold.ttf",
"example-font-1.2.3/ExampleFontUI-Regular.ttf",
"example-font-1.2.3/ExampleFontUI-Bold.ttf",
]
Required fields
This section is a quick checklist, not a complete field reference. See Package Manifest Reference for a detailed description of every field.
At minimum, a manifest must define:
nameversionsources
For the exact fields inside each source entry, see Package Manifest Reference.
Choosing a package version
Choose a version that identifies one specific immutable release and sorts in
release order for that package.
A practical way to choose package versions is:
- Use the upstream release version when it already fits
foton’s package-version format. - If there is no usable upstream version, use a calendar-based version such as
2024.05.11. - If you need to publish a pre-release, add a suffix to the final part. A
suffix marks the version as a pre-release and sorts it before the
corresponding version without a suffix, such as
1.4.0-rc-1 < 1.4.0or2024.05.11-beta-2 < 2024.05.11. - If the upstream version does not fit
foton’s package-version syntax, rewrite it in a form that still preserves the upstream release ordering and whether the release is stable or pre-release. For example, rewritev1.4.0as1.4.0, and rewrite1.4.0-rc10as1.4.0-rc-10. - Keep the notation consistent within the same package to avoid non-intuitive
ordering results:
- Do not mix forms such as
2024.5.11and2024.05.11, because they are different versions. - Keep the same number of numeric parts within a package. For example,
prefer a consistent series such as
1.2.0,1.3.0, and1.4.0-rc-1over mixing forms such as1.2,1.3.0, and1.4-rc-1.
- Do not mix forms such as
For the exact package-version syntax and ordering rules, see Package Manifest Reference.
Recommended fields
These fields are optional, but strongly recommended because they help users
understand the package and the fonts it provides. In particular,
description appears in search results and is used by foton search.
See Package Manifest Reference for the
complete field definitions and constraints.
These fields are recommended:
descriptionlicensehomepagerepository
These metadata fields describe the package and the fonts it provides, not the
manifest structure itself. In particular, homepage, repository, and
license should refer to the upstream font project or the upstream font files
included in the package.
If there is no suitable upstream homepage or repository, omit that field. Do
not repeat repository in homepage just to fill both fields.
foton manifest check warns if description or license is missing.
Prepare source information
Each sources[] entry needs a source digest.
For archive sources, you also need the exact archive entry paths for the font
files you want to install.
Get the source hash
The hash field stores the SHA-256 digest of the downloaded source file,
written as sha256:<hex-digest>.
Download the exact file referenced by url, compute its SHA-256 digest with a
local tool, and copy the hexadecimal digest into the manifest.
On Windows, one way to do this is:
Get-FileHash -Algorithm SHA256 <downloaded-file-path>
Then write the result in the manifest as:
hash = "sha256:<hex-digest>"
Find archive entry paths
For contents.type = "archive", the fonts and ignore rules use paths
inside the ZIP archive, not paths from an extracted directory on disk.
Open the ZIP archive in Explorer or another archive tool and copy each entry
path exactly as it appears in the archive.
For example, if the archive contains
example-font-1.2.3/ExampleFont-Regular.ttf, use that full archive path in
fonts.
Choosing fonts from a source
Each sources[] entry must define a [sources.contents] table.
That table tells foton what kind of downloaded source it is working with and,
for archive sources, which font files inside that source should be installed.
If contents.type = "font-file", the downloaded source itself is one font
file.
If contents.type = "archive", the downloaded source is a ZIP archive that
contains one or more font files.
See Package Manifest Reference for the exact
field definitions and constraints.
Archive sources (contents.type = "archive")
For an archive source, the fonts field under [sources.contents] selects
which archive entries should be installed as fonts.
If you omit fonts, foton uses these default glob rules:
**/*.ttf**/*.otf**/*.ttc**/*.otc
Prefer fonts entries that list each font file path explicitly.
If the archive entry’s file name is unsuitable, you can also specify
file-name on a path entry written as { path = ... } to tell foton
what file name to store locally.
Avoid glob rules when possible.
This makes it clear from the manifest exactly which files belong to the
package, and it reduces the chance of unintentionally picking up extra or
unexpected files from the source archive.
If the source archive contains other font-like files such as *.ttf, *.otf,
*.ttc, or *.otc that you do not want to install, prefer listing those paths in
ignore explicitly.
That makes the omission visible in the manifest and shows that the files were
left out intentionally.
Direct font sources (contents.type = "font-file")
For a source with contents.type = "font-file", the downloaded source itself
is installed as one font file.
You can set file-name to override the local file name when the URL path is
not suitable.
[[sources]]
url = "https://example.com/download?id=123"
hash = "sha256:0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"
[sources.contents]
type = "font-file"
file-name = "Example-Regular.ttf"
Validate the manifest
Run:
foton manifest check <manifest-path>
By default, manifest check does more than syntax validation.
It reads the manifest, stages the package, downloads the sources, and verifies
that installation would succeed.
Use --no-source-checks to skip those source-dependent checks when needed.
For common warning types, see Package Manifest Reference.
If you want warnings to fail the command, use the global
--warnings-as-errors option.
foton --warnings-as-errors manifest check <manifest-path>
Test the manifest locally
You can install a package directly from a local manifest file:
foton install --manifest <manifest-path>
This is useful before publishing the manifest in a registry. It lets you test the actual install workflow with the same manifest content.
Publish through a registry
Once a manifest works locally, place it in a package registry so it can be resolved by package name. See Setting Up Your Own Package Registry.