Skip to content

Conversation

@abhakat
Copy link
Contributor

@abhakat abhakat commented Jan 6, 2026

What changed / motivation

This PR introduces create-stylex-app, a new CLI scaffolding tool that enables developers to quickly bootstrap StyleX projects using official templates. This addresses the need for an official, maintained way to start
new StyleX projects, similar to create-react-app, create-next-app, and other ecosystem tools.

Key features:

  • Interactive CLI with polished UI using @clack/prompts for framework selection
  • 13 official templates covering all major bundlers and frameworks:
    • Next.js (App Router) - Recommended
    • Vite + React
    • Vite (Vanilla)
    • Webpack + React
    • Rollup + React
    • esbuild + React
    • Rspack + React
    • React Router (RSC)
    • Waku
    • Vite + RSC
    • RedwoodSDK
    • Storybook
    • CLI (Standalone)
  • GitHub-based template fetching - Downloads templates directly from the facebook/stylex repo using giget, ensuring users always get the latest version
  • Remote template manifest - Template definitions are fetched from GitHub, with bundled fallback if GitHub fetch fails
  • Custom template support - --template github:user/repo/path for community templates
  • Smart dependency management - Auto-detects package manager (npm/yarn/pnpm) and installs dependencies
  • Automatic script detection - Determines correct run command (dev/build/start) based on available scripts

Implementation details:

Note: Please see TEMPLATE_ISSUES.md for known issues with specific templates that need to be addressed before merging.

  • New package at packages/@stylexjs/create-stylex-app/
  • Uses giget for efficient tarball-based GitHub downloads (no API rate limiting)
  • Bundled templates.json as fallback if GitHub fetch fails
  • Lightweight argument parsing (no external dependencies for CLI args)
  • Filters out monorepo-only dependencies like @stylexjs/shared-ui
  • Normalizes package.json scripts (removes example: prefix)
  • Generates clean README.md with correct next steps for each template

Usage:


 # Interactive mode
 npx create-stylex-app my-app

 # With framework flag
 npx create-stylex-app my-app --framework nextjs

 # Custom template
 npx create-stylex-app my-app --template github:user/repo/template

 # Skip dependency installation
 npx create-stylex-app my-app --no-install

Changes to examples:

This PR also inlines @stylexjs/shared-ui into 6 example templates to fix npm 404 errors when scaffolding (since @stylexjs/shared-ui is a private monorepo package not published to npm):

  • example-react-router
  • example-redwoodsdk
  • example-vite-react
  • example-vite-rsc
  • example-vite
  • example-waku

Each now has a local src/shared-ui/ directory with the inlined code.

Files changed:

New package (packages/@stylexjs/create-stylex-app/):

  • package.json - Package configuration with dependencies
  • src/index.js - Main CLI entry point (~400 lines)
  • src/templates.js - Template loading with GitHub fallback
  • src/utils/fetch-template.js - GitHub template fetching via giget
  • src/utils/packages.js - Package manager detection and installation
  • src/utils/files.js - File utilities
  • templates.json - Bundled template definitions (13 templates)
  • TEMPLATE_ISSUES.md - Known issues tracker (to be deleted before final merge)
  • .babelrc.js - Babel configuration for build

Examples (shared-ui inlining):

  • 6 examples updated with local src/shared-ui/ directories

Linked PR/Issues

Fixes # 1395

  • npx create-stylex-app #1395

    Additional Context

    Testing performed:

    • ✅ Tested local npx execution for all three templates
    • ✅ Verified Next.js template scaffolding with correct
      dependencies
    • ✅ Verified Vite + React template scaffolding with correct
      dependencies
    • ✅ Verified Vite (Vanilla) template scaffolding with
      correct dependencies
    • ✅ Confirmed monorepo-specific packages are filtered from
      generated package.json
    • ✅ Validated script normalization (example: prefix
      removed)
    • ✅ Build process works correctly (yarn build compiles src/
      to lib/)

    Future enhancements (deferred to follow-up PRs):

    • automatic dependency management?
    • TypeScript template variants
    • Additional polish and feature flags

    Breaking changes: None - this is a new package with no
    existing dependents

    Publishing note: Package is currently marked "private": true
    and will require:

    1. Permission from @stylexjs organization maintainers
    2. Removal of private flag
    3. Publishing to npm with --access public

Pre-flight checklist

Anay Bhakat added 6 commits January 5, 2026 14:59
- Add package.json with dependencies (yargs, ansis, fs-extra)
- Configure Babel for CommonJS transpilation
- Implement CLI with project name validation
- Add template system reading from examples/
- Implement file copying with exclusions
- Generate package.json and README.md dynamically
- Complete first milestone: working vite-react template

Implements Steps 1-28 from CREATE_STYLEX_APP_PLAN.md
  functionality

  - Move package to @stylexjs/create-stylex-app for monorepo
  consistency
  - Add all 3 templates (nextjs, vite-react, vite)
  - Add --framework/-f flag with interactive selection via
  prompts
  - Add prompts dependency for interactive CLI
  - Update plan: defer feature flags & polish to future work

  Implements Steps 35-39. Core scaffolding tool now functional
   with
  template selection, dependency installation, and all 3
  framework
  templates working end-to-end.
@vercel
Copy link

vercel bot commented Jan 6, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Review Updated (UTC)
stylex Skipped Skipped Jan 15, 2026 5:38am

@meta-cla meta-cla bot added the CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. label Jan 6, 2026
@github-actions
Copy link

github-actions bot commented Jan 6, 2026

workflow: benchmarks/perf

Comparison of performance test results, measured in operations per second. Larger is better.
yarn workspace v1.22.22
yarn run v1.22.22
$ node ./compare.js /tmp/tmp.VOGr38kLRl /tmp/tmp.VwNi80gv9M

Results Base Patch Ratio
babel-plugin: stylex.create
· basic create 546 538 0.99 -
· complex create 67 66 0.99 -
babel-plugin: stylex.createTheme
· basic themes 443 438 0.99 -
· complex themes 34 34 1.00
Done in 0.07s.
Done in 0.31s.

@github-actions
Copy link

github-actions bot commented Jan 6, 2026

workflow: benchmarks/size

Comparison of minified (terser) and compressed (brotli) size results, measured in bytes. Smaller is better.
yarn workspace v1.22.22
yarn run v1.22.22
$ node ./compare.js /tmp/tmp.FHW6dj6ww5 /tmp/tmp.hwvMKNw4YF

Results Base Patch Ratio
@stylexjs/stylex/lib/cjs/stylex.js
· compressed 1,311 1,311 1.00
· minified 4,150 4,150 1.00
@stylexjs/stylex/lib/cjs/inject.js
· compressed 1,793 1,793 1.00
· minified 4,915 4,915 1.00
benchmarks/size/.build/bundle.js
· compressed 496,650 496,650 1.00
· minified 4,847,840 4,847,840 1.00
benchmarks/size/.build/stylex.css
· compressed 99,853 99,853 1.00
· minified 747,541 747,541 1.00
Done in 0.08s.
Done in 0.34s.

@abhakat abhakat changed the title Create Stylex App NPX Create Stylex App Jan 6, 2026
…hed tool with

  branded colors, progress tracking, helpful errors, and a clean success
  screen. Adds ora@^9.0.0 for spinner functionality. Main gripe: selection part, might want to change colors. Updating yarn.lock, make sure this is fine.
Copy link
Collaborator

@nmn nmn left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great start! Thanks for doing this.

* Template configuration
* Each template references an example directory in /examples
*/
const TEMPLATES = [
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's make sure that all examples are given as options.

return `${Math.floor(ms / 60000)}m ${Math.floor((ms % 60000) / 1000)}s`;
}

function showWelcomeBanner() {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's use @clack/prompts for the CLI here.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That looks a lot cleaner.

const { TEMPLATES } = require('./templates');
const { copyDirectory } = require('./utils/files');
const {
detectPackageManager,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can probably use nypm to auto-detect the package manager here.

Copy link
Collaborator

@nmn nmn left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Templates will not resolve for the CLI.

Comment on lines 165 to 169
const exampleDir = path.resolve(
__dirname,
'../../../../examples',
template.exampleSource,
);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This won't work standalone.

When this package is installed as a standalone CLI, the examples directory won't exist in the same relative path.

There are two options around this problem:

  1. The TEMPLATES should be fetched over the network from the github repo. This has the benefit of letting us update the templates without needing to update the CLI. This should also make it possible to pass in custom templates to the CLI which can be fetched.
  2. If fetching a folder from Github seems too problematic, we could create some kind of build step to copy all the examples into the CLI package before publishing. This is far from ideal, but may be acceptable as a temporary solution.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds good, I will try and get the 1st one working.

1. Updated dependencies (package.json):
   - Removed: prompts, ora, ansis
   - Added: @clack/prompts (^0.11.0), picocolors (^1.1.0)

2. Rewrote src/index.js using @clack/prompts API:
   - p.intro() - Clean intro header (replaces ASCII art banner)
   - p.select() - Framework selection with hints
   - p.spinner() - Progress indication for copy/config steps
   - p.spinner({ indicator: 'timer' }) - Install with elapsed time display
   - p.log.success/info/warn/error() - Status messages
   - p.note() - Boxed "Next steps" display
   - p.outro() - Clean closing message
   - p.cancel() and p.isCancel() - Graceful cancellation handling

3. Deleted 4 utility files (~200 lines removed):
   - src/utils/logger.js
   - src/utils/spinner.js
   - src/utils/success.js
   - src/utils/errors.js

'use strict';

const yargs = require('yargs/yargs');
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think @clack/prompts should have something for parsing args too. Look at the create-vite-app CLI for an example.

Comment on lines 138 to 139
'package.json', // We'll generate this separately
'README.md', // We'll generate this separately
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's probably easier for us to take the existing package.json and README.md file and edit them.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can probably take the pre-existing README.md and append a block about npx create-stylex-app and its args

await fs.ensureDir(targetDir);

// Resolve example source directory
const exampleDir = path.resolve(
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK. still waiting for the change to fetch this from github over the network.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will do. Sorry got caught up with some other stuff.

  - Replace yargs with lightweight manual arg parsing
  - Switch from local example copying to GitHub downloads via giget
  - Add --template flag for custom GitHub templates (github:user/repo/path)
  - Remove detect-deps logic and detective dependency (was a runtime workaround)
  - Generate README/next-steps based on available scripts (dev → build → start)
  - Improve error feedback with package counts and stderr display

  Known issues with examples (need upstream fixes):
  - example-nextjs: missing autoprefixer in package.json
  - example-rollup: missing @babel/preset-flow in package.json
  - example-esbuild: no dev/serve script, only builds
  - example-storybook: vitest v4 conflicts with @vitest/* v3
  - 6 examples use private @stylexjs/shared-ui (not on npm)

  The examples were designed for monorepo use and rely on hoisted dependencies.
  They need to be fixed to declare all dependencies explicitly before the CLI
  can scaffold them successfully for standalone use.

p.note(nextSteps, 'Next steps');

p.outro(`${pc.green('Done!')} Happy coding with StyleX`);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like the welcome banner changes got overridden. Can we also add a screenshot of the CLI logs to the test plan?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Screenshot 2026-01-11 at 11 04 58 PM

This is what it looks like when it works

  The @stylexjs/shared-ui package is private and not published to npm,
  causing 404 errors when users scaffold these templates with create-stylex-app.

  Fixed by inlining the shared-ui components (Button + tokens) directly into
  each example's src/shared-ui/ directory.

  Affected templates:
  - example-react-router
  - example-redwoodsdk
  - example-vite-react
  - example-vite-rsc
  - example-vite
  - example-waku

  See packages/@stylexjs/create-stylex-app/TEMPLATE_ISSUES.md for full
  template status tracker including other issues to address (nextjs/autoprefixer,
  rollup/babel-preset-flow, storybook/vitest version conflict).
… shared-ui

  fetching for templates that depend on @stylexjs/shared-ui, and rewrites the
  dependency to file:./shared-ui for npm resolution. Several templates have
  upstream issues (missing deps, version conflicts) tracked in TEMPLATE_ISSUES.md.
@mellyeliu
Copy link
Member

The merge conflicts will be from the recent patch release. I think we can get the important examples (Next.js, Vite+React, Vite, etc) working and add the rest as a follow up to unblock you. Let's add a --help command that shares some basic info and lists the available frameworks

force: true,
});

return targetDir;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we need to modify this to copy the shared-ui package into the example as well, copy it into this directory, then replace the shared-ui reference to point to the copied package path instead

},
"dependencies": {
"@stylexjs/stylex": "0.17.4",
"@stylexjs/shared-ui": "0.17.4",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

let's revert these changes to the examples/ folder

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants