Compare commits

...

67 Commits

Author SHA1 Message Date
Jack Hsu e5ffa35c2d chore(repo): fix failing nx-dev build due to missing files from master 2026-01-09 16:07:34 -05:00
Jack Hsu d2b31f0792 fix(linter): handle variable references in replaceOverride (#34026)
The migration generator (`@nx/plugin:migration`) fails when due to
ESLint flat config not being parsed correctly, leading to an error.

This happens because `replaceOverride` uses `parseTextToJson` to parse
the config, which fails for non-JSON-serializable JavaScript
expressions.

This PR fixes the issue by using AST parsing, like we did for
`hasOverrides` here https://github.com/nrwl/nx/pull/33548.

Fixes #34010

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-09 12:12:11 -05:00
Jack Hsu 183d8813c8 chore(misc) bump pnpm to v10.11.1 2025-11-21 09:14:04 -05:00
Jack Hsu 499e97e031 chore(misc): change NPM_CONFIG_LOGLEVEL to error 2025-11-20 16:47:59 -05:00
Jack Hsu 1e73846354 chore(misc): remove auto-install-peers for npm/pnpm 2025-11-20 15:45:53 -05:00
Jack Hsu d477b9489b chore(misc): bump to npm 11.5 for trusted publishing 2025-11-20 15:13:30 -05:00
MaxKless 38fd7e1fb9 chore(misc): replace !process.env.NODE_AUTH_TOKEN with !process.env.GITHUB_ACTIONS in release script 2025-11-20 13:53:11 -05:00
Jack Hsu a28c8b56bc chore(repo): use npm 10 for publish job 2025-11-20 12:16:54 -05:00
Jack Hsu dfeb020cea chore(repo): remove explicit pnpm version from build jobs 2025-11-20 11:35:59 -05:00
Jack Hsu cae9f9a95b chore(repo): update node and pnpm versions 2025-11-20 11:26:34 -05:00
Jack Hsu 3d64a456e2 chore(repo): set pnpm to 9.8 2025-11-20 10:57:06 -05:00
Jack Hsu e754bc8eda chore(repo): update publish.yml to align with master 2025-11-20 10:45:31 -05:00
Jack Hsu a9794d16db fix(linter): handle various flat config override structures (#33548)
Flat config overrides util may fail when it isn't a plain JS object.
This PR makes the `hasOverrides` function more robust against these
cases.


Fixes #31796
2025-11-19 16:48:13 -05:00
Craigory Coppola b1bb06be59 fix(core): error when restoring http cache with no outputs (#30961)
(cherry picked from commit 91f5249fbf)
2025-05-16 13:21:10 -04:00
James Henry e2d68cd0e5 fix(release): ensure versionData is always populated even when no bumps (#30866)
(cherry picked from commit c0426c1b35)
2025-04-25 09:35:15 -04:00
Thomas Dekiere ae0318a366 fix(release): ensure generatorOptions and rootVersionActionsOptions are passed to updateLockfile function (#30796)
(cherry picked from commit 69ea6327d3)
2025-04-25 09:35:09 -04:00
Miroslav Jonaš 0a94b430b3 feat(linter): add support for package based secondary entry points (#30809)
This PR adds support for package.json based secondary entry points and
implements fix for situation when package imports base entry point as
dynamic dependency and secondary entry point as static dependency.

## Current Behavior
When the package is imported from itself, check for a secondary entry
point checks only Angular-style secondary entry points.

When package is importing from the same library as dynamic import from
root and static import from secondary entry point we still get linter
errror.

## Expected Behavior
Check for secondary entry points should also support standard
package.json-based entry points.

Importing from the same library as dynamic import from root and static
import from secondary entry point should be allowed.

## Related Issue(s)
<!-- Please link the issue being fixed so it gets closed when this is
merged. -->

Fixes #18552

(cherry picked from commit cd55dfcb3e)
2025-04-25 09:34:55 -04:00
Colum Ferry 71a594be31 feat(rspack): use custom WriteIndexHtmlPlugin to handle variable interpolation (#30805)
## Current Behavior
The `HtmlRspackPlugin` does not support interpolation of %VAR% in the
index.html.
This is supported with a custom Webpack Plugin for `@nx/webpack` for
generating index.html files.

## Expected Behavior
The `@nx/rspack` plugin should support the same feature set as webpack
for seamless migration.
Add a new `WriteIndexHtmlPlugin` for Rspack to support this.
It should only be used when `useLegacyHtmlPlugin` is set to true

(cherry picked from commit a65f0f421b)
2025-04-25 09:34:45 -04:00
Nicholas Cunningham 074e24a949 fix(module-federation): remove disabling runtimeChunk (#30637)
<!-- Please make sure you have read the submission guidelines before
posting an PR -->
<!--
https://github.com/nrwl/nx/blob/master/CONTRIBUTING.md#-submitting-a-pr
-->

<!-- Please make sure that your commit message follows our format -->
<!-- Example: `fix(nx): must begin with lowercase` -->

<!-- If this is a particularly complex change or feature addition, you
can request a dedicated Nx release for this pull request branch. Mention
someone from the Nx team or the `@nrwl/nx-pipelines-reviewers` and they
will confirm if the PR warrants its own release for testing purposes,
and generate it for you if appropriate. -->

## Current Behavior
<!-- This is the behavior we have today -->
When using Module Federation with an app that defines styles as a
separate entry point, HMR fails to update in the browser. Instead of
updating automatically, a warning is shown in the console related to a
missing chunk. A full-page reload is typically required, which is not
the intended behaviour.

## Expected Behavior
<!-- This is the behaviour we should expect with the changes in this PR
-->
HMR should work with styles as an entrypoint.

## Related Issue(s)
<!-- Please link the issue being fixed so it gets closed when this is
merged. -->
The default is for `runtimeChunk` is `config.optimization.runtimeChunk =
{name: 'runtime'}` it is _not_ the same as `single` but the naming will
be the same.

Fixes #9582

(cherry picked from commit 939cc732de)
2025-04-25 09:34:22 -04:00
Colum Ferry ed3eaa801e feat(angular): update angular-rspack to 20.7 (#30737)
(cherry picked from commit 67732d6217)
2025-04-25 09:33:18 -04:00
Benjamin Cabanes 7f89c9bea3 docs(nx-dev): remove deprecated RFC references & update link (#30849)
Removed outdated references to RFC #30548 in FAQ and remote cache solutions components. Updated the link to point to the relevant documentation on building a custom caching server.
2025-04-24 20:38:56 -04:00
Benjamin Cabanes 065f0c73d6 docs(nx-cloud): remove redundant max-lg rounded styles from CI cards (#30847)
The `max-lg` rounded styles were unnecessary as they were being overridden by `lg` styles.
2025-04-24 20:38:56 -04:00
Jason Jean 47a5245291 chore(repo): disable failing gradle test (#30841) 2025-04-24 20:38:56 -04:00
Altan Stalker e901d69a9b fix(core): allow disabling output streaming with NX_STREAM_OUTPUT (#30834)
Previously NX_STREAM_OUTPUT only influenced the streaming behavior if it
were set to 'true', this ensures the negated case is also handled
2025-04-24 20:38:56 -04:00
Altan Stalker cbb1958c7e chore(core): enable output flag for cloud (#30833)
<!-- Please make sure you have read the submission guidelines before
posting an PR -->
<!--
https://github.com/nrwl/nx/blob/master/CONTRIBUTING.md#-submitting-a-pr
-->

<!-- Please make sure that your commit message follows our format -->
<!-- Example: `fix(nx): must begin with lowercase` -->

<!-- If this is a particularly complex change or feature addition, you
can request a dedicated Nx release for this pull request branch. Mention
someone from the Nx team or the `@nrwl/nx-pipelines-reviewers` and they
will confirm if the PR warrants its own release for testing purposes,
and generate it for you if appropriate. -->

## Current Behavior
Flag not on

## Expected Behavior
Flag on

## Related Issue(s)
<!-- Please link the issue being fixed so it gets closed when this is
merged. -->

Fixes #
2025-04-24 20:38:56 -04:00
Nicholas Cunningham 09184018ff docs(nx-dev): fix node support matrix (#30829) 2025-04-24 20:38:56 -04:00
James Henry e7b0f72e98 chore(core): add maxRetries to temp-fs cleanup (#30828) 2025-04-24 20:38:56 -04:00
Jack Hsu 08f4dd921a fix(js): remove check that ts plugin is used for ts sync generator (#30743)
This PR ensures that when `@nx/js/typescript` is not used, we do not add
`@nx/js:typescript-sync` sync generator to targets such as build, serve,
etc.

It resolves issues where `nx init` into a repo that is compatible with
TS solution will add the sync generator, even if the plugin is unused.
It leads to errors everytime users run a task like build. The error is
like this:

```
[@nx/js:typescript-sync] The `@nx/js/typescript` plugin is not registered

...

> Would you like to ignore the sync failures and continue running the task?
Yes
No
```

It makes it confusing for users, especially new users that don't know
what sync generators are. They will always run into the error and have
to choose to continue despite the failure.

**Note:** In a future follow-up, we could consider adding better info
and prompts so we can let users know that Nx also helps keep workspace
up to date, and can learn more about it.

## Current Behavior
Users see an error when running `nx add @nx/vite` and then `nx build
<project>`.

## Expected Behavior


## Related Issue(s)
<!-- Please link the issue being fixed so it gets closed when this is
merged. -->

Fixes #
2025-04-24 20:38:56 -04:00
Juri 3f522b8dae docs(nx-dev): add JPG version of hero img for social media 2025-04-24 20:38:56 -04:00
Juri Strumpflohner 9ea879790d docs(nx-dev): some adjustments to the test splitting article (#30823)
quick updates to an upcomign blog post:
https://nx-dev-git-blog-fix-splitting-techniques-article-nrwl.vercel.app/blog/test-splitting-techniques
2025-04-24 20:38:55 -04:00
Colum Ferry 845cac6263 fix(angular): convert-to-rspack correctly migrating existing custom webpack configs (#30778)
## Current Behavior
The `createConfig` helper from `@nx/angular-rspack` became an async
function.
This meant that the handling of custom webpack configs in the migration
done by `convert-to-rspack` was incorrect.

## Expected Behavior
Ensure the migration is handled correctly.
Ensure that Module Federation migrations work correctly.

## Related Issues
Fixes https://github.com/nrwl/angular-rspack/issues/53
2025-04-24 20:38:55 -04:00
Nicholas Cunningham 92ce35f542 chore(rspack): update convert inferred generator description (#30799)
<!-- Please make sure you have read the submission guidelines before
posting an PR -->
<!--
https://github.com/nrwl/nx/blob/master/CONTRIBUTING.md#-submitting-a-pr
-->

<!-- Please make sure that your commit message follows our format -->
<!-- Example: `fix(nx): must begin with lowercase` -->

<!-- If this is a particularly complex change or feature addition, you
can request a dedicated Nx release for this pull request branch. Mention
someone from the Nx team or the `@nrwl/nx-pipelines-reviewers` and they
will confirm if the PR warrants its own release for testing purposes,
and generate it for you if appropriate. -->

## Current Behavior
<!-- This is the behavior we have today -->
Currently, the `convert-to-inferred` generator description inside the
rspack package references Webpack when it should reference Rspack
instead.

## Expected Behavior
<!-- This is the behavior we should expect with the changes in this PR
-->
The `convert-to-inferred` generator description should reference Rspack
instead of Webpack.

## Related Issue(s)
<!-- Please link the issue being fixed so it gets closed when this is
merged. -->

Fixes
2025-04-24 20:38:55 -04:00
D. Ror. 2ac21e1ccb docs(misc): update add-dotnet.md (#27540)
<!-- Please make sure you have read the submission guidelines before
posting an PR -->
<!--
https://github.com/nrwl/nx/blob/master/CONTRIBUTING.md#-submitting-a-pr
-->

<!-- Please make sure that your commit message follows our format -->
<!-- Example: `fix(nx): must begin with lowercase` -->

<!-- If this is a particularly complex change or feature addition, you
can request a dedicated Nx release for this pull request branch. Mention
someone from the Nx team or the `@nrwl/nx-pipelines-reviewers` and they
will confirm if the PR warrants its own release for testing purposes,
and generate it for you if appropriate. -->

See
https://github.com/nx-dotnet/nx-dotnet/blob/1ff848c54bc2207a9c77fc31c7a9a62489a30a88/packages/core/src/generators/init/generator.ts#L30-L41

## Current Behavior
<!-- This is the behavior we have today -->

## Expected Behavior
<!-- This is the behavior we should expect with the changes in this PR
-->

## Related Issue(s)
<!-- Please link the issue being fixed so it gets closed when this is
merged. -->

Co-authored-by: Miroslav Jonaš <missing.manual@gmail.com>
2025-04-24 20:38:55 -04:00
Miroslav Jonaš 381d2c598f docs(nx-dev): add blog post for test splitting techniques (#30621)
This PR creates a new enterprise blog post for test task-splitting
techniques

<img width="876" alt="image"
src="https://github.com/user-attachments/assets/1fe26716-e947-4c46-974c-d4d286e50d4e"
/>


## Current Behavior
<!-- This is the behavior we have today -->

## Expected Behavior
<!-- This is the behavior we should expect with the changes in this PR
-->

## Related Issue(s)
<!-- Please link the issue being fixed so it gets closed when this is
merged. -->

Fixes #

---------

Co-authored-by: Juri <juri.strumpflohner@gmail.com>
Co-authored-by: Isaac Mann <isaacplmann@gmail.com>
2025-04-24 20:38:55 -04:00
Philip Fulcher ebd79fb6b9 docs(nx-dev): adjusting publish date 2025-04-24 20:38:55 -04:00
Philip Fulcher b2ab904357 docs(nx-dev): updating youtube link for nx cloud update 2025-04-24 20:38:55 -04:00
Philip Fulcher d543f5f192 docs(nx-dev): fixing typoes in Nx Cloud update post 2025-04-24 20:38:55 -04:00
Philip Fulcher cc45a74cbe docs(nx-dev): add nx cloud update for april 2025 2025-04-24 20:38:55 -04:00
mauicode26 953bd884c8 docs(core): update typo in mental-model.md (#30797)
## Current Behavior
Typo in `mental-model.md`.

## Expected Behavior
No typos in `mental-model.md`.

## Related Issue(s)
N/A
2025-04-24 20:38:55 -04:00
Benjamin Cabanes 29e30e4c31 docs(nx-dev): update nx in brand kits (#30781)
Replaced the existing nx-logos-assets.zip file with a new version.
2025-04-24 20:38:55 -04:00
Juri fc17e16891 docs(nx-dev): add webinar link to AI article 2025-04-24 20:38:55 -04:00
Juri 56e18a0d24 fix(nx-dev): toc should only include headings from the article body 2025-04-24 20:38:55 -04:00
Isaac Mann 964f6eb955 docs(core): fix broken links (#30775)
Fix broken link to react router github repo
2025-04-24 20:29:45 -04:00
Isaac Mann 93d617caae docs(core): add april webinar (#30773)
Adds the 2025 April webinar to the webinar listing
2025-04-24 20:28:57 -04:00
Isaac Mann 793067ff4b docs(core): add migrate keyword to feature page (#30771)
Add migrate keyword to Automate Update Dependencies feature page
2025-04-24 20:28:54 -04:00
Leosvel Pérez Espinosa 9df9ff4093 chore(nx-dev): ignore the public directory in the eslint configuration (#30770)
## Current Behavior

The `nx-dev:lint` task is processing the `public` directory. That
directory is meant to contain assets that ESLint shouldn't process. It
results in extra time being spent linting the project, and it could
result in some errors due to linting some generated output that's copied
there (e.g. `documentation` and `tutorials` directories).

## Expected Behavior

The `nx-dev:lint` task should not process the `public` directory.

## Related Issue(s)

Fixes #
2025-04-24 20:28:51 -04:00
Colum Ferry 6972a5add6 docs(angular): add getting started document for angular-rspack (#30767)
## Current Behavior
There is no Getting Started document for helping people to get up and
running quickly with Angular Rspack applications.
There is only a blog post about scaffolding the applications.

## Expected Behavior
Add a Getting Started document to help people get up and running
2025-04-24 20:28:47 -04:00
Juri 6ed36f0a76 docs(nx-dev): article about Nx and AI 2025-04-24 20:28:44 -04:00
Benjamin Cabanes 0fd03d1504 docs(nx-dev): enable WebinarNotifier for April 30th event (#30759)
Reactivated the `WebinarNotifier` component and updated references to reflect the new webinar scheduled for April 30th, 2025.
2025-04-24 20:28:41 -04:00
Nicholas Cunningham 7f04d5b05c fix(core): improve flaky ci test (#30738)
This PR updates `lerna-smoke-tests.test.ts` test file to improve the
consistency of the snapshots.
The serializer has been updated to reduce flakiness from spacing and
line breaks.
2025-04-24 20:28:16 -04:00
Colum Ferry 8fb421aa95 docs(angular): add guide on i18n for Angular Rspack (#30732)
## Current Behavior
There is currently no documetation on how to configure i18n for Angular
Rspack applications

## Expected Behavior
Add documetation giving details on how to configure i18n for Angular
Rspack applications
2025-04-24 20:28:10 -04:00
Colum Ferry e0242f284d fix(angular): handle ssr with convert-to-rspack (#30752)
## Current Behavior
The `convert-to-rspack` generator for `@nx/angular` does not currently
handle SSR Webpack applications correctly.

## Expected Behavior
Ensure that the `convert-to-rspack` generator handles SSR correctly.
2025-04-24 20:28:07 -04:00
Juri 83b235e9dd feat(nx-dev): add course preview component 2025-04-24 20:28:04 -04:00
MaxKless c8a6711dbb docs(react): update react lib generator (#30527)
the examples are outdated, the new ones make more sense
2025-04-24 20:28:01 -04:00
Juri d7538ffec4 docs(nx-dev): update PNPM article linking to Nx PNM course 2025-04-24 20:27:56 -04:00
Mike Hartington 823ba68a9c feat(nx-dev): add React landing page (#30612)
Co-authored-by: Juri <juri.strumpflohner@gmail.com>
2025-04-24 20:27:52 -04:00
Jason Jean 35d80be8a4 fix(nx-dev): refer to the youtube video instead of storing the videos… (#30739)
… again ourselves

<!-- Please make sure you have read the submission guidelines before
posting an PR -->
<!--
https://github.com/nrwl/nx/blob/master/CONTRIBUTING.md#-submitting-a-pr
-->

<!-- Please make sure that your commit message follows our format -->
<!-- Example: `fix(nx): must begin with lowercase` -->

<!-- If this is a particularly complex change or feature addition, you
can request a dedicated Nx release for this pull request branch. Mention
someone from the Nx team or the `@nrwl/nx-pipelines-reviewers` and they
will confirm if the PR warrants its own release for testing purposes,
and generate it for you if appropriate. -->

## Current Behavior
<!-- This is the behavior we have today -->

This article has parts of a youtube video baked into it as mp4 files.

## Expected Behavior
<!-- This is the behavior we should expect with the changes in this PR
-->

The article points to the youtube video instead of baking in mp4 files.


https://nx-dev-git-fix-docs-nrwl.vercel.app/blog/nx-made-cursor-smarter#lets-see-it-in-action


![image](https://github.com/user-attachments/assets/35ae025e-2632-4c32-9d1d-a6420d97d229)


## Related Issue(s)
<!-- Please link the issue being fixed so it gets closed when this is
merged. -->

Fixes #
2025-04-24 20:27:45 -04:00
Isaac Mann 657e35de63 docs(core): partners page (#30376)
Creates a
[/partners](https://nx-dev-git-nx-dev-partners-nrwl.vercel.app/partners)
page

---------

Co-authored-by: Jordan Powell <jordan@jpdesigning.com>
2025-04-24 20:27:38 -04:00
Leosvel Pérez Espinosa cd39cb527b docs(core): fix package manager workspaces' patterns in typescript project linking concept page (#30729)
## Current Behavior

The "Typescript Project Linking" concept page shows package manager
workspaces' patterns like `apps/**`. While this could be correct, it's
not what Nx generators will generate, and it can result in some nested
and non-expected directories being matched (e.g., fixtures).

## Expected Behavior

The "Typescript Project Linking" concept page should show package
manager workspaces' patterns like `apps/*` so it's aligned with what Nx
generators will generate. It would be a safer example, so it doesn't
match potentially undesired directories.

## Related Issue(s)

Fixes #
2025-04-24 20:27:33 -04:00
Jack Hsu 26b05db46a fix(testing): fix cypress and playwright atomized targetDefaults so they match correctly (#30717)
Currently, we provide `targetDefaults` for atomized targets (e.g.
`e2e-ci`) with a glob pattern that may not match nested paths.

i.e.

```
"e2e-ci--**/*": {
  "dependsOn": [
    "^build",
  ],
},
```

The `e2e-ci--**/*` pattern should be `e2e-ci--**/**`.

<!-- If this is a particularly complex change or feature addition, you
can request a dedicated Nx release for this pull request branch. Mention
someone from the Nx team or the `@nrwl/nx-pipelines-reviewers` and they
will confirm if the PR warrants its own release for testing purposes,
and generate it for you if appropriate. -->

## Current Behavior
The generated `e2e-ci` pattern in `nx.json` does not match nested paths
for split tasks.

## Expected Behavior
The generated `e2e-ci` pattern should apply to all split tasks.

## Related Issue(s)
<!-- Please link the issue being fixed so it gets closed when this is
merged. -->

Fixes #28842
2025-04-24 20:27:29 -04:00
Colum Ferry 7140c0efca docs(angular): add blog post for scaffolding angular rspack apps (#30667)
Add blog post on scaffolding new Angular Rspack applications
2025-04-24 20:27:22 -04:00
Juri f96d6282a8 docs(nx-dev): add blog post about MCP support for VSCode 2025-04-24 20:27:19 -04:00
Colum Ferry 170bf820ee fix(angular): remove deprecated standaloneConfig from generators (#30578)
## Current Behavior
The `standaloneConfig` option has long been deprecated as it is the only
behaviour that Nx now provides.
Using it is a no-op.

## Expected Behavior
Remove the `standaloneConfig` option.
2025-04-24 20:26:51 -04:00
Jason Jean 197b3556d9 chore(repo): fix unit tests (#30431)
<!-- Please make sure you have read the submission guidelines before
posting an PR -->
<!--
https://github.com/nrwl/nx/blob/master/CONTRIBUTING.md#-submitting-a-pr
-->

<!-- Please make sure that your commit message follows our format -->
<!-- Example: `fix(nx): must begin with lowercase` -->

<!-- If this is a particularly complex change or feature addition, you
can request a dedicated Nx release for this pull request branch. Mention
someone from the Nx team or the `@nrwl/nx-pipelines-reviewers` and they
will confirm if the PR warrants its own release for testing purposes,
and generate it for you if appropriate. -->

## Current Behavior
<!-- This is the behavior we have today -->

Unit tests are broken after rebase

## Expected Behavior
<!-- This is the behavior we should expect with the changes in this PR
-->

Unit tests are passing

## Related Issue(s)
<!-- Please link the issue being fixed so it gets closed when this is
merged. -->

Fixes #
2025-04-24 20:23:53 -04:00
Leosvel Pérez Espinosa b69a0587da fix(linter): remove empty entry in typescript eslint flat config (#30727)
## Current Behavior

The `flat/typescript` config contains a config block with the `files`
containing an invalid empty entry.

## Expected Behavior

The `flat/typescript` config should be correct.

## Related Issue(s)

Fixes #30725
2025-04-24 20:23:49 -04:00
Jack Stevenson a0d834770d chore(core): nx plugin submission @aws/nx-plugin (#30545)
<!-- 
_[Please make sure you have read the submission guidelines before
posting an
PR](https://github.com/nrwl/nx/blob/master/CONTRIBUTING.md#submit-pr)_

# Community Plugin Submission

Thanks for submitting your Nx Plugin to our community plugins list. Make
sure to follow these steps to ensure that your PR is approved in a
timely manner.

## Plugin Requirements

Before you submit your plugin to be listed in our registry, it needs to
meet the following requirements:
- Run some kind of automated e2e tests in your repository
- Include `@nx/devkit` as a `dependency` in the plugin's `package.json`
- List a `repository.url` in the plugin's `package.json`

i.e.

```
{
  "repository": {
    "type": "git",
    "url": "https://github.com/nrwl/nx.git",
    "directory": "packages/web"
  }
}
```

Note: We reserve the right to remove unmaintained plugins from the
registry. If the plugins become maintained again, they can be
resubmitted to the registry.

## Steps to Submit Your Plugin
- Use the following commit message template: `chore(core): nx plugin
submission [PLUGIN_NAME]`
- Update the `community/approved-plugins.json` file with a new entry for
your plugin that includes `name`, `url`, `description`:

Example:

```json
// community/approved-plugins.json

[{
    "name": "@community/plugin",
    "url": "https://github.com/community/plugin",
    "description": "This plugin provides the following capabilities."
}]
```

Once merged, your plugin will be available when running the `nx list`
command, and will also be available in the Plugin Registry on
[nx.dev](https://nx.dev/plugin-registry)
-->

# Community Plugin Submission

## Nx Plugin for AWS (@aws/nx-plugin)

<!-- 
Describe what your plugin is and what is its goal or issues it
addresses. If you don't provide a description, we will not merge your
PR.
Is it focused on a technology, tooling or behaviour? Does the plugin
provide generators, executors or graph support?
Do you know who is already using the plugin? Mention who is the author
of the plugin.
-->
This plugin is for building cloud-native applications with AWS. At
present it provides the following generators:

- `ts#project` - Generate a new TypeScript library.
- `ts#infra` - Generate a Typescript AWS CDK infrastructure project for
your application.
- `ts#cloudscape-website` - Generate a new Cloudscape/React/Vite based
web application.
- `ts#cloudscape-website#auth` - Add AWS Cognito authentication to your
Cloudscape website.
- `ts#trpc-api` - Generate a tRPC backend service with Amazon API
Gateway/AWS Lambda integration and [AWS
Powertools](https://github.com/aws-powertools/powertools-lambda-typescript)
pre-configured.
- `py#project` - Generate a uv based Python project.
- `py#fast-api` - Generate a FastAPI backend service with [AWS
Powertools](https://github.com/aws-powertools/powertools-lambda-python)
pre-configured.
- `api-connection` - Connect frontend applications to backend APIs.
- `license` - Automatically manage LICENSE files and source code headers
in your workspace.

(Note that the ts/py project generators are our simplified/opinionated
generators for base projects in TypeScript and Python, eg enforcing ESM
for TypeScript etc)

Our prototyping organisation here at AWS uses the plugin to quickly
bootstrap and build prototypes for various AWS customers in different
industries.

The primary authors are Adrian Dimech @agdimech and myself (Jack
Stevenson).
2025-04-24 20:23:46 -04:00
Josh VanAllen a6a54cf5d0 docs(misc): add josh vanallen to company list (#30680)
Add myself to the company list as a DPE

Signed-off-by: Josh VanAllen <5290334+joshvanallen@users.noreply.github.com>
2025-04-24 20:23:43 -04:00
217 changed files with 6132 additions and 901 deletions
+1
View File
@@ -23,6 +23,7 @@ jobs:
NX_E2E_RUN_E2E: 'true'
NX_CI_EXECUTION_ENV: 'linux'
NX_CLOUD_NO_TIMEOUTS: 'true'
NX_CLOUD_USE_NEW_STREAM_OUTPUT: 'true'
steps:
- name: Checkout
+286 -93
View File
@@ -3,7 +3,7 @@ name: publish
on:
# Automated schedule - canary releases from master
schedule:
- cron: "0 3 * * 2-6" # Tuesdays - Saturdays, at 3am UTC
- cron: "0 19 * * 1-5" # Monday - Friday, at 19:00 UTC (7pm UTC)
# Manual trigger - PR releases or dry-runs (based on workflow inputs)
workflow_dispatch:
inputs:
@@ -21,8 +21,9 @@ env:
DEBUG: napi:*
NX_RUN_GROUP: ${{ github.run_id }}-${{ github.run_attempt }}
CYPRESS_INSTALL_BINARY: 0
NODE_VERSION: 18
PNPM_VERSION: 9.8.0 # Aligned with root package.json (pnpm/action-setup will helpfully error if out of sync)
NODE_VERSION: 22.16.0
PNPM_VERSION: 10.11.1 # Aligned with root package.json (pnpm/action-setup will helpfully error if out of sync)
NPM_CONFIG_LOGLEVEL: error
jobs:
# We first need to determine the version we are releasing, and if we need a custom repo or ref to use for the git checkout in subsequent steps.
@@ -37,7 +38,7 @@ jobs:
# ref resolution in actions/checkout. The exact version will be generated within scripts/nx-release.ts.
#
# - workflow_dispatch:
# - We are either running a dry-run on the current branch, in which case the version will be statica and we can use
# - We are either running a dry-run on the current branch, in which case the version will be static and we can use
# default ref resolution in actions/checkout, or we are creating a PR release for the given PR number, in which case
# we should generate an applicable version number within publish-resolve-data.js and use a custom ref of the PR branch name.
resolve-required-data:
@@ -51,31 +52,23 @@ jobs:
publish_branch: ${{ steps.script.outputs.publish_branch }}
ref: ${{ steps.script.outputs.ref }}
repo: ${{ steps.script.outputs.repo }}
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
pr_number: ${{ steps.script.outputs.pr_number }}
pr_author: ${{ steps.script.outputs.pr_author }}
steps:
# Default checkout on the triggering branch so that the latest publish-resolve-data.js script is available
- uses: actions/checkout@v4
# Set up pnpm and node so that we can verify our setup and that the NPM_TOKEN secret will work later
- uses: pnpm/action-setup@v4
with:
version: ${{ env.PNPM_VERSION }}
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
- name: Setup node
uses: actions/setup-node@v4
uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5.0.0
with:
node-version: ${{ env.NODE_VERSION }}
registry-url: 'https://registry.npmjs.org'
check-latest: true
# Ensure that the NPM_TOKEN secret is still valid before wasting any time deriving data or building projects
- name: Check NPM Credentials
run: npm whoami && echo "NPM credentials are valid" || (echo "NPM credentials are invalid or have expired." && exit 1)
package-manager-cache: false
- name: Resolve and set checkout and version data to use for release
id: script
uses: actions/github-script@v7
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0
env:
PR_NUMBER: ${{ github.event.inputs.pr }}
with:
@@ -86,7 +79,7 @@ jobs:
- name: (PR Release Only) Check out latest master
if: ${{ steps.script.outputs.ref != '' }}
uses: actions/checkout@v4
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with:
# Check out the latest master branch to get its copy of nx-release.ts
repository: nrwl/nx
@@ -95,24 +88,31 @@ jobs:
- name: (PR Release Only) Check out PR branch
if: ${{ steps.script.outputs.ref != '' }}
uses: actions/checkout@v4
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with:
# Check out the PR branch to get its copy of nx-release.ts
repository: ${{ steps.script.outputs.repo }}
ref: ${{ steps.script.outputs.ref }}
path: pr-branch-checkout
- name: (PR Release Only) Ensure that nx-release.ts has not changed in the PR being released
- name: (PR Release Only) Ensure that release scripts have not changed in the PR being released
if: ${{ steps.script.outputs.ref != '' }}
env:
FILE_TO_COMPARE: "scripts/nx-release.ts"
run: |
if ! cmp -s "latest-master-checkout/${{ env.FILE_TO_COMPARE }}" "pr-branch-checkout/${{ env.FILE_TO_COMPARE }}"; then
echo "🛑 Error: The file ${{ env.FILE_TO_COMPARE }} is different on the ${{ steps.script.outputs.ref }} branch on ${{ steps.script.outputs.repo }} vs latest master on nrwl/nx, cancelling workflow. If you did not modify the file, then you likely just need to rebase/merge latest master."
exit 1
else
echo "✅ The file ${{ env.FILE_TO_COMPARE }} is identical between the ${{ steps.script.outputs.ref }} branch on ${{ steps.script.outputs.repo }} and latest master on nrwl/nx."
fi
# List of files that must not change in PR releases
FILES_TO_CHECK=(
"scripts/nx-release.ts"
"scripts/publish-resolve-data.js"
)
for FILE in "${FILES_TO_CHECK[@]}"; do
if ! cmp -s "latest-master-checkout/$FILE" "pr-branch-checkout/$FILE"; then
echo "🛑 Error: The file $FILE is different on the ${{ steps.script.outputs.ref }} branch on ${{ steps.script.outputs.repo }} vs latest master on nrwl/nx, cancelling workflow."
echo "If you did not modify the file, then you likely just need to rebase/merge latest master."
exit 1
else
echo "✅ The file $FILE is identical between the ${{ steps.script.outputs.ref }} branch on ${{ steps.script.outputs.repo }} and latest master on nrwl/nx."
fi
done
build:
needs: [ resolve-required-data ]
@@ -121,12 +121,21 @@ jobs:
fail-fast: false
matrix:
settings:
- host: macos-13
- host: macos-latest
target: x86_64-apple-darwin
setup: |-
rustup target add aarch64-apple-darwin
build: |
pnpm nx run-many --target=build-native -- --target=x86_64-apple-darwin
- host: windows-latest
build: pnpm nx run-many --target=build-native -- --target=x86_64-pc-windows-msvc
setup: |-
choco install openjdk --version=21.0.0 -y
rustup target add aarch64-pc-windows-msvc
build: |
export JAVA_HOME="C:\Program Files\OpenJDK\jdk-21"
export PATH="$JAVA_HOME\bin:$PATH"
java -version
pnpm nx run-many --target=build-native -- --target=x86_64-pc-windows-msvc
target: x86_64-pc-windows-msvc
# Windows 32bit (not needed)
# - host: windows-latest
@@ -136,23 +145,65 @@ jobs:
- host: ubuntu-latest
target: x86_64-unknown-linux-gnu
docker: ghcr.io/napi-rs/napi-rs/nodejs-rust:lts-debian
build: |-
set -e &&
npm i -g pnpm@9.8.0 --force &&
pnpm --version &&
pnpm install --frozen-lockfile &&
build: |
set -e
apt-get update
# Install Java 21
apt-get install -y openjdk-21-jdk
export JAVA_HOME=/usr/lib/jvm/java-21-openjdk-amd64
export PATH="$JAVA_HOME/bin:$PATH"
java --version
curl -fsSL https://deb.nodesource.com/setup_22.x | bash -
apt-get install -y nodejs=22.16.0-1nodesource1
export PATH="/usr/local/bin:$PATH"
node --version
npm --version
npm i -g pnpm@${PNPM_VERSION} --force
pnpm --version
pnpm install --frozen-lockfile
rustup target add x86_64-unknown-linux-gnu
pnpm nx run-many --verbose --target=build-native -- --target=x86_64-unknown-linux-gnu
- host: ubuntu-latest
target: x86_64-unknown-linux-musl
docker: ghcr.io/napi-rs/napi-rs/nodejs-rust:lts-alpine
build: |-
set -e &&
npm i -g pnpm@9.8.0 --force &&
pnpm --version &&
pnpm install --frozen-lockfile &&
pnpm nx run-many --verbose --target=build-native -- --target=x86_64-unknown-linux-musl
- host: macos-13
build: |
bash -c "
set -e
echo 'https://dl-cdn.alpinelinux.org/alpine/edge/community' >> /etc/apk/repositories
apk add --no-cache curl xz openjdk21
# Set up Java 21
export JAVA_HOME=/usr/lib/jvm/java-21-openjdk
export PATH=\"\$JAVA_HOME/bin:\$PATH\"
java --version
curl -fsSL https://unofficial-builds.nodejs.org/download/release/v22.16.0/node-v22.16.0-linux-x64-musl.tar.xz -o node.tar.xz
tar -xJf node.tar.xz
mv node-v22.16.0-linux-x64-musl /usr/local/node
export PATH=\"/usr/local/node/bin:\$PATH\"
echo Node: \$(node -v)
echo NPM: \$(npm -v)
# Install PNPM
npm i -g pnpm@${PNPM_VERSION} --force
pnpm --version
# Install deps and run native build
pnpm install --frozen-lockfile
rustup target add x86_64-unknown-linux-musl
pnpm nx run-many --verbose --target=build-native -- --target=x86_64-unknown-linux-musl
"
- host: macos-latest
target: aarch64-apple-darwin
setup: |-
rustup target add aarch64-apple-darwin
build: |
sudo rm -Rf /Library/Developer/CommandLineTools/SDKs/*;
export CC=$(xcrun -f clang);
@@ -163,17 +214,35 @@ jobs:
- host: ubuntu-latest
target: aarch64-unknown-linux-gnu
docker: ghcr.io/napi-rs/napi-rs/nodejs-rust:lts-debian-aarch64
build: |-
set -e &&
npm i -g pnpm@9.8.0 --force &&
pnpm --version &&
pnpm install --frozen-lockfile &&
build: |
set -e
apt-get update
# Install Java 21
apt-get install -y openjdk-21-jdk
export JAVA_HOME=/usr/lib/jvm/java-21-openjdk-amd64
export PATH="$JAVA_HOME/bin:$PATH"
java --version
curl -fsSL https://deb.nodesource.com/setup_22.x | bash -
apt-get install -y nodejs=22.16.0-1nodesource1
export PATH="/usr/local/bin:$PATH"
node --version
npm --version
npm i -g pnpm@${PNPM_VERSION} --force
pnpm --version
pnpm install --frozen-lockfile
rustup target add aarch64-unknown-linux-gnu
pnpm nx run-many --verbose --target=build-native -- --target=aarch64-unknown-linux-gnu
- host: ubuntu-latest
target: armv7-unknown-linux-gnueabihf
setup: |
sudo apt-get update
sudo apt-get install gcc-arm-linux-gnueabihf -y
rustup target add armv7-unknown-linux-gnueabihf
build: |
CARGO_TARGET_ARMV7_UNKNOWN_LINUX_GNUEABIHF_LINKER=/usr/bin/arm-linux-gnueabihf-gcc pnpm nx run-many --target=build-native -- --target=armv7-unknown-linux-gnueabihf
# Android (not needed)
@@ -188,30 +257,59 @@ jobs:
- host: ubuntu-latest
target: aarch64-unknown-linux-musl
docker: ghcr.io/napi-rs/napi-rs/nodejs-rust:lts-alpine
build: |-
set -e &&
rustup target add aarch64-unknown-linux-musl &&
npm i -g pnpm@9.8.0 --force &&
pnpm --version &&
pnpm install --frozen-lockfile &&
pnpm nx run-many --verbose --target=build-native -- --target=aarch64-unknown-linux-musl
build: |
bash -c "
set -e
echo 'https://dl-cdn.alpinelinux.org/alpine/edge/community' >> /etc/apk/repositories
apk add --no-cache curl xz openjdk21
# Set up Java 21
export JAVA_HOME=/usr/lib/jvm/java-21-openjdk
export PATH=\"\$JAVA_HOME/bin:\$PATH\"
java --version
curl -fsSL https://unofficial-builds.nodejs.org/download/release/v22.16.0/node-v22.16.0-linux-x64-musl.tar.xz -o node.tar.xz
tar -xJf node.tar.xz
mv node-v22.16.0-linux-x64-musl /usr/local/node
export PATH=\"/usr/local/node/bin:\$PATH\"
echo Node: \$(node -v)
echo NPM: \$(npm -v)
# Install PNPM
npm i -g pnpm@${PNPM_VERSION} --force
pnpm --version
# Install deps and run native build
pnpm install --frozen-lockfile
rustup target add aarch64-unknown-linux-musl
pnpm nx run-many --verbose --target=build-native -- --target=aarch64-unknown-linux-musl
"
- host: windows-latest
target: aarch64-pc-windows-msvc
build: pnpm nx run-many --target=build-native -- --target=aarch64-pc-windows-msvc
name: stable - ${{ matrix.settings.target }} - node@18
setup: |-
choco install openjdk --version=21.0.0 -y
rustup target add aarch64-pc-windows-msvc
build: |
export JAVA_HOME="C:\Program Files\OpenJDK\jdk-21"
export PATH="$JAVA_HOME\bin:$PATH"
java -version
pnpm nx run-many --target=build-native -- --target=aarch64-pc-windows-msvc
name: stable - ${{ matrix.settings.target }} - node@22.16.0
runs-on: ${{ matrix.settings.host }}
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with:
repository: ${{ needs.resolve-required-data.outputs.repo }}
ref: ${{ needs.resolve-required-data.outputs.ref }}
repository: ${{ needs.resolve-required-data.outputs.repo || github.repository }}
ref: ${{ needs.resolve-required-data.outputs.ref || github.ref }}
- uses: pnpm/action-setup@v4
- uses: pnpm/action-setup@7088e561eb65bb68695d245aa206f005ef30921d # v4.1.0
with:
version: ${{ env.PNPM_VERSION }}
- name: Setup node
uses: actions/setup-node@v4
uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5.0.0
if: ${{ !matrix.settings.docker }}
with:
node-version: ${{ env.NODE_VERSION }}
@@ -219,13 +317,14 @@ jobs:
cache: 'pnpm'
- name: Install
uses: dtolnay/rust-toolchain@stable
uses: actions-rust-lang/setup-rust-toolchain@ac90e63697ac2784f4ecfe2964e1a285c304003a # v1
if: ${{ !matrix.settings.docker }}
with:
targets: ${{ matrix.settings.target }}
target: ${{ matrix.settings.target }}
rustflags: ''
- name: Cache cargo
uses: actions/cache@v4
uses: actions/cache@0400d5f644dc74513175e3cd8d07132dd4860809 # v4.2.4
with:
path: |
~/.cargo/registry/index/
@@ -235,7 +334,7 @@ jobs:
target/
key: ${{ matrix.settings.target }}-cargo-registry
- uses: goto-bus-stop/setup-zig@v2
- uses: goto-bus-stop/setup-zig@abea47f85e598557f500fa1fd2ab7464fcb39406 # v2.2.1
if: ${{ matrix.settings.target == 'armv7-unknown-linux-gnueabihf' }}
with:
version: 0.10.0
@@ -256,7 +355,7 @@ jobs:
timeout-minutes: 30
- name: Setup node x86
uses: actions/setup-node@v4
uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5.0.0
if: matrix.settings.target == 'i686-pc-windows-msvc'
with:
node-version: ${{ env.NODE_VERSION }}
@@ -265,7 +364,7 @@ jobs:
architecture: x86
- name: Build in docker
uses: addnab/docker-run-action@v3
uses: addnab/docker-run-action@4f65fabd2431ebc8d299f8e5a018d79a769ae185 # v3
if: ${{ matrix.settings.docker }}
with:
image: ${{ matrix.settings.docker }}
@@ -278,12 +377,12 @@ jobs:
shell: bash
- name: Upload artifact
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with:
name: bindings-${{ matrix.settings.target }}
path: |
packages/**/*.node
packages/**/*.wasm
packages/nx/src/native/*.node
packages/nx/src/native/*.wasm
if-no-files-found: error
build-freebsd:
@@ -293,30 +392,35 @@ jobs:
name: Build FreeBSD
timeout-minutes: 45
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with:
repository: ${{ needs.resolve-required-data.outputs.repo }}
ref: ${{ needs.resolve-required-data.outputs.ref }}
repository: ${{ needs.resolve-required-data.outputs.repo || github.repository }}
ref: ${{ needs.resolve-required-data.outputs.ref || github.ref }}
- name: Build
id: build
uses: cross-platform-actions/action@v0.25.0
uses: cross-platform-actions/action@462ed697694d2ac9aa49e1225f395f7bb6dd49fe # v0.29.0
env:
DEBUG: napi:*
RUSTUP_IO_THREADS: 1
NX_PREFER_TS_NODE: true
PLAYWRIGHT_BROWSERS_PATH: 0
NODE_VERSION: 22.16.0
with:
operating_system: freebsd
version: '14.0'
architecture: x86-64
environment_variables: DEBUG RUSTUP_IO_THREADS CI NX_PREFER_TS_NODE PLAYWRIGHT_BROWSERS_PATH
environment_variables: DEBUG RUSTUP_IO_THREADS CI NX_PREFER_TS_NODE PLAYWRIGHT_BROWSERS_PATH NODE_VERSION
shell: bash
run: |
env
whoami
sudo pkg install -y -f node libnghttp2 www/npm git
sudo npm install --location=global --ignore-scripts pnpm@9.8.0
sudo pkg install -y -f node libnghttp2 www/npm git openjdk17
sudo npm install --location=global --ignore-scripts pnpm@10.11.1
# Set up Java 17
export JAVA_HOME=/usr/local/openjdk17
export PATH="$JAVA_HOME/bin:$PATH"
java --version
curl https://sh.rustup.rs -sSf --output rustup.sh
sh rustup.sh -y --profile minimal --default-toolchain stable
source "$HOME/.cargo/env"
@@ -331,8 +435,59 @@ jobs:
whoami
env
freebsd-version
echo "Installing dependencies"
pnpm install --frozen-lockfile --ignore-scripts
echo "Checking disk space before cleanup"
df -h
echo "Removing unnecessary preinstalled packages"
# List all packages first to see what's installed
sudo pkg info -a
echo "Cleaning up to free disk space"
# Clean package caches
sudo pkg clean -a -y
sudo pkg autoremove -y
# Remove unnecessary system files
sudo rm -rf /usr/local/lib/*.a
sudo rm -rf /usr/local/share/doc/*
sudo rm -rf /usr/local/share/man/*
sudo rm -rf /usr/local/share/examples/*
sudo rm -rf /usr/local/share/locale/*
sudo rm -rf /usr/local/share/gtk-doc/*
sudo rm -rf /usr/local/share/info/*
sudo rm -rf /usr/src/*
sudo rm -rf /usr/obj/*
sudo rm -rf /usr/tests/*
sudo rm -rf /usr/lib/debug/*
# Clean var directories
sudo rm -rf /var/cache/pkg/*
sudo rm -rf /var/db/pkg/*.tbz
sudo rm -rf /var/log/*.log
sudo rm -rf /var/log/*.old
# Clean temporary files
sudo rm -rf /tmp/*
sudo rm -rf /var/tmp/*
# Remove Python cache if present
sudo find /usr/local -type d -name "__pycache__" -exec rm -rf {} + 2>/dev/null || true
sudo find /usr/local -name "*.pyc" -delete 2>/dev/null || true
sudo find /usr/local -name "*.pyo" -delete 2>/dev/null || true
# Clean npm/pnpm caches
npm cache clean --force || true
pnpm store prune || true
rm -rf ~/.npm || true
rm -rf ~/.pnpm-store || true
# Remove Rust build artifacts if any
rm -rf ~/.cargo/registry || true
rm -rf ~/.cargo/git || true
rm -rf ~/.rustup/toolchains/*/share || true
# Remove other development tool caches
rm -rf ~/.cache/* || true
echo "Checking disk space after cleanup"
df -h
echo "Building FreeBSD bindings"
pnpm nx run-many --verbose --outputStyle stream --target=build-native -- --target=x86_64-unknown-freebsd
echo "Cleaning up"
pnpm nx reset
rm -rf node_modules
rm -rf dist
@@ -341,16 +496,18 @@ jobs:
echo "COMPLETE"
- name: Upload artifact
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with:
name: bindings-freebsd
path: packages/**/*.node
path: |
packages/nx/src/native/*.node
if-no-files-found: error
publish:
if: ${{ github.repository_owner == 'nrwl' }}
name: Publish
runs-on: ubuntu-latest
environment: npm-registry
permissions:
id-token: write
contents: write
@@ -361,31 +518,32 @@ jobs:
- build
env:
GH_TOKEN: ${{ github.token }}
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
NPM_CONFIG_PROVENANCE: true
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with:
repository: ${{ needs.resolve-required-data.outputs.repo }}
ref: ${{ needs.resolve-required-data.outputs.ref }}
repository: ${{ needs.resolve-required-data.outputs.repo || github.repository }}
ref: ${{ needs.resolve-required-data.outputs.ref || github.ref }}
- uses: pnpm/action-setup@v4
- uses: pnpm/action-setup@7088e561eb65bb68695d245aa206f005ef30921d # v4.1.0
with:
version: ${{ env.PNPM_VERSION }}
- name: Setup node
uses: actions/setup-node@v4
uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5.0.0
with:
node-version: ${{ env.NODE_VERSION }}
registry-url: 'https://registry.npmjs.org'
check-latest: true
cache: 'pnpm'
- name: Use npm 11.5.2
run: npm install -g npm@11.5.2
- name: Install dependencies
run: pnpm install --frozen-lockfile
- name: Download all artifacts
uses: actions/download-artifact@v4
uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 # v5.0.0
with:
path: artifacts
@@ -403,6 +561,7 @@ jobs:
VERSION: ${{ needs.resolve-required-data.outputs.version }}
DRY_RUN: ${{ needs.resolve-required-data.outputs.dry_run_flag }}
PUBLISH_BRANCH: ${{ needs.resolve-required-data.outputs.publish_branch }}
NX_VERBOSE_LOGGING: true
run: |
echo ""
# Create and check out the publish branch
@@ -420,11 +579,11 @@ jobs:
- name: (PR Release Only) Create comment for successful PR release
if: success() && github.event.inputs.pr
uses: actions/github-script@v7
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0
env:
SUCCESS_COMMENT: ${{ needs.resolve-required-data.outputs.success_comment }}
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
# github-token defaults to ${{ github.token }} so we don't need to specify it
script: |
const successComment = JSON.parse(process.env.SUCCESS_COMMENT);
await github.rest.issues.createComment({
@@ -434,22 +593,55 @@ jobs:
body: successComment
});
report-pending-publish:
name: Report Pending Publish to Slack
if: ${{ github.repository_owner == 'nrwl' }}
needs:
- resolve-required-data
- build-freebsd
- build
runs-on: ubuntu-latest
timeout-minutes: 10
continue-on-error: true # Don't fail the workflow if notification fails
steps:
- name: Send Slack notification
uses: ravsamhq/notify-slack-action@be814b201e233b2dc673608aa46e5447c8ab13f2 # v11
with:
status: ${{ job.status }}
notification_title: >-
${{ needs.resolve-required-data.outputs.pr_number &&
format('📦 PR #{0} Publish Pending Review', needs.resolve-required-data.outputs.pr_number) ||
'📦 Publish Pending Review' }}
message_format: >-
${{ needs.resolve-required-data.outputs.pr_number &&
format('Version {0} from PR #{1} by @{2} is being published to NPM - manual review is required',
needs.resolve-required-data.outputs.version,
needs.resolve-required-data.outputs.pr_number,
needs.resolve-required-data.outputs.pr_author) ||
format('Version {0} is being published to NPM - manual review is required',
needs.resolve-required-data.outputs.version) }}
footer: '<{run_url}|View Workflow Run>'
mention_users: 'U9NPA6C90' # Jason
env:
SLACK_WEBHOOK_URL: ${{ secrets.ACTION_MONITORING_SLACK }}
pr_failure_comment:
# Run this job if it is a PR release, running on the nrwl origin, and any of the required jobs failed
if: ${{ github.repository_owner == 'nrwl' && github.event.inputs.pr && always() && contains(needs.*.result, 'failure') }}
needs: [ resolve-required-data, build, build-freebsd, publish ]
name: (PR Release Failure Only) Create comment for failed PR release
runs-on: ubuntu-latest
permissions:
pull-requests: write
steps:
- name: Create comment for failed PR release
uses: actions/github-script@v7
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
# This script is intentionally kept inline (and e.g. not generated in publish-resolve-data.js)
# to ensure that an error within the data generation itself is not missed.
script: |
const message = `
Failed to publish a PR release of this pull request, triggered by @${{ github.triggering_actor }}.
Failed to publish a PR release of this pull request, triggered by @${{ github.triggering_actor }}.
See the failed workflow run at: https://github.com/nrwl/nx/actions/runs/${{ github.run_id }}
`;
await github.rest.issues.createComment({
@@ -458,3 +650,4 @@ jobs:
issue_number: ${{ github.event.inputs.pr }},
body: message
});
+5
View File
@@ -513,5 +513,10 @@
"name": "nx-foundry",
"description": "Foundry generators and inferred tasks for Nx",
"url": "https://github.com/juliangsibecas/nx-foundry"
},
{
"name": "@aws/nx-plugin",
"description": "Nx Plugin for AWS: Accelerate building cloud-native applications with AWS",
"url": "https://github.com/awslabs/nx-plugin-for-aws"
}
]
+8
View File
@@ -299,6 +299,14 @@ Have a more decent button-like widget that you can place below sections of a tut
{% video-link link="https://youtu.be/OQ-Zc5tcxJE?t=64" /%}
```
#### Course video embed
This is for embedding a video just like with the Youtube component, but in addition to have a link to a Nx Course (nx.dev/courses) video to improve the discoverability of these courses.
```markdown
{% course-video src="https://youtu.be/3hW53b1IJ84" courseTitle="From PNPM Workspaces to Distributed CI" courseUrl="/courses/pnpm-nx-next/lessons-01-nx-init" title="Initialize Nx in Your Project with nx init" /%}
```
#### Project Details View
Embed a Project Details View that is identical what is shown in Nx Console or `nx show project myproject --web`
@@ -9,6 +9,15 @@ description: Learn to set up a monorepo with PNPM workspaces for Remix and React
In this article we're going to have a deep dive into setting up a new monorepo using [PNPM workspaces](https://pnpm.io/workspaces) that hosts a Remix application as well as a React-based library. We will learn how to run commands with PNPM, how to run them in parallel and finally we're going to add Nx for a more sophisticated task scheduling, including command caching and more.
{% callout type="warning" title="Updated video!" %}
We made a lot of improvements since we last wrote this article. Here's our **updated content**:
- [the full all-in-one video on Youtube](https://youtu.be/zX-1tpqUG5c)
- [our free course: From PNPM Workspaces to Distributed CI](/courses/pnpm-nx-next)
{% /callout %}
**Important:** If you are already familiar with the setup and configuration of a new PNPM workspace, feel free to skip to the part where we add Nx later in the article.
**Prefer a video walkthrough?**
@@ -8,6 +8,15 @@ cover_image: /blog/images/articles/monorepos-are-ai-future-proof-bg.jpg
youtubeUrl: https://youtu.be/RNilYmJJzdk
---
{% callout type="deepdive" title="Series: Making your LLM smarter" expanded=true %}
- **Nx Just Made Your LLM Way Smarter**
- [Making Cursor Smarter with an MCP Server For Nx Monorepos](/blog/nx-made-cursor-smarter)
- [Nx MCP Now Available for VS Code Copilot](/blog/nx-mcp-vscode-copilot)
- [Nx and AI: Why They Work so Well Together](/blog/nx-and-ai-why-they-work-together)
{% /callout %}
Everyone is constantly pushing to be more productive: delivering more features, reducing overhead, and keeping up with increasing demands. Companies want to move faster, and engineering teams work toward the same goal, looking for ways to streamline development and ship more with fewer resources. LLMs offer a promising way to boost efficiency, whether by assisting individual developers or improving workflows across a team.
However, the quality of an LLM's response depends entirely on the data and context it has access to. Ask an LLM (in this case, GitHub Copilot with GPT-4o) about the structure of an NPM workspace monorepo, and you probably won't be satisfied with the result:
+7 -13
View File
@@ -12,7 +12,9 @@ pinned: true
{% callout type="deepdive" title="Series: Making your LLM smarter" expanded=true %}
- [Nx Just Made Your LLM Way Smarter](/blog/nx-just-made-your-llm-smarter)
- **Making Cursor Smarter**
- **Making Cursor Smarter with an MCP Server For Nx Monorepos**
- [Nx MCP Now Available for VS Code Copilot](/blog/nx-mcp-vscode-copilot)
- [Nx and AI: Why They Work so Well Together](/blog/nx-and-ai-why-they-work-together)
{% /callout %}
@@ -124,19 +126,11 @@ If you want to use our MCP integration with other tools that support the protoco
## Let's see it in action
Here are some example queries, showing how Cursor leverages the different exposed Nx MCP tools to get more information to correctly take action. Jump to the [Youtube video for the full run-through]().
The [Youtube video]() above showcases the below example queries, showing how Cursor leverages the different exposed Nx MCP tools to get more information to correctly take action.
**Query:** "If I change the public API of feat-product-detail, which other projects might be affected by that change?"
{% video-player src="/documentation/blog/media/nx-mcp-cursor-dependencies.mp4" alt="Asking Cursor about the impact of changing a project's public API" showDescription=true showControls=true autoPlay=false loop=false /%}
**Query:** "Use Nx to generate a new React library for handling past orders."
{% video-player src="/documentation/blog/media/nx-mcp-cursor-generate-project.mp4" alt="Asking Cursor to generate a new React project for listing past orders" showDescription=true showControls=true autoPlay=false loop=false /%}
**Query:** "Can you configure Nx release for the packages of this workspace? Just update nx.json with the necessary configuration. Use conventional commits as the versioning strategy. Also feel free to use the Nx docs to pull more info on how to configure it."
{% video-player src="/documentation/blog/media/nx-mcp-cursor-nx-release.mp4" alt="Asking Cursor to use the docs to configure Nx release for the workspace" showDescription=true showControls=true autoPlay=false loop=false /%}
- If I change the public API of feat-product-detail, which other projects might be affected by that change?
- Use Nx to generate a new React library for handling past orders.
- Can you configure Nx release for the packages of this workspace? Just update nx.json with the necessary configuration. Use conventional commits as the versioning strategy. Also feel free to use the Nx docs to pull more info on how to configure it.
## Wrapping up
@@ -7,7 +7,7 @@ authors: ['Victor Savkin', 'Max Kless']
tags: [webinar]
cover_image: /blog/images/2025-03-19/March-2025-Webinar-card.png
time: 1pm EDT/5pm UTC
status: Upcoming
status: Past - Gated
registrationUrl: https://go.nx.dev/march2025-webinar
---
@@ -17,4 +17,4 @@ Presented by Victor Savkin and Max Kless
In this webinar, Nx CTO Victor Savkin and Senior Engineer Max Kless will break down **why monorepos are inherently more AI-friendly**, giving LLMs the full context they need to generate more accurate, actionable insights. Youll also learn how Nx provides deep architectural awareness, making AI tools smarter and more effective.
{% call-to-action title="Register today!" url="https://go.nx.dev/march2025-webinar" description="Save your spot" /%}
{% call-to-action title="Download the recording" url="https://go.nx.dev/march2025-webinar" description="Sign up to gain access" /%}
@@ -0,0 +1,139 @@
---
title: 'Scaffolding New Apps With Angular Rspack'
date: 2025-04-15
slug: scaffold-angular-rspack-applications
authors: [Colum Ferry]
tags: [angular, webpack, rspack, nx]
cover_image: /blog/images/2025-04-14/scaffold-angular-rspack-applications.avif
description: Learn about how to scaffold a new Angular Rspack application with Nx.
---
It is not uncommon to see [Angular](https://angular.dev) applications that rely on a custom [Webpack](https://webpack.js.org) configuration - especially in enterprise settings. These applications rely heavily on the extensibility offered by Webpack via its Plugin and Loader ecosystem.
However, building Angular applications with Webpack has historically been slow. In fact, slow builds with Webpack is something that even the wider JavaScript Ecosystem has come to expect. The result? Many new bundler options have been created to tackle the issue. Vite, Rollup, Rolldown, Esbuild, Turbopack and more.
The frustration over build performance became so great that the Angular team decided to switch to [Esbuild](https://esbuild.github.io) which has offered an incredible improvement on build speed.
The problem with Esbuild and with the other bundler options listed above stems from the _reason_ teams needed custom Webpack configurations in the first place. The extensibility.
While most of the bundler options that are available today offer some kind of API to extend the build process, the ability to replicate the functionality of certain Webpack plugins and loaders is either impossible or would involve a large effort to build a homebrewed solution that would need to be maintained internally over time.
That is, until [ByteDance](https://bytedance.com/en) released [Rspack](https://rspack.dev).
## Rspack
![Rspack Logo](/blog/images/2025-04-14/rspack-logo.avif)
Rspack is a high performance JavaScript bundler written in Rust. It offers strong compatibility with the Webpack ecosystem, allowing for near-seamless replacement of Webpack, while providing lightning fast build speeds.
That sounds compelling enough as it is, especially for anyone that is currently using Webpack to build their applications. You can see from the benchmark results below just _how much_ faster than Webpack it really is. You can view the benchmark details [here](https://github.com/rspack-contrib/build-tools-performance).
![Rspack Benchmarks](/blog/images/2025-04-14/rspack-benchmarks.png)
Docusaurus has even [reported that switching to Rspack has resulted in a 2x-4x faster production build](https://docusaurus.io/blog/releases/3.6#docusaurus-faster)!
However, Angulars Webpack build pipeline proved to be an issue. It had not been possible to use Rspack as a drop-in replacement for Angular applications.
Which is why [Angular Rspack](/recipes/angular/rspack/introduction) was created.
## Angular Rspack
![Angular Rspack Logo](/blog/images/2025-03-19/angular-rspack-logo-small.avif)
Angular Rspack provides Rspack Plugins and Loaders that makes it possible to build Angular applications with Rspack.
{% callout type="note" title="Learn More" %}
You can learn more about Angular Rspack from the resources below:
- [Angular Rspack - Introduction](/recipes/angular/rspack/introduction)
- [Using Rspack with Angular](/blog/using-rspack-with-angular)
{% /callout %}
At the time of writing, Angular still supports building applications with Webpack alongside Esbuild. However, they are two different build pipelines.
Therefore, if the Angular team were to **drop support for Webpack** and remove the code from the Angular Devkit packages entirely, **Angular Rspack will continue to operate**.
- By using Rspack the majority of Plugins and Loaders used by Angular applications with custom Webpack Configurations will continue to be supported
- It does not rely on Angulars Webpack build pipeline directly. Instead it uses the abstractions in place for the Esbuild pipeline.
From the benchmark results below, you can see the vast improvement using Angular Rspack has over sticking with Webpack. You can view the benchmark details [here](https://github.com/nrwl/ng-bundler-benchmark).
![Angular Rspack Benchmarks](/blog/images/2025-03-19/bundler-build-times.avif)
You can see that the results from Rspack are comparable to the results provided by Angulars Esbuild build pipeline.
That said, it is worth noting that there are still currently some [known limitations and missing features](/recipes/angular/rspack/introduction#known-limitations-and-missing-features).
## Why Choose Rspack for New Projects?
Given the results above, its clear that migrating Angular Webpack applications to Rspack can lead to significant time savings — reducing CI durations and boosting overall developer productivity.
But at this point, you might be asking _why_ you should start a new Angular project with **Rspack** instead of **Esbuild**, especially considering that benchmarks show Esbuild is still slightly faster when building Angular apps.
Heres why Rspack is often the better choice for new projects:
- **Speed** While Esbuild may still win out slightly in raw benchmarks, Rspack delivers massive speed improvements over traditional Webpack — especially in large projects or CI environments. Its fast enough to feel like a completely different experience for developers used to legacy builds.
- **Extensibility** Rspack provides a much more extensible architecture than Esbuild. This allows teams to customize and fine-tune their build processes far more effectively. For projects that have complex build requirements or need to integrate custom tooling, this flexibility is a major advantage.
- **Compatibility** Rspack is designed to be highly compatible with the existing Webpack ecosystem. This means many plugins and loaders that teams already rely on can continue to work with minimal or no changes. It eases the migration path and preserves your existing investment in tooling and configuration.
- **Micro-frontend support** If you're building applications that rely heavily on **[Module Federation](https://module-federation.io)**, Rspack is the clear winner. Its compatibility and support for advanced use cases in micro-frontends are significantly more mature than what's possible with Esbuild.
- **Chunking control** Esbuild has a long-standing [issue](https://github.com/angular/angular-cli/issues/27715) with generating an excessive number of chunks, offering very limited control over how chunking is performed. This can cause performance issues in certain scenarios. In contrast, Rspack offers fine-grained chunking strategies that let teams precisely shape how their bundles are produced.
These advantages make Rspack not just a performance play, but a more adaptable and production-ready solution for modern Angular projects.
## How to Scaffold a New Angular Rspack Project?
Nx provides two methods for creating a new Angular Rspack project, one for existing Nx Workspaces and one for new Workspaces.
### New Workspaces
To create a new Nx Workspace with an Angular Rspack project run the following command and select the options listed below:
```{% command="npx create-nx-workspace myorg" path="~/" %}
NX Let's create a new workspace [[https://nx.dev/getting-started/intro](https://nx.dev/getting-started/intro)]
✔ Which stack do you want to use? · angular
✔ Integrated monorepo, or standalone project? · integrated
✔ Application name · myorg
✔ Which bundler would you like to use? · rspack
✔ Default stylesheet format · css
✔ Do you want to enable Server-Side Rendering (SSR)? · No
✔ Which unit test runner would you like to use? · vitest
✔ Test runner to use for end to end (E2E) tests · playwright
✔ Which CI provider would you like to use? · skip
✔ Would you like remote caching to make your build faster? · skip
NX Creating your v20.8.0 workspace.
```
### Existing Workspaces
In existing Nx Workspaces, ensure you are on Nx version `20.8.0` or greater and simply run:
```
npx nx g @nx/angular:app myapp --bundler=rspack
```
### Converting an Existing Angular Webpack Application
If you have an existing Angular Webpack application you can easily migrate it to use Angular Rspack by using the `@nx/angular:convert-to-rspack` generator. The [Migrate Angular with Webpack to Rspack](/recipes/angular/rspack/migrate-from-webpack) guide explains more on this.
## Future Work
Its been great to see the progress on Angular Rspack so far, but its not done yet. Well be working on making it closer to feature parity with the Angular CLI by addressing:
- Internationalization (i18n) support
- Static Site Generation (SSG) support
- and more!
Stay tuned to our socials to stay up to date on the latest Angular Rspack news!
- 🧠 [**Nx Docs**](/getting-started/intro)
- 👩‍💻 [**Nx GitHub**](https://github.com/nrwl/nx)
- 💬 [**Nx Official Discord Server**](https://go.nx.dev/community)
- 📹 [**Nx Youtube Channel**](https://www.youtube.com/@nxdevtools)
@@ -0,0 +1,126 @@
---
title: 'Nx MCP Now Available for VS Code Copilot'
slug: nx-mcp-vscode-copilot
authors: ['Juri Strumpflohner']
tags: ['nx', 'nx-console', 'ai']
cover_image: /blog/images/articles/bg-copilot-nx-mcp.avif
description: 'Learn how to enhance VS Code Copilot with Nx MCP integration, providing rich monorepo context for smarter AI assistance.'
youtubeUrl: https://youtu.be/dRQq_B1HSLA
---
{% callout type="deepdive" title="Series: Making your LLM smarter" expanded=true %}
- [Nx Just Made Your LLM Way Smarter](/blog/nx-just-made-your-llm-smarter)
- [Making Cursor Smarter with an MCP Server For Nx Monorepos](/blog/nx-made-cursor-smarter)
- **Nx MCP Now Available for VS Code Copilot**
- [Nx and AI: Why They Work so Well Together](/blog/nx-and-ai-why-they-work-together)
{% /callout %}
Back in [February we shipped the first version of Nx Console with AI features](/blog/nx-just-made-your-llm-smarter), directly integrating with GitHub Copilot's APIs to provide rich monorepo context. Now, VS Code has finally adopted the [Model Context Protocol (MCP)](https://modelcontextprotocol.io/introduction), and we've adapted our Cursor-based MCP implementation to work with all MCP clients, including Copilot. This integration makes your AI assistant even more powerful by providing rich context about your Nx workspace. Let's see how to set it up and what it can do for you.
{% toc /%}
## Setting up MCP in VS Code
Getting started with Nx's MCP integration in VS Code is straightforward:
1. **Install Nx Console** from the VS Code marketplace if you haven't already.
2. Once installed, VS Code will show a notification to "Improve Copilot agent with Nx-specific context"
3. Click "Yes" to automatically configure the Nx MCP server in your `.vscode/mcp.json` file
![VS Code showing the Nx MCP installation prompt](/blog/images/articles/copilot-mcp-install.avif)
{% callout type="note" title="Missed the notification?" %}
If you missed the notification, you can always run the `nx.configureMcpServer` command from the command palette (`Ctrl/Cmd + Shift + P`).
{% /callout %}
VS Code will automatically start the MCP server when needed during your interactions with the LLM. You can verify the installation by checking your VS Code settings, where you should see the Nx MCP server listed along with its available tools.
## Why Use Nx MCP in Your Monorepo?
While VS Code and Copilot can already gather information from your monorepo context, Nx MCP provides several advantages:
1. **Efficient Data Access**: Instead of analyzing numerous files to infer relationships, Nx MCP provides direct access to pre-computed metadata about your workspace.
2. **Rich Project Context**: Nx maintains detailed information about:
- Project relationships and dependencies
- Project tags and categorization
- Available tasks and their configurations
- Code ownership
- And more...
This information is already maintained by Nx for optimizing your monorepo, and the Nx MCP makes it now available to your AI assistant as well. Most importantly, this enables Copilot to move beyond simple file-level understanding to gain more of an **architectural awareness of your workspace**. Instead of just seeing individual files and their contents, it now understands the broader context: how projects are connected, where integration points exist, which teams own what, and how changes might impact the broader system. This architectural awareness is particularly powerful in a monorepo setting, where understanding these relationships is crucial for making informed development decisions.
## Nx MCP in Action
Let's look at some practical examples of how Nx MCP enhances your AI assistant's capabilities:
### Understanding Project Relationships
You can ask questions about project dependencies and get accurate answers based on the actual project graph:
```typescript
// Example query:
'Use the provided Nx MCP tools to figure out which order projects
are related to the data-access-order project';
```
The AI will use the `nx_workspace` tool to analyze project relationships and can even visualize them using the `nx_visualize_graph` tool, showing both direct dependencies and upstream projects.
### Smart Code Generation
While LLMs can generate code on their own, Nx MCP provides a powerful combination of predictable code generation through Nx generators and AI-driven customization:
```typescript
// Example query:
"Create a new feature library in packages/order/feat-cancel-order.
Make it a React library and link it to the data-access-order project.
Don't use a bundler or generate components."
```
The AI will:
1. Use `nx_generators` to identify available generators
2. Execute the React library generator with precise options
3. Set up proper project tags and dependencies
### Documentation-Aware Configuration
To prevent hallucination and ensure up-to-date information, Nx MCP provides access to the current Nx documentation:
```typescript
// Example query:
'Add a task pipeline in nx.json that runs the build of all downstream projects before the dev command';
```
The AI will:
1. Query the Nx docs for task pipeline configuration
2. Update `nx.json` with the correct syntax
3. Configure the dependencies accurately
## Beyond File-Level Thinking
This integration isn't just about fancy AI features - it's about making your existing editor experience more productive by integrating AI capabilities where they actually make sense. Instead of jumping on the AI hype train, we're focusing on exposing Nx's deep understanding of your workspace directly in your editor through tools like Copilot. This enables:
- More precise and contextual suggestions
- Architecture-aware refactoring
- Better understanding of project boundaries and relationships
- Improved onboarding assistance for new team members
We're actively developing this integration and would love to hear your feedback! If you have ideas about what you'd like to see or how we can make this more useful for your workflow, reach out to us on [Twitter/X](https://x.com/NxDevTools), [Bluesky](https://bsky.app/profile/nx.dev), [LinkedIn](https://www.linkedin.com/company/nrwl/), or join our [weekly office hours on Discord](http://go.nx.dev/office-hours).
Also, subscribe to our [YouTube channel](https://www.youtube.com/@nxdevtools) for upcoming feature announcements and demonstrations.
Want to try it out? Install [Nx Console from the VS Code marketplace](/getting-started/editor-setup) and follow the MCP setup prompts to get started.
---
Learn more:
- 🧠 [Nx AI Docs](/features/enhance-AI)
- 📖 [Making Cursor Smarter with MCP](/blog/nx-made-cursor-smarter)
- 👩‍💻 [Nx GitHub](https://github.com/nrwl/nx)
- 👩‍💻 [Nx Console GitHub](https://github.com/nrwl/nx-console)
- 💬 [Nx Official Discord Server](https://go.nx.dev/community)
- 📹 [Nx Youtube Channel](https://www.youtube.com/@nxdevtools)
@@ -0,0 +1,190 @@
---
title: 'Nx and AI - Why They Work so Well Together'
slug: nx-and-ai-why-they-work-together
authors: ['Victor Savkin']
tags: ['nx', 'ai', 'monorepo']
cover_image: /blog/images/articles/bg-nx-and-ai-powered-dev.avif
description: 'Explore how Nx monorepos amplify AI benefits by providing complete context and consistent tooling, creating a growing competitive advantage for enterprise development.'
---
{% callout type="deepdive" title="Series: Making your LLM smarter" expanded=true %}
- [Nx Just Made Your LLM Way Smarter](/blog/nx-just-made-your-llm-smarter)
- [Making Cursor Smarter with an MCP Server For Nx Monorepos](/blog/nx-made-cursor-smarter)
- [Nx MCP Now Available for VS Code Copilot](/blog/nx-mcp-vscode-copilot)
- **Nx and AI: Why They Work so Well Together**
{% /callout %}
**TLDR:**
1. **Monorepos Amplify AI Benefits**: Monorepos inherently enhance the utility of coding assistants by providing complete context, creating a growing competitive advantage.
2. **Consistency is Key**: The primary challenge with AI coding assistants is maintaining consistency and reliability. This affects both AI and human developers' future effectiveness, but can be mitigated with Nx capabilities.
3. **Integrated Tooling**: Tools connecting CI, editors, and coding assistants create powerful development workflows.
4. **Mitigated Downsides**: Traditional monorepo disadvantages (like the necessity for large-scale code changes) can be effectively addressed with agentic AI.
5. **Cross-Repository Context**: Benefits extend beyond single repositories to connected repositories using Nx Cloud Polygraph.
{% toc /%}
{% call-to-action title="Are Monorepos the Answer to Better AI-Assisted Development?" url="https://go.nx.dev/april2025-webinar" description="Upcoming webinar: save your spot" /%}
## It's All About Context
> _"Context is worth 80 IQ points." — Alan Kay_
Why do tools like Bolt.new work so well for streamers and indie developers bootstrapping new projects but not so much for enterprise developers that work on an existing large codebase? The answer is context. With Bolt, an LLM can access the entire context of a smaller repo, making local changes with short-term considerations.
Enterprise systems present a different challenge:
- Highly complex and interdependent
- Built by hundreds of engineers over many years
- Often spread across hundreds of repositories
- Integrated with numerous external systems
In these environments, **LLMs lack the necessary context to make changes that account for all considerations**. Like human developers, LLMs struggle with complex systems, but unlike humans, they don't have tacit knowledge from wikis, meetings, or informal conversations. As a result, they only see a small fraction of the system.
![LLMs with limited context can only see a small fraction of the system](/blog/images/articles/nx-ai-limited-context-problem.avif)
LLMs rely entirely on provided context. Because monorepos consolidate all code in one place, they fundamentally improve contextual access. However, **raw code access isn't enough. It's analogous to navigating a city using only street view.** This makes it unlikely to pick optimal routes.
![Navigating code with raw access only is like using street view without a map](/blog/images/articles/nx-ai-street-view-problem.avif)
**What's needed is a "map" of your codebase and organization. Nx via its plugins builds this "map".** It includes:
1. High-level repository structure
2. System architecture
3. Organizational structure and ownership
4. Information about used tools, frameworks, their versions and dependencies
5. CI information (frequency, failures)
This information is used to make CI execution fast, to ensure boundaries, and now **Nx provides this information to [coding assistants through MCP servers](/features/enhance-AI), enabling LLMs to answer questions like**:
- "Who should I consult about creating a new bank library for overdraft payments?"
- "Create a library using the bank team's best practices."
- "Identify and suggest fixes for circular dependencies."
- "Which shared libraries does the overdraft library depend on? Which teams own them?"
- "Which projects owned by my team fail frequently in CI? Which ones affect other teams' work?"
![Nx provides a 30,000-foot view map of your entire system](/blog/images/articles/nx-ai-map-view-visualization.avif)
With this map, Nx provides a "30,000-foot view" of the entire system (architecture, organization, CI). Coding assistants are able to read relevant files and see the 0-foot view. This combination creates very powerful interactions.
But we are working on providing a "10,000-foot view" by compressing relevant content about projects and project clusters in the repository. Another way to think of this is **"d.ts" files for AI coding assistants**. With this, your coding assistant is able to jump between different abstraction levels to get relevant information.
![Different abstraction levels help AI understand your codebase better](/blog/images/articles/nx-ai-abstraction-levels.avif)
## Beyond Speed: Writing Correct and Consistent Code
> _"It is better to take many small steps in the right direction than to make a great leap forward only to stumble backward." — Chinese Proverb_
Research shows enterprise developers commit only 20-30 lines of code daily. The bottleneck isn't coding speed but determining the correct approach to minimize technical debt and long-term impact.
Enterprise developers spend 90%+ of their time not actively writing code. **LLMs excel at generating code, and if that's what they are used for, they can only help with that 10% of the development process.**
To realize substantial gains we need to:
1. Enable LLMs to help with the 90% by providing better context (see section above)
2. Ensure generated code is correct, consistent with the organization's best practices, and doesn't introduce technical debt
Without these considerations, you might be 5x more productive in the first month but progressively slower throughout the year due to accumulated technical debt. So you might not even break even.
### Consistency Through Best Practices and Metadata
One way to minimize technical debt is by codifying and reusing best practices:
**Human Approach**:
- Senior developers examine feature libraries from the bank team
- They identify common patterns and create a local plugin with a generator
- They teach other developers about the new generator
**LLM Approach**:
- Developers ask LLM powered by Nx to extract common patterns from all bank libraries
- LLM creates a local plugin with a generator for bank libraries
- Developer refines the generator
- Another developer requests a new bank feature library
- LLM finds and runs the new generator in dry-run mode for confirmation
- LLM can open a generator UI for parameter tweaking
- Developer selects parameters and generates code
- LLM picks it up and offers additional customization
You don't have to create libraries reflecting organization's best practices. Nx plugins come with many generators.
The reason why this approach works with Nx is that everything in Nx (including [its generators](/features/generate-code)) comes with a lot of static metadata. Traditionally this metadata was used to power the terminal UI, graphic UI, docs and more. Turns out it's also extremely useful for LLMs. **With this metadata they know all the inputs into each generator and what each of them does. But it gets better! Nx's virtual file system lets LLMs run the generators in dry run mode to get the generator outputs.** With this, LLMs can derive which generators work well with which parameters. **Additional metadata specifically designed for LLMs is being added.**
LLMs excel at impressive demonstrations but struggle with consistency and correctness. This is why they work better for new applications where correctness is loosely defined and consistency is not important. Being able to access a large library of annotated generators helps LLMs reduce variability of what they generate, which improves consistency and quality. They use a generator and make some small modifications on top instead of trying to author everything from scratch.
### Migrations
[Nx Migrations](/features/automate-updating-dependencies) are special generators that update codebases to use newer tool versions and new APIs. AI agents can enhance this process with specialized metadata for validation and fixes.
### Human in the Loop
Human oversight remains crucial as AI is good at being "almost correct." Having a human in the loop, especially for high-impact operations, helps with the need to correct what LLMs generate. Nx offers a tool that lets LLMs open the generator UI and allows the developer to customize and preview what will be generated.
## The Integrated Development Advantage: Multiplying AI's Power
> _"The whole is greater than the sum of its parts." — Aristotle_
The utility of your coding assistant goes up significantly as the number of tools it can access increases, which includes the rest of your editor and IDE and your local tools. Nx has always believed in this, and that's why we always put so much effort into our VSCode and IntelliJ plugins. The bet paid off. With agentic AI being available, the value of those plugins is going up 10x.
This is the sketch I drew a while back, and we have been moving toward this vision:
![Integrated development tools and AI systems working together seamlessly](/blog/images/articles/nx-ai-integrated-tools-vision.avif)
**These are some of the things Nx either already does or is about to do in the next couple of weeks:**
1. Coding assistants can open and manipulate the [Nx project graph visualization](/features/explore-graph).
2. Coding assistants are able to open the generation UI, prefill the right values.
3. Coding assistants are able to fetch up-to-date docs to ensure they don't hallucinate.
4. Coding assistants get notified about CI execution results while the CI is still running. The assistant gets relevant logs and files and is able to explain or fix the CI error and push changes before the CI execution even completes.
5. Coding assistants will integrate with the new Nx interactive UI so they can see what the developer sees and are able to address issues while the Nx command is still running. **Tell the LLM to fix the error, and it will know what error you are looking at.**
## From Pain Points to Power Moves
> _"What was once impossible becomes merely difficult; what was difficult becomes easy; and what was easy becomes elegant." — Alan Kay_
Monorepos offer many benefits but come with caveats. The main concern is managing large-scale changes across the repository, such as updating all applications to the latest React version.
Nx has always addressed this with ["migrations" - specialized generators](/features/automate-updating-dependencies) optimized for such tasks. Typically, migrations handle 80% of the work, with the remaining 20% potentially taking weeks for a small team in large repos.
This is precisely where agentic coding assistants excel. **By building on Nx's migration capabilities, AI increases completion from 80% to a much higher percentage, reducing effort from weeks to days or even hours.** What was difficult becomes easy.
The ability to update all code simultaneously is also a significant benefit of monorepos. Small changes like renaming can be executed in a single step, eliminating entire classes of "breaking" changes. Your code is less defensive. This is a huge advantage preventing your code from becoming stale. It's a form of economy of scale, where you can make a code cleanup for a dozen applications in a time that is a tiny fraction of what it would have taken if they were in separate repos.
**Agentic coding assistants significantly expand the range of "reliable transformations" that can be done quickly, turning what were before long refactorings into minutes-long tasks. With this, the delta between what you can do in a monorepo compared to a polyrepo gets substantially more significant.**
## Repository Interconnectedness: Breaking Down the Final Silos
> _"Silos create boundaries. Networks create possibilities." — Anonymous_
This document was about Nx monorepos. But most organizations using Nx have dozens or hundreds of Nx repos and oftentimes hundreds or thousands of other repos as well. Because we recognize this reality, we built **Nx Polygraph** (available for [Nx Enterprise users](/enterprise)) which lets you connect multiple repositories into a federated meta-repo. With this, you will get some of the advantages outlined in this document in H1 2025.
## The Long View: Designing for AI's Continued Evolution
_"The path of technological progress is neither random nor accidental, but follows paths of least resistance toward inevitable destinations." — Kevin Kelly_
Some might argue that coding assistants aren't that reliable now and perhaps some of the benefits aren't realizable. A lot of it is new ([VSCode MCP support is a few weeks old](/blog/nx-mcp-vscode-copilot)) so we are working hard to provide the necessary context to them, and not everything at this point is as good as it should be. What matters though is not the current state but the direction.
**Many advantages are inherent to Nx's approach:**
- Consolidating information
- Providing a navigable "map" of the codebase
- Using metadata-driven generators and migrations that are inherently LLM-friendly
- Enabling large-scale transformations in a monorepo
Although it's not entirely impossible, it is significantly harder to provide the same advantages in a polyrepo where information isn't consolidated, where there is no "map", where there is no codification of best practices, where cross-cutting code changes are effortful and non-atomic.
**The trajectory is clear: monorepos with tools like Nx are positioned to leverage AI capabilities more effectively as the technology evolves.**
---
Learn more:
- 🧠 [Nx AI Docs](/features/enhance-AI)
- 📖 [Nx MCP Now Available for VS Code Copilot](/blog/nx-mcp-vscode-copilot)
- 👩‍💻 [Nx GitHub](https://github.com/nrwl/nx)
- 👩‍💻 [Nx Console GitHub](https://github.com/nrwl/nx-console)
- 💬 [Nx Official Discord Server](https://go.nx.dev/community)
- 📹 [Nx Youtube Channel](https://www.youtube.com/@nxdevtools)
@@ -0,0 +1,100 @@
---
title: 'Nx Cloud Update - Assignment rules come out of beta and more!'
slug: nx-cloud-update-april-2025
authors: ['Philip Fulcher']
tags: ['nx-cloud']
cover_image: /blog/images/2025-04-21/header.avif
description: 'Nx Cloud updates for April 2025 include assignment rules coming out of beta, CIPE filters, flaky retry configuration, and more!'
youtubeUrl: https://youtu.be/mug02alT7rQ
---
We're rolling out updates to Nx Cloud constantly, so we wanted to bring you up to date with what we've been working on lately.
{% toc /%}
## Assignment Rules come out of beta
In your CI pipeline, you've got some tasks of different sizes. Some tasks are quick, like linting or format checking, but you've got more resource-intensive tasks like building apps or running e2e suites. Your smaller tasks can run on a small agent with fewer CPU cores or less memory, but your larger tasks need a larger agent.
But when you're spreading tasks across multiple agents, it's inefficient to increase the size of all the agents to accommodate your larger tasks. So ideally, you have smaller agents for small tasks and larger agents for your larger tasks. But how do you make sure tasks get assigned to the right agent?
Many CI tools have ways of handling this, but we wanted to make things easier. That's why Nx Cloud now has [Assignment Rules](/ci/reference/assignment-rules). This configuration allows you to control which tasks are assigned to certain agents.
Let's take a look at a quick example for [Nx Agents](/ci/features/distribute-task-execution):
```yaml {% fileName=".nx/workflows/distribution-config.yaml" /%}
# Create five agents using the `linux-medium-js` launch template and five agents using `linux-large-js`
distribute-on:
default: 5 linux-medium-js, 5 linux-large-js
assignment-rules:
# for our `app1` projects...
- projects:
- app1
# for targets beginning with "e2e-ci"...
targets:
- e2e-ci*
# and using the `production` configuration
configurations:
- production
# run matching tasks on a `linux-medium-js` agent with parallelism set to 5
run-on:
- agent: linux-medium-js
parallelism: 5
# for lint and build tasks on any project
- targets:
- lint
- build
# run matching tasks on a `linux-large-js` agent with parallelism set to 10
run-on:
- agent: linux-large-js
parallelism: 10
```
As you can see, there's a lot of flexibility in the configuration here to fine-tune your agent assignments.
We're so excited about this feature that we've built it to work with both [Agents](/ci/features/distribute-task-execution) and [Manual DTE](/ci/recipes/dte/github-dte). So, no matter how you're distributing tasks using Nx Cloud, you can use this new feature! Be sure to [check the docs](/ci/reference/assignment-rules) for more details.
We're also providing a new UI that tells you exactly what tasks are being run on which agents and the rules impacting them.
![Screenshot of UI showing how assignment rules are affecting tasks](/blog/images/2025-04-21/assignment-rules-viz.avif)
## Find your CIPEs with better filtering
![Screenshot of UI showing filters for CIPEs view](/blog/images/2025-04-21/cipe-filters.avif)
Having trouble finding a CI Pipeline Execution (CIPE)? We've added new filter options for the CIPEs list. You can now filter by committer, branch, or date range. You can even sort by duration to help find your longest CIPEs.
## Control how flaky task retries work with your workspace
![Screenshot of UI showing configuration options for flaky task retries](/blog/images/2025-04-21/flaky-retries.avif)
Flaky retries are great at unblocking your CI pipelines by automatically retrying tasks that Nx Cloud detects as flaky. This means you spend less time re-running CI pipelines when you have a task that passes sometimes and fails other times. You now have more control over this process. You can fine-tune how Nx Cloud retries tasks, specify a time range when flakiness is determined, or even turn it off entirely. This helps optimize when tasks are retried so you can control resource use and CI cost.
## Request access to protected views
![Screenshot of UI showing an option to request access to a protected resource](/blog/images/2025-04-21/request-access.avif)
Access control is important, but it can be time-consuming to give the right access to the right people. Now, users can request access with a simple button click, and an admin will be alerted to adjust their access. This automated process saves your team time by not having to send another email or submit a support ticket for access.
## Nx Agents supports custom GitHub domains
![Screenshot of UI showing how to use a custom GitHub URL for Nx Agents](/blog/images/2025-04-21/github-url.avif)
Using GitHub Enterprise and having a custom URL? Nx Agents now works with these custom domains, check for the option to override your domain during setup.
{% call-to-action title="Not using Nx Cloud yet?" url="https://cloud.nx.app/get-started/?utm_source=nx-dev" icon="nxcloud" description="Get started now for free!" /%}
---
## Learn more
- [Nx Cloud Docs](/ci)
- [Nx Docs](/getting-started/intro)
- [X/Twitter](https://twitter.com/nxdevtools)
- [LinkedIn](https://www.linkedin.com/company/nrwl/)
- [Nx GitHub](https://github.com/nrwl/nx)
- [Nx Official Discord Server](https://go.nx.dev/community)
- [Nx Youtube Channel](https://www.youtube.com/@nxdevtools)
- [Speed up your CI](/nx-cloud)
@@ -0,0 +1,170 @@
---
title: '3 Test Splitting Techniques that Cut E2E Times up to 90%'
slug: test-splitting-techniques
authors: [Miroslav Jonaš]
description: "Learn the techniques for optimizing CI by splitting long-running tests, using sharding, Atomizer, and manual E2E project splitting, all enhanced by Nx Cloud's distributed task execution for improved stability and performance."
tags: [nx, architecture]
cover_image: /blog/images/articles/bg-test-splitting-techniques.avif
---
> "There's nothing worse than waiting for a build to complete, or those e2e tests to run. With Nx Cloud, our development team has saved over 104 hours, almost cutting our build times in half. The installation is seamless and the results are immediate. It's nice to have a tool that passively saves so much development time." - Director of Software Development, enterprise digital marketing firm
One of the most impactful core features of Nx is the affected graph. The affected graph helps us to skip unnecessary work and focus only on the things that have been changed, speeding up our CI and helping us ship features and hotfixes faster.
However, long-running tasks, especially End-to-End (E2E) tests, can become a significant bottleneck and prevent getting the code changes out faster. This is particularly true for monolithic projects, but also in cases when there is a single large E2E project that covers the entire scope of the application. In these scenarios, the full benefits of an affected graph cannot be realized.
In this guide, we'll explore three techniques to speed up your CI by splitting these lengthy test tasks.
{% toc /%}
## Built-in Test Sharding
One of the simplest ways to split long-running tests is by using built-in test sharding features available in popular testing frameworks like **Jest** and **Playwright**. These tools allow you to divide your test suite into multiple shards that can be executed in parallel, reducing the perceived test execution time.
In **Jest** we can utilize the new `--shard` option to split your test suite. The example below shows splitting into 4 shards.
```shell
nx affected -t test -- --shard=1/4
nx affected -t test -- --shard=2/4
nx affected -t test -- --shard=3/4
nx affected -t test -- --shard=4/4
```
**Playwright** also supports the `--shard` option:
```shell
nx affected -t e2e -- --shard=1/4
nx affected -t e2e -- --shard=2/4
nx affected -t e2e -- --shard=3/4
nx affected -t e2e -- --shard=4/4
```
Now that we have our tests sharded, we can distribute the test load and achieve faster feedback. But what about the test runners that don't support sharding?
## Nx Atomizer
{% youtube
src="https://youtu.be/0YxcxIR7QU0"
title="10x Faster e2e Tests!"
width="100%" /%}
For more granular control over test distribution, Nx offers the [Atomizer](/ci/features/split-e2e-tasks). This feature allows you to split tasks per file. This splitting further allows us to distribute long-running tasks across a larger number of agents, providing detailed insights into flaky tests and enabling automatic re-runs. If one of the flaky tests fails, we will still cache the results of all the other task slices and can even have a successful run if the flaky test re-run succeeded.
![The `nx-e2e` task atomized to 13 e2e sub-tasks](/blog/images/articles/atomized-nx-e2e-ci.avif)
With Atomizer, you can achieve a higher level of parallelism and ensure that only the necessary tests are executed, further optimizing your CI pipeline.
To enable the Atomizer, we need to use supported inferred plugins or create our own.
```json {% fileName="nx.json" %}
{
// ...
"plugins": [
{
"plugin": "@nx/cypress/plugin",
"options": {
"targetName": "e2e",
"ciTargetName": "e2e-ci"
}
},
{
"plugin": "@nx/playwright/plugin",
"options": {
"targetName": "e2e",
"ciTargetName": "e2e-ci"
}
},
{
"plugin": "@nx/jest/plugin",
"options": {
"targetName": "test",
"ciTargetName": "test-ci"
}
},
{
"plugin": "@nx/gradle",
"options": {
"classesTargetName": "classes",
"buildTargetName": "build",
"testTargetName": "test",
"ciTargetName": "test-ci"
}
}
]
}
```
The `test-ci` and `e2e-ci` targets will automatically be split into the following format:
- `e2e-ci--path/to/test/file`
- `test-ci--path/to/test/file`
Or more generically:
- `{ciTargetName}--{path/to/test/file}`
You can find more information on how to configure the Atomizer on the respective [Jest](/nx-api/jest#splitting-e2e-tests), [Cypress](/nx-api/cypress#nxcypress-configuration), [Playwright](/nx-api/playwright#nxplaywright-configuration), [Gradle](/nx-api/gradle/documents/overview#nxgradle-configuration) or follow [this recipe](/extending-nx/recipes/project-graph-plugins) to create your own inferred plugin.
## Manual E2E Project Splitting
In addition to automated splitting like sharding or atomization, manually splitting E2E projects into scopes can provide additional significant performance benefits.
Let's look at the simplified graph below:
![Nx graph with single application, e2e project and several libraries](/blog/images/articles/single-e2e-project.avif)
Our E2E project contains tests for each of the application features - products, orders and checkout. Any change made in the graph will cause all our E2E tests to be re-run. Even if we only modified `products`, we will still re-run the tests for `orders` and `checkout`. Although the Atomizer will help us split that work per file and distribute it, we will still end up running unnecessary work.
By defining scopes that implicitly depend on feature libraries rather than the entire application, you can ensure that only relevant tests are run when changes are made.
- **Scope Definition**: Break down your E2E tests into smaller, focused scopes.
- **Dependency Management**: Ensure that scopes depend on specific feature libraries, reducing unnecessary test execution.
![Nx graph with several e2e applications depending on different scopes of the application](/blog/images/articles/manually-split-e2e-projects.avif)
This approach offers both speed of distribution and caching efficiency. Every time the application is affected, we will only run the small subset of sanity smoke tests to ensure the application still runs, but specific features will only be tested if the relevant feature library has been modified or affected and skipped otherwise.
The tricky part comes from the fact that our split E2E applications still depend on the full application being served. But using the combination of `implicitDependencies` and `dependsOn` we can ensure that the application is running for our E2E tests without explicitly depending on it.
```json {% fileName="libs/checkout-e2e/project.json" %}
{
...
"implicitDependencies": ["checkout"],
"targets": {
"e2e": {
"dependsOn": ["^build", { "target": "build", "projects": "app" }]
}
}
}
```
When we look at the graph, we will only see an edge from `checkout-e2e` to `checkout`, but having an explicit `dependsOn` `app:build` ensures that the build of the application was successful and the distributed agent running our E2E task has app's build cache replayed.
As of Nx version `20.8.0` you can now combine manual splitting with the Atomizer. In order to split atomized projects, we will have to override their `dependsOn` property to target also `app:build`:
```json {% fileName="libs/checkout-e2e/project.json" %}
{
...
"implicitDependencies": ["checkout"],
"targets": {
"e2e": {
"dependsOn": ["^build", { "target": "build", "projects": "app" }]
},
"e2e-ci--**/**": {
"dependsOn": ["^build", { "target": "build", "projects": "app" }]
}
}
}
```
This small improvement gives us the best of both worlds - using the Atomizer to automatically split long running tasks into smaller chunks and using manual splitting to skip entire work if dependencies haven't changed.
## Conclusion
By implementing these techniques — the built-in test sharding, Nx Atomizer, and manual E2E project splitting — you can significantly cut down CI time. That means fewer bottlenecks, less time waiting on pipelines, and more time spent delivering features, fixing bugs, and improving the product. When CI runs faster, teams can iterate quickly, merge with confidence, and ship value to users without the drag of slow test cycles.
Faster CI is just the beginning. When combined with Nx Cloud's distributed task execution, these strategies not only bring stability and improved performance but also offer better developer ergonomics and a comprehensive overview of your testing processes. This powerful combination allows your team to ship with greater confidence.
Give these techniques a try and see the difference for yourself.
{% call-to-action title="Ready to go further?" url="/contact/sales?utm_source=nx-blog&utm_medium=blog&utm_campaign=technical-blog&utm_id=040925" icon="nxcloud" description="Let's talk about how Nx Cloud can help you scale with speed." /%}
@@ -0,0 +1,20 @@
---
title: 'Are Monorepos the Answer to Better AI-Assisted Development?'
description: 'In this webinar, Nx CTO Victor Savkin and Senior Engineer Max Kless will break down **why monorepos are inherently more AI-friendly**, giving LLMs the full context they need to generate more accurate, actionable insights. Youll also learn how Nx provides deep architectural awareness, making AI tools smarter and more effective.'
date: 2025-04-16
slug: 'are-monorepos-the-answer-to-better-aiassisted-development'
authors: ['Victor Savkin', 'Max Kless']
tags: [webinar]
cover_image: /blog/images/2025-04-30/April-2025-Webinar-Card.png
time: 10:30am ET/2:30pm UTC
status: Upcoming
registrationUrl: https://go.nx.dev/april2025-webinar
---
**Apr 30, 2025 - 10:30am ET/2:30pm UTC**
Presented by Victor Savkin and Max Kless
In this webinar, Nx CTO Victor Savkin and Senior Engineer Max Kless will break down **why monorepos are inherently more AI-friendly**, giving LLMs the full context they need to generate more accurate, actionable insights. Youll also learn how Nx provides deep architectural awareness, making AI tools smarter and more effective.
{% call-to-action title="Register today!" url="https://go.nx.dev/april2025-webinar" description="Save your spot" /%}
Binary file not shown.

After

Width:  |  Height:  |  Size: 125 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 281 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 584 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 49 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 103 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 92 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 101 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 163 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 67 KiB

Binary file not shown.
Binary file not shown.
Binary file not shown.
+64
View File
@@ -1542,6 +1542,14 @@
"children": [],
"disableCollapsible": false
},
{
"name": "Getting Started",
"path": "/recipes/angular/rspack/getting-started",
"id": "getting-started",
"isExternal": false,
"children": [],
"disableCollapsible": false
},
{
"name": "Migrate from Angular Webpack",
"path": "/recipes/angular/rspack/migrate-from-webpack",
@@ -1557,6 +1565,14 @@
"isExternal": false,
"children": [],
"disableCollapsible": false
},
{
"name": "Internationalization (i18n)",
"path": "/recipes/angular/rspack/internationalization",
"id": "internationalization",
"isExternal": false,
"children": [],
"disableCollapsible": false
}
],
"disableCollapsible": false
@@ -3020,6 +3036,14 @@
"children": [],
"disableCollapsible": false
},
{
"name": "Getting Started",
"path": "/recipes/angular/rspack/getting-started",
"id": "getting-started",
"isExternal": false,
"children": [],
"disableCollapsible": false
},
{
"name": "Migrate from Angular Webpack",
"path": "/recipes/angular/rspack/migrate-from-webpack",
@@ -3035,6 +3059,14 @@
"isExternal": false,
"children": [],
"disableCollapsible": false
},
{
"name": "Internationalization (i18n)",
"path": "/recipes/angular/rspack/internationalization",
"id": "internationalization",
"isExternal": false,
"children": [],
"disableCollapsible": false
}
],
"disableCollapsible": false
@@ -3121,6 +3153,14 @@
"children": [],
"disableCollapsible": false
},
{
"name": "Getting Started",
"path": "/recipes/angular/rspack/getting-started",
"id": "getting-started",
"isExternal": false,
"children": [],
"disableCollapsible": false
},
{
"name": "Migrate from Angular Webpack",
"path": "/recipes/angular/rspack/migrate-from-webpack",
@@ -3136,6 +3176,14 @@
"isExternal": false,
"children": [],
"disableCollapsible": false
},
{
"name": "Internationalization (i18n)",
"path": "/recipes/angular/rspack/internationalization",
"id": "internationalization",
"isExternal": false,
"children": [],
"disableCollapsible": false
}
],
"disableCollapsible": false
@@ -3148,6 +3196,14 @@
"children": [],
"disableCollapsible": false
},
{
"name": "Getting Started",
"path": "/recipes/angular/rspack/getting-started",
"id": "getting-started",
"isExternal": false,
"children": [],
"disableCollapsible": false
},
{
"name": "Migrate from Angular Webpack",
"path": "/recipes/angular/rspack/migrate-from-webpack",
@@ -3164,6 +3220,14 @@
"children": [],
"disableCollapsible": false
},
{
"name": "Internationalization (i18n)",
"path": "/recipes/angular/rspack/internationalization",
"id": "internationalization",
"isExternal": false,
"children": [],
"disableCollapsible": false
},
{
"name": "Migration",
"path": "/recipes/angular/migration",
+10
View File
@@ -444,6 +444,16 @@
}
},
"migrations": {
"/nx-api/angular/migrations/20.8.1-package-updates": {
"description": "",
"file": "generated/packages/angular/migrations/20.8.1-package-updates.json",
"hidden": false,
"name": "20.8.1-package-updates",
"version": "20.8.1-beta.0",
"originalFilePath": "/packages/angular",
"path": "/nx-api/angular/migrations/20.8.1-package-updates",
"type": "migration"
},
"/nx-api/angular/migrations/20.5.0-angular-eslint-package-updates": {
"description": "",
"file": "generated/packages/angular/migrations/20.5.0-angular-eslint-package-updates.json",
+88
View File
@@ -2111,6 +2111,17 @@
"path": "/recipes/angular/rspack/introduction",
"tags": ["introduction"]
},
{
"id": "getting-started",
"name": "Getting Started",
"description": "",
"mediaImage": "",
"file": "shared/guides/angular-rspack/getting-started",
"itemList": [],
"isExternal": false,
"path": "/recipes/angular/rspack/getting-started",
"tags": ["getting-started", "angular", "rspack", "setup"]
},
{
"id": "migrate-from-webpack",
"name": "Migrate from Angular Webpack",
@@ -2132,6 +2143,17 @@
"isExternal": false,
"path": "/recipes/angular/rspack/handling-configurations",
"tags": ["handling-configurations", "configurations"]
},
{
"id": "internationalization",
"name": "Internationalization (i18n)",
"description": "",
"mediaImage": "",
"file": "shared/guides/angular-rspack/internationalization",
"itemList": [],
"isExternal": false,
"path": "/recipes/angular/rspack/internationalization",
"tags": ["internationalization", "i18n"]
}
],
"isExternal": false,
@@ -4137,6 +4159,17 @@
"path": "/recipes/angular/rspack/introduction",
"tags": ["introduction"]
},
{
"id": "getting-started",
"name": "Getting Started",
"description": "",
"mediaImage": "",
"file": "shared/guides/angular-rspack/getting-started",
"itemList": [],
"isExternal": false,
"path": "/recipes/angular/rspack/getting-started",
"tags": ["getting-started", "angular", "rspack", "setup"]
},
{
"id": "migrate-from-webpack",
"name": "Migrate from Angular Webpack",
@@ -4158,6 +4191,17 @@
"isExternal": false,
"path": "/recipes/angular/rspack/handling-configurations",
"tags": ["handling-configurations", "configurations"]
},
{
"id": "internationalization",
"name": "Internationalization (i18n)",
"description": "",
"mediaImage": "",
"file": "shared/guides/angular-rspack/internationalization",
"itemList": [],
"isExternal": false,
"path": "/recipes/angular/rspack/internationalization",
"tags": ["internationalization", "i18n"]
}
],
"isExternal": false,
@@ -4276,6 +4320,17 @@
"path": "/recipes/angular/rspack/introduction",
"tags": ["introduction"]
},
{
"id": "getting-started",
"name": "Getting Started",
"description": "",
"mediaImage": "",
"file": "shared/guides/angular-rspack/getting-started",
"itemList": [],
"isExternal": false,
"path": "/recipes/angular/rspack/getting-started",
"tags": ["getting-started", "angular", "rspack", "setup"]
},
{
"id": "migrate-from-webpack",
"name": "Migrate from Angular Webpack",
@@ -4297,6 +4352,17 @@
"isExternal": false,
"path": "/recipes/angular/rspack/handling-configurations",
"tags": ["handling-configurations", "configurations"]
},
{
"id": "internationalization",
"name": "Internationalization (i18n)",
"description": "",
"mediaImage": "",
"file": "shared/guides/angular-rspack/internationalization",
"itemList": [],
"isExternal": false,
"path": "/recipes/angular/rspack/internationalization",
"tags": ["internationalization", "i18n"]
}
],
"isExternal": false,
@@ -4314,6 +4380,17 @@
"path": "/recipes/angular/rspack/introduction",
"tags": ["introduction"]
},
"/recipes/angular/rspack/getting-started": {
"id": "getting-started",
"name": "Getting Started",
"description": "",
"mediaImage": "",
"file": "shared/guides/angular-rspack/getting-started",
"itemList": [],
"isExternal": false,
"path": "/recipes/angular/rspack/getting-started",
"tags": ["getting-started", "angular", "rspack", "setup"]
},
"/recipes/angular/rspack/migrate-from-webpack": {
"id": "migrate-from-webpack",
"name": "Migrate from Angular Webpack",
@@ -4336,6 +4413,17 @@
"path": "/recipes/angular/rspack/handling-configurations",
"tags": ["handling-configurations", "configurations"]
},
"/recipes/angular/rspack/internationalization": {
"id": "internationalization",
"name": "Internationalization (i18n)",
"description": "",
"mediaImage": "",
"file": "shared/guides/angular-rspack/internationalization",
"itemList": [],
"isExternal": false,
"path": "/recipes/angular/rspack/internationalization",
"tags": ["internationalization", "i18n"]
},
"/recipes/angular/migration": {
"id": "migration",
"name": "Migration",
+52
View File
@@ -881,6 +881,13 @@
"name": "Faster Builds with Module Federation",
"path": "/concepts/module-federation/faster-builds-with-module-federation"
},
{
"description": "",
"file": "shared/guides/angular-rspack/getting-started",
"id": "getting-started",
"name": "Getting Started",
"path": "/recipes/angular/rspack/getting-started"
},
{
"description": "",
"file": "shared/recipes/module-federation-with-ssr",
@@ -1089,6 +1096,33 @@
"path": "/recipes/angular/rspack/introduction"
}
],
"getting-started": [
{
"description": "",
"file": "shared/guides/angular-rspack/getting-started",
"id": "getting-started",
"name": "Getting Started",
"path": "/recipes/angular/rspack/getting-started"
}
],
"rspack": [
{
"description": "",
"file": "shared/guides/angular-rspack/getting-started",
"id": "getting-started",
"name": "Getting Started",
"path": "/recipes/angular/rspack/getting-started"
}
],
"setup": [
{
"description": "",
"file": "shared/guides/angular-rspack/getting-started",
"id": "getting-started",
"name": "Getting Started",
"path": "/recipes/angular/rspack/getting-started"
}
],
"migrate-from-webpack": [
{
"description": "",
@@ -1116,6 +1150,24 @@
"path": "/recipes/angular/rspack/handling-configurations"
}
],
"internationalization": [
{
"description": "",
"file": "shared/guides/angular-rspack/internationalization",
"id": "internationalization",
"name": "Internationalization (i18n)",
"path": "/recipes/angular/rspack/internationalization"
}
],
"i18n": [
{
"description": "",
"file": "shared/guides/angular-rspack/internationalization",
"id": "internationalization",
"name": "Internationalization (i18n)",
"path": "/recipes/angular/rspack/internationalization"
}
],
"deployment": [
{
"description": "",
+10
View File
@@ -439,6 +439,16 @@
}
],
"migrations": [
{
"description": "",
"file": "generated/packages/angular/migrations/20.8.1-package-updates.json",
"hidden": false,
"name": "20.8.1-package-updates",
"version": "20.8.1-beta.0",
"originalFilePath": "/packages/angular",
"path": "angular/migrations/20.8.1-package-updates",
"type": "migration"
},
{
"description": "",
"file": "generated/packages/angular/migrations/20.5.0-angular-eslint-package-updates.json",
@@ -53,4 +53,5 @@ Below is a reference table that matches versions of [Angular Rspack](/recipes/an
| Angular Rspack | Angular | Nx |
| -------------- | ----------- | ------------------- |
| ~20.7.0 | **~19.2.0** | >= 20.8.1 <= latest |
| ~20.6.0 | **~19.2.0** | >= 20.6.0 <= latest |
@@ -127,12 +127,6 @@
"description": "Create an application with stricter type checking and build optimization options.",
"default": true
},
"standaloneConfig": {
"description": "Split the project configuration into `<projectRoot>/project.json` rather than including it inside `workspace.json`.",
"type": "boolean",
"default": true,
"x-deprecated": "Nx only supports standaloneConfig"
},
"port": {
"type": "number",
"description": "The port at which the remote application should be served."
@@ -141,12 +141,6 @@
"description": "Create an application with stricter type checking and build optimization options.",
"default": true
},
"standaloneConfig": {
"description": "Split the project configuration into `<projectRoot>/project.json` rather than including it inside `workspace.json`.",
"type": "boolean",
"default": true,
"x-deprecated": "Nx only supports standaloneConfig"
},
"setParserOptionsProject": {
"type": "boolean",
"description": "Whether or not to configure the ESLint `parserOptions.project` option. We do not do this by default for lint performance reasons.",
@@ -108,12 +108,6 @@
"enum": ["eslint", "none"],
"default": "eslint"
},
"standaloneConfig": {
"description": "Split the project configuration into `<projectRoot>/project.json` rather than including it inside `workspace.json`.",
"type": "boolean",
"default": true,
"x-deprecated": "Nx only supports standaloneConfig"
},
"compilationMode": {
"description": "Specifies the compilation mode to use. If not specified, it will default to `partial` for publishable libraries and to `full` for buildable libraries. The `full` value can not be used for publishable libraries.",
"type": "string",
@@ -135,12 +135,6 @@
"description": "Create an application with stricter type checking and build optimization options.",
"default": true
},
"standaloneConfig": {
"description": "Split the project configuration into `<projectRoot>/project.json` rather than including it inside `workspace.json`.",
"type": "boolean",
"default": true,
"x-deprecated": "Nx only supports standaloneConfig"
},
"setParserOptionsProject": {
"type": "boolean",
"description": "Whether or not to configure the ESLint `parserOptions.project` option. We do not do this by default for lint performance reasons.",
@@ -0,0 +1,17 @@
{
"name": "20.8.1-package-updates",
"version": "20.8.1-beta.0",
"packages": {
"@nx/angular-rspack": {
"version": "^20.7.0",
"alwaysAddToPackageJson": false
}
},
"aliases": [],
"description": "",
"hidden": false,
"implementation": "",
"path": "/packages/angular",
"schema": null,
"type": "migration"
}
@@ -10,12 +10,12 @@
"type": "object",
"examples": [
{
"command": "nx g lib mylib --directory=myapp",
"description": "Generate `libs/myapp/mylib`"
"command": "nx g @nx/react:lib libs/mylib",
"description": "Generate a library under `libs/mylib`"
},
{
"command": "nx g lib mylib --appProject=myapp",
"description": "Generate a library with routes and add them to `myapp`"
"command": "nx g @nx/react:lib mylib --appProject=myapp",
"description": "Generate a library under mylib with routes and add them to `myapp`"
}
],
"properties": {
@@ -3,14 +3,14 @@
"factory": "./src/generators/convert-to-inferred/convert-to-inferred#convertToInferred",
"schema": {
"$schema": "https://json-schema.org/schema",
"$id": "NxWebpackConvertToInferred",
"description": "Convert existing Webpack project(s) using `@nx/webpack:wepack` executor to use `@nx/webpack/plugin`.",
"title": "Convert a Webpack project from executor to plugin",
"$id": "NxRspackConvertToInferred",
"description": "Convert existing Rspack project(s) using `@nx/rspack:rspack` executor to use `@nx/rspack/plugin`.",
"title": "Convert a Rspack project from executor to plugin",
"type": "object",
"properties": {
"project": {
"type": "string",
"description": "The project to convert from using the `@nx/webpack:webpack` executor to use `@nx/webpack/plugin`. If not provided, all projects using the `@nx/webpack:webpack` executor will be converted.",
"description": "The project to convert from using the `@nx/rspack:rspack` executor to use `@nx/rspack/plugin`. If not provided, all projects using the `@nx/rspack:rspack` executor will be converted.",
"x-priority": "important"
},
"skipFormat": {
@@ -13,11 +13,8 @@ and the version of NodeJS that we tested it against.
| Nx Version | Node Version | Typescript Version |
| --------------- | ---------------- | ------------------ |
| 20.x (latest) | 22.x, 20.x | ~5.4.2 |
| 21.x (next) | 22.x, ^20.19.0, | ~5.4.2 |
| 20.x (latest) | 22.x, 20.x, 18.x | ~5.4.2 |
| 19.x (previous) | 22.x, 20.x, 18.x | ~5.4.2 |
| 18.x | 20.x, 18.x | ~5.4.2 |
| 17.x | 20.x, 18.x | ~5.1.0 |
| 16.x | 20.x, 18.x, 16.x | ~5.1.0 |
| 15.x | 18.x, 16.x, 14.x | ~5.0.0 |
| 14.x | 16.x, 14.x, 12.x | ~4.7.2 |
| 13.x | 14.x, 12.x, 10.x | ~4.6.2 |
+12
View File
@@ -720,6 +720,12 @@
"tags": ["introduction"],
"file": "shared/guides/angular-rspack/introduction"
},
{
"name": "Getting Started",
"id": "getting-started",
"tags": ["getting-started", "angular", "rspack", "setup"],
"file": "shared/guides/angular-rspack/getting-started"
},
{
"name": "Migrate from Angular Webpack",
"id": "migrate-from-webpack",
@@ -731,6 +737,12 @@
"id": "handling-configurations",
"tags": ["handling-configurations", "configurations"],
"file": "shared/guides/angular-rspack/handling-configurations"
},
{
"name": "Internationalization (i18n)",
"id": "internationalization",
"tags": ["internationalization", "i18n"],
"file": "shared/guides/angular-rspack/internationalization"
}
]
},
+1 -1
View File
@@ -165,7 +165,7 @@ configs. Builds can depend on the `.d.ts` files of the compiled libs instead of
After Nx computes the hash for a task, it then checks if it ran this exact computation before. First, it checks locally,
and then if it is missing, and if a remote cache is configured, it checks remotely.
If Nx finds the computation, Nx retrieves it and replay it. Nx places the right files in the right folders and prints
If Nx finds the computation, Nx retrieves it and replays it. Nx places the right files in the right folders and prints
the terminal output. So from the user's point of view, the command ran the same, just a lot faster.
![cache](/shared/mental-model/cache.svg)
@@ -48,7 +48,7 @@ The configuration for package manager workspaces varies based on which package m
```json {% fileName="package.json" %}
{
"workspaces": ["apps/**", "packages/**"]
"workspaces": ["apps/*", "packages/*"]
}
```
@@ -69,7 +69,7 @@ If you want to reference a local library project with its own `build` task, you
```json {% fileName="package.json" %}
{
"workspaces": ["apps/**", "packages/**"]
"workspaces": ["apps/*", "packages/*"]
}
```
@@ -90,7 +90,7 @@ If you want to reference a local library project with its own `build` task, you
```json {% fileName="package.json" %}
{
"workspaces": ["apps/**", "packages/**"]
"workspaces": ["apps/*", "packages/*"]
}
```
@@ -111,8 +111,8 @@ If you want to reference a local library project with its own `build` task, you
```yaml {% fileName="pnpm-workspace.yaml" %}
packages:
- 'apps/**'
- 'packages/**'
- 'apps/*'
- 'packages/*'
```
Defining the `packages` property in the root `pnpm-workspaces.yaml` file lets pnpm know to look for project `package.json` files in the specified folders. With this configuration in place, all the dependencies for the individual projects will be installed in the root `node_modules` folder when `pnpm install` is run in the root folder.
@@ -1,7 +1,7 @@
---
title: Automate Updating Dependencies
description: Learn how to use Nx migrate to automatically update package dependencies, configuration files, and source code to match new package versions.
keywords: [update]
keywords: [update, migrate]
---
# Automate Updating Dependencies
@@ -0,0 +1,132 @@
---
title: 'Getting Started - Angular Rspack'
description: 'Learn how to get started with Angular Rspack applications in Nx.'
---
# Getting Started
This guide will walk you through setting up a new Angular Rspack application in Nx. By the end of this guide, you will have a new Angular application with Rspack configured.
There are two paths you can follow to get started with Angular Rspack in Nx:
1. Create a new Nx Workspace with preconfigured Angular Rspack application
2. Add an existing Angular Rspack application to an Nx Workspace
## Create a new Nx Workspace with preconfigured Angular Rspack application
To create a new Nx Workspace with a preconfigured Angular Rspack application, run the following command:
{% tabs %}
{% tab label="Client-Side Rendering (CSR)" %}
```{% command="npx create-nx-workspace myorg" path="~/" %} {% highlightLines=[7,9] %}
NX Let's create a new workspace [[https://nx.dev/getting-started/intro](https://nx.dev/getting-started/intro)]
✔ Which stack do you want to use? · angular
✔ Integrated monorepo, or standalone project? · integrated
✔ Application name · myorg
✔ Which bundler would you like to use? · rspack
✔ Default stylesheet format · css
✔ Do you want to enable Server-Side Rendering (SSR)? · No
✔ Which unit test runner would you like to use? · vitest
✔ Test runner to use for end to end (E2E) tests · playwright
NX Creating your v20.8.0 workspace.
```
{%/tab %}
{% tab label="Server-Side Rendering (SSR)" %}
```{% command="npx create-nx-workspace myorg" path="~/" %} {% highlightLines=[7,9] %}
NX Let's create a new workspace [[https://nx.dev/getting-started/intro](https://nx.dev/getting-started/intro)]
✔ Which stack do you want to use? · angular
✔ Integrated monorepo, or standalone project? · integrated
✔ Application name · myorg
✔ Which bundler would you like to use? · rspack
✔ Default stylesheet format · css
✔ Do you want to enable Server-Side Rendering (SSR)? · Yes
✔ Which unit test runner would you like to use? · vitest
✔ Test runner to use for end to end (E2E) tests · playwright
NX Creating your v20.8.0 workspace.
```
{% /tab %}
{% /tabs %}
This command will create a new Nx Workspace with an Angular Rspack application in the `myorg` directory.
## Add an existing Angular Rspack application to an Nx Workspace
To add an existing Angular Rspack application to an Nx Workspace, run the following command:
{% callout type="info" title="Minimum Nx Version" %}
The minimum Nx version required to add an Angular Rspack application to an Nx Workspace is `20.6.1`.
If you are using an older version of Nx, run `npx nx migrate` to migrate your workspace to the latest version.
You can learn more about Nx migrations [here](/features/automate-updating-dependencies).
{% /callout %}
{% tabs %}
{% tab label="Client-Side Rendering (CSR)" %}
```bash
npx nx g @nx/angular:app myapp --bundler=rspack
```
{% /tab %}
{% tab label="Server-Side Rendering (SSR)" %}
```bash
npx nx g @nx/angular:app myapp --bundler=rspack --ssr
```
{% /tab %}
{% /tabs %}
This command will add an Angular Rspack application to the `myapp` directory.
## Working with the Angular Rspack application
After generating the application, you will notice the following:
- A `rspack.config.ts` file in the root of the project
- The `project.json` file does not have a `targets.build` or `targets.serve` target
The `rspack.config.ts` file is a configuration file for Rspack. It contains the configuration options for Rspack and for Angular Rspack a helper [createConfig](/nx-api/angular-rspack/documents/create-config)
function is used to map the options you would expect to set in the `project.json` or `angular.json` files to the Rspack configuration.
The `project.json` file does not contain the `targets.build` or `targets.serve` targets because Angular Rspack uses Nx's [Inferred Tasks](concepts/inferred-tasks) to build and serve your application with Rspack.
## Building your Angular Rspack application
To build your Angular Rspack application, run the following command:
```bash
npx nx build myapp
```
This command will build your Angular Rspack application and output the results to the `dist/browser` directory.
If you are using the Angular Rspack application with Server-Side Rendering (SSR), the `dist/server` directory will contain the server files. The same `nx build` command will build both the client and server files.
## Serving your Angular Rspack application
To serve your Angular Rspack application, run the following command:
```bash
npx nx serve myapp
```
This command will serve your Angular Rspack application.
For Client-Side Rendering (CSR) applications, the default port is `4200`. You can visit the application by navigating to `http://localhost:4200` in your browser.
For Server-Side Rendering (SSR) applications, the default port is `4000`. You can visit the application by navigating to `http://localhost:4000` in your browser.
HMR is enabled by default so you can make changes to your application and see the changes in real-time.
@@ -0,0 +1,88 @@
---
title: 'Build-time Internationalization (i18n) with Angular Rspack'
description: "Guide on how to use Angular's build-time i18n with Angular Rspack"
---
# Build-time Internationalization (i18n) with Angular Rspack
Angular Rspack supports Angular's [build-time i18n](https://angular.dev/guide/i18n) out of the box. This guide will walk you through how to use it.
You can follow the steps completely, just make sure to place any changes to `angular.json` in your project's `project.json` file. Some of these changes may also need to be made to the `rspack.config` file.
The steps below indicate where to make these changes.
The process of building an Angular Rspack application with i18n is similar to building an Angular application with i18n and reuses most of the same steps and configuration.
## Prerequisites
- `@angular/localize` must be installed in your project.
- You must have an `i18n` configuration in your `project.json` file.
It is assumed you have an `i18n` property in your `project.json` file that looks like this:
```json {% highlightLines=["3-10"] %}
{
"name": "my-app",
"i18n": {
"sourceLocale": "en-GB",
"locales": {
"fr": {
"translation": "src/locale/messages.fr.xlf"
}
}
},
"targets": {
"extract-i18n": {}
}
}
```
{% callout type="note" title="Extracting i18n messages" %}
The `extract-i18n` target found in Angular projects will still be used to extract the i18n messages into XLIFF (or chosen format) files.
You simply need to run `nx extract-i18n my-app` to extract the messages.
{% /callout %}
## Step 1: Configure the Rspack Configuration
To enable i18n, you need to add the following configuration to your `rspack.config` file:
```js {% highlightLines=[7,15] %}
export default createConfig(
{
options: {
root: __dirname,
polyfills: [
'zone.js',
'@angular/localize/init',
],
...,
},
},
{
production: {
options: {
localize: true,
},
},
}
);
```
## Step 2: Run the build
After configuring the Rspack configuration, you can run the build with the following command:
```bash
npx nx build my-app
```
It will output bundles in the `dist` directory with the following structure:
```text
dist
├── browser
│ ├── [localeCode]
│ │ ├── main.js
│ │ ├── main.js.map
│ │ ├── index.html
│ │ ├── styles.css
│ │ ├── ...
```
@@ -1,5 +1,5 @@
---
title: 'Introduction - Angular Rspack and Rsbuild'
title: 'Introduction - Angular Rspack'
description: 'Learn how Rspack can help you speed up your Angular applications.'
---
@@ -17,18 +17,16 @@ This succeeded in reducing the build times for Angular applications, however, it
---
## Rspack and Rsbuild
## Rspack
The solution to this problem was to create a new build pipeline that would be able to leverage the existing Webpack ecosystem and plugins, while also providing faster builds for Angular applications.
This is where [Rspack](https://rspack.dev) and [Rsbuild](https://rsbuild.dev) come into play.
This is where [Rspack](https://rspack.dev) come into play.
Rspack is a high performance JavaScript bundler written in Rust. It offers strong compatibility with the Webpack ecosystem, allowing for almost seamless replacement of webpack, and provides lightning fast build speeds.
Because it supports the existing Webpack ecosystem, it provides an answer to teams that maintain Angular applications using Webpack and want to migrate to a faster build pipeline.
Rsbuild is a build tool based on Rspack, however it does not support the Webpack ecosystem. It does provide out-of-the-box (OOTB) Module Federation support and a plugin system for extending the build with build speeds comparable to Esbuild.
This makes it a great solution for teams that want to migrate to a faster build pipeline, but still want the ability to easily extend their builds and use [Module Federation](https://module-federation.io).
{% callout type="warning" title="Angular Rspack Status" %}
@@ -42,7 +40,6 @@ Please not that Angular Rspack support is still experimental and is not yet cons
The following are known limitations and missing features of Angular Rspack:
- Static Site Generation (SSG) is not supported.
- Angular's built-in support for Internationalization (i18n) is not supported.
- Server Routing is not supported - still experimental in Angular currently.
- App Engine APIs are not supported - still experimental in Angular currently.
- Optimization is not currently 1:1 with Angular's optimization - however, there are still great optimizations that are made.
@@ -69,7 +66,6 @@ Below is a table of benchmarks for different bundlers, tested on an application
| ------------- | ------------ | -------- | ------- |
| Webpack | 198.614 | 154.339 | 159.436 |
| esbuild | 23.701 | 19.569 | 15.358 |
| Rsbuild | 23.949 | 20.490 | 18.209 |
| Rspack | 30.589 | 19.269 | 19.940 |
You can find the benchmarks and run them yourself: [https://github.com/nrwl/ng-bundler-benchmark](https://github.com/nrwl/ng-bundler-benchmark)
+1 -1
View File
@@ -173,4 +173,4 @@ Now if we serve or app and navigate to `https://localhost:4200/contact` we will
You can find an example of an Nx Workspace using React Router by clicking below
{% github-repository url="<https://github.com/nrwl/nx-recipes/tree/main/react-router>" /%}
{% github-repository url="https://github.com/nrwl/nx-recipes/tree/main/react-router" /%}
+1 -4
View File
@@ -21,10 +21,7 @@ an existing NPM/Yarn or PNPM-based monorepo setup, you can easily add Nx to get
This is a low-impact operation because all that needs to be done is to install the `nx` package at the root level and
add an `nx.json` for configuring caching and task pipelines.
{% youtube
src="https://www.youtube.com/embed/ngdoUQBvAjo"
title="Add Nx to a PNPM workspaces monorepo"
width="100%" /%}
{% course-video src="https://youtu.be/3hW53b1IJ84" courseTitle="From PNPM Workspaces to Distributed CI" courseUrl="/courses/pnpm-nx-next/lessons-01-nx-init" title="Initialize Nx in Your Project with nx init" /%}
## Installing Nx
@@ -53,4 +53,5 @@ Below is a reference table that matches versions of [Angular Rspack](/recipes/an
| Angular Rspack | Angular | Nx |
| -------------- | ----------- | ------------------- |
| ~20.7.0 | **~19.2.0** | >= 20.8.1 <= latest |
| ~20.6.0 | **~19.2.0** | >= 20.6.0 <= latest |
@@ -13,11 +13,8 @@ and the version of NodeJS that we tested it against.
| Nx Version | Node Version | Typescript Version |
| --------------- | ---------------- | ------------------ |
| 20.x (latest) | 22.x, 20.x | ~5.4.2 |
| 21.x (next) | 22.x, ^20.19.0, | ~5.4.2 |
| 20.x (latest) | 22.x, 20.x, 18.x | ~5.4.2 |
| 19.x (previous) | 22.x, 20.x, 18.x | ~5.4.2 |
| 18.x | 20.x, 18.x | ~5.4.2 |
| 17.x | 20.x, 18.x | ~5.1.0 |
| 16.x | 20.x, 18.x, 16.x | ~5.1.0 |
| 15.x | 18.x, 16.x, 14.x | ~5.0.0 |
| 14.x | 16.x, 14.x, 12.x | ~4.7.2 |
| 13.x | 14.x, 12.x, 10.x | ~4.6.2 |
+8 -6
View File
@@ -76,12 +76,6 @@ This generates the following files:
}
```
```json {% fileName=".nx-dotnet.rc.json" %}
{
"nugetPackages": {}
}
```
```xml {% fileName="Directory.Build.props" %}
<!--
This file is imported early in the build order.
@@ -120,6 +114,14 @@ This generates the following files:
</Project>
```
And on Nx versions earlier than 17:
```json {% fileName=".nx-dotnet.rc.json" %}
{
"nugetPackages": {}
}
```
## Create an Application
Use the `app` generator to create a new .NET app. For this demo, use the `nx` path naming convention and the `web-api` project template.
+2
View File
@@ -112,8 +112,10 @@
- [Angular](/recipes/angular)
- [Angular Rspack](/recipes/angular/rspack)
- [Introduction](/recipes/angular/rspack/introduction)
- [Getting Started](/recipes/angular/rspack/getting-started)
- [Migrate from Angular Webpack](/recipes/angular/rspack/migrate-from-webpack)
- [Handling Configurations](/recipes/angular/rspack/handling-configurations)
- [Internationalization (i18n)](/recipes/angular/rspack/internationalization)
- [Migration](/recipes/angular/migration)
- [Migrating from Angular CLI](/recipes/angular/migration/angular)
- [Migrating From Multiple Angular CLI Repos](/recipes/angular/migration/angular-multiple)
+1 -1
View File
@@ -42,7 +42,7 @@ describe('Gradle', () => {
);
});
it('should track dependencies for new app', () => {
xit('should track dependencies for new app', () => {
if (type === 'groovy') {
createFile(
`app2/build.gradle`,
@@ -13,17 +13,13 @@ import {
expect.addSnapshotSerializer({
serialize(str: string) {
return (
str
// Not all package managers print the package.json path in the output
.replace(tmpProjPath(), '')
.replace('/private', '')
.replace('/packages/package-1', '')
// We trim each line to reduce the chances of snapshot flakiness
.split('\n')
.map((r) => r.trim())
.join('\n')
);
return str
.replace(/(\r\n|\n)+/g, '\n')
.replace(/\n\s+/g, '\n')
.replace(/\s+\n/g, '\n')
.replace(tmpProjPath(), '')
.replace('/private', '')
.replace('/packages/package-1', '');
},
test(val: string) {
return val != null && typeof val === 'string';
@@ -48,12 +44,9 @@ describe('Lerna Smoke Tests', () => {
.replace(/Running migration.*\n/g, '') // start of individual migration run
.replace(/Ran .* from .*\n .*\n\n/g, '') // end of individual migration run
.replace(/No changes were made\n\n/g, ''); // no changes during individual migration run
expect(result).toMatchInlineSnapshot(`
Lerna No changes were necessary. This workspace is up to date!
`);
expect(result).toContain(
'Lerna No changes were necessary. This workspace is up to date!'
);
}, 1000000);
});
@@ -76,18 +69,12 @@ describe('Lerna Smoke Tests', () => {
.replace('$ echo test-package-1', '> echo test-package-1');
expect(result).toMatchInlineSnapshot(`
> package-1:print-name
> package-1:print-name
> echo test-package-1
test-package-1
Lerna (powered by Nx) Successfully ran target print-name for project package-1
> echo test-package-1
test-package-1
Lerna (powered by Nx) Successfully ran target print-name for project package-1
`);
`);
}, 1000000);
});
});
+1 -1
View File
@@ -1,4 +1,4 @@
{
"extends": ["plugin:@nx/react", "../../.eslintrc.json"],
"ignorePatterns": ["!**/*", "**/.next"]
"ignorePatterns": ["!**/*", "**/.next", "public"]
}
+58
View File
@@ -0,0 +1,58 @@
import { DefaultLayout } from '@nx/nx-dev/ui-common';
import {
CallToAction,
Features,
GettingStarted,
Hero,
} from '@nx/nx-dev/ui-react';
import { NxBenefitsVideo } from '@nx/nx-dev/ui-react';
import type { Metadata } from 'next';
export const metadata: Metadata = {
title: 'Nx For React',
description:
'Add Nx to your React project for distributed task execution, intelligent caching, and affected commands.',
alternates: {
canonical: 'https://nx.dev/react',
},
openGraph: {
url: 'https://nx.dev/react',
title: 'Nx For React',
description:
'Add Nx to your React project for distributed task execution, intelligent caching, and affected commands.',
images: [
{
url: 'https://nx.dev/socials/nx-react-media.png',
width: 800,
height: 421,
alt: 'Nx For React',
type: 'image/jpeg',
},
],
siteName: 'Nx',
type: 'website',
},
};
export default function ReactPage(): JSX.Element {
return (
<DefaultLayout>
<Hero />
<div className="mt-8 scroll-mt-8 lg:mt-16">
<NxBenefitsVideo />
</div>
<div className="mx-auto max-w-7xl px-6 lg:px-8">
<div className="mt-16 scroll-mt-16 lg:mt-32" id="features">
<Features />
</div>
</div>
<div className="mt-16 scroll-mt-16 lg:mt-32">
<GettingStarted />
</div>
<div className="overflow-hidden py-8 sm:py-8">
<CallToAction />
</div>
</DefaultLayout>
);
}
+1 -1
View File
@@ -109,7 +109,7 @@ export default function CustomApp({
</Link>
<Component {...pageProps} />
{/* <LiveStreamNotifier /> */}
{/*<WebinarNotifier />*/}
<WebinarNotifier />
{/* Global Site Tag (gtag.js) - Google Analytics */}
<Script
+44
View File
@@ -0,0 +1,44 @@
import { DefaultLayout } from '@nx/nx-dev/ui-common';
import { Hero, PartnersList } from '@nx/nx-dev/ui-partners';
import { NextSeo } from 'next-seo';
import { useRouter } from 'next/router';
import { contactButton } from '../lib/components/headerCtaConfigs';
export function Partners(): JSX.Element {
const router = useRouter();
return (
<>
<NextSeo
title="Our Partners"
description="Partner"
openGraph={{
url: 'https://nx.dev' + router.asPath,
title: 'Partners',
description: 'Partner ',
images: [
{
url: 'https://nx.dev/socials/nx-media.png',
width: 800,
height: 421,
alt: 'Nx: Smart Monorepos · Fast CI',
type: 'image/jpeg',
},
],
siteName: 'Nx',
type: 'website',
}}
/>
<DefaultLayout headerCTAConfig={[contactButton]}>
<div>
<Hero />
</div>
<div className="mt-16">
<PartnersList />
</div>
</DefaultLayout>
</>
);
}
export default Partners;
+1 -1
View File
@@ -31,7 +31,7 @@ interface BrowseProps {
export async function getStaticProps(): Promise<{ props: BrowseProps }> {
const res = await fetch(
'https://raw.githubusercontent.com/nrwl/nx/master/community/approved-plugins.json'
'https://raw.githubusercontent.com/nrwl/nx/refs/heads/20.8.x/community/approved-plugins.json'
);
const pluginList = await res.json();
Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 625 KiB

+1 -2
View File
@@ -656,7 +656,6 @@ const packagesIndexes = {
'/nest': '/packages/nest',
'/next': '/packages/next',
'/node': '/packages/node',
'/react': '/packages/react',
'/react-native': '/packages/react',
'/rollup': '/packages/rollup',
'/storybook': '/packages/storybook',
@@ -879,7 +878,7 @@ const missingAndCatchAllRedirects = {
// catch all
'/(l|latest|p|previous)/(a|angular|r|react|n|node)/:path*': '/:path*',
'/(l|latest|p|previous)/:path*': '/:path*',
'/(a|angular|r|react|n|node)/:path*': '/:path*',
'/(a|angular|n|node)/:path*': '/:path*',
// Storybook
'/(l|latest)/(r|react)/storybook/overview': '/storybook/overview-react',
'/(l|latest)/(a|angular)/storybook/overview': '/storybook/overview-angular',
+9 -6
View File
@@ -52,21 +52,24 @@ pre,
iframe[src*='youtube'] {
aspect-ratio: 16 / 9;
}
.prose iframe,
.prose img {
.prose iframe:not(.not-prose):not(.not-prose *),
.prose img:not(.not-prose):not(.not-prose *) {
display: block;
margin: 2rem auto;
}
.prose iframe {
.prose iframe:not(.not-prose):not(.not-prose *) {
width: 100%;
max-width: 560px;
}
.prose img {
.prose img:not(.not-prose):not(.not-prose *) {
width: max-content;
}
.prose iframe[src^="https://staging.nx.app"],
.prose iframe[src^="https://nx.app"]
.prose iframe:not(.not-prose):not(.not-prose *)[src^="https://staging.nx.app"],
.prose iframe:not(.not-prose):not(.not-prose *)[src^="https://nx.app"]
{
height: 80vh;
max-width: 100%;
+1 -1
View File
@@ -100,7 +100,7 @@ export function BlogDetails({ post, allPosts }: BlogDetailsProps) {
</div>
{/* Main grid layout */}
<div className="mx-auto max-w-7xl px-4 lg:px-8">
<div className="mx-auto max-w-7xl px-4 lg:px-8" data-content-area>
<div className="relative isolate grid grid-cols-1 gap-8 xl:grid-cols-[200px_minmax(0,1fr)_200px]">
<div className="hidden min-h-full xl:block">
{post.metrics && (
+1
View File
@@ -17,6 +17,7 @@ export * from './lib/tweet';
export * from './lib/typography';
export * from './lib/github-star-widget';
export * from './lib/youtube.component';
export * from './lib/course-video';
export * from './lib/x-icon';
export * from './lib/discord-icon';
export * from './lib/trusted-by';
+48
View File
@@ -0,0 +1,48 @@
import { ButtonLink } from './button';
import { YouTube } from './youtube.component';
export interface CourseVideoProps {
/**
* The YouTube video URL
*/
src: string;
courseTitle: string;
courseUrl: string;
}
export function CourseVideo({
src: videoUrl,
courseTitle,
courseUrl,
}: CourseVideoProps): JSX.Element {
return (
<div className="not-prose mx-auto max-w-4xl">
<div className="overflow-hidden rounded-xl bg-slate-50 shadow-sm ring-1 ring-slate-900/5 dark:bg-slate-800/50 dark:ring-slate-700/50">
<div className="aspect-video w-full">
<YouTube
src={videoUrl}
title={courseTitle}
width="100%"
disableRoundedCorners={true}
/>
</div>
<div className="px-6 py-4">
<div className="flex flex-col items-center gap-3 sm:flex-row sm:items-center sm:justify-between">
<h3 className="text-center text-xl font-medium text-slate-900 sm:text-left dark:text-white">
{courseTitle}
</h3>
<ButtonLink
href={courseUrl}
variant="primary"
size="small"
title={`Watch the full "${courseTitle}" course`}
className="whitespace-nowrap"
>
Watch full course
</ButtonLink>
</div>
</div>
</div>
</div>
);
}
@@ -16,6 +16,7 @@ import {
MicrophoneIcon,
VideoCameraIcon,
CheckBadgeIcon,
LifebuoyIcon,
BookOpenIcon,
} from '@heroicons/react/24/outline';
import { FC, SVGProps } from 'react';
@@ -277,6 +278,14 @@ export const companyItems: MenuItem[] = [
isNew: false,
isHighlight: false,
},
{
name: 'Partners',
description: null,
icon: LifebuoyIcon,
href: '/partners',
isNew: false,
isHighlight: false,
},
];
export const resourceMenuItems = {
@@ -11,7 +11,7 @@ import {
export function WebinarNotifier(): ReactElement | null {
const [isMounted, setIsMounted] = useState(false);
const [isVisible, setIsVisible] = useState<boolean>(true);
const localStorageKey = 'webinar-march-19-2025--notifier-closed';
const localStorageKey = 'webinar-april-30-2025--notifier-closed';
useEffect(() => {
setIsMounted(true);
@@ -61,19 +61,19 @@ export function WebinarNotifier(): ReactElement | null {
aria-hidden="true"
className="size-8 flex-shrink-0"
/>
<span>Join our webinar + live Q&A on March 19th</span>
<span>Join our webinar + live Q&A on April 30th</span>
</motion.h3>
<motion.div key="live-event" className="mt-4 space-y-4">
<p className="mb-2 text-sm">
Join Victor Savkin and Max Kless discussing why LLMs struggle with
Join Victor Savkin and Max Kless discuss why LLMs struggle with
fragmented codebases, how monorepos + Nx create AI-powered
architectural decisions, the before-and-after experience of
architectural decisions, and the before-and-after experience of
AI-powered coding in Nx.
</p>
<div className="flex flex-wrap items-center justify-end gap-1 sm:gap-4">
<a
title="Signup"
href="https://bit.ly/3XvOwIl"
href="https://bit.ly/42dwGwm"
target="_blank"
rel="noopener noreferrer"
className="inline-flex items-center justify-center gap-2 rounded-lg bg-pink-600 px-2 py-2 text-sm font-semibold text-white transition hover:bg-pink-700 focus:outline-none focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-blue-500 active:text-black/70 md:px-4"
+5
View File
@@ -107,6 +107,11 @@ const teamMembers = [
title: 'Developer Productivity Engineer',
imageUrl: 'jordan-powell.avif',
},
{
name: 'Josh VanAllen',
title: 'Developer Productivity Engineer',
imageUrl: 'josh-vanallen.avif',
},
{
name: 'Juri Strumpflohner',
title: 'Director of Developer Experience',
+18 -18
View File
@@ -25,24 +25,24 @@ export function Hero(): ReactElement {
<div className="absolute inset-0">
<div className="mx-auto max-w-7xl lg:flex">
<div className="mx-auto max-w-3xl px-6 pb-24 pt-36 lg:mx-0 lg:shrink-0 lg:px-8">
{/*<p>*/}
{/* <a*/}
{/* href="https://bit.ly/3XvOwIl"*/}
{/* title="See live event in details"*/}
{/* className="group/event-link inline-flex space-x-6"*/}
{/* >*/}
{/* <span className="rounded-full bg-blue-600/10 px-3 py-1 text-sm/6 font-semibold text-blue-600 ring-1 ring-inset ring-blue-600/10 dark:bg-cyan-600/10 dark:text-cyan-600 dark:ring-cyan-600/10">*/}
{/* Live event*/}
{/* </span>*/}
{/* <span className="inline-flex items-center space-x-2 text-sm/6 font-medium">*/}
{/* <span>Webinar + live Q&A on March 19th</span>*/}
{/* <ChevronRightIcon*/}
{/* aria-hidden="true"*/}
{/* className="size-5 transform transition-all group-hover/event-link:translate-x-1"*/}
{/* />*/}
{/* </span>*/}
{/* </a>*/}
{/*</p>*/}
<p>
<a
href="https://bit.ly/42dwGwm"
title="See live event in details"
className="group/event-link inline-flex space-x-6"
>
<span className="rounded-full bg-blue-600/10 px-3 py-1 text-sm/6 font-semibold text-blue-600 ring-1 ring-inset ring-blue-600/10 dark:bg-cyan-600/10 dark:text-cyan-600 dark:ring-cyan-600/10">
Live event
</span>
<span className="inline-flex items-center space-x-2 text-sm/6 font-medium">
<span>Webinar + live Q&A on March 19th</span>
<ChevronRightIcon
aria-hidden="true"
className="size-5 transform transition-all group-hover/event-link:translate-x-1"
/>
</span>
</a>
</p>
<SectionHeading
id="get-speed-and-scale"
as="h1"
@@ -61,7 +61,7 @@ export function MakeYourCiFast(): ReactElement {
</div>
</div>
<div className="relative lg:col-span-2">
<div className="relative flex h-full flex-col overflow-hidden rounded-[calc(theme(borderRadius.lg)+1px)] bg-white shadow ring-1 ring-black/5 max-lg:rounded-t-[calc(2rem+1px)] lg:rounded-tr-[calc(2rem+1px)] dark:bg-slate-950 dark:ring-white/10">
<div className="relative flex h-full flex-col overflow-hidden rounded-[calc(theme(borderRadius.lg)+1px)] bg-white shadow ring-1 ring-black/5 lg:rounded-tr-[calc(2rem+1px)] dark:bg-slate-950 dark:ring-white/10">
<img
alt="Nx Atomizer: split large tasks & E2E in chunks"
src="/images/enterprise/nx-atomizer.avif"
@@ -86,7 +86,7 @@ export function MakeYourCiFast(): ReactElement {
</div>
</div>
<div className="relative lg:col-span-3">
<div className="relative flex h-full flex-col overflow-hidden rounded-[calc(theme(borderRadius.lg)+1px)] bg-white shadow ring-1 ring-black/5 max-lg:rounded-b-[calc(2rem+1px)] lg:rounded-bl-[calc(2rem+1px)] dark:bg-slate-950 dark:ring-white/10">
<div className="relative flex h-full flex-col overflow-hidden rounded-[calc(theme(borderRadius.lg)+1px)] bg-white shadow ring-1 ring-black/5 lg:rounded-bl-[calc(2rem+1px)] dark:bg-slate-950 dark:ring-white/10">
<img
alt="Nx Agents: simple & fast task distribution"
src="/images/enterprise/nx-agents.avif"
@@ -111,7 +111,7 @@ export function MakeYourCiFast(): ReactElement {
</div>
</div>
<div className="relative lg:col-span-3">
<div className="relative flex h-full flex-col overflow-hidden rounded-[calc(theme(borderRadius.lg)+1px)] bg-white shadow ring-1 ring-black/5 max-lg:rounded-b-[calc(2rem+1px)] lg:rounded-br-[calc(2rem+1px)] dark:bg-slate-950 dark:ring-white/10">
<div className="relative flex h-full flex-col overflow-hidden rounded-[calc(theme(borderRadius.lg)+1px)] bg-white shadow ring-1 ring-black/5 lg:rounded-br-[calc(2rem+1px)] dark:bg-slate-950 dark:ring-white/10">
<img
alt="Partner with the Nx Team for guidances"
src="/images/enterprise/nx-partnership.avif"
+7
View File
@@ -89,6 +89,13 @@ export * from './lib/others/linux';
export * from './lib/others/min-io';
export * from './lib/others/windows';
// PARTNERS
export * from './lib/partners/bitovi';
export * from './lib/partners/callstack';
export * from './lib/partners/hero-devs';
export * from './lib/partners/push-based';
export * from './lib/partners/e-square';
// PODCASTS
export * from './lib/podcasts/amazon-music';
export * from './lib/podcasts/apple-podcasts';
@@ -0,0 +1,48 @@
import { FC, SVGProps } from 'react';
export const BitoviIcon: FC<SVGProps<SVGSVGElement>> = (props) => {
return (
<svg
width="1272"
height="397"
viewBox="0 0 1272 397"
fill="none"
xmlns="http://www.w3.org/2000/svg"
{...props}
>
<title>Bitovi</title>
<path
d="M87.406 385.527C86.4424 391.273 83.3039 393.357 77.9091 393.32C55.4139 393.167 32.917 393.258 10.4208 393.255C1.76093 393.254 0.0181025 391.5 0.0113125 382.625C-0.00603751 359.962 0.00523942 337.299 0.00511742 314.636C0.00458342 219.152 0.0040498 123.668 0.0036068 28.1845C0.0035918 27.1846 -0.00637256 26.1846 0.00688744 25.185C0.104543 17.8226 2.14118 15.6543 9.58571 15.6058C23.916 15.5125 38.2474 15.5778 52.5783 15.5778C60.9103 15.5778 69.2431 15.503 77.5739 15.6024C84.8338 15.689 87.4207 18.3613 87.4254 25.6629C87.4481 60.4904 87.3857 95.3182 87.54 130.145C87.5511 132.657 89.0509 135.162 89.8585 137.67C92.2244 136.871 94.933 136.567 96.9044 135.2C124.939 115.761 155.716 108.891 188.937 116.633C220.768 124.051 244.974 143.068 262.512 170.264C297.044 223.813 295.456 296.485 257.844 347.394C231.279 383.351 194.665 398.544 150.157 394.369C130.507 392.525 112.933 385.042 96.6719 374.069C94.7105 372.745 91.6686 371.696 89.6425 372.286C88.3999 372.648 87.8856 376.334 87.5093 378.604C87.1599 380.713 87.4276 382.924 87.406 385.527ZM108.285 304.752C132.769 325.36 171.824 319.824 188.727 292.726C202.635 270.429 202.851 246.625 192.671 222.932C176.172 184.533 124.995 182.944 102.668 209.253C89.4364 224.844 85.9239 243.273 87.9011 263.033C89.5104 279.116 95.3948 293.292 108.285 304.752Z"
fill="#F5532D"
/>
<path
d="M629.699 167.355C651.156 140.72 678.108 122.826 711.354 116.664C766.462 106.45 813.511 122.391 849.112 166.069C896.609 224.343 890.251 306.873 835.654 358.532C785.171 406.298 705.295 408.76 651.119 364.218C591.77 315.424 582.209 228.599 629.699 167.355ZM684.417 269.495C684.74 272.969 684.889 276.469 685.415 279.912C689.248 305.009 708.36 323.515 732.832 325.922C759.021 328.498 781.407 314.182 789.903 289.566C794.931 275 793.706 260.397 790.443 245.778C786.588 228.507 779.974 212.47 767.949 199.19C751.287 180.788 728.065 180.062 711.09 198.002C692.5 217.649 684.947 241.857 684.417 269.495Z"
fill="#F5532D"
/>
<path
d="M984.388 190.178C993.296 217.557 1002.07 244.563 1011.03 271.511C1011.71 273.574 1013.65 275.221 1015.01 277.062C1016.24 275.289 1017.97 273.683 1018.62 271.719C1034.3 224.088 1049.86 176.419 1065.44 128.755C1068.04 120.815 1071.36 118.279 1079.63 118.266C1103.62 118.227 1127.62 118.229 1151.61 118.264C1160.38 118.277 1163.64 122.961 1160.59 131.297C1134.15 203.653 1107.81 276.049 1081.12 348.318C1069.65 379.391 1041.84 397.67 1009.11 394.877C979.463 392.346 958.979 375.986 948.681 348.266C921.797 275.897 895.469 203.32 868.967 130.809C866.145 123.09 869.459 118.297 877.573 118.275C901.898 118.211 926.224 118.216 950.549 118.273C958.344 118.291 961.815 121.006 964.337 128.707C971.005 149.064 977.648 169.429 984.388 190.178Z"
fill="#F5532D"
/>
<path
d="M594.444 383.135C571.793 393.691 548.244 396.456 523.964 394.697C510.305 393.707 496.938 391.4 484.111 386.317C455.248 374.881 438.984 353.259 433.578 323.244C431.935 314.126 431.324 304.712 431.301 295.432C431.121 223.117 431.198 150.802 431.203 78.4877C431.203 70.9 432.495 69.1687 439.772 67.3766C462.365 61.8128 484.969 56.2969 507.571 50.7726C514.592 49.0568 518.581 52.0108 518.619 59.25C518.71 76.4118 518.644 93.5744 518.654 110.737C518.658 117.696 519.492 118.56 526.322 118.571C538.819 118.592 551.316 118.536 563.812 118.593C571.731 118.629 574.323 121.227 574.334 129.045C574.361 147.707 574.356 166.369 574.337 185.031C574.329 193.01 571.79 195.587 563.986 195.596C551.323 195.612 538.659 195.586 525.996 195.607C519.475 195.617 518.662 196.387 518.659 202.704C518.642 232.029 518.597 261.355 518.674 290.681C518.717 307.243 527.804 316.506 544.447 317.284C555.081 317.781 565.28 315.657 575.269 312.237C580.117 310.577 582.797 311.565 584.672 316.474C591.259 333.722 600.5 349.372 612.146 363.679C615.559 367.872 614.951 371.283 610.385 374.159C605.335 377.341 600.009 380.088 594.444 383.135Z"
fill="#F5532D"
/>
<path
d="M1240.51 392.339C1209.22 402.427 1179.59 382.213 1178.2 349.809C1177.57 335.17 1177.99 320.485 1177.98 305.821C1177.97 258.157 1177.97 210.494 1177.98 162.831C1177.99 141.594 1187.26 126.032 1206.77 117.269C1233 105.484 1265.23 122.66 1270.39 150.974C1271.04 154.556 1271.39 158.247 1271.39 161.888C1271.45 223.717 1271.46 285.546 1271.42 347.375C1271.41 368.106 1259.88 384.922 1240.51 392.339Z"
fill="#F5532D"
/>
<path
d="M397.323 138.353C401.302 146.1 402.835 153.995 402.83 162.3C402.794 223.8 402.918 285.299 402.765 346.799C402.694 375.263 381.719 395.951 354.298 395.182C330.287 394.509 309.82 374.29 309.537 350.179C309.186 320.183 309.415 290.181 309.408 260.181C309.399 227.015 309.195 193.847 309.488 160.683C309.656 141.569 318.494 127.22 335.611 118.48C356.135 108.001 382.016 115.015 394.781 134.213C395.609 135.458 396.373 136.746 397.323 138.353Z"
fill="#F5532D"
/>
<path
d="M1241.17 90.9424C1214.48 99.9006 1187.73 86.4943 1179.94 60.5506C1172.38 35.4027 1187.39 8.28435 1212.49 1.75332C1236.19 -4.41518 1260.22 8.04123 1268.56 30.8252C1276.92 53.668 1266.74 78.6398 1244.7 89.3489C1243.65 89.8574 1242.59 90.3381 1241.17 90.9424Z"
fill="#F5532D"
/>
<path
d="M329.154 85.4313C313.045 72.7243 306.367 56.4871 310.684 36.7707C314.677 18.531 326.373 6.43183 344.453 1.75066C363.647 -3.21917 380.264 2.46454 392.554 17.8817C404.709 33.1301 406.477 50.4785 397.772 67.9645C388.851 85.8838 373.579 94.3756 353.633 93.9368C344.823 93.743 336.778 90.5303 329.154 85.4313Z"
fill="#F5532D"
/>
</svg>
);
};
@@ -0,0 +1,32 @@
import { FC, SVGProps } from 'react';
export const CallstackIcon: FC<SVGProps<SVGSVGElement>> = (props) => {
return (
<svg
width="599"
height="321"
viewBox="0 0 599 321"
fill="none"
xmlns="http://www.w3.org/2000/svg"
{...props}
>
<title>Callstack</title>
<path
d="M436.051 218.435C444.412 229.58 452.397 240.242 461.7 252.663C450.289 252.663 440.345 251.429 430.826 252.915C409.73 256.21 396.266 248.499 385.38 230.012C373.479 209.8 358.226 191.562 342.632 172.586C342.632 198.878 342.632 225.169 342.632 251.85C325.009 251.85 308.937 251.85 292.372 251.85C292.372 177.634 292.372 103.854 292.372 29.3044C308.665 29.3044 324.949 29.3044 342.375 29.3044C342.375 71.813 342.375 114.496 342.375 157.178C343.047 157.429 343.719 157.679 344.391 157.929C354.275 146.109 364.158 134.29 374.041 122.469C376.59 119.419 379.705 116.679 381.586 113.261C392.185 93.9926 408.342 87.7777 429.561 91.0097C437.776 92.2609 446.34 91.2139 456.796 91.2139C442.239 108.149 429.023 123.542 415.786 138.916C410.043 145.586 404.413 152.363 398.428 158.809C395.285 162.194 395.428 164.683 398.212 168.301C410.856 184.73 423.214 201.381 436.051 218.435Z"
fill="#8232FF"
/>
<path
d="M32.5149 275.682C32.2422 252.21 32.0572 229.486 31.8222 206.762C31.7811 202.79 31.7803 198.792 31.3275 194.855C30.119 184.35 25.4529 179.707 14.9436 178.758C10.4752 178.354 5.93991 178.69 0.883057 178.69C0.883057 166.445 0.883057 154.974 0.883057 143C6.36124 142.651 11.6962 142.603 16.9461 141.911C25.7175 140.754 30.9235 135.604 31.2286 126.663C31.6935 113.043 31.6424 99.4049 31.8432 85.7751C32.044 72.1446 31.6844 58.4723 32.6429 44.894C34.2622 21.9541 49.6399 4.94079 72.5986 1.6259C83.6947 0.0237978 95.2055 1.01754 106.508 1.41226C108.271 1.47383 111.313 4.55301 111.401 6.35272C111.885 16.208 111.632 26.0994 111.632 36.3083C106.521 36.0185 102.348 35.4883 98.1922 35.6004C85.0001 35.9565 78.8475 41.8218 78.6099 55.0519C78.2784 73.5163 78.5159 91.9907 78.4722 110.461C78.4621 114.721 78.4216 118.988 78.185 123.24C77.3077 139.008 73.7735 153.308 54.9731 160.218C74.7588 167.515 77.7758 182.914 78.1854 199.269C78.6761 218.864 78.441 238.478 78.4785 258.083C78.5224 281.036 83.4792 285.751 106.194 284.372C107.568 284.288 108.952 284.361 111.606 284.361C111.606 294.706 111.822 304.817 111.379 314.899C111.311 316.448 108.305 319.015 106.5 319.162C91.503 320.379 76.3836 321.722 61.9143 315.954C44.0755 308.843 34.8875 295.152 32.5149 275.682Z"
fill="#8232FF"
/>
<path
d="M598.512 161.382C598.511 167.271 598.511 172.329 598.511 178.477C594.724 178.477 591.708 178.421 588.694 178.486C572.726 178.831 567.147 184.038 566.79 200.083C566.424 216.549 566.894 233.033 566.612 249.503C566.419 260.818 566.915 272.39 564.731 283.375C560.223 306.051 541.921 319.931 518.945 319.979C510.708 319.996 502.464 319.772 494.236 320.053C488.938 320.235 486.413 318.716 486.658 312.882C487.039 303.845 486.759 294.781 486.759 284.943C491.259 285.238 495.073 285.658 498.892 285.709C513.333 285.902 520.018 279.878 520.285 265.371C520.666 244.643 520.293 223.902 520.558 203.171C520.641 196.678 521.221 190.094 522.494 183.737C524.715 172.65 531.596 165.058 543.664 160.608C523.673 152.918 520.731 136.991 520.526 119.855C520.294 100.543 520.508 81.2262 520.461 61.9116C520.407 39.7837 514.051 34.112 492 36.3261C490.622 36.4645 489.218 36.3441 486.819 36.3441C486.819 26.0766 486.608 15.931 487.037 5.81245C487.104 4.21941 490.058 1.43992 491.691 1.43012C504.103 1.35562 516.851 0.137348 528.86 2.49996C552.46 7.14293 565.926 24.386 566.474 48.4936C566.97 70.3533 566.633 92.2317 566.694 114.102C566.704 117.507 566.652 120.936 567.011 124.313C568.364 137.03 573.457 141.836 586.157 142.455C589.82 142.633 593.499 142.482 598.512 142.482C598.512 148.879 598.512 154.715 598.512 161.382Z"
fill="#8232FF"
/>
<path
d="M257.762 94.8268C266.052 96.7624 268.476 101.34 267.938 109.214C267.166 120.516 267.741 131.91 267.741 144.559C264.816 143.166 262.656 142.228 260.579 141.132C247.549 134.261 233.803 130.325 218.952 130.559C196.499 130.912 178.099 148.782 177.551 170.895C176.968 194.464 194.137 213.44 217.19 214.64C233.51 215.489 248.715 211.657 262.877 203.56C264.765 202.48 266.668 201.426 270.16 199.464C270.16 214.324 270.262 227.785 270.013 241.239C269.986 242.708 268.248 244.773 266.779 245.496C227.852 264.643 169.411 260.915 140.583 219.755C106.843 171.582 131.825 107.256 190.149 91.6546C212.74 85.6117 235.111 86.5895 257.762 94.8268Z"
fill="#8232FF"
/>
</svg>
);
};
@@ -0,0 +1,43 @@
import { FC, SVGProps } from 'react';
export const ESquareIcon: FC<SVGProps<SVGSVGElement>> = (props) => {
return (
<svg
width="1348"
height="117"
viewBox="0 0 1348 117"
fill="none"
xmlns="http://www.w3.org/2000/svg"
{...props}
>
<title>E-Square</title>
<path
fill-rule="evenodd"
clip-rule="evenodd"
d="M0.0397949 2.2313H73.2583V21.3643H21.0526V47.9899H68.7987V67.123H21.0574V94.7069H74.2053V113.84H0.0446265V2.22646L0.0397949 2.2313ZM132.161 82.2629V64.0882H179.269V82.2629H132.161ZM280.023 0C303.901 0 321.247 13.0684 321.247 35.3959V40.1779H300.876V36.8286C300.876 24.0748 292.759 18.4941 280.023 18.4941C268.886 18.4941 262.04 24.0748 262.04 31.7271C262.04 42.2495 271.906 44.1662 285.28 47.1913L286.71 47.5107C309.627 52.6122 323.155 60.7437 323.155 80.9948C323.155 103.477 305.65 116.071 281.936 116.071C254.72 116.071 237.21 101.406 237.21 75.2544V71.7453H257.904V74.6155C257.904 88.3276 265.702 97.5771 282.569 97.5771C296.098 97.5771 302.466 90.3992 302.466 82.108C302.466 72.3842 294.189 69.1945 279.55 66.0049L278.115 65.6854C255.039 60.5839 241.346 52.6171 241.346 32.366C241.346 12.4343 258.377 0 280.023 0ZM590.204 2.22646H611.212V75.2544C611.212 88.8068 619.329 97.2576 633.815 97.2576C648.3 97.2576 656.417 88.8068 656.417 75.2544V2.2313H677.425V74.3009C677.425 99.8084 661.669 116.071 633.815 116.071C605.96 116.071 590.204 99.8084 590.204 74.3009V2.22646ZM756.06 2.22646H789.799L820.678 113.84H799.032L792.345 88.9616H753.513L746.826 113.84H725.181L756.06 2.22646ZM758.446 69.8334H787.412L773.884 19.7671H771.975L758.446 69.8334ZM955.335 37.4675C955.335 54.3692 945.788 66.4841 931.467 70.7918L954.065 113.84H930.825L910.295 72.5439H891.674V113.84H870.666V2.39103H919.688C940.696 2.39103 955.335 16.2628 955.335 37.4675ZM891.674 21.5192V53.406H917.62C927.645 53.406 934.328 47.1865 934.328 37.4626C934.328 27.734 927.645 21.5192 917.615 21.5192H891.669H891.674ZM1009.15 2.22646H1082.36V21.3595H1030.15V47.9851H1077.9V67.1181H1030.15V94.702H1083.31V113.835H1009.15V2.22646Z"
fill="#0F110E"
/>
<path
d="M495.456 2.44971C498.389 2.44971 500.761 4.83105 500.761 7.76417V94.6107H521.914C524.842 94.6107 527.219 96.992 527.219 99.93V111.019C527.219 113.957 524.842 116.333 521.914 116.333H392.31C389.382 116.333 387.005 113.957 387.005 111.019V7.76417C387.005 4.83105 389.382 2.44971 392.31 2.44971H495.456ZM408.607 24.0851V94.7026H479.159V24.0851H408.607Z"
fill="url(#paint0_linear_9_3)"
/>
<path
d="M1138.81 104.344C1138.81 111.314 1144.06 116.425 1150.87 116.425C1157.82 116.425 1162.93 111.314 1162.93 104.344C1162.93 97.3742 1157.82 92.263 1150.87 92.263C1144.06 92.263 1138.81 97.3742 1138.81 104.344ZM1206.29 15.1307C1206.29 21.4809 1211.09 26.1274 1217.43 26.1274C1223.92 26.1274 1228.71 21.4809 1228.71 15.1307C1228.71 8.62553 1223.92 3.979 1217.43 3.979C1211.09 3.979 1206.29 8.62553 1206.29 15.1307ZM1224.69 38.2084H1210.16V114.257H1224.69V38.2084ZM1269.61 76.3099C1269.61 100.007 1286.15 116.425 1308.73 116.425C1331.45 116.425 1348 100.007 1348 76.3099C1348 52.6127 1331.45 36.04 1308.73 36.04C1286.15 36.04 1269.61 52.6127 1269.61 76.3099ZM1284.14 76.3099C1284.14 60.3569 1293.88 49.0503 1308.73 49.0503C1323.72 49.0503 1333.46 60.0471 1333.46 76.3099C1333.46 92.263 1323.72 103.415 1308.73 103.415C1293.88 103.415 1284.14 92.5728 1284.14 76.3099Z"
fill="#0F110E"
/>
<defs>
<linearGradient
id="paint0_linear_9_3"
x1="387.005"
y1="-493.171"
x2="8497.63"
y2="12795.9"
gradientUnits="userSpaceOnUse"
>
<stop stopColor="#272A7F" />
<stop offset="1" stopColor="#35DCD8" />
</linearGradient>
</defs>
</svg>
);
};
@@ -0,0 +1,57 @@
import { FC, SVGProps } from 'react';
export const HeroDevsIcon: FC<SVGProps<SVGSVGElement>> = (props) => {
return (
<svg
width="484"
height="500"
viewBox="0 0 484 500"
fill="none"
xmlns="http://www.w3.org/2000/svg"
{...props}
>
<title>HeroDevs</title>
<g clip-path="url(#clip0_6_102)">
<path
fillRule="evenodd"
clipRule="evenodd"
d="M168.465 193.671C96.0868 172.261 104.27 358.657 188.649 307.589C213 292.848 245.097 271.662 283.516 271.662C318.175 271.662 337.138 309.212 371.797 309.212C421.722 303.779 419.576 209.004 385.85 205.936C350.385 205.936 321.323 265.829 275.427 251.754C235.8 239.604 195.13 201.557 168.465 193.671ZM178.261 163.624C215.231 174.56 247.435 209.939 284.762 221.383C287.8 222.315 290.385 222.337 293.443 221.508C300.588 219.573 308.772 213.546 314.638 209.106C336.291 192.715 356.204 174.493 385.051 174.493H386.495L387.933 174.624C462.26 181.382 461.541 333.617 374.543 343.087L372.827 343.274H370.679C367.931 343.274 365.171 343.193 362.444 342.855C340.063 340.077 324.796 329.948 308.908 318.821C302.583 314.392 291.657 305.994 283.451 305.994C255.029 305.994 229.41 322.751 205.823 337.028C182.609 351.078 155.543 356.167 130.914 342.421C101.852 326.2 89.3382 290.624 88.058 258.549C86.7283 225.261 97.2242 186.159 127.537 168.72C143.279 159.665 161.076 158.541 178.261 163.624Z"
fill="url(#paint0_linear_6_102)"
/>
<path
fillRule="evenodd"
clipRule="evenodd"
d="M241.698 41.3313C-41.5403 22.7742 140.463 40.2031 77.0514 123.994C50.0436 159.711 33.9091 204.522 33.9091 253.367C33.9091 370.468 126.94 465.395 241.698 465.395C326.662 465.395 399.707 413.357 431.911 338.83C451.999 298.895 464.1 240.899 432.259 169.912C400.189 96.65 326.827 46.9144 241.698 41.3313ZM243.874 6.80207C374.211 15.3389 483.405 116.04 483.405 253.367C483.405 389.57 375.177 500 241.698 500C108.228 500 0 389.561 0 253.367C0 198.743 17.4913 146.099 50.2069 102.847C55.0511 96.4452 59.5501 89.514 56.6917 81.377C50.3631 63.3884 36.987 53.7323 45.0175 29.9563C54.9336 0.592672 87.2957 -0.126835 112.399 0.0108551C155.723 0.250703 200.613 3.96831 243.874 6.80207Z"
fill="url(#paint1_linear_6_102)"
/>
</g>
<defs>
<linearGradient
id="paint0_linear_6_102"
x1="87.9473"
y1="262.865"
x2="441.888"
y2="259.733"
gradientUnits="userSpaceOnUse"
>
<stop stopColor="#F926E1" />
<stop offset="1" stopColor="#2AB5FB" />
</linearGradient>
<linearGradient
id="paint1_linear_6_102"
x1="-1.04689e-07"
y1="269.231"
x2="483.483"
y2="267.011"
gradientUnits="userSpaceOnUse"
>
<stop stopColor="#F926E1" />
<stop offset="1" stopColor="#2AB5FB" />
</linearGradient>
<clipPath id="clip0_6_102">
<rect width="484" height="500" fill="white" />
</clipPath>
</defs>
</svg>
);
};
@@ -0,0 +1,24 @@
import { FC, SVGProps } from 'react';
export const PushBasedIcon: FC<SVGProps<SVGSVGElement>> = (props) => {
return (
<svg
width="366"
height="509"
viewBox="0 0 366 509"
fill="none"
xmlns="http://www.w3.org/2000/svg"
{...props}
>
<title>Push Based</title>
<path
d="M129.299 474.655C134.496 449.514 132.497 423.177 136.894 397.637C140.092 378.083 146.489 358.13 159.681 342.168C172.073 327.403 192.461 311.84 207.252 300.666C240.432 275.126 278.01 251.981 303.595 218.061C303.595 218.061 304.394 216.864 304.794 216.465C309.991 208.883 316.387 201.301 320.784 192.92C330.379 174.165 335.176 153.414 335.176 132.663C335.176 49.2598 272.413 0.175781 187.664 0.175781H58.9408C26.5601 0.175781 0.175903 26.5136 0.175903 58.8372V449.514C0.175903 481.838 26.5601 508.176 58.9408 508.176H96.5184C116.107 508.176 125.701 491.814 129.299 474.655Z"
fill="#2D0064"
/>
<path
d="M365.176 388.788C365.176 427.788 349.59 458.829 323.614 480.319C322.415 481.115 321.216 482.308 320.416 483.104C298.436 499.819 271.261 508.176 243.286 508.176H144.176C152.568 502.206 157.364 492.257 159.362 481.91C164.558 458.033 162.559 433.359 166.955 409.482C170.152 390.778 176.547 372.074 189.735 357.349C202.123 343.421 222.505 328.696 237.292 318.349C240.888 315.962 244.086 313.176 247.682 310.788C264.467 298.849 282.451 287.308 298.436 274.176C311.225 284.523 323.214 295.666 333.205 308.4C333.205 308.4 334.004 309.594 334.404 309.992C339.599 317.155 345.993 324.319 350.389 332.278C359.981 349.39 364.776 369.288 364.776 388.788H365.176Z"
fill="#FF003C"
/>
</svg>
);
};
+5 -1
View File
@@ -39,6 +39,8 @@ import { Tab, Tabs } from './lib/tags/tabs.component';
import { tab, tabs } from './lib/tags/tabs.schema';
import { Tweet, tweet } from '@nx/nx-dev/ui-common';
import { YouTube, youtube } from '@nx/nx-dev/ui-common';
import { CourseVideo } from '@nx/nx-dev/ui-common';
import { courseVideo } from './lib/tags/course-video.schema';
import { VideoLink, videoLink } from './lib/tags/video-link.component';
// import { SvgAnimation, svgAnimation } from './lib/tags/svg-animation.component';
import { Pill } from './lib/tags/pill.component';
@@ -91,6 +93,7 @@ export const getMarkdocCustomConfig = (
toc: tableOfContents,
tweet,
youtube,
'course-video': courseVideo,
'video-link': videoLink,
metrics,
// 'svg-animation': svgAnimation,
@@ -123,6 +126,7 @@ export const getMarkdocCustomConfig = (
Testimonial,
Tweet,
YouTube,
CourseVideo,
VideoLink,
VideoPlayer,
Metrics,
@@ -176,4 +180,4 @@ export const renderMarkdown: (
};
};
export { Metrics, VideoLink, GithubRepository };
export { Metrics, VideoLink, GithubRepository, CourseVideo };
@@ -0,0 +1,19 @@
import { Schema } from '@markdoc/markdoc';
export const courseVideo: Schema = {
render: 'CourseVideo',
attributes: {
src: {
type: 'String',
required: true,
},
courseTitle: {
type: 'String',
required: true,
},
courseUrl: {
type: 'String',
required: true,
},
},
};

Some files were not shown because too many files have changed in this diff Show More