npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@zidsa/vitrin-cli

v1.2.1

Published

CLI for Zid theme development

Readme

Vitrin CLI

command-line interface for Zid theme development.

Vitrin CLI Demo

Installation

npm install -g @zidsa/vitrin-cli

Quick Start

# Launch the interactive TUI (recommended)
vitrin

# Or use CLI commands directly:
vitrin login                  # Authenticate with Zid
vitrin new my-theme           # Create a new theme
cd my-theme
vitrin push                   # Push theme to Zid (updates latest version)
vitrin push --new-version     # Cut a fresh version (asset paths changed)
vitrin status                 # View / change a version's lifecycle status
vitrin download               # Pull the latest version's .zip artifact
vitrin presets list           # Manage theme presets
vitrin translations           # Generate / update translation catalogs

Commands

Theme Management Commands

vitrin themes list [options]            # List all themes from server
vitrin themes delete <id> [-f]          # Delete a theme from server
vitrin status [-v <ver>] [-s <status>]  # View / change version status
vitrin download [-v <ver>] [-o <path>]  # Download a version artifact
vitrin presets <list|show|create|update|delete|upload-image>

Options for themes list:

  • -s, --search <term> - Search themes by name

Options for themes delete:

  • -f, --force - Skip confirmation

See the dedicated sections below for status, download, and presets.

Authentication

vitrin login

Authenticates with Zid Partner Dashboard. Opens browser for OAuth flow.

Example:

$ vitrin login
Opening Zid Partner Dashboard in your default browser...
Listening for authentication callback on http://localhost:4444/auth/callback

✅ Authentication successful!
Token saved to ~/.vitrin/config.json

Theme Creation

vitrin new <theme-name> [options]

Creates a new theme. By default, clones the official Growth Theme template from https://github.com/zidsa/growth-theme and writes a .vitrin/theme.json into the new directory. The template URL is disclosed in the CLI output so you know exactly what is being cloned. Vitrin-specific notes are written to VITRIN.md; the template's own README.md is left untouched.

Options:

  • -d, --directory <dir> — Target directory (default: theme name)
  • -e, --from-existing <path>Skip the clone and register a directory you already have as a Vitrin theme. Writes .vitrin/theme.json and a global-registry entry in place, without copying or modifying your files. Useful for adopting an existing repo or an unzipped template under Vitrin.
  • --no-git — Skip git init (only relevant on the clone path)

Example — clone the default template:

$ vitrin new my-store-theme
Creating new theme: my-store-theme
Target directory: my-store-theme
Template will be cloned from: https://github.com/zidsa/growth-theme
✅ Theme "my-store-theme" created successfully!
Path: /Users/you/themes/my-store-theme
Saved to local .vitrin/theme.json and global registry.

Example — register an existing directory:

$ vitrin new acme-theme --from-existing ./checkouts/acme-theme
Registering existing theme: acme-theme
Source directory: ./checkouts/acme-theme
Found theme files in /Users/you/checkouts/acme-theme
✅ Theme "acme-theme" registered at /Users/you/checkouts/acme-theme
Saved to local .vitrin/theme.json and global registry.

The path is recorded in ~/.vitrin/themes.json immediately, so the theme shows up in Switch Theme (TUI) before you push to Zid for the first time.

Push Theme to Zid

vitrin push [options]

Builds and pushes your theme to Zid servers, creating or updating the theme.

Push validates the directory before doing any work and refuses to upload a folder that is missing any of the required theme files (layout.jinja, header.jinja, footer.jinja, templates/home.jinja), so a stale .vitrin/theme.json from the wrong directory cannot silently push the wrong files. It also runs the same asset-compile step as vitrin build, so Tailwind/Vite output is in the upload, not just sources.

If the theme contains any templates that Zid manages with platform defaults (templates/account_profile.jinja, templates/account_orders.jinja, templates/account_wishlist.jinja, templates/loyalty_program.jinja, templates/address_form.jinja), push pauses and asks whether to upload them anyway, remove them locally, or cancel. Uploading overrides the platform default — only do it if you intend to customize that page.

Options:

  • -s, --store <id> - Dev store ID to install on
  • -a, --activate - Activate theme after installation
  • -v, --version <version> - Version number (X.Y.Z)
  • -c, --changelog <text> - English changelog for this push
  • --changelog-ar <text> - Arabic changelog (sent as { en, ar })
  • -n, --new-version - Cut a brand new version instead of updating the latest one
  • -b, --bump <kind> - With --new-version, auto-compute the next version from the latest server version: patch, minor, or major. Overrides --version unless both are provided.

Example:

$ vitrin push --store 123456 --activate
✅ Theme pushed successfully!
Theme ID: abc123
Version: 1.0.0

Update the latest version vs. create a new one

By default vitrin push updates the latest existing version of the theme in place (the backend treats keep_using_latest=true as the default). Pass --new-version (TUI: pick Create a new version in the push wizard) to cut a fresh version instead.

Update the latest version (default — no flag). Use for changes that don't move asset URLs or break clients that have already cached the previous push. Stores already on the latest version pick the changes up immediately.

  • Quick template patches in .jinja files
  • Bugfixes in templates or translations
  • Copy / wording / translation tweaks

Create a new version (--new-version). Required when shipping the template change against the latest version would break clients that still hold the older assets in cache.

  • Asset files renamed, removed, or restructured under assets/
  • CSS/JS bundle paths or hashes changed
  • Breaking template changes that depend on assets that only exist in this push

Existing installs stay on the older version until they update explicitly, so cached-asset clients keep matching the templates they were served with.

# in-place patch on latest version (template tweak, copy fix, bugfix)
vitrin push

# cut a fresh version (assets moved / breaking change)
vitrin push --new-version

Link Theme Directory

vitrin link [theme-id] [options]

Link or unlink current directory to a Zid theme. Useful for managing multiple themes with the same codebase, or adopting an existing API theme into a local checkout.

Options:

  • -p, --path <path> - Path to theme directory (default: current)
  • -f, --force - Force link even if already linked to another theme
  • -s, --show - Show current linked theme

Examples:

# Show current linked theme
$ vitrin link --show
📎 Currently linked to theme: theme-123

# Link to a theme
$ vitrin link theme-456
✅ Linked to theme: theme-456

# Switch to a different theme
$ vitrin link theme-789 --force
✅ Switched from theme theme-456 to theme-789

# Unlink from theme — local files and path remain registered
$ vitrin link
✅ Unlinked from theme: theme-789

TUI link flow. In the TUI, after picking an API theme (manual ID or from the list), Vitrin asks where the theme should be linked: the current directory, any directory in the global registry, or a custom path you type in. The path is validated to exist. This means you can pick a theme from the API and tie it to the actual folder where its files live, instead of always linking the cwd.

Use Cases:

  • Work with same codebase for multiple themes
  • Switch between development and production themes
  • Share codebase across different stores
  • Pull an API theme down (vitrin download) and then link it into the unzipped folder

Versions & Changelogs

The TUI now has a dedicated view for managing the versions of a linked theme. Open it from the dashboard (📚 Versions & Changelogs, only shown when a theme is linked) or from Manage Themes by pressing [V] on any theme row.

What it shows. Each version is listed with its number, status (Published / Draft / Pending Review / …), creation date, and the first line of its English changelog. Selecting a row reveals the full detail panel, including both English and Arabic changelogs and the minimum API version.

Editing a changelog. Press [E] on a version to edit. The form walks through changelog.en then changelog.ar (optional), and saves via PATCH /v2/themes/{id}/versions/{vid}/. English is required; Arabic is dropped from the payload if left empty.

Changing status. Press [S] on a version to open a status picker. Vitrin pulls allowed transitions from the same partner-allowed transition table that vitrin status uses, and only shows targets you can actually reach (admin-only ones like in_review / approved / rejected are filtered out). in_review and deprecated versions are flagged as locked.

Intentional new-version push

The push wizard makes creating a new version a deliberate, multi-step choice:

  1. Pick deployment target — a store to install on, or push without installing.
  2. Pick strategyUpdate latest version is highlighted as the default and is the right choice for template patches, copy tweaks and bugfixes. Create a new version is required when asset URLs move or you ship breaking changes.
  3. Confirmation (new-version path only) — Vitrin warns that a new version is permanent and existing stores stay on their current version until they explicitly update. You have to confirm before continuing.
  4. Bump strategy (new-version path only) — pick patch, minor, major (each option shows the resulting version number computed from the latest one on the server) or custom. A custom version must be valid X.Y.Z and strictly greater than the current latest.
  5. Changelog (en, then optional ar) — both languages flow into the API as { en, ar }. English is required.
  6. Review — recap of strategy, deployment target and changelog. Press Enter to actually push.

The same primitives are exposed on the CLI:

# Update latest version with a fresh changelog
vitrin push --changelog "Fix product page typo" \
            --changelog-ar "إصلاح خطأ مطبعي في صفحة المنتج"

# Cut a new patch version automatically (latest 1.0.5 → 1.0.6)
vitrin push --new-version --bump patch \
            --changelog "Bugfix release"

# Cut a new major version
vitrin push --new-version --bump major \
            --changelog "Redesigned cart" --changelog-ar "إعادة تصميم السلة"

Edit theme name and description

The TUI Manage Themes view now edits English and Arabic for both fields. Pressing [E] on a row cycles through name (en), name (ar), description (en), description (ar). Arabic fields are optional — empty values are dropped from the payload, so you can clear an Arabic translation by leaving the field blank.

Local Theme Registry

Vitrin maintains a registry at ~/.vitrin/themes.json of every theme you have created or linked, keyed by absolute path. Each entry holds the same fields as the project-local .vitrin/theme.json (id, slug, name, push history, installations, …), so you have a single place to see all themes across all directories — even ones that have never been pushed.

The registry is updated automatically by vitrin new, vitrin link, vitrin push, and any TUI flow that touches theme state. Stale entries (directories that no longer exist on disk) are pruned on next read.

In the TUI, Switch Theme lists registered themes with 🔗 for ones linked to a Zid theme and · for ones that are local-only. Choosing one chdirs the current session into that directory.

Building Themes

vitrin build [path] [options]

Builds theme into a distributable .zip package.

Pipeline:

  1. Validate theme structure (must contain layout.jinja, header.jinja, footer.jinja, and templates/home.jinja). On failure, reports the resolved path and the missing files so you can confirm the build is looking at the right directory.
  2. Compile theme assets. If package.json declares a build script (the Growth Theme uses Tailwind + Vite), Vitrin runs <installer> install when node_modules is missing, then <installer> run build. The installer is detected from the lockfile — pnpm-lock.yaml → pnpm, yarn.lock → yarn, otherwise npm. stdout/stderr is streamed live into the BuildView/PushView UI. Themes without a build script skip this step transparently.
  3. Strip .DS_Store files.
  4. Zip everything except node_modules/, .git*, .vitrin/, and *.zip.
  5. Verify the archive on disk.

Options:

  • -n, --name <name> - Name for the build output
  • -o, --output <path> - Output directory
  • -c, --compression <level> - Compression level 0-9 (default: 9)
  • --validate - Validate theme structure before building
  • -e, --exclude <patterns...> - Additional exclude patterns

Example:

$ vitrin build
Building theme: my-theme
Source path: /Users/you/themes/my-theme
Compiling theme assets...
  Installing dependencies with pnpm...
  Running "pnpm run build"...
  Asset build complete
✅ Assets built with pnpm
Cleaning .DS_Store files...
✅ Build complete: my-theme-1714492800000.zip (2.4 MB)

Preview on Dev Store

vitrin preview [store-id] [theme-path] [options]

Preview your theme on a dev store. After upload, Vitrin prints both the preview URL and a hosted theme validation report at <preview-url>/validate — open it to see Zid's automated review of the theme that was just deployed.

Like push, preview also detects platform-managed templates (templates/account_profile.jinja, templates/account_orders.jinja, templates/account_wishlist.jinja, templates/loyalty_program.jinja, templates/address_form.jinja) and asks whether to upload them anyway, remove them locally and use the platform defaults, or cancel.

Arguments:

  • store-id - Dev store ID (optional if default store is set)
  • theme-path - Path to theme directory (default: current directory)

Options:

  • -t, --theme-id <id> - Use existing theme ID
  • -n, --name <name> - Theme name for preview
  • --build - Build theme before previewing
  • --validate - Validate theme structure
  • --new-theme - Force creation of a new theme

Example:

$ vitrin preview 123 --build
📦 Preparing theme preview for store 123
Building theme...
✅ Theme built successfully
Creating theme...
✅ Theme created: 45678
Creating version...
✅ Version 1.0.0 created
Uploading theme package...
✅ Upload complete
Installing on store...

🎉 Theme ready for preview!

Theme ID: 45678
Version: 90123
Installation: 11111

💡 To activate: vitrin activate 123 11111

List Resources

vitrin list                    # List both themes and stores (default)
vitrin list --themes           # List themes only
vitrin list --stores           # List dev stores only
vitrin themes list             # Alternative: list themes only

Lists themes and/or dev stores.

Options:

  • -t, --themes - List themes only
  • -s, --stores - List dev stores only
  • --json - Output as JSON

Example:

$ vitrin list --stores
Fetching dev stores...
✅ Found 2 dev stores:

ID          Name                     Email                         Domain
--------------------------------------------------------------------------------
123         Test Store 1             [email protected]            test1.zidtest.com
456         Test Store 2             [email protected]            test2.zidtest.com

Theme Installation

vitrin install <store-id> <theme-id> <version-id>

Installs a specific theme version on a store.

Example:

$ vitrin install 123 45678 90123
Installing theme on store...
✅ Theme installed successfully!
Installation ID: 11111

Theme Activation

vitrin activate <store-id> <installation-id>

Activates an installed theme on a store.

Example:

$ vitrin activate 123 11111
Activating theme...
✅ Theme activated successfully!

Update Theme Version

vitrin update <theme-id> [theme-path] [options]

Updates an existing theme with a new version.

Options:

  • -v, --version <version> - Version number
  • -c, --changelog <text> - Version changelog
  • --skip-build - Skip building theme package

Example:

$ vitrin update abc123 --version 2.0.0 --changelog "Added new features"
Building theme package...
✓ Theme package built
Creating version 2.0.0...
✓ Version created
Uploading theme...
✓ Upload complete

Change Theme Version Status

vitrin status [options]

Reads or changes the lifecycle status of a theme version. Defaults to the linked theme's latest version when no IDs are passed. The CLI knows the status state machine and only offers transitions the partner is allowed to make.

Options:

  • -t, --theme <id> - Theme ID (default: linked theme)
  • -v, --version <id> - Version ID (default: latest)
  • -s, --target <status> - Target status (skip the picker)
  • -y, --yes - Skip the confirmation prompt

Statuses: draft, pending_review, in_review, approved, rejected, published, deprecated, archived.

Partner-allowed transitions:

| From | Allowed targets | | --------------- | ----------------------- | | draft | pending_review, archived| | pending_review | draft | | approved | published, archived | | rejected | draft, archived | | published | deprecated | | archived | draft |

Examples:

$ vitrin status
Theme abc · version 1.2.0
Current status: Draft (draft)
Allowed transitions: pending_review, archived
? Move to: › Pending Review (pending_review)

$ vitrin status --target pending_review --yes   # submit for review, no prompt
$ vitrin status -v <version-id> -s archived     # archive a specific version

Download Theme Artifact

vitrin download [options]

Downloads the published .zip artifact for a theme version (the same package that gets unpacked on the server). Useful for pulling a previously-pushed version back onto disk for inspection or rollback.

Options:

  • -t, --theme <id> - Theme ID (default: linked theme)
  • -v, --version <id> - Version ID (default: latest)
  • -o, --output <path> - Output file path (default: ./<version-id>.zip)
  • -f, --force - Overwrite the output file if it exists

Example:

$ vitrin download
Requesting download URL...
Downloading version 1.2.0...
✅ Saved 1.84 MB to /…/9b…f3.zip

Theme Presets

vitrin presets <subcommand> [options]

Manage theme presets — named bundles of template settings that ship as the "starter looks" for a theme. Each theme can have multiple presets, one per type.

Subcommands:

  • list - List presets (--type <t> to filter, --json for raw output)
  • show <id> - Show a single preset
  • create <file> - Create from a JSON file
  • update <id> <file> - Patch from a JSON file
  • delete <id> - Delete (use --force to skip confirmation)
  • upload-image <file> - Upload an image, prints the public URL

Preset JSON shape:

{
  "type": "default",
  "name": { "en": "Default", "ar": "افتراضي" },
  "images": ["https://.../preview.png"],
  "presets": [
    { "path": "sections/product.jinja", "settings": { "...": "..." } }
  ]
}

Examples:

$ vitrin presets list
$ vitrin presets show <preset-id> --json
$ vitrin presets create ./preset.json
$ vitrin presets upload-image ./preview.png

Generate Translations

vitrin translations [path] [options]

Extracts translatable strings from .jinja templates (anything wrapped in _("...")), writes a locale/messages.pot template, and updates per-language messages.po / messages.mo catalogs in place. Re-run it any time templates change — existing translations are preserved.

Options:

  • -l, --languages <langs...> - Languages to update/compile (default: ar)

Examples:

$ vitrin translations                       # current dir, default lang (ar)
$ vitrin translations ./my-theme            # specific theme path
$ vitrin translations -l ar en fr           # multiple languages at once

The same flow is available in the TUI under 🌐 Generate Translations on the dashboard.

After running, edit the generated locale/<lang>/LC_MESSAGES/messages.po files to fill in msgstr entries, then run the command again to recompile the binary messages.mo catalogs.

Interactive TUI Mode

Launch the interactive terminal interface (recommended):

vitrin

Features

Theme-Centric Workflow

  • Create new themes from the Growth Theme GitHub template (URL disclosed before clone) or register an existing local directory
  • Push themes directly to Zid servers, with pre-push validation
  • Automatic Tailwind/Vite asset compilation before zipping
  • Track push history and versions
  • Switch between registered themes from any cwd via Switch Theme
  • Automatic theme detection in current directory

🚀 Streamlined Deployment

  • Build and push in one workflow
  • Automatic version management
  • Install and activate on dev stores
  • S3 upload progress tracking

🎨 Theme Management

  • List server-side themes
  • Update theme versions
  • Manage theme metadata
  • Generate / refresh translation catalogs from .jinja templates

🔐 Authentication & Settings

  • OAuth login flow
  • Configure API endpoints
  • Persistent settings management

📦 Store Operations

  • List and manage dev stores
  • Preview themes on stores
  • One-click activation

Configuration

Environment Variables

  • VITRIN_API_URL - API endpoint (default: https://api.zid.sa)
  • VITRIN_PARTNER_URL - Partner dashboard URL (default: https://partner.zid.sa)
  • LOG_LEVEL - Logging level (debug, info, error)

Debug Mode

Run with detailed logging for troubleshooting:

LOG_LEVEL=debug vitrin preview 123

File Structure

Expected theme structure (Growth Theme layout):

my-theme/
├── .vitrin/
│   └── theme.json          # local link/push state (managed by Vitrin)
├── assets/
│   ├── tailwindcss.css     # Tailwind source (input)
│   ├── styles.css          # Tailwind output — generated by `build:css`
│   ├── js/
│   │   ├── main.js         # Vite entry — bundled to assets/dist/theme.js
│   │   └── cart/controller.js  # Vite entry — bundled to assets/dist/cart-controller.js
│   ├── dist/               # Vite outputs — generated by `build:js`
│   └── images/
├── components/             # Reusable .jinja partials
├── sections/               # Dynamic sections for the theme editor
├── templates/
│   ├── home.jinja
│   ├── product.jinja
│   └── cart.jinja
├── locale/
│   ├── en.json
│   └── ar.json
├── layout.jinja            # required
├── header.jinja            # required
├── footer.jinja            # required (templates/home.jinja is required too)
├── package.json            # `scripts.build` is invoked before zipping
├── vite.config.js
└── theme.json

Vitrin's global state lives in ~/.vitrin/:

~/.vitrin/
├── config.json   # auth token + saved env vars
└── themes.json   # registry of every theme created/linked, keyed by path

Authentication

Authentication tokens are stored in ~/.vitrin/config.json.

To logout:

vitrin logout

Troubleshooting

Authentication Issues

# Check authentication status
vitrin themes list
# or
vitrin list --themes

# If you see "Authentication required", login again
vitrin login

Build Failures

# Validate theme structure
vitrin build --validate

# Check for common issues
- Missing required directories (assets, templates)
- Invalid package.json
- .DS_Store files (automatically cleaned)

Preview Errors

# Run with debug logging
LOG_LEVEL=debug vitrin preview 123

# Common issues:
- Expired authentication token - run `vitrin login`
- Invalid store ID - check with `vitrin list --stores`
- Theme already exists - will auto-generate unique name

Support

Report issues at: https://github.com/zidsa/vitrin-cli/issues