Skip to content

Repository files navigation

@nowly/cli

CLI to create, build, and validate Nowly presences.

Install

npm install -g @nowly/cli

Requires Node.js 22+.

Quick start

nowly init "YouTube"
cd src/Y/YouTube
# Edit presence.ts, then:
nowly build YouTube

nowly build outputs to dist/presences/{slug}/ with bundle.js, metadata.json, and optional settings and language packs.

Commands

nowly init [name]

Scaffold a new presence.

Option Type Default Description
--category string - streaming, music, video, social, gaming, tools, ai, learning, creator, other
--color hex #555555 Accent color for the presence
--urls string - Comma-separated list of URLs the presence runs on
--author string Nowly Author name
--github string - Author GitHub handle
--description string - Short description (en-US)
--discord-native boolean prompt Write discordNative: true when Discord already supports the platform via account linking

Omitting an option starts an interactive prompt. Without --discord-native, init asks this as a yes/no (default no) and only writes the flag when the answer is yes.

nowly init "Netflix" --category streaming --color "#E50914" --urls "netflix.com" --author "Steellgold"
nowly init "Spotify" --discord-native

Creates:

src/N/Netflix/
├── presence.ts
├── metadata.json
└── assets/

nowly build [slug]

Build one or all presences.

nowly build              # Build every presence in src/
nowly build youtube      # Build only the "youtube" presence

Each build produces:

  • dist/presences/{slug}/bundle.js - Minified IIFE (esbuild, es2022 target)
  • dist/presences/{slug}/metadata.json - Presence metadata
  • dist/presences/{slug}/settings.json - Extracted user settings (if any)
  • dist/presences/{slug}/assets/ - Copied assets

A dist/presences/registry.json is generated listing all built presences. When a presence contains a locales directory, its validated JSON files are also copied to dist/presences/{slug}/locales/ and included in generated metadata.

Optional language packs

A presence can keep using inline strings without adding language files. To localize its Discord text, add all three supported dictionaries:

src/Y/YouTube/locales/
├── en-US.json
├── fr-FR.json
└── es-ES.json

Each file must be a flat JSON object containing the same keys and string values. en-US.json is the reference dictionary and runtime fallback. Invalid JSON, unsupported files, missing locales, non-string values, and mismatched keys fail validation and builds.

Use the English dictionary to get typed autocomplete without generating types:

import type enUS from "./locales/en-US.json"

const locale = await presence.getStrings<typeof enUS>()

nowly pack <slug>

Build a presence and zip it for drop-install in the extension Debug panel.

nowly pack youtube

Writes dist/packs/{slug}.zip (metadata.json + bundle.js, plus assets and locales when present). Unsigned zips install only on unpacked builds or with developer mode enabled.

nowly extension <slugs...>

Download (or copy) a Chrome dev extension and bake one or more built presences into it.

nowly extension youtube
nowly extension youtube github --from ../nowly/apps/extension/dist/chrome

Writes dist/extension-dev with dev-presences.json. Load that folder unpacked at chrome://extensions.

See Load and test locally.

nowly list (alias: ls)

List all presences in src/.

nowly list

  Name       Category      Slug
 ─────────────────────────────────
  YouTube    video         youtube
  Netflix    streaming     netflix
  GitHub     tools         github
  ...

nowly validate [slug]

Validate presence metadata and structure.

nowly validate           # Validate all presences
nowly validate youtube   # Validate only "youtube"

Checks for required fields: name, color, category, description.en-US, url, presence.ts, locales/en-US.json, and assets/. If discordNative is present, it must be a boolean.

Interactive mode

Run nowly with no arguments to open a menu:

┌──────────────────────────────────┐
│  Nowly CLI v1.2.2                │
│                                  │
│  ○ Create a new presence         │
│  ○ Build presences               │
│  ○ Pack a presence zip           │
│  ○ List all presences            │
│  ○ Validate presences            │
│  ○ Exit                          │
└──────────────────────────────────┘

After each action you can choose to continue or exit.

Project structure

├── src/
│   ├── A/
│   │   └── Amazon/
│   │       ├── presence.ts
│   │       └── metadata.json
│   ├── G/
│   │   └── GitHub/
│   │       ├── presence.ts
│   │       └── metadata.json
│   └── ...
├── dist/
│   └── presences/
│       ├── amazon/
│       │   ├── bundle.js
│       │   ├── metadata.json
│       │   └── settings.json
│       ├── github/
│       │   └── ...
│       └── registry.json
└── package.json

Presence script API

See @nowly/sdk for the full presence API documentation.

import { Presence, PresenceType } from "@nowly/presence";

const presence = new Presence({
  Settings({
    "show-button": {
      title: "Show button",
      description: "Display a button on Discord",
      type: "boolean",
      value: true,
    },
  }),
});

presence.on("UpdateData", async () => {
  presence.setActivity({
    details: "Browsing",
    state: "Some page",
    largeImageKey: "logo",
    type: PresenceType.Watching,
  });
});

License

MIT

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages