ADocumentation Index
Fetch the complete documentation index at: https://mintlify.com/mohameodo/nano/llms.txt
Use this file to discover all available pages before exploring further.
.rink file is an encrypted CommonJS module. Before encryption it is a plain .js (or .ts) file that exports a ScraperPlugin object — or an array of them. nano’s build pipeline compiles the source with esbuild, encrypts the resulting bundle with AES-256-CBC, and stores the ciphertext as a binary file. At runtime, getPlugins() reverses this process in memory: it decrypts and evaluates the bundle, then registers the resulting exports as active stream providers.
Unencrypted plugin structure
Before compilation, a plugin source file is a standard Node.js CommonJS module. It must assign aScraperPlugin object — or an array of them — to module.exports. The shape of the export must satisfy the ScraperPlugin interface described in the Plugins reference.
The bundled catalog sources installed via
shiopa add are pre-compiled and ready to use. You only need to write and compile your own .rink if you want to add a custom source that isn’t in the catalog.Important constraints
CommonJS only
The module must use
module.exports, not ESM export default. The compile script bundles with esbuild in cjs format.No dynamic imports
Do not use
import(). Use require() for any dependencies. Only Node.js built-ins and global fetch are available inside the sandbox at runtime.Unique key
The
key field must be unique across all installed plugins. Duplicate keys are silently deduplicated — only the first loaded plugin with a given key is registered.Return null on failure
fetchStream must return null when the source is unavailable or the content isn’t found. Do not throw — unhandled exceptions from fetchStream are caught but leave no trace in the response.Returning subtitles
If the source provides subtitle tracks, include them in the returned object. nano proxies each subtitle URL through/api/proxy the same way it handles stream URLs:
Returning multiple quality levels
For HLS sources that expose discrete quality variants, include aqualities array. nano proxies each quality URL independently and exposes them to the player’s quality selector:
Providing custom stream headers
Some CDNs require specificReferer or Origin headers. Return them in a headers object and nano will merge them into the proxy request (plugin-provided values override the inferred ones):
Compiling and encrypting a plugin
Use thecompile-rink.mjs script to bundle and encrypt a single source file. The script uses esbuild to bundle your TypeScript or JavaScript source into a self-contained CommonJS module, then encrypts the output and writes a binary .rink file.
Write your plugin source
Create your plugin at any path, for example
src/shade/dev/my-source.ts (or .js). Export a ScraperPlugin via module.exports.Compile to .rink
Run the compiler, pointing it at your source file. If you omit You can override the plugin
outDir, the .rink is written beside the source file. If you omit aliasId, the file’s key field is used as the output filename.key and name at compile time using the optional alias arguments:Compile all sources at once
To recompile every source in To build only the publicly listed sources:
src/shade/dev/ (as mapped in scripts/rink-aliases.mjs), use the compile-rinks script:Registering a source alias
If you maintain multiple source files and compile them all withcompile-all-rinks.mjs, add a mapping to scripts/rink-aliases.mjs so the compiler knows which alias ID and display name to apply:
Encryption details
The following is informational — the compile script handles all of this automatically.| Property | Value |
|---|---|
| Algorithm | AES-256-CBC |
| Key derivation | crypto.scryptSync(passphrase, "rink-salt-nano-67", 32) |
| Binary layout | [16 bytes IV] [32 bytes HMAC-SHA256] [ciphertext] |
| On-disk format | Binary (raw bytes) — base64 is also accepted by the decryptor |
| HMAC validation | Computed over iv + ciphertext; verified with crypto.timingSafeEqual before decryption |
.rink file that fails HMAC verification is rejected with a “Corrupted rink file” error and silently skipped during plugin loading.