{"id":"cxmeel/font-list","name":"font-list","scope":"cxmeel","platform":"roblox","description":"An automatically updated list of available local and cloud fonts. https://github.com/cxmeel/roblox-font-list-generator","version":"2026.8.25","latest":"2026.8.25","versions":["0.0.1","2026.1.29","2026.8.2","2026.8.7","2026.8.13","2026.8.19","2026.8.25"],"license":"MIT","licenseRating":"safe","licenseCaveats":["License identified from the packaged LICENSE file; the manifest declared none."],"licenseVerified":true,"dependencies":{},"integrity":"317c5dff6df10942f06d3992310eee695d3988b24f4a5934ea8b74b389ad419e","likes":0,"downloads":0,"install":"forest install cxmeel/font-list","url":"https://forest.dev/p/roblox/cxmeel/font-list","files":"https://api.forest.dev/ai/package/roblox/cxmeel/font-list/files","readme":"# Roblox Font List Generator\r\n\r\nAutomatically generate a list of all Roblox fonts, including local and cloud\r\nfonts.\r\n\r\n## Usage\r\n\r\nYou'll need to have [Rokit](https://github.com/rojo-rbx/rokit) installed.\r\nThis is a toolchain manager and will automatically install the required\r\ntools for this project ([Lune](https://github.com/filiptibell/lune) and\r\n[StyLua](https://github.com/johnnymorganz/stylua)).\r\n\r\nOnce you have Rokit installed, you can run the following command to install\r\nthe required tools:\r\n\r\n```sh\r\nrokit install\r\n```\r\n\r\nThen, you can run the following command to generate the font list:\r\n\r\n```sh\r\nlune run generate\r\n```\r\n\r\nThe font list will be written to `build/FontList.luau` in the current directory, and comes with built-in type definitions. A `build/FontList.json` file will also be generated (minified, enums shortened to a string; see [the JSON preview](#json-preview) below).\r\n\r\n## Commands\r\n\r\nEvery command takes `-v` for progress logging, or `-vv` to include debug detail.\r\n\r\n### Authentication\r\n\r\nRoblox has required authentication on the asset delivery endpoints since April\r\n2025, and throttles unauthenticated traffic — which is what a CI runner looks\r\nlike from the outside. `generate` and `preview` both accept an optional\r\n`--auth`:\r\n\r\n| Form | Credential |\r\n| --- | --- |\r\n| *omitted* | Whatever the environment carries: `ROBLOX_OPEN_CLOUD_API_KEY`, then `ROBLOSECURITY`. Unauthenticated if neither is set. |\r\n| `--auth` | A `.ROBLOSECURITY` cookie: `ROBLOSECURITY` from the environment if set, otherwise one from a Roblox installation on this machine. |\r\n| `--auth <value>` | The given credential, sent as whichever kind it turns out to be. |\r\n\r\nA value is classified by what it looks like rather than by where it came from, so\r\neither kind works anywhere one is accepted. Cookies carry the warning text\r\nRoblox embeds in them, or arrive already in `.ROBLOSECURITY=` form; anything\r\nelse is treated as an API key. A cookie put in `ROBLOX_OPEN_CLOUD_API_KEY` still\r\nauthenticates as a cookie rather than silently failing.\r\n\r\nCredentials can also live in a `.env` file in the working directory — see\r\n[`.env.example`](.env.example). Real environment variables take precedence, so\r\nCI supplies the same names as secrets. Passing a credential as `--auth <value>`\r\nworks but puts it in process listings and usually in CI logs, so the command\r\nwarns when you do.\r\n\r\n> [!CAUTION]\r\n> A `.ROBLOSECURITY` cookie is full access to the account it belongs to, not a\r\n> scoped credential. An Open Cloud API key can be scoped and revoked\r\n> individually, so prefer one wherever it is sufficient.\r\n\r\nAsset delivery is throttled hard enough that a credential is not always enough\r\non its own, so requests work down a ladder: the v2 endpoint with whatever\r\ncredential is configured, retried five times with backoff reaching a minute,\r\nthen the v1 endpoint with **no credential at all**, on the same ladder. Running\r\nunauthenticated against v1 is how this generator worked for a long time, so it\r\nis worth one genuinely different-looking attempt before giving up. Whichever\r\nrung answers is reused for the rest of the run.\r\n\r\n### `generate`\r\n\r\nBuilds the font list from the current Roblox Studio release and the cloud font\r\ncatalogue, writing `build/FontList.luau` and `build/FontList.json`.\r\n\r\n```sh\r\nlune run generate\r\n```\r\n\r\n| Argument | Default | Description |\r\n| --- | --- | --- |\r\n| `--ext <extension>` | `luau` | Extension for the generated Luau file. |\r\n\r\n### `diff`\r\n\r\nCompares two generated font lists and writes the additions and deletions to\r\n`build/FontList.diff`. Either file may be the Luau flavour or the JSON one, in\r\neither position, chosen by file extension. Entries are matched on `ContentUri`,\r\nand each line ends with the uri it matched:\r\n\r\n```diff\r\n- Montserrat (rbxassetid://11702779517)\r\n\r\n+ Builder Extended (rbxassetid://16658237174)\r\n+ Zekton (rbxasset://fonts/families/Zekton.json)\r\n```\r\n\r\n```sh\r\nlune run diff build/OldFontList.luau build/FontList.luau\r\n```\r\n\r\nModifications to fonts that exist in both lists are not reported, only whole\r\nentries appearing and disappearing.\r\n\r\n### `preview`\r\n\r\nRenders a sample of the given fonts to a pair of SVG files, one with black\r\ntext and one with white, so the right one can be shown for the reader's theme.\r\n\r\n```sh\r\nlune run preview -- --fonts \"rbxasset://fonts/families/BuilderSans.json,rbxassetid://12187360881\"\r\n```\r\n\r\n| Argument | Default | Description |\r\n| --- | --- | --- |\r\n| `--fonts <ids>` | *required* | Comma separated content uris, as they appear in the font list. |\r\n| `--text <text>` | `The quick brown fox jumps over the lazy dog.` | Sample text. |\r\n| `--width <pixels>` | `1024` | Maximum image width. The sample size shrinks to fit rather than the text being clipped. |\r\n| `--output <dir>` | `temp/preview` | Where the pair is written. Files are named after a hash of the inputs. |\r\n| `--registry <dir>` | `temp/downloads` | Where cloud font descriptors and downloads are kept. Runs `generate` first if it does not exist. |\r\n| `--content <dir>` | Studio install | Overrides the Roblox Studio content directory that local fonts are read from. |\r\n| `--resvg [path]` | off | Also write PNGs, using [resvg](https://github.com/linebender/resvg). On its own it uses whatever is on `PATH`; give it a path to use a binary that is not. |\r\n| `--scale <factor>` | `2` | Multiplies the PNG dimensions, so a preview stays sharp when displayed at the SVG's nominal width. |\r\n\r\nFonts are laid out alphabetically by family name, regardless of the order they\r\nare listed in. Every glyph is emitted as an outline path rather than as text,\r\nbecause GitHub renders README images in a sandbox with no access to webfonts,\r\nso a `<text>` element would silently fall back to a default face.\r\n\r\n`--content` exists for machines with no Roblox Studio installation. Unpack the\r\nStudio fonts package into a directory named `fonts` and point at its parent;\r\nthe workflow in this repository does exactly that to render previews on a\r\nrunner.\r\n\r\n`--resvg` writes a matching pair of PNGs alongside the SVGs, for places that\r\nwill not render an SVG at all — GitHub release notes being the case this was\r\nadded for. resvg is not bundled; install it with `cargo install resvg`, or\r\ngrab a [prebuilt binary](https://github.com/linebender/resvg/releases) if one\r\nexists for your platform. Labels are set in Arimo, taken from the same content\r\ndirectory as the fonts themselves, so the output does not depend on which\r\nfonts happen to be installed on the machine doing the rendering.\r\n\r\nEmbed the pair with a `<picture>` element so it follows the reader's theme:\r\n\r\n```html\r\n<picture>\r\n  <source media=\"(prefers-color-scheme: dark)\" srcset=\"preview_white.svg\">\r\n  <img alt=\"Font preview\" src=\"preview_black.svg\">\r\n</picture>\r\n```\r\n\r\n## Preview\r\n\r\nHere's a preview of the generated font list:\r\n\r\n```luau\r\n--!strict\r\n-- This file is automatically generated by Font List Generate\r\n-- by @cxmeel (cxmeels). Do not edit this file manually.\r\n\r\nexport type IFont = {\r\n    ContentUri: string,\r\n    Name: string,\r\n    PostScript: string,\r\n    Aliases: { string },\r\n    Weights: { Enum.FontWeight },\r\n    Styles: { Enum.FontStyle },\r\n}\r\n\r\nlocal fonts: { IFont } = {\r\n    -- Local fonts --\r\n    {\r\n        Name = \"Accanthis ADF Std\",\r\n        PostScript = \"accanthis_adf_std\",\r\n        Aliases = {},\r\n        ContentUri = \"rbxasset://fonts/families/AccanthisADFStd.json\",\r\n        Weights = { Enum.FontWeight.Regular },\r\n        Styles = { Enum.FontStyle.Normal },\r\n    },\r\n    {\r\n        Name = \"Amatic SC\",\r\n        PostScript = \"amatic_sc\",\r\n        Aliases = {},\r\n        ContentUri = \"rbxasset://fonts/families/AmaticSC.json\",\r\n        Weights = { Enum.FontWeight.Regular, Enum.FontWeight.Bold },\r\n        Styles = { Enum.FontStyle.Normal },\r\n    },\r\n    {\r\n        Name = \"Arimo\",\r\n        PostScript = \"arimo\",\r\n        Aliases = {},\r\n        ContentUri = \"rbxasset://fonts/families/Arimo.json\",\r\n        Weights = {\r\n            Enum.FontWeight.Bold,\r\n            Enum.FontWeight.Regular,\r\n            Enum.FontWeight.Medium,\r\n            Enum.FontWeight.SemiBold,\r\n        },\r\n        Styles = { Enum.FontStyle.Normal, Enum.FontStyle.Italic },\r\n    },\r\n    {\r\n        Name = \"Arimo (Legacy)\",\r\n        PostScript = \"arimo_legacy\",\r\n        Aliases = {},\r\n        ContentUri = \"rbxasset://fonts/families/LegacyArimo.json\",\r\n        Weights = { Enum.FontWeight.Regular, Enum.FontWeight.Bold },\r\n        Styles = { Enum.FontStyle.Normal },\r\n    },\r\n    {\r\n        Name = \"Arimo (Legacy)\",\r\n        PostScript = \"arimo_legacy\",\r\n        Aliases = {},\r\n        ContentUri = \"rbxasset://fonts/families/LegacyArial.json\",\r\n        Weights = { Enum.FontWeight.Regular, Enum.FontWeight.Bold },\r\n        Styles = { Enum.FontStyle.Normal },\r\n    },\r\n    {\r\n        Name = \"Balthazar\",\r\n        PostScript = \"balthazar\",\r\n        Aliases = {},\r\n        ContentUri = \"rbxasset://fonts/families/Balthazar.json\",\r\n        Weights = { Enum.FontWeight.Regular },\r\n        Styles = { Enum.FontStyle.Normal },\r\n    },\r\n    ...\r\n    -- Cloud fonts --\r\n    {\r\n        Name = \"Noto Sans\",\r\n        PostScript = \"noto_sans\",\r\n        Aliases = {\r\n            \"Noto Color Emoji\",\r\n            \"Noto Sans Symbols\",\r\n            \"Noto Sans Symbols2\",\r\n        },\r\n        ContentUri = \"rbxassetid://12187370747\",\r\n        Weights = {\r\n            Enum.FontWeight.Bold,\r\n            Enum.FontWeight.SemiBold,\r\n            Enum.FontWeight.ExtraLight,\r\n            Enum.FontWeight.Thin,\r\n            Enum.FontWeight.ExtraBold,\r\n            Enum.FontWeight.Medium,\r\n            Enum.FontWeight.Light,\r\n            Enum.FontWeight.Regular,\r\n            Enum.FontWeight.Heavy,\r\n        },\r\n        Styles = { Enum.FontStyle.Normal, Enum.FontStyle.Italic },\r\n    },\r\n    ...\r\n}\r\n\r\nreturn fonts\r\n```\r\n\r\n## JSON Preview\r\n\r\n```json\r\n[\r\n    {\r\n        \"Aliases\": {},\r\n        \"ContentUri\": \"rbxasset://fonts/families/AccanthisADFStd.json\",\r\n        \"Name\": \"Accanthis ADF Std\",\r\n        \"PostScript\": \"accanthis_adf_std\",\r\n        \"Styles\": [\r\n            \"Normal\"\r\n        ],\r\n        \"Weights\": [\r\n            \"Regular\"\r\n        ]\r\n    },\r\n    {\r\n        \"Aliases\": {},\r\n        \"ContentUri\": \"rbxasset://fonts/families/AmaticSC.json\",\r\n        \"Name\": \"Amatic SC\",\r\n        \"PostScript\": \"amatic_sc\",\r\n        \"Styles\": [\r\n            \"Normal\"\r\n        ],\r\n        \"Weights\": [\r\n            \"Regular\",\r\n            \"Bold\"\r\n        ]\r\n    },\r\n    ...,\r\n    {\r\n        \"Aliases\": [\r\n            \"Noto Color Emoji\",\r\n            \"Noto Sans Symbols\",\r\n            \"Noto Sans Symbols2\"\r\n        ],\r\n        \"ContentUri\": \"rbxassetid://12187370747\",\r\n        \"Name\": \"Noto Sans\",\r\n        \"PostScript\": \"noto_sans\",\r\n        \"Styles\": [\r\n            \"Normal\",\r\n            \"Italic\"\r\n        ],\r\n        \"Weights\": [\r\n            \"Bold\",\r\n            \"SemiBold\",\r\n            \"ExtraLight\",\r\n            \"Thin\",\r\n            \"ExtraBold\",\r\n            \"Medium\",\r\n            \"Light\",\r\n            \"Regular\",\r\n            \"Heavy\"\r\n        ]\r\n    },\r\n    ...\r\n]\r\n```\r\n\r\n## Duplicate Entries\r\n\r\nA handful of families are published twice: once as a local font shipped with\r\nRoblox Studio, and once as a cloud asset. Both entries are listed, because both\r\nare real things you can reference, and the pairs carry identical weight and\r\nstyle coverage — the only difference is where the font comes from.\r\n\r\nPrefer the local entry where you have the choice. It is already on the user's\r\nmachine and needs no additional content download.\r\n\r\n`ContentUri` is the only field guaranteed to be unique. To keep lookups\r\nunambiguous, the cloud copy of a duplicated family carries a `_cloud` suffix on\r\nits `PostScript` name, leaving the bare name on the local one:\r\n\r\n| Name | ContentUri | PostScript |\r\n| --- | --- | --- |\r\n| Builder Sans | `rbxasset://fonts/families/BuilderSans.json` | `builder_sans` |\r\n| Builder Sans | `rbxassetid://16658221428` | `builder_sans_cloud` |\r\n\r\nThe exception is `Arimo (Legacy)`, which appears twice as a local font. Roblox\r\ndropped Arial in favour of Arimo and renamed the family in place, so both\r\n`LegacyArimo.json` and `LegacyArial.json` now declare the same name. Neither is\r\na cloud duplicate, and both are left as they are.\r\n","readmeTruncated":false}