feat(nx-dev): powerpack landing page (#27963)
<!-- 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 --> ## 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 #
This commit is contained in:
parent
7f4c39ead4
commit
529ab9455c
@ -119,4 +119,4 @@ In addition, we are actively exploring ways to provide advanced analytics for yo
|
|||||||
- [Nx GitHub](https://github.com/nrwl/nx)
|
- [Nx GitHub](https://github.com/nrwl/nx)
|
||||||
- [Nx Official Discord Server](https://go.nx.dev/community)
|
- [Nx Official Discord Server](https://go.nx.dev/community)
|
||||||
- [Nx Youtube Channel](https://www.youtube.com/@nxdevtools)
|
- [Nx Youtube Channel](https://www.youtube.com/@nxdevtools)
|
||||||
- [Speed up your CI](https://nx.app/)
|
- [Speed up your CI](/nx-cloud)
|
||||||
|
|||||||
@ -335,4 +335,4 @@ If the prettier UI and better performance haven’t convinced you, this surely w
|
|||||||
- [Nx GitHub](https://github.com/nrwl/nx)
|
- [Nx GitHub](https://github.com/nrwl/nx)
|
||||||
- [Nx Official Discord Server](https://go.nx.dev/community)
|
- [Nx Official Discord Server](https://go.nx.dev/community)
|
||||||
- [Nx Youtube Channel](https://www.youtube.com/@nxdevtools)
|
- [Nx Youtube Channel](https://www.youtube.com/@nxdevtools)
|
||||||
- [Speed up your CI](https://nx.app/)
|
- [Speed up your CI](/nx-cloud)
|
||||||
|
|||||||
@ -608,4 +608,4 @@ This journey through Qwik and Nx demonstrates how thoughtful architecture and th
|
|||||||
- [Nx GitHub](https://github.com/nrwl/nx)
|
- [Nx GitHub](https://github.com/nrwl/nx)
|
||||||
- [Nx Official Discord Server](https://go.nx.dev/community)
|
- [Nx Official Discord Server](https://go.nx.dev/community)
|
||||||
- [Nx Youtube Channel](https://www.youtube.com/@nxdevtools)
|
- [Nx Youtube Channel](https://www.youtube.com/@nxdevtools)
|
||||||
- [Speed up your CI](https://nx.app/)
|
- [Speed up your CI](/nx-cloud)
|
||||||
|
|||||||
@ -18,4 +18,4 @@ Victor and I are excited to announce that Nx has raised another $16M in a Series
|
|||||||
- [Nx GitHub](https://github.com/nrwl/nx)
|
- [Nx GitHub](https://github.com/nrwl/nx)
|
||||||
- [Nx Official Discord Server](https://go.nx.dev/community)
|
- [Nx Official Discord Server](https://go.nx.dev/community)
|
||||||
- [Nx Youtube Channel](https://www.youtube.com/@nxdevtools)
|
- [Nx Youtube Channel](https://www.youtube.com/@nxdevtools)
|
||||||
- [Speed up your CI](https://nx.app/)
|
- [Speed up your CI](/nx-cloud)
|
||||||
|
|||||||
@ -495,4 +495,4 @@ If you enjoyed these, [subscribe to our YouTube channel](https://www.youtube.com
|
|||||||
- [Nx GitHub](https://github.com/nrwl/nx)
|
- [Nx GitHub](https://github.com/nrwl/nx)
|
||||||
- [Nx Official Discord Server](https://go.nx.dev/community)
|
- [Nx Official Discord Server](https://go.nx.dev/community)
|
||||||
- [Nx Youtube Channel](https://www.youtube.com/@nxdevtools)
|
- [Nx Youtube Channel](https://www.youtube.com/@nxdevtools)
|
||||||
- [Speed up your CI](https://nx.app/)
|
- [Speed up your CI](/nx-cloud)
|
||||||
|
|||||||
@ -284,4 +284,4 @@ That’s all for now folks! We’re just starting up a new iteration of developm
|
|||||||
- [Nx GitHub](https://github.com/nrwl/nx)
|
- [Nx GitHub](https://github.com/nrwl/nx)
|
||||||
- [Nx Official Discord Server](https://go.nx.dev/community)
|
- [Nx Official Discord Server](https://go.nx.dev/community)
|
||||||
- [Nx Youtube Channel](https://www.youtube.com/@nxdevtools)
|
- [Nx Youtube Channel](https://www.youtube.com/@nxdevtools)
|
||||||
- [Speed up your CI](https://nx.app/)
|
- [Speed up your CI](/nx-cloud)
|
||||||
|
|||||||
@ -621,4 +621,4 @@ Nx is a powerful monorepo tool. Together with Nx and these 2 state management to
|
|||||||
- [Nx GitHub](https://github.com/nrwl/nx)
|
- [Nx GitHub](https://github.com/nrwl/nx)
|
||||||
- [Nx Official Discord Server](https://go.nx.dev/community)
|
- [Nx Official Discord Server](https://go.nx.dev/community)
|
||||||
- [Nx Youtube Channel](https://www.youtube.com/@nxdevtools)
|
- [Nx Youtube Channel](https://www.youtube.com/@nxdevtools)
|
||||||
- [Speed up your CI](https://nx.app/)
|
- [Speed up your CI](/nx-cloud)
|
||||||
|
|||||||
@ -312,4 +312,4 @@ This role, in the context of OpenAI’s chat models, is the response of the AI.
|
|||||||
- [Nx GitHub](https://github.com/nrwl/nx)
|
- [Nx GitHub](https://github.com/nrwl/nx)
|
||||||
- [Nx Official Discord Server](/community)
|
- [Nx Official Discord Server](/community)
|
||||||
- [Nx Youtube Channel](https://www.youtube.com/@nxdevtools)
|
- [Nx Youtube Channel](https://www.youtube.com/@nxdevtools)
|
||||||
- [Speed up your CI](https://nx.app/)
|
- [Speed up your CI](/nx-cloud)
|
||||||
|
|||||||
@ -212,4 +212,4 @@ That’s all for now folks! We’re just starting up a new iteration of developm
|
|||||||
- [Nx GitHub](https://github.com/nrwl/nx)
|
- [Nx GitHub](https://github.com/nrwl/nx)
|
||||||
- [Nx Official Discord Server](https://go.nx.dev/community)
|
- [Nx Official Discord Server](https://go.nx.dev/community)
|
||||||
- [Nx Youtube Channel](https://www.youtube.com/@nxdevtools)
|
- [Nx Youtube Channel](https://www.youtube.com/@nxdevtools)
|
||||||
- [Speed up your CI](https://nx.app/)
|
- [Speed up your CI](/nx-cloud)
|
||||||
|
|||||||
@ -389,4 +389,4 @@ Exciting stuff! So keep an eye on our channels, and subscribe if you haven’t a
|
|||||||
- [Nx GitHub](https://github.com/nrwl/nx)
|
- [Nx GitHub](https://github.com/nrwl/nx)
|
||||||
- [Nx Official Discord Server](https://go.nx.dev/community)
|
- [Nx Official Discord Server](https://go.nx.dev/community)
|
||||||
- [Nx Youtube Channel](https://www.youtube.com/@nxdevtools)
|
- [Nx Youtube Channel](https://www.youtube.com/@nxdevtools)
|
||||||
- [Speed up your CI](https://nx.app/)
|
- [Speed up your CI](/nx-cloud)
|
||||||
|
|||||||
@ -185,4 +185,4 @@ We just released Project Crystal, so this is just the beginning of it. While we
|
|||||||
- [Nx GitHub](https://github.com/nrwl/nx)
|
- [Nx GitHub](https://github.com/nrwl/nx)
|
||||||
- [Nx Official Discord Server](https://go.nx.dev/community)
|
- [Nx Official Discord Server](https://go.nx.dev/community)
|
||||||
- [Nx Youtube Channel](https://www.youtube.com/@nxdevtools)
|
- [Nx Youtube Channel](https://www.youtube.com/@nxdevtools)
|
||||||
- [Speed up your CI](https://nx.app/)
|
- [Speed up your CI](/nx-cloud)
|
||||||
|
|||||||
@ -124,4 +124,4 @@ If you have a task that can’t be run on Nx Agents for some reason, you can eas
|
|||||||
- [Nx GitHub](https://github.com/nrwl/nx)
|
- [Nx GitHub](https://github.com/nrwl/nx)
|
||||||
- [Nx Official Discord Server](https://go.nx.dev/community)
|
- [Nx Official Discord Server](https://go.nx.dev/community)
|
||||||
- [Nx Youtube Channel](https://www.youtube.com/@nxdevtools)
|
- [Nx Youtube Channel](https://www.youtube.com/@nxdevtools)
|
||||||
- [Speed up your CI](https://nx.app/)
|
- [Speed up your CI](/nx-cloud)
|
||||||
|
|||||||
@ -319,4 +319,4 @@ Here are some example repositories already leveraging Nx release:
|
|||||||
- [Nx GitHub](https://github.com/nrwl/nx)
|
- [Nx GitHub](https://github.com/nrwl/nx)
|
||||||
- [Nx Official Discord Server](https://go.nx.dev/community)
|
- [Nx Official Discord Server](https://go.nx.dev/community)
|
||||||
- [Nx Youtube Channel](https://www.youtube.com/@nxdevtools)
|
- [Nx Youtube Channel](https://www.youtube.com/@nxdevtools)
|
||||||
- [Speed up your CI](https://nx.app/)
|
- [Speed up your CI](/nx-cloud)
|
||||||
|
|||||||
@ -145,4 +145,4 @@ That’s all for now folks! We’re just starting up a new iteration of developm
|
|||||||
- [Nx GitHub](https://github.com/nrwl/nx)
|
- [Nx GitHub](https://github.com/nrwl/nx)
|
||||||
- [Nx Official Discord Server](https://go.nx.dev/community)
|
- [Nx Official Discord Server](https://go.nx.dev/community)
|
||||||
- [Nx Youtube Channel](https://www.youtube.com/@nxdevtools)
|
- [Nx Youtube Channel](https://www.youtube.com/@nxdevtools)
|
||||||
- [Speed up your CI](https://nx.app/)
|
- [Speed up your CI](/nx-cloud)
|
||||||
|
|||||||
@ -215,4 +215,4 @@ Here is how to set up Nx with the Gradle workspace. Hopefully, this gives you a
|
|||||||
- [Nx GitHub](https://github.com/nrwl/nx)
|
- [Nx GitHub](https://github.com/nrwl/nx)
|
||||||
- [Nx Official Discord Server](https://go.nx.dev/community)
|
- [Nx Official Discord Server](https://go.nx.dev/community)
|
||||||
- [Nx Youtube Channel](https://www.youtube.com/@nxdevtools)
|
- [Nx Youtube Channel](https://www.youtube.com/@nxdevtools)
|
||||||
- [Speed up your CI](https://nx.app/)
|
- [Speed up your CI](/nx-cloud)
|
||||||
|
|||||||
@ -235,4 +235,4 @@ Zack
|
|||||||
- [Nx GitHub](https://github.com/nrwl/nx)
|
- [Nx GitHub](https://github.com/nrwl/nx)
|
||||||
- [Nx Official Discord Server](https://go.nx.dev/community)
|
- [Nx Official Discord Server](https://go.nx.dev/community)
|
||||||
- [Nx Youtube Channel](https://www.youtube.com/@nxdevtools)
|
- [Nx Youtube Channel](https://www.youtube.com/@nxdevtools)
|
||||||
- [Speed up your CI](https://nx.app/)
|
- [Speed up your CI](/nx-cloud)
|
||||||
|
|||||||
@ -56,4 +56,4 @@ This is just the first of a series of AI-powered features that we're going to be
|
|||||||
- [Nx GitHub](https://github.com/nrwl/nx)
|
- [Nx GitHub](https://github.com/nrwl/nx)
|
||||||
- [Nx Official Discord Server](https://go.nx.dev/community)
|
- [Nx Official Discord Server](https://go.nx.dev/community)
|
||||||
- [Nx Youtube Channel](https://www.youtube.com/@nxdevtools)
|
- [Nx Youtube Channel](https://www.youtube.com/@nxdevtools)
|
||||||
- [Speed up your CI](https://nx.app/)
|
- [Speed up your CI](/nx-cloud)
|
||||||
|
|||||||
@ -292,4 +292,4 @@ The [Monorepo World conference](https://monorepo.world) is coming up soon on Oct
|
|||||||
- [Nx GitHub](https://github.com/nrwl/nx)
|
- [Nx GitHub](https://github.com/nrwl/nx)
|
||||||
- [Nx Official Discord Server](https://go.nx.dev/community)
|
- [Nx Official Discord Server](https://go.nx.dev/community)
|
||||||
- [Nx Youtube Channel](https://www.youtube.com/@nxdevtools)
|
- [Nx Youtube Channel](https://www.youtube.com/@nxdevtools)
|
||||||
- [Speed up your CI](https://nx.app/)
|
- [Speed up your CI](/nx-cloud)
|
||||||
|
|||||||
@ -91,4 +91,4 @@ can [find more details in our docs](/ci/recipes/security/personal-access-tokens)
|
|||||||
- [Nx GitHub](https://github.com/nrwl/nx)
|
- [Nx GitHub](https://github.com/nrwl/nx)
|
||||||
- [Nx Official Discord Server](https://go.nx.dev/community)
|
- [Nx Official Discord Server](https://go.nx.dev/community)
|
||||||
- [Nx Youtube Channel](https://www.youtube.com/@nxdevtools)
|
- [Nx Youtube Channel](https://www.youtube.com/@nxdevtools)
|
||||||
- [Speed up your CI](https://nx.app/)
|
- [Speed up your CI](/nx-cloud)
|
||||||
|
|||||||
@ -110,4 +110,4 @@ The [Monorepo World conference](https://monorepo.world) is coming up soon on Oct
|
|||||||
- [Nx GitHub](https://github.com/nrwl/nx)
|
- [Nx GitHub](https://github.com/nrwl/nx)
|
||||||
- [Nx Official Discord Server](https://go.nx.dev/community)
|
- [Nx Official Discord Server](https://go.nx.dev/community)
|
||||||
- [Nx Youtube Channel](https://www.youtube.com/@nxdevtools)
|
- [Nx Youtube Channel](https://www.youtube.com/@nxdevtools)
|
||||||
- [Speed up your CI](https://nx.app/)
|
- [Speed up your CI](/nx-cloud)
|
||||||
|
|||||||
54
docs/blog/2024-09-25-evolving-nx.md
Normal file
54
docs/blog/2024-09-25-evolving-nx.md
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
---
|
||||||
|
title: Evolving Nx
|
||||||
|
slug: evolving-nx
|
||||||
|
authors: [Jeff Cross]
|
||||||
|
tags: [nx, release]
|
||||||
|
cover_image: /blog/images/evolving-nx/thumbnail.png
|
||||||
|
---
|
||||||
|
|
||||||
|
Over the years, Nx has grown from a small 20% side project of our consulting business into a tool that empowers millions of developers worldwide and helps Fortune 500 companies ship high-quality software faster. In the last two years, we successfully transformed our consulting business into a product company, where our team can fully focus on evolving Nx and building Nx Cloud to extend Nx’s capabilities beyond local development.
|
||||||
|
|
||||||
|
This success is in large part thanks to:
|
||||||
|
|
||||||
|
- Our commitment to building Nx as MIT-licensed open-source software, supported by the incredible contributions from our vibrant Nx community.
|
||||||
|
- Close collaboration with our customers, allowing us to understand their needs and continuously improve Nx and Nx Cloud to address their demanding and complex challenges.
|
||||||
|
|
||||||
|
When we have new ideas to make Nx better, we’ve always had two options: it could be in the open source build system, or it could be in the paid cloud product, [Nx Cloud](/nx-cloud). But sometimes, there are important things we want to offer that can solve some gnarly problems for teams but don’t require them to spend months convincing their IT department to incorporate yet another cloud service. So, we decided to create a collection of non-cloud-dependent Nx add-ons in a new package called **Nx Powerpack**, which will require paid licenses to use.
|
||||||
|
|
||||||
|
## Introducing Nx Powerpack
|
||||||
|
|
||||||
|
**[Nx Powerpack](/powerpack)** — our newest product designed to elevate the Nx CLI experience for enterprise environments. Powerpack offers advanced features like self-hosted remote cache storage, code ownership for monorepos, and workspace conformance, seamlessly integrating into sealed systems with strict security requirements. It’s also designed for ease of implementation, helping enterprises bypass lengthy procurement processes and quickly access the tools they need.
|
||||||
|
|
||||||
|
> If you want to get into the technical details, we wrote a separate blog post diving deeper into the technical details: [Introducing Nx Powerpack](/blog/introducing-nx-powerpack).
|
||||||
|
|
||||||
|
Everything in Powerpack is new functionality, not previously free features that we’re now putting behind a paywall. However, this change coincides with some Nx improvements that will eventually interfere with users who were relying on our original filesystem-based implementation of local caching. We’ve completely rewritten Nx's local caching to be faster and more secure, partly by using a local database instead of checking the filesystem for artifact metadata. With this rewrite, any custom remote caches that rely on metadata reflected in the filesystem will not work as of Nx 21. This is why we decided to build an API into Powerpack to be able to connect Nx’s cache to different clouds and data sources. Now with Powerpack, teams can use an officially-supported implementation of remote caching, without needing to use Nx Cloud.
|
||||||
|
|
||||||
|
There’s a Steve Jobs quote that I think rings true with all of us at Nx:
|
||||||
|
|
||||||
|
> "I think money is a wonderful thing because it enables you to do things. It enables you to invest in ideas that don't have a short-term payback." - Steve Jobs
|
||||||
|
|
||||||
|
As Nx has grown, we’ve hired more people to make the product better. Naturally, those people want to do good work and be paid. We all show up for work to build things we’re passionate about, and solve real pains for the millions of developers using Nx every day. Money is what enables us to keep doing what we love. So as much as Victor Savkin and I want to just build things and give them away for free, we need to balance our personal passion with what’s the best long-term decisions for Nx — the project, the community, and the company.
|
||||||
|
|
||||||
|
Like many open source projects, one of the bigger challenges to sustainability in recent years has been larger cloud products who wait for projects to become successful, and then try to capitalize on that success at the expense of the maintainers. I call these companies “parasite vendors” since they benefit from the host, but give no value back. To battle this, many open source projects have decided to make their open source licensing more restrictive, or introduce dual licenses, forcing those parasite vendors to work with the maintainers on a fair arrangement. We think we’ve come up with a better solution for the community by introducing a new package, Powerpack, with a new commercial license, with only new functionality. **Nx itself still has one license: the MIT license.**
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
## How to Get Nx Powerpack
|
||||||
|
|
||||||
|
Powerpack is automatically included for all existing enterprise customers. If you’re looking to purchase a new license, you can easily [do so on this page](/powerpack).
|
||||||
|
|
||||||
|
Are you a startup? If these features make sense for your team but the cost is a concern, reach out to our support team, and we’ll work with you to find a solution that fits.
|
||||||
|
|
||||||
|
## Got Questions?
|
||||||
|
|
||||||
|
If you’re curious to learn more about these changes for Nx and how to get started, [check out our docs](/features/powerpack).
|
||||||
|
|
||||||
|
## Learn more
|
||||||
|
|
||||||
|
- [Nx Powerpack](/powerpack)
|
||||||
|
- [Blog: Introducing Nx Powerpack](/blog/introducing-nx-powerpack)
|
||||||
|
- [Docs: Powerpack features](/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)
|
||||||
252
docs/blog/2024-09-25-introducing-nx-powerpack.md
Normal file
252
docs/blog/2024-09-25-introducing-nx-powerpack.md
Normal file
@ -0,0 +1,252 @@
|
|||||||
|
---
|
||||||
|
title: Introducing Nx Powerpack
|
||||||
|
slug: introducing-nx-powerpack
|
||||||
|
authors: [Juri Strumpflohner]
|
||||||
|
tags: [nx, release]
|
||||||
|
cover_image: /blog/images/introducing-powerpack/thumbnail.png
|
||||||
|
youtubeUrl: https://youtu.be/KZ0nh2lj8zE
|
||||||
|
---
|
||||||
|
|
||||||
|
Today we're introducing our latest product, **Nx Powerpack**, a suite of paid extensions for Nx, specifically designed around common enterprise needs. Now, before anyone draws the wrong conclusions:
|
||||||
|
|
||||||
|
- No, we’re **not going to restrict Nx’s license**, lock you in, and then harvest. Nx remains MIT licensed and fully open source.
|
||||||
|
- No, we’re **not placing existing features behind a paywall**. Nx Powerpack introduces new features on top of Nx (more about that below).
|
||||||
|
- Yes, we still **strongly believe in OSS and our community**, and we will keep improving Nx more than ever; if anything, Powerpack will help us fund our OSS work on Nx core and ensure its long-term sustainability.
|
||||||
|
|
||||||
|
So this leaves us with:
|
||||||
|

|
||||||
|
|
||||||
|
> But why do we release Nx Powerpack under a commercial license? Read all about our strategy, the reasoning behind Powerpack and OSS funding in the **blog post from our CEO, Jeff Cross**: [Evolving Nx](/blog/evolving-nx).
|
||||||
|
|
||||||
|
But now to the fun, technical part! Nx Powerpack is a bundle that - in this very first release - comes with three major features:
|
||||||
|
|
||||||
|
- [Codeowners for monorepos](#codeowners-for-monorepos)
|
||||||
|
- [Self-hosted cache storage](#selfhosted-cache-storage)
|
||||||
|
- [Workspace conformance (beta)](#workspace-conformance-beta)
|
||||||
|
|
||||||
|
Let’s dive in!
|
||||||
|
|
||||||
|
## Getting an Nx Powerpack license
|
||||||
|
|
||||||
|
All Powerpack features require a dedicated commercial license. You can get one here: [Nx Powerpack](/powerpack).
|
||||||
|
|
||||||
|
Once you have your license, run the following command
|
||||||
|
|
||||||
|
```shell
|
||||||
|
npx nx activate-powerpack <your-license>
|
||||||
|
```
|
||||||
|
|
||||||
|
## Codeowners for monorepos
|
||||||
|
|
||||||
|
Setting up Codeowners is highly recommended when designing a monorepo. If you’re not closely familiar, Codeowners is a common feature of VCS providers (such as GitHub, GitLab, Bitbucket, etc.), allowing you to enforce specific code reviewers to approve PRs. This functionality is especially important in a monorepo, where you manage multiple projects with multiple teams. You want to ensure the right people are reviewing the code being submitted.
|
||||||
|
|
||||||
|
Here’s a simple example of a [GitHub CODEOWNERS definition](https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/about-code-owners):
|
||||||
|
|
||||||
|
```plain {% fileName=".github/CODEOWNERS" %}
|
||||||
|
/docs/ @doc-owner
|
||||||
|
/apps/orders @orders-team
|
||||||
|
/apps/products @products-team
|
||||||
|
/libs/orders/** @orders-team
|
||||||
|
/libs/products/** @products-team
|
||||||
|
/libs/shared/** @infra-team
|
||||||
|
```
|
||||||
|
|
||||||
|
One of the downsides of how codeowners works on today's VCS providers is that **they are folder-based**. That requires you to map your project paths to your codeowner files and keep maintaining that as you change your monorepo structure. And **this is exactly what we're going to automate**.
|
||||||
|
|
||||||
|
In a monorepo you reason based on projects. That's what you pass to your [Nx run commands](/features/run-tasks), what you see on the [project graph](/features/explore-graph) and also where owners should be defined. To get started install the Codeowners Powerpack plugin:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
npx nx add @nx/powerpack-owners
|
||||||
|
```
|
||||||
|
|
||||||
|
This will allow you to define an owners section in your `nx.json` where you can define owners at the project level or even leveraging project tags. Here's a small example:
|
||||||
|
|
||||||
|
```json {% fileName="nx.json" %}
|
||||||
|
{
|
||||||
|
...
|
||||||
|
"owners": {
|
||||||
|
"format": "github",
|
||||||
|
"patterns": [
|
||||||
|
{
|
||||||
|
"description": "CI configuration",
|
||||||
|
"owners": ["@devops"],
|
||||||
|
"files": [".github/workflows/**"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"description": "Order team",
|
||||||
|
"owners": ["@team-orders"],
|
||||||
|
"projects": ["tag:scope:orders"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"description": "Product team",
|
||||||
|
"owners": ["@team-products"],
|
||||||
|
"projects": ["tag:scope:products"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"description": "Design team",
|
||||||
|
"owners": ["@team-design"],
|
||||||
|
"projects": ["tag:scope:design-system"]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
...
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
A dedicated `nx sync` command automatically synchronizes such definition to a `CODEOWNERS` that matches your VCS provider:
|
||||||
|
|
||||||
|
```{% fileName=".github/CODEOWNERS" %}
|
||||||
|
|
||||||
|
# CI configuration
|
||||||
|
.github/workflows/** @devops
|
||||||
|
|
||||||
|
# Design team
|
||||||
|
/libs/shared/ui/angular/form-controls/ @team-design
|
||||||
|
|
||||||
|
# Design team
|
||||||
|
/libs/shared/ui/react/form-controls/ @team-design
|
||||||
|
|
||||||
|
# Product team
|
||||||
|
/libs/products/feat-product-detail/ @team-products
|
||||||
|
|
||||||
|
# Order team
|
||||||
|
/libs/orders/feat-current-orders/ @team-orders
|
||||||
|
|
||||||
|
...
|
||||||
|
```
|
||||||
|
|
||||||
|
Read all about how to [configure Codeowners for your project on our docs](/features/powerpack/owners).
|
||||||
|
|
||||||
|
## Self-hosted cache storage
|
||||||
|
|
||||||
|
A continuous effort on our Nx core is to improve speed. Last year, we began **rewriting performance-critical parts of Nx into Rust**, and more core components are being rewritten. As part of this effort, we also changed how we manage local cache, moving from a **file-based to a database-based approach**. In addition to small performance gains from reduced I/O, this opens up many opportunities for improving local cache handling, such as keeping only relevant cache based on usage, more easily controlling maximum cache size, and optimizing task orchestration by running failed tasks earlier.
|
||||||
|
|
||||||
|
As part of this new approach we're also going to [deprecate custom `taskRunners`](/deprecated/custom-task-runners) in Nx 20. I bring this up because it might affect users that relied on 3rd party tools that hooked into the task runners API.
|
||||||
|
|
||||||
|
To fill in on the custom task runner API we're providing a new Powerpack plugin that allows you to use S3 or a network drive as your storing mechanism for your Nx cache.
|
||||||
|
|
||||||
|
Here's an example on how to get started with AWS S3 based remote caching. First add the powerpack plugin:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
npx nx add @nx/powerpack-s3-cache
|
||||||
|
```
|
||||||
|
|
||||||
|
This will update your `nx.json` to add the new `cache` section.
|
||||||
|
|
||||||
|
```json {% fileName="nx.json" %}
|
||||||
|
{
|
||||||
|
...
|
||||||
|
"s3": {
|
||||||
|
"bucket": "your-s3-bucket-name",
|
||||||
|
"region": "us-east-1"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
To then leverage the S3 powered remote cache on CI, [follow the official AWS documentation](https://github.com/aws-actions/configure-aws-credentials). Here's a short example snippet using OIDC to authenticate with AWS on GitHub Actions:
|
||||||
|
|
||||||
|
```yaml {% fileName=".github/workflows/ci.yml" %}
|
||||||
|
name: CI
|
||||||
|
...
|
||||||
|
permissions:
|
||||||
|
id-token: write
|
||||||
|
...
|
||||||
|
|
||||||
|
env:
|
||||||
|
NX_DB_CACHE: true
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
main:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
...
|
||||||
|
|
||||||
|
- name: 'Configure AWS Credentials'
|
||||||
|
uses: aws-actions/configure-aws-credentials@v4.0.2
|
||||||
|
with:
|
||||||
|
role-to-assume: arn:aws:iam::123456789123:role/GhAIBucketUserRole
|
||||||
|
aws-region: us-east-1
|
||||||
|
|
||||||
|
...
|
||||||
|
|
||||||
|
- run: pnpm exec nx affected -t lint test build
|
||||||
|
```
|
||||||
|
|
||||||
|
Similarly you can **set up network file based caching** using the `nx add @nx/powerpack-shared-fs-cache` package and by setting the `cacheDirectory` path in your `nx.json`.
|
||||||
|
|
||||||
|
Read all about how to [set up S3 or network drive based caching for your Nx workspace on our docs](/features/powerpack/custom-caching).
|
||||||
|
|
||||||
|
## Workspace conformance (Beta)
|
||||||
|
|
||||||
|
We're releasing the `@nx/powerpack-conformance` plugin in an early preview. This new package focuses specifically on the maintainability of your monorepo. It allows you to encode your organization's standards so they can be enforced automatically. In this first version, the workspace conformance package ships with:
|
||||||
|
|
||||||
|
- [Enforce Module Boundaries](/nx-api/powerpack-conformance#enforce-module-boundaries): Similar to the Nx ESLint [Enforce Module Boundaries rule](https://nx-dev-git-docs-powerpack-nrwl.vercel.app/features/enforce-module-boundaries), but enforces boundaries on every project dependency, not just those created from TypeScript imports or `package.json` dependencies.
|
||||||
|
- [Ensure Owners](/nx-api/powerpack-conformance#ensure-owners): Requires every project to have an owner defined for the `@nx/powerpack-owners` plugin.
|
||||||
|
|
||||||
|
To get started, install the following package:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
npx nx add @nx/powerpack-conformance
|
||||||
|
```
|
||||||
|
|
||||||
|
This allows you to define conformance rules in your `nx.json`. Here is an example:
|
||||||
|
|
||||||
|
```json {% fileName="nx.json" %}
|
||||||
|
{
|
||||||
|
...
|
||||||
|
"conformance": {
|
||||||
|
"rules": [
|
||||||
|
{
|
||||||
|
"rule": "@nx/powerpack-conformance/enforce-module-boundaries",
|
||||||
|
"projects": ["!remix-app-e2e"],
|
||||||
|
"options": {}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"rule": "@nx/powerpack-conformance/ensure-owners",
|
||||||
|
"projects": ["!remix-app-e2e"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"rule": "./tools/local-conformance-rule.ts"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
You can also define rules locally, as shown in the example above, which are simple TypeScript files:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
import { createConformanceRule } from '@nx/powerpack-conformance';
|
||||||
|
|
||||||
|
const rule = createConformanceRule({
|
||||||
|
name: 'local-conformance-rule-example',
|
||||||
|
category: 'security',
|
||||||
|
reporter: 'project-reporter',
|
||||||
|
implementation: async (context) => {
|
||||||
|
return {
|
||||||
|
severity: 'low',
|
||||||
|
details: {
|
||||||
|
violations: [],
|
||||||
|
},
|
||||||
|
};
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export default rule;
|
||||||
|
```
|
||||||
|
|
||||||
|
You can then run `nx conformance` to execute the conformance checks:
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
In this first preview release, you'll only be able to run workspace conformance rules on a single workspace. In future iterations, you **will be able to connect it to your existing Nx Cloud organization**, allowing you to upload conformance rules and run them across connected workspaces.
|
||||||
|
|
||||||
|
Read all the details on how to [get started with workspace conformance rules in our docs](/features/powerpack/conformance).
|
||||||
|
|
||||||
|
## Learn more
|
||||||
|
|
||||||
|
- [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)
|
||||||
BIN
docs/blog/images/evolving-nx/nx-products-licenses.avif
Normal file
BIN
docs/blog/images/evolving-nx/nx-products-licenses.avif
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 16 KiB |
BIN
docs/blog/images/evolving-nx/thumbnail.png
Normal file
BIN
docs/blog/images/evolving-nx/thumbnail.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 519 KiB |
BIN
docs/blog/images/introducing-powerpack/conformance-check.avif
Normal file
BIN
docs/blog/images/introducing-powerpack/conformance-check.avif
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 72 KiB |
BIN
docs/blog/images/introducing-powerpack/thumbnail.png
Normal file
BIN
docs/blog/images/introducing-powerpack/thumbnail.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 911 KiB |
52
nx-dev/nx-dev/app/powerpack/page.tsx
Normal file
52
nx-dev/nx-dev/app/powerpack/page.tsx
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
import { DefaultLayout } from '@nx/nx-dev/ui-common';
|
||||||
|
import {
|
||||||
|
CallToAction,
|
||||||
|
GetStarted,
|
||||||
|
Hero,
|
||||||
|
PowerpackFeatures,
|
||||||
|
} from '@nx/nx-dev/ui-powerpack';
|
||||||
|
|
||||||
|
import type { Metadata } from 'next';
|
||||||
|
|
||||||
|
export const metadata: Metadata = {
|
||||||
|
title: 'Nx PowerPack',
|
||||||
|
description:
|
||||||
|
'Nx Powerpack is a suite of paid extensions for the Nx CLI specifically designed for enterprises.',
|
||||||
|
openGraph: {
|
||||||
|
url: 'https://nx.dev/powerpack',
|
||||||
|
title: 'Nx PowerPack',
|
||||||
|
description:
|
||||||
|
'Nx Powerpack is a suite of paid extensions for the Nx CLI specifically designed for enterprises.',
|
||||||
|
images: [
|
||||||
|
{
|
||||||
|
url: 'https://nx.dev/socials/nx-powerpack-media.png',
|
||||||
|
width: 800,
|
||||||
|
height: 421,
|
||||||
|
alt: 'Nx PowerPack: Advanced tools for enterprises',
|
||||||
|
type: 'image/jpeg',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
siteName: 'NxDev',
|
||||||
|
type: 'website',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export default function NxPowerPackPage(): JSX.Element {
|
||||||
|
return (
|
||||||
|
<DefaultLayout>
|
||||||
|
<Hero />
|
||||||
|
|
||||||
|
<div className="mt-32 scroll-mt-32 lg:mt-56" id="features">
|
||||||
|
<PowerpackFeatures />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="mt-32 scroll-mt-32 lg:mt-56">
|
||||||
|
<GetStarted />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="mt-32 lg:mt-56">
|
||||||
|
<CallToAction />
|
||||||
|
</div>
|
||||||
|
</DefaultLayout>
|
||||||
|
);
|
||||||
|
}
|
||||||
@ -1,3 +1,4 @@
|
|||||||
|
export * from './lib/animated-beam';
|
||||||
export * from './lib/animate-value';
|
export * from './lib/animate-value';
|
||||||
export * from './lib/blur-fade';
|
export * from './lib/blur-fade';
|
||||||
export * from './lib/fit-text';
|
export * from './lib/fit-text';
|
||||||
|
|||||||
371
nx-dev/ui-animations/src/lib/animated-beam.tsx
Normal file
371
nx-dev/ui-animations/src/lib/animated-beam.tsx
Normal file
@ -0,0 +1,371 @@
|
|||||||
|
'use client';
|
||||||
|
import { FC, RefObject, useEffect, useId, useState } from 'react';
|
||||||
|
import { motion, TargetAndTransition } from 'framer-motion';
|
||||||
|
import { cx } from '@nx/nx-dev/ui-primitives';
|
||||||
|
|
||||||
|
export interface AnimatedCurvedBeamProps {
|
||||||
|
className?: string;
|
||||||
|
containerRef: RefObject<HTMLElement>; // Container ref
|
||||||
|
fromRef: RefObject<HTMLElement>;
|
||||||
|
toRef: RefObject<HTMLElement>;
|
||||||
|
curvature?: number;
|
||||||
|
reverse?: boolean;
|
||||||
|
pathColor?: string;
|
||||||
|
pathWidth?: number;
|
||||||
|
pathOpacity?: number;
|
||||||
|
gradientStartColor?: string;
|
||||||
|
gradientStopColor?: string;
|
||||||
|
delay?: number;
|
||||||
|
duration?: number;
|
||||||
|
startXOffset?: number;
|
||||||
|
startYOffset?: number;
|
||||||
|
endXOffset?: number;
|
||||||
|
endYOffset?: number;
|
||||||
|
bidirectional?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
type BeamAnimation = {
|
||||||
|
x1: [string, string];
|
||||||
|
x2: [string, string];
|
||||||
|
y1: [string, string];
|
||||||
|
y2: [string, string];
|
||||||
|
};
|
||||||
|
|
||||||
|
export const AnimatedCurvedBeam: FC<AnimatedCurvedBeamProps> = ({
|
||||||
|
className,
|
||||||
|
containerRef,
|
||||||
|
fromRef,
|
||||||
|
toRef,
|
||||||
|
curvature = 0,
|
||||||
|
reverse = false, // Include the reverse prop
|
||||||
|
duration = Math.random() * 3 + 8,
|
||||||
|
delay = 0,
|
||||||
|
pathColor = 'gray',
|
||||||
|
pathWidth = 2,
|
||||||
|
pathOpacity = 0.2,
|
||||||
|
gradientStartColor = '#ffaa40',
|
||||||
|
gradientStopColor = '#9c40ff',
|
||||||
|
startXOffset = 0,
|
||||||
|
startYOffset = 0,
|
||||||
|
endXOffset = 0,
|
||||||
|
endYOffset = 0,
|
||||||
|
bidirectional = false,
|
||||||
|
}) => {
|
||||||
|
const id = useId();
|
||||||
|
const [pathD, setPathD] = useState('');
|
||||||
|
const [svgDimensions, setSvgDimensions] = useState({ width: 0, height: 0 });
|
||||||
|
|
||||||
|
// Calculate the gradient coordinates based on the reverse prop
|
||||||
|
const forwardAnimation: BeamAnimation = {
|
||||||
|
x1: reverse ? ['90%', '-10%'] : ['10%', '110%'],
|
||||||
|
x2: reverse ? ['100%', '0%'] : ['0%', '100%'],
|
||||||
|
y1: ['0%', '0%'],
|
||||||
|
y2: ['0%', '0%'],
|
||||||
|
};
|
||||||
|
|
||||||
|
const backwardAnimation: BeamAnimation = {
|
||||||
|
x1: reverse ? ['-10%', '90%'] : ['110%', '10%'],
|
||||||
|
x2: reverse ? ['0%', '100%'] : ['100%', '0%'],
|
||||||
|
y1: ['0%', '0%'],
|
||||||
|
y2: ['0%', '0%'],
|
||||||
|
};
|
||||||
|
|
||||||
|
const animateValue: TargetAndTransition = bidirectional
|
||||||
|
? {
|
||||||
|
x1: [
|
||||||
|
forwardAnimation.x1[0],
|
||||||
|
forwardAnimation.x1[1],
|
||||||
|
backwardAnimation.x1[1],
|
||||||
|
backwardAnimation.x1[0],
|
||||||
|
],
|
||||||
|
x2: [
|
||||||
|
forwardAnimation.x2[0],
|
||||||
|
forwardAnimation.x2[1],
|
||||||
|
backwardAnimation.x2[1],
|
||||||
|
backwardAnimation.x2[0],
|
||||||
|
],
|
||||||
|
y1: ['0%', '0%', '0%', '0%'],
|
||||||
|
y2: ['0%', '0%', '0%', '0%'],
|
||||||
|
}
|
||||||
|
: forwardAnimation;
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const updatePath = () => {
|
||||||
|
if (containerRef.current && fromRef.current && toRef.current) {
|
||||||
|
const containerRect = containerRef.current.getBoundingClientRect();
|
||||||
|
const rectA = fromRef.current.getBoundingClientRect();
|
||||||
|
const rectB = toRef.current.getBoundingClientRect();
|
||||||
|
|
||||||
|
const svgWidth = containerRect.width;
|
||||||
|
const svgHeight = containerRect.height;
|
||||||
|
setSvgDimensions({ width: svgWidth, height: svgHeight });
|
||||||
|
|
||||||
|
const startX =
|
||||||
|
rectA.left - containerRect.left + rectA.width / 2 + startXOffset;
|
||||||
|
const startY =
|
||||||
|
rectA.top - containerRect.top + rectA.height / 2 + startYOffset;
|
||||||
|
const endX =
|
||||||
|
rectB.left - containerRect.left + rectB.width / 2 + endXOffset;
|
||||||
|
const endY =
|
||||||
|
rectB.top - containerRect.top + rectB.height / 2 + endYOffset;
|
||||||
|
|
||||||
|
const controlY = startY - curvature;
|
||||||
|
const d = `M ${startX},${startY} Q ${
|
||||||
|
(startX + endX) / 2
|
||||||
|
},${controlY} ${endX},${endY}`;
|
||||||
|
setPathD(d);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Initialize ResizeObserver
|
||||||
|
const resizeObserver = new ResizeObserver((entries) => {
|
||||||
|
// For all entries, recalculate the path
|
||||||
|
for (let entry of entries) {
|
||||||
|
updatePath();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Observe the container element
|
||||||
|
if (containerRef.current) {
|
||||||
|
resizeObserver.observe(containerRef.current);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Call the updatePath initially to set the initial path
|
||||||
|
updatePath();
|
||||||
|
|
||||||
|
// Clean up the observer on component unmount
|
||||||
|
return () => {
|
||||||
|
resizeObserver.disconnect();
|
||||||
|
};
|
||||||
|
}, [
|
||||||
|
containerRef,
|
||||||
|
fromRef,
|
||||||
|
toRef,
|
||||||
|
curvature,
|
||||||
|
startXOffset,
|
||||||
|
startYOffset,
|
||||||
|
endXOffset,
|
||||||
|
endYOffset,
|
||||||
|
]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<svg
|
||||||
|
fill="none"
|
||||||
|
width={svgDimensions.width}
|
||||||
|
height={svgDimensions.height}
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
className={cx(
|
||||||
|
'pointer-events-none absolute left-0 top-0 transform-gpu stroke-2',
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
viewBox={`0 0 ${svgDimensions.width} ${svgDimensions.height}`}
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
d={pathD}
|
||||||
|
stroke={pathColor}
|
||||||
|
strokeWidth={pathWidth}
|
||||||
|
strokeOpacity={pathOpacity}
|
||||||
|
strokeLinecap="round"
|
||||||
|
/>
|
||||||
|
<path
|
||||||
|
d={pathD}
|
||||||
|
strokeWidth={pathWidth}
|
||||||
|
stroke={`url(#${id})`}
|
||||||
|
strokeOpacity="1"
|
||||||
|
strokeLinecap="round"
|
||||||
|
/>
|
||||||
|
<defs>
|
||||||
|
<motion.linearGradient
|
||||||
|
className="transform-gpu"
|
||||||
|
id={id}
|
||||||
|
gradientUnits={'userSpaceOnUse'}
|
||||||
|
initial={{
|
||||||
|
x1: '0%',
|
||||||
|
x2: '0%',
|
||||||
|
y1: '0%',
|
||||||
|
y2: '0%',
|
||||||
|
}}
|
||||||
|
animate={animateValue}
|
||||||
|
transition={{
|
||||||
|
delay,
|
||||||
|
duration,
|
||||||
|
ease: [0.16, 1, 0.3, 1], // https://easings.net/#easeOutExpo
|
||||||
|
repeat: Infinity,
|
||||||
|
repeatDelay: 0,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<stop stopColor={gradientStartColor} stopOpacity="0"></stop>
|
||||||
|
<stop stopColor={gradientStartColor}></stop>
|
||||||
|
<stop offset="32.5%" stopColor={gradientStopColor}></stop>
|
||||||
|
<stop
|
||||||
|
offset="100%"
|
||||||
|
stopColor={gradientStopColor}
|
||||||
|
stopOpacity="0"
|
||||||
|
></stop>
|
||||||
|
</motion.linearGradient>
|
||||||
|
</defs>
|
||||||
|
</svg>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export interface AnimatedAngledBeamProps {
|
||||||
|
className?: string;
|
||||||
|
containerRef: RefObject<HTMLElement>;
|
||||||
|
fromRef: RefObject<HTMLElement>;
|
||||||
|
toRef: RefObject<HTMLElement>;
|
||||||
|
reverse?: boolean;
|
||||||
|
pathColor?: string;
|
||||||
|
pathWidth?: number;
|
||||||
|
pathOpacity?: number;
|
||||||
|
gradientStartColor?: string;
|
||||||
|
gradientStopColor?: string;
|
||||||
|
delay?: number;
|
||||||
|
duration?: number;
|
||||||
|
startXOffset?: number;
|
||||||
|
startYOffset?: number;
|
||||||
|
endXOffset?: number;
|
||||||
|
endYOffset?: number;
|
||||||
|
bidirectional?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const AnimatedAngledBeam: FC<AnimatedAngledBeamProps> = ({
|
||||||
|
className,
|
||||||
|
containerRef,
|
||||||
|
fromRef,
|
||||||
|
toRef,
|
||||||
|
reverse = false,
|
||||||
|
duration = Math.random() * 3 + 8,
|
||||||
|
delay = 0,
|
||||||
|
pathColor = '#cbd5e1',
|
||||||
|
pathWidth = 2,
|
||||||
|
pathOpacity = 1,
|
||||||
|
gradientStartColor = '#ffaa40',
|
||||||
|
gradientStopColor = '#9c40ff',
|
||||||
|
startXOffset = 0,
|
||||||
|
startYOffset = 0,
|
||||||
|
endXOffset = 0,
|
||||||
|
endYOffset = 0,
|
||||||
|
bidirectional = false,
|
||||||
|
}) => {
|
||||||
|
const id = useId();
|
||||||
|
const [pathD, setPathD] = useState('');
|
||||||
|
const [svgDimensions, setSvgDimensions] = useState({ width: 0, height: 0 });
|
||||||
|
const [totalLength, setTotalLength] = useState(0);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const updatePath = () => {
|
||||||
|
if (containerRef.current && fromRef.current && toRef.current) {
|
||||||
|
const containerRect = containerRef.current.getBoundingClientRect();
|
||||||
|
const fromRect = fromRef.current.getBoundingClientRect();
|
||||||
|
const toRect = toRef.current.getBoundingClientRect();
|
||||||
|
|
||||||
|
const svgWidth = containerRect.width;
|
||||||
|
const svgHeight = containerRect.height;
|
||||||
|
setSvgDimensions({ width: svgWidth, height: svgHeight });
|
||||||
|
|
||||||
|
const startX =
|
||||||
|
fromRect.left -
|
||||||
|
containerRect.left +
|
||||||
|
fromRect.width / 2 +
|
||||||
|
startXOffset;
|
||||||
|
const startY =
|
||||||
|
fromRect.top - containerRect.top + fromRect.height / 2 + startYOffset;
|
||||||
|
const endX =
|
||||||
|
toRect.left - containerRect.left + toRect.width / 2 + endXOffset;
|
||||||
|
const endY =
|
||||||
|
toRect.top - containerRect.top + toRect.height / 2 + endYOffset;
|
||||||
|
|
||||||
|
// Create a path with 90-degree angles
|
||||||
|
const midY = (startY + endY) / 2;
|
||||||
|
const d = `M ${startX},${startY} V ${midY} H ${endX} V ${endY}`;
|
||||||
|
setPathD(d);
|
||||||
|
|
||||||
|
// Calculate total length of the path
|
||||||
|
const tempPath = document.createElementNS(
|
||||||
|
'http://www.w3.org/2000/svg',
|
||||||
|
'path'
|
||||||
|
);
|
||||||
|
tempPath.setAttribute('d', d);
|
||||||
|
setTotalLength(tempPath.getTotalLength());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const resizeObserver = new ResizeObserver((entries) => {
|
||||||
|
for (let entry of entries) {
|
||||||
|
updatePath();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (containerRef.current) {
|
||||||
|
resizeObserver.observe(containerRef.current);
|
||||||
|
}
|
||||||
|
|
||||||
|
updatePath();
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
resizeObserver.disconnect();
|
||||||
|
};
|
||||||
|
}, [
|
||||||
|
containerRef,
|
||||||
|
fromRef,
|
||||||
|
toRef,
|
||||||
|
startXOffset,
|
||||||
|
startYOffset,
|
||||||
|
endXOffset,
|
||||||
|
endYOffset,
|
||||||
|
]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<svg
|
||||||
|
fill="none"
|
||||||
|
width={svgDimensions.width}
|
||||||
|
height={svgDimensions.height}
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
className={cx(
|
||||||
|
'pointer-events-none absolute left-0 top-0 transform-gpu stroke-2',
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
viewBox={`0 0 ${svgDimensions.width} ${svgDimensions.height}`}
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
d={pathD}
|
||||||
|
stroke={pathColor}
|
||||||
|
strokeWidth={pathWidth}
|
||||||
|
strokeOpacity={pathOpacity}
|
||||||
|
strokeLinecap="round"
|
||||||
|
/>
|
||||||
|
<path
|
||||||
|
d={pathD}
|
||||||
|
strokeWidth={pathWidth}
|
||||||
|
stroke={`url(#${id})`}
|
||||||
|
strokeOpacity="1"
|
||||||
|
strokeLinecap="round"
|
||||||
|
strokeDasharray={totalLength}
|
||||||
|
strokeDashoffset="0"
|
||||||
|
>
|
||||||
|
<animate
|
||||||
|
attributeName="stroke-dashoffset"
|
||||||
|
values={
|
||||||
|
bidirectional
|
||||||
|
? `${reverse ? -totalLength : totalLength};${
|
||||||
|
reverse ? totalLength : -totalLength
|
||||||
|
};${reverse ? -totalLength : totalLength}`
|
||||||
|
: `${reverse ? -totalLength : totalLength};${
|
||||||
|
reverse ? totalLength : -totalLength
|
||||||
|
}`
|
||||||
|
}
|
||||||
|
dur={`${bidirectional ? duration * 2 : duration}s`}
|
||||||
|
repeatCount="indefinite"
|
||||||
|
/>
|
||||||
|
</path>
|
||||||
|
<defs>
|
||||||
|
<linearGradient id={id} gradientUnits="userSpaceOnUse">
|
||||||
|
<stop stopColor={gradientStartColor} stopOpacity="0" offset="0%" />
|
||||||
|
<stop stopColor={gradientStartColor} offset="10%"></stop>
|
||||||
|
<stop stopColor={gradientStopColor} offset="90%"></stop>
|
||||||
|
<stop stopColor={gradientStopColor} stopOpacity="0" offset="100%" />
|
||||||
|
</linearGradient>
|
||||||
|
</defs>
|
||||||
|
</svg>
|
||||||
|
);
|
||||||
|
};
|
||||||
@ -27,7 +27,7 @@ export { resourceMenuItems } from './lib/headers/menu-items';
|
|||||||
export { solutionsMenuItems } from './lib/headers/menu-items';
|
export { solutionsMenuItems } from './lib/headers/menu-items';
|
||||||
export { eventItems } from './lib/headers/menu-items';
|
export { eventItems } from './lib/headers/menu-items';
|
||||||
export { learnItems } from './lib/headers/menu-items';
|
export { learnItems } from './lib/headers/menu-items';
|
||||||
export { plans } from './lib/headers/menu-items';
|
export { solutions as plans } from './lib/headers/menu-items';
|
||||||
export { featuresItems } from './lib/headers/menu-items';
|
export { featuresItems } from './lib/headers/menu-items';
|
||||||
export { DefaultMenuItem } from './lib/headers/default-menu-item';
|
export { DefaultMenuItem } from './lib/headers/default-menu-item';
|
||||||
export { MobileMenuItem } from './lib/headers/mobile-menu-item';
|
export { MobileMenuItem } from './lib/headers/mobile-menu-item';
|
||||||
|
|||||||
@ -8,7 +8,7 @@ export function DefaultLayout({
|
|||||||
children,
|
children,
|
||||||
}: { isHome?: boolean } & PropsWithChildren): JSX.Element {
|
}: { isHome?: boolean } & PropsWithChildren): JSX.Element {
|
||||||
return (
|
return (
|
||||||
<div className="dark:bg-slate-950">
|
<div className="w-full overflow-hidden dark:bg-slate-950">
|
||||||
<Header />
|
<Header />
|
||||||
<div className="relative isolate">
|
<div className="relative isolate">
|
||||||
<div
|
<div
|
||||||
|
|||||||
@ -14,7 +14,7 @@ import {
|
|||||||
eventItems,
|
eventItems,
|
||||||
featuresItems,
|
featuresItems,
|
||||||
learnItems,
|
learnItems,
|
||||||
plans,
|
solutions,
|
||||||
resourceMenuItems,
|
resourceMenuItems,
|
||||||
solutionsMenuItems,
|
solutionsMenuItems,
|
||||||
} from './menu-items';
|
} from './menu-items';
|
||||||
@ -431,7 +431,7 @@ export function Header(): JSX.Element {
|
|||||||
/>
|
/>
|
||||||
</Disclosure.Button>
|
</Disclosure.Button>
|
||||||
<Disclosure.Panel as="ul" className="space-y-1">
|
<Disclosure.Panel as="ul" className="space-y-1">
|
||||||
{plans.map((item) => (
|
{solutions.map((item) => (
|
||||||
<MobileMenuItem
|
<MobileMenuItem
|
||||||
key={item.name}
|
key={item.name}
|
||||||
item={item}
|
item={item}
|
||||||
|
|||||||
@ -120,7 +120,7 @@ export const featuresItems: MenuItem[] = [
|
|||||||
isHighlight: true,
|
isHighlight: true,
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
export const plans: MenuItem[] = [
|
export const solutions: MenuItem[] = [
|
||||||
{
|
{
|
||||||
name: 'Nx Cloud',
|
name: 'Nx Cloud',
|
||||||
description:
|
description:
|
||||||
@ -130,6 +130,15 @@ export const plans: MenuItem[] = [
|
|||||||
isNew: false,
|
isNew: false,
|
||||||
isHighlight: false,
|
isHighlight: false,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: 'Nx Powerpack',
|
||||||
|
description:
|
||||||
|
'A suite of paid extensions for the Nx CLI specifically designed for enterprises.',
|
||||||
|
href: '/powerpack',
|
||||||
|
icon: null,
|
||||||
|
isNew: false,
|
||||||
|
isHighlight: false,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: 'Nx Enterprise',
|
name: 'Nx Enterprise',
|
||||||
description:
|
description:
|
||||||
@ -278,7 +287,7 @@ export const companyItems: MenuItem[] = [
|
|||||||
},
|
},
|
||||||
];
|
];
|
||||||
export const solutionsMenuItems = {
|
export const solutionsMenuItems = {
|
||||||
'Helping you grow': plans,
|
'Helping you grow': solutions,
|
||||||
// 'Use cases': useCaseItems
|
// 'Use cases': useCaseItems
|
||||||
};
|
};
|
||||||
export const resourceMenuItems = {
|
export const resourceMenuItems = {
|
||||||
|
|||||||
@ -76,6 +76,7 @@ export * from './lib/editors/visual-studio-code';
|
|||||||
|
|
||||||
// OTHERS
|
// OTHERS
|
||||||
export * from './lib/monorepo-world';
|
export * from './lib/monorepo-world';
|
||||||
|
export * from './lib/others/amazon-s3';
|
||||||
|
|
||||||
// PODCASTS
|
// PODCASTS
|
||||||
export * from './lib/podcasts/amazon-music';
|
export * from './lib/podcasts/amazon-music';
|
||||||
|
|||||||
17
nx-dev/ui-icons/src/lib/others/amazon-s3.tsx
Normal file
17
nx-dev/ui-icons/src/lib/others/amazon-s3.tsx
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
import { FC, SVGProps } from 'react';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Use `#569A31` for a colored version.
|
||||||
|
*/
|
||||||
|
export const AmazonS3Icon: FC<SVGProps<SVGSVGElement>> = (props) => (
|
||||||
|
<svg
|
||||||
|
role="img"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
fill="currentColor"
|
||||||
|
{...props}
|
||||||
|
>
|
||||||
|
<title>Amazon S3</title>
|
||||||
|
<path d="M20.913 13.147l.12-.895c.947.576 1.258.922 1.354 1.071-.16.031-.562.046-1.474-.176zm-2.174 7.988a.547.547 0 0 0-.005.073c0 .084-.207.405-1.124.768a10.28 10.28 0 0 1-1.438.432c-1.405.325-3.128.504-4.853.504-4.612 0-7.412-1.184-7.412-1.704a.547.547 0 0 0-.005-.073L1.81 5.602c.135.078.28.154.432.227.042.02.086.038.128.057.134.062.272.122.417.18l.179.069c.154.058.314.114.478.168.043.013.084.029.13.043.207.065.423.127.646.187l.176.044c.175.044.353.087.534.127a23.414 23.414 0 0 0 .843.17l.121.023c.252.045.508.085.768.122.071.011.144.02.216.03.2.027.4.053.604.077l.24.027c.245.026.49.05.74.07l.081.009c.275.022.552.04.83.056l.233.012c.21.01.422.018.633.025a33.088 33.088 0 0 0 2.795-.026l.232-.011c.278-.016.555-.034.83-.056l.08-.008c.25-.02.497-.045.742-.072l.238-.026c.205-.024.408-.05.609-.077.07-.01.141-.019.211-.03.261-.037.519-.078.772-.122l.111-.02c.215-.04.427-.082.634-.125l.212-.047c.186-.041.368-.085.546-.13l.166-.042c.225-.06.444-.122.654-.189.04-.012.077-.026.115-.038a10.6 10.6 0 0 0 .493-.173c.058-.021.114-.044.17-.066.15-.06.293-.12.43-.185.038-.017.079-.034.116-.052.153-.073.3-.15.436-.228l-.976 7.245c-2.488-.78-5.805-2.292-7.311-3a1.09 1.09 0 0 0-1.088-1.085c-.6 0-1.088.489-1.088 1.088 0 .6.488 1.089 1.088 1.089.196 0 .378-.056.537-.148 1.72.812 5.144 2.367 7.715 3.15zm-7.42-20.047c5.677 0 9.676 1.759 9.75 2.736l-.014.113c-.01.033-.031.067-.048.101-.015.028-.026.057-.047.087-.024.033-.058.068-.09.102-.028.03-.051.06-.084.09-.038.035-.087.07-.133.105-.04.03-.074.06-.119.091-.053.036-.116.071-.177.107-.05.03-.095.06-.15.09-.068.036-.147.073-.222.11-.059.028-.114.057-.177.085-.084.038-.177.074-.268.111-.068.027-.13.054-.203.082-.097.036-.205.072-.31.107-.075.026-.148.053-.228.079-.111.035-.233.069-.35.103-.085.024-.165.05-.253.073-.124.034-.258.065-.389.098-.093.022-.181.046-.278.068-.139.032-.287.061-.433.091-.098.02-.191.041-.293.06-.155.03-.32.057-.482.084-.1.018-.198.036-.302.052-.166.026-.342.048-.515.072-.11.014-.213.03-.325.044-.181.023-.372.041-.56.06-.11.012-.218.025-.332.036-.188.016-.386.029-.58.043-.122.009-.24.02-.364.028-.207.012-.422.02-.635.028-.12.005-.234.012-.354.016a35.605 35.605 0 0 1-2.069 0c-.12-.004-.234-.011-.352-.016-.214-.008-.43-.016-.637-.028-.122-.008-.238-.02-.36-.027-.195-.015-.394-.028-.584-.044-.11-.01-.215-.024-.324-.035-.19-.02-.384-.038-.568-.06l-.315-.044c-.176-.024-.355-.046-.525-.073-.1-.015-.192-.033-.29-.05-.167-.028-.335-.055-.494-.086-.096-.018-.183-.038-.276-.056-.151-.032-.305-.062-.45-.095-.09-.02-.173-.043-.26-.064-.138-.034-.277-.067-.407-.102-.082-.022-.157-.046-.235-.069a11.75 11.75 0 0 1-.368-.108c-.075-.024-.141-.049-.213-.073-.11-.037-.223-.075-.325-.113-.067-.025-.125-.051-.188-.077-.096-.038-.195-.076-.282-.115-.06-.027-.11-.054-.166-.08-.08-.039-.162-.077-.233-.116-.052-.028-.094-.055-.142-.084-.063-.038-.13-.075-.185-.113-.043-.029-.075-.058-.113-.086-.048-.037-.098-.073-.139-.11-.032-.029-.054-.057-.08-.087-.033-.035-.069-.07-.093-.104-.02-.03-.031-.058-.046-.086-.018-.035-.039-.068-.049-.102l-.015-.113c.076-.977 4.074-2.736 9.748-2.736zm12.182 12.124c-.118-.628-.84-1.291-2.31-2.128l.963-7.16a.531.531 0 0 0 .005-.073C22.16 1.581 16.447 0 11.32 0 6.194 0 .482 1.581.482 3.851a.58.58 0 0 0 .005.072L2.819 21.25c.071 2.002 5.236 2.75 8.5 2.75 1.805 0 3.615-.188 5.098-.531.598-.138 1.133-.3 1.592-.48 1.18-.467 1.789-1.053 1.813-1.739l.945-7.018c.557.131 1.016.197 1.389.197.54 0 .902-.137 1.134-.413a.956.956 0 0 0 .21-.804Z" />
|
||||||
|
</svg>
|
||||||
|
);
|
||||||
18
nx-dev/ui-powerpack/.eslintrc.json
Normal file
18
nx-dev/ui-powerpack/.eslintrc.json
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
{
|
||||||
|
"extends": ["plugin:@nx/react", "../../.eslintrc.json"],
|
||||||
|
"ignorePatterns": ["!**/*"],
|
||||||
|
"overrides": [
|
||||||
|
{
|
||||||
|
"files": ["*.ts", "*.tsx", "*.js", "*.jsx"],
|
||||||
|
"rules": {}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"files": ["*.ts", "*.tsx"],
|
||||||
|
"rules": {}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"files": ["*.js", "*.jsx"],
|
||||||
|
"rules": {}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
7
nx-dev/ui-powerpack/README.md
Normal file
7
nx-dev/ui-powerpack/README.md
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
# ui-powerpack
|
||||||
|
|
||||||
|
This library was generated with [Nx](https://nx.dev).
|
||||||
|
|
||||||
|
## Running unit tests
|
||||||
|
|
||||||
|
Run `nx test ui-powerpack` to execute the unit tests via [Jest](https://jestjs.io).
|
||||||
9
nx-dev/ui-powerpack/project.json
Normal file
9
nx-dev/ui-powerpack/project.json
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"name": "ui-powerpack",
|
||||||
|
"$schema": "../../node_modules/nx/schemas/project-schema.json",
|
||||||
|
"sourceRoot": "nx-dev/ui-powerpack/src",
|
||||||
|
"projectType": "library",
|
||||||
|
"tags": [],
|
||||||
|
"// targets": "to see all targets run: nx show project ui-powerpack --web",
|
||||||
|
"targets": {}
|
||||||
|
}
|
||||||
7
nx-dev/ui-powerpack/src/index.ts
Normal file
7
nx-dev/ui-powerpack/src/index.ts
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
// Use this file to export React client components (e.g. those with 'use client' directive) or other non-server utilities
|
||||||
|
|
||||||
|
export * from './lib/hero';
|
||||||
|
export * from './lib/powerpack-features';
|
||||||
|
export * from './lib/get-started';
|
||||||
|
export * from './lib/powerpack-pricing';
|
||||||
|
export * from './lib/call-to-action';
|
||||||
85
nx-dev/ui-powerpack/src/lib/call-to-action.tsx
Normal file
85
nx-dev/ui-powerpack/src/lib/call-to-action.tsx
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
import Link from 'next/link';
|
||||||
|
import { ReactElement } from 'react';
|
||||||
|
|
||||||
|
export function CallToAction(): ReactElement {
|
||||||
|
return (
|
||||||
|
<section className="relative isolate px-6 py-32 sm:py-40 lg:px-8">
|
||||||
|
<svg
|
||||||
|
className="absolute inset-0 -z-10 h-full w-full stroke-black/10 [mask-image:radial-gradient(100%_100%_at_top_right,white,transparent)] dark:stroke-white/10"
|
||||||
|
aria-hidden="true"
|
||||||
|
>
|
||||||
|
<defs>
|
||||||
|
<pattern
|
||||||
|
id="1d4240dd-898f-445f-932d-e2872fd12de3"
|
||||||
|
width={200}
|
||||||
|
height={200}
|
||||||
|
x="50%"
|
||||||
|
y={0}
|
||||||
|
patternUnits="userSpaceOnUse"
|
||||||
|
>
|
||||||
|
<path d="M.5 200V.5H200" fill="none" />
|
||||||
|
</pattern>
|
||||||
|
</defs>
|
||||||
|
<svg
|
||||||
|
x="50%"
|
||||||
|
y={0}
|
||||||
|
className="overflow-visible fill-slate-200/20 dark:fill-slate-800/20"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
d="M-200 0h201v201h-201Z M600 0h201v201h-201Z M-400 600h201v201h-201Z M200 800h201v201h-201Z"
|
||||||
|
strokeWidth={0}
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
<rect
|
||||||
|
width="100%"
|
||||||
|
height="100%"
|
||||||
|
strokeWidth={0}
|
||||||
|
fill="url(#1d4240dd-898f-445f-932d-e2872fd12de3)"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
<div
|
||||||
|
className="pointer-events-none absolute inset-x-0 top-10 -z-10 flex transform-gpu justify-center overflow-hidden blur-3xl"
|
||||||
|
aria-hidden="true"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
className="aspect-[1108/632] w-[69.25rem] flex-none bg-gradient-to-r from-[#80caff] to-[#4f46e5] opacity-20"
|
||||||
|
style={{
|
||||||
|
clipPath:
|
||||||
|
'polygon(73.6% 51.7%, 91.7% 11.8%, 100% 46.4%, 97.4% 82.2%, 92.5% 84.9%, 75.7% 64%, 55.3% 47.5%, 46.5% 49.4%, 45% 62.9%, 50.3% 87.2%, 21.3% 64.1%, 0.1% 100%, 5.4% 51.1%, 21.4% 63.9%, 58.9% 0.2%, 73.6% 51.7%)',
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="mx-auto max-w-2xl text-center">
|
||||||
|
<h2
|
||||||
|
id="cta"
|
||||||
|
className="text-3xl font-medium tracking-tight text-slate-950 sm:text-5xl dark:text-white"
|
||||||
|
>
|
||||||
|
Ready to enhance your CLI?
|
||||||
|
</h2>
|
||||||
|
<div className="mt-10 flex items-center justify-center gap-x-6">
|
||||||
|
<a
|
||||||
|
href="https://cloud.nx.app/powerpack/purchase"
|
||||||
|
title="Get your Nx Powerapp license"
|
||||||
|
className="rounded-md bg-slate-950 px-3.5 py-2.5 text-sm font-semibold text-slate-100 shadow-sm hover:bg-slate-800 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-white dark:bg-white dark:text-slate-900 dark:hover:bg-slate-100"
|
||||||
|
>
|
||||||
|
Get Nx Powerpack
|
||||||
|
</a>
|
||||||
|
<Link
|
||||||
|
href="/contact"
|
||||||
|
title="Get in touch"
|
||||||
|
prefetch={false}
|
||||||
|
className="group text-sm font-semibold leading-6 text-slate-950 dark:text-white"
|
||||||
|
>
|
||||||
|
Contact us{' '}
|
||||||
|
<span
|
||||||
|
aria-hidden="true"
|
||||||
|
className="inline-block transition group-hover:translate-x-1"
|
||||||
|
>
|
||||||
|
→
|
||||||
|
</span>
|
||||||
|
</Link>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
);
|
||||||
|
}
|
||||||
172
nx-dev/ui-powerpack/src/lib/get-started.tsx
Normal file
172
nx-dev/ui-powerpack/src/lib/get-started.tsx
Normal file
@ -0,0 +1,172 @@
|
|||||||
|
import { SectionHeading, TextLink } from '@nx/nx-dev/ui-common';
|
||||||
|
import { ReactElement } from 'react';
|
||||||
|
import { TerminalOutput } from '@nx/nx-dev/ui-fence';
|
||||||
|
import { PowerpackPricing } from './powerpack-pricing';
|
||||||
|
|
||||||
|
export function GetStarted(): ReactElement {
|
||||||
|
return (
|
||||||
|
<section id="get-started">
|
||||||
|
<div className="mx-auto max-w-7xl px-6 lg:px-8">
|
||||||
|
<div className="mx-auto max-w-3xl text-center">
|
||||||
|
<SectionHeading as="h2" variant="title">
|
||||||
|
Premium features, <br /> carefully crafted DX
|
||||||
|
</SectionHeading>
|
||||||
|
<SectionHeading as="p" variant="subtitle" className="text mt-6">
|
||||||
|
Expand you capabilities with Nx Powerpack, <br /> a suite of
|
||||||
|
advanced tools designed for enterprises.
|
||||||
|
</SectionHeading>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="relative mx-auto mt-16 max-w-2xl space-y-12">
|
||||||
|
<svg
|
||||||
|
className="absolute left-0 top-0 -z-10 -ml-20 hidden -translate-x-full -translate-y-1/2 transform lg:block"
|
||||||
|
width={200}
|
||||||
|
height={400}
|
||||||
|
fill="none"
|
||||||
|
viewBox="0 0 200 400"
|
||||||
|
aria-hidden="true"
|
||||||
|
>
|
||||||
|
<defs>
|
||||||
|
<pattern
|
||||||
|
id="de316486-4a29-4312-bdfc-fbce2132a2c1"
|
||||||
|
x={0}
|
||||||
|
y={0}
|
||||||
|
width={20}
|
||||||
|
height={20}
|
||||||
|
patternUnits="userSpaceOnUse"
|
||||||
|
>
|
||||||
|
<rect
|
||||||
|
x={0}
|
||||||
|
y={0}
|
||||||
|
width={4}
|
||||||
|
height={4}
|
||||||
|
className="text-slate-100 dark:text-slate-800/60"
|
||||||
|
fill="currentColor"
|
||||||
|
/>
|
||||||
|
</pattern>
|
||||||
|
</defs>
|
||||||
|
<rect
|
||||||
|
width={200}
|
||||||
|
height={400}
|
||||||
|
fill="url(#de316486-4a29-4312-bdfc-fbce2132a2c1)"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
<svg
|
||||||
|
className="absolute bottom-0 right-0 -z-10 -mr-20 hidden translate-x-full translate-y-1/2 transform lg:block"
|
||||||
|
width={200}
|
||||||
|
height={400}
|
||||||
|
fill="none"
|
||||||
|
viewBox="0 0 200 400"
|
||||||
|
aria-hidden="true"
|
||||||
|
>
|
||||||
|
<defs>
|
||||||
|
<pattern
|
||||||
|
id="de316486-4a29-4312-bdfc-fbce2132a2c1"
|
||||||
|
x={0}
|
||||||
|
y={0}
|
||||||
|
width={20}
|
||||||
|
height={20}
|
||||||
|
patternUnits="userSpaceOnUse"
|
||||||
|
>
|
||||||
|
<rect
|
||||||
|
x={0}
|
||||||
|
y={0}
|
||||||
|
width={4}
|
||||||
|
height={4}
|
||||||
|
className="text-slate-100 dark:text-slate-800/60"
|
||||||
|
fill="currentColor"
|
||||||
|
/>
|
||||||
|
</pattern>
|
||||||
|
</defs>
|
||||||
|
<rect
|
||||||
|
width={200}
|
||||||
|
height={400}
|
||||||
|
fill="url(#de316486-4a29-4312-bdfc-fbce2132a2c1)"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
<div className="space-y-6 lg:space-y-12">
|
||||||
|
<div className="flex items-start gap-6">
|
||||||
|
<div className="relative flex size-10 place-items-center rounded-full p-4 shadow-sm ring-1 ring-slate-200 dark:ring-slate-800/60">
|
||||||
|
<span className="text-lg text-slate-900 dark:text-slate-100">
|
||||||
|
1
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<h4 className="relative text-base font-medium leading-6 text-slate-900 dark:text-slate-100">
|
||||||
|
Buy an Nx Powerpack license
|
||||||
|
</h4>
|
||||||
|
<p className="mt-2">
|
||||||
|
Select between monthly payments or a one-time annual fee for
|
||||||
|
your license.
|
||||||
|
</p>
|
||||||
|
<div className="mx-auto mt-4 max-w-md">
|
||||||
|
<PowerpackPricing />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="flex items-start gap-6">
|
||||||
|
<div className="relative flex size-10 place-items-center rounded-full p-4 shadow-sm ring-1 ring-slate-200 dark:ring-slate-800/60">
|
||||||
|
<span className="text-lg text-slate-900 dark:text-slate-100">
|
||||||
|
2
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<h4 className="relative text-base font-medium leading-6 text-slate-900 dark:text-slate-100">
|
||||||
|
Activate Nx Powerpack right from your terminal
|
||||||
|
</h4>
|
||||||
|
<p className="mt-2">
|
||||||
|
In your Nx workspace, run the following command to activate
|
||||||
|
your new license.
|
||||||
|
</p>
|
||||||
|
<div className="mt-4">
|
||||||
|
<TerminalOutput
|
||||||
|
command="nx activate-powerpack {YOUR_LICENSE_KEY}"
|
||||||
|
path="~/my-workspace"
|
||||||
|
title=""
|
||||||
|
content=""
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="flex items-start gap-6">
|
||||||
|
<div className="relative flex size-10 place-items-center rounded-full p-4 shadow-sm ring-1 ring-slate-200 dark:ring-slate-800/60">
|
||||||
|
<span className="text-lg text-slate-900 dark:text-slate-100">
|
||||||
|
3
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<h4 className="relative text-base font-medium leading-6 text-slate-900 dark:text-slate-100">
|
||||||
|
Install Powerpack plugins
|
||||||
|
</h4>
|
||||||
|
<p className="mt-2">
|
||||||
|
Install Powerpack plugins such as{' '}
|
||||||
|
<TextLink
|
||||||
|
href="/features/powerpack/custom-caching"
|
||||||
|
title="Self-hosted cache storage"
|
||||||
|
>
|
||||||
|
Self-hosted cache storage
|
||||||
|
</TextLink>
|
||||||
|
,{' '}
|
||||||
|
<TextLink
|
||||||
|
href="/features/powerpack/conformance"
|
||||||
|
title="Workspace conformance"
|
||||||
|
>
|
||||||
|
workspace conformance
|
||||||
|
</TextLink>
|
||||||
|
, and{' '}
|
||||||
|
<TextLink
|
||||||
|
href="/features/powerpack/owners"
|
||||||
|
title="Codeowners for monorepos"
|
||||||
|
>
|
||||||
|
Codeowners for monorepos
|
||||||
|
</TextLink>
|
||||||
|
.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
);
|
||||||
|
}
|
||||||
29
nx-dev/ui-powerpack/src/lib/hero.tsx
Normal file
29
nx-dev/ui-powerpack/src/lib/hero.tsx
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
'use client';
|
||||||
|
import { ButtonLink, SectionHeading, Strong } from '@nx/nx-dev/ui-common';
|
||||||
|
import { ReactElement } from 'react';
|
||||||
|
|
||||||
|
export function Hero(): ReactElement {
|
||||||
|
return (
|
||||||
|
<div className="mx-auto max-w-7xl px-6 lg:px-8">
|
||||||
|
<div className="mx-auto max-w-2xl text-center">
|
||||||
|
<SectionHeading as="h1" variant="display">
|
||||||
|
Nx Powerpack
|
||||||
|
</SectionHeading>
|
||||||
|
<SectionHeading as="p" variant="subtitle" className="mt-6 text-center">
|
||||||
|
A suite of paid extensions for the Nx CLI specifically designed for
|
||||||
|
enterprises, <Strong>built and supported by the Nx core team</Strong>.
|
||||||
|
</SectionHeading>
|
||||||
|
<div className="mt-10 text-center">
|
||||||
|
<ButtonLink
|
||||||
|
href="https://cloud.nx.app/powerpack/purchase?utm_source=nx.dev&utm_medium=referral&utm_campaign=nx-powerpackurl"
|
||||||
|
title="Talk to the engineering team"
|
||||||
|
variant="primary"
|
||||||
|
size="default"
|
||||||
|
>
|
||||||
|
Get Powerpack
|
||||||
|
</ButtonLink>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
262
nx-dev/ui-powerpack/src/lib/powerpack-features.tsx
Normal file
262
nx-dev/ui-powerpack/src/lib/powerpack-features.tsx
Normal file
@ -0,0 +1,262 @@
|
|||||||
|
'use client';
|
||||||
|
import { forwardRef, ReactElement, ReactNode, useRef } from 'react';
|
||||||
|
import { ButtonLink, SectionHeading, Strong } from '@nx/nx-dev/ui-common';
|
||||||
|
import { cx } from '@nx/nx-dev/ui-primitives';
|
||||||
|
import { AnimatedAngledBeam } from '@nx/nx-dev/ui-animations';
|
||||||
|
import {
|
||||||
|
CalendarDaysIcon,
|
||||||
|
CircleStackIcon,
|
||||||
|
ServerIcon,
|
||||||
|
} from '@heroicons/react/24/outline';
|
||||||
|
import { NxIcon } from '@nx/nx-dev/ui-icons';
|
||||||
|
|
||||||
|
export function PowerpackFeatures(): ReactElement {
|
||||||
|
return (
|
||||||
|
<section className="relative isolate">
|
||||||
|
<div className="mx-auto max-w-7xl px-6 lg:px-8">
|
||||||
|
<div className="grid grid-cols-1 gap-8 lg:grid-cols-2">
|
||||||
|
<div className="col-span-full flex max-w-full flex-col gap-16 bg-white/50 px-6 py-16 ring-1 ring-slate-200 sm:rounded-3xl sm:p-8 lg:mx-0 lg:max-w-full lg:flex-row lg:items-center lg:py-16 xl:px-16 dark:bg-white/5 dark:ring-white/10">
|
||||||
|
<div className="xl:max-w-xl">
|
||||||
|
<SectionHeading
|
||||||
|
as="h2"
|
||||||
|
variant="title"
|
||||||
|
id="self-hosted-cache-storage"
|
||||||
|
className="scroll-mt-48"
|
||||||
|
>
|
||||||
|
Self-hosted cache storage
|
||||||
|
</SectionHeading>
|
||||||
|
<p className="mt-6 text-pretty text-lg">
|
||||||
|
Nx Powerpack enables you to use <Strong>AWS S3</Strong> or a{' '}
|
||||||
|
<Strong>shared network drive</Strong> as your remote cache
|
||||||
|
storage, offering a flexible, self-managed solution for faster
|
||||||
|
builds.
|
||||||
|
</p>
|
||||||
|
<div className="mt-16">
|
||||||
|
<ButtonLink
|
||||||
|
href="/features/powerpack/custom-caching"
|
||||||
|
title="Learn more about self-hosted cache storage"
|
||||||
|
variant="secondary"
|
||||||
|
size="default"
|
||||||
|
>
|
||||||
|
Learn more about self-hosted cache storage
|
||||||
|
</ButtonLink>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="hidden w-full lg:block">
|
||||||
|
<CustomRemoteCacheAnimation />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="flex flex-col gap-16 bg-white/50 px-6 py-16 ring-1 ring-slate-200 sm:rounded-3xl sm:p-8 lg:mx-0 lg:max-w-none lg:justify-between lg:py-16 xl:px-16 dark:bg-white/5 dark:ring-white/10">
|
||||||
|
<div className="max-w-2xl">
|
||||||
|
<SectionHeading
|
||||||
|
as="h2"
|
||||||
|
variant="title"
|
||||||
|
id="codeowners-for-monorepos"
|
||||||
|
className="scroll-mt-48"
|
||||||
|
>
|
||||||
|
Codeowners for monorepos
|
||||||
|
</SectionHeading>
|
||||||
|
<p className="mt-6 text-pretty text-lg">
|
||||||
|
Common VCS providers require folder-based ownership definitions.
|
||||||
|
Now, define and manage ownership where it matters—
|
||||||
|
<Strong>at the project level</Strong>
|
||||||
|
</p>
|
||||||
|
<p className="mt-6 text-pretty text-lg">
|
||||||
|
Nx Powerpack codeowners bridges this gap by{' '}
|
||||||
|
<Strong>
|
||||||
|
automatically tracking changes and syncing ownership data
|
||||||
|
</Strong>{' '}
|
||||||
|
with GitHub, GitLab, or Bitbucket-specific CODEOWNERS files.
|
||||||
|
This ensures clear responsibilities and enables efficient
|
||||||
|
collaboration across large-scale projects.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div className="flex">
|
||||||
|
<ButtonLink
|
||||||
|
href="/features/powerpack/owners"
|
||||||
|
title="Learn more about codeowners"
|
||||||
|
variant="secondary"
|
||||||
|
size="default"
|
||||||
|
>
|
||||||
|
Learn more about codeowners
|
||||||
|
</ButtonLink>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="flex flex-col gap-16 bg-white/50 px-6 py-16 ring-1 ring-slate-200 sm:rounded-3xl sm:p-8 lg:mx-0 lg:max-w-none lg:justify-between lg:py-16 xl:px-16 dark:bg-white/5 dark:ring-white/10">
|
||||||
|
<div className="max-w-2xl">
|
||||||
|
<SectionHeading
|
||||||
|
as="h2"
|
||||||
|
variant="title"
|
||||||
|
id="workspace-conformance"
|
||||||
|
className="scroll-mt-48"
|
||||||
|
>
|
||||||
|
Workspace conformance
|
||||||
|
</SectionHeading>
|
||||||
|
<p className="mt-6 text-pretty text-lg">
|
||||||
|
Ensuring consistent code quality and long-term maintainability
|
||||||
|
across large teams is critical. Nx Powerpack allows you to{' '}
|
||||||
|
<Strong>
|
||||||
|
define and run conformance rules throughout your workspace
|
||||||
|
</Strong>
|
||||||
|
, leverage built-in rules or{' '}
|
||||||
|
<Strong>
|
||||||
|
create your own to ensure compliance with organizational
|
||||||
|
standards.
|
||||||
|
</Strong>
|
||||||
|
</p>
|
||||||
|
<p className="mt-6 text-pretty text-lg">
|
||||||
|
With Nx Cloud Enterprise Edition, you can{' '}
|
||||||
|
<Strong>
|
||||||
|
upload your custom rules to your Nx Cloud organization
|
||||||
|
</Strong>{' '}
|
||||||
|
and automatically enforce them across multiple repositories and
|
||||||
|
workspaces, regardless of your tech stack.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div className="flex">
|
||||||
|
<ButtonLink
|
||||||
|
href="/features/powerpack/conformance"
|
||||||
|
title="Learn how to set up conformance rules"
|
||||||
|
variant="secondary"
|
||||||
|
size="default"
|
||||||
|
>
|
||||||
|
Learn how to use conformance rules
|
||||||
|
</ButtonLink>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div
|
||||||
|
className="absolute inset-x-0 top-16 -z-10 flex transform-gpu justify-center overflow-hidden blur-3xl"
|
||||||
|
aria-hidden="true"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
className="aspect-[1318/752] w-[82.375rem] flex-none bg-gradient-to-r from-[#80caff] to-[#4f46e5] opacity-25"
|
||||||
|
style={{
|
||||||
|
clipPath:
|
||||||
|
'polygon(73.6% 51.7%, 91.7% 11.8%, 100% 46.4%, 97.4% 82.2%, 92.5% 84.9%, 75.7% 64%, 55.3% 47.5%, 46.5% 49.4%, 45% 62.9%, 50.3% 87.2%, 21.3% 64.1%, 0.1% 100%, 5.4% 51.1%, 21.4% 63.9%, 58.9% 0.2%, 73.6% 51.7%)',
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const Card = forwardRef<
|
||||||
|
HTMLDivElement,
|
||||||
|
{ className?: string; children?: ReactNode }
|
||||||
|
>(({ className, children }, ref) => {
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
ref={ref}
|
||||||
|
className={cx(
|
||||||
|
'z-10 flex flex-col items-center justify-between rounded-lg border border-slate-200 bg-white p-4 shadow-sm dark:border-white/10 dark:bg-slate-950',
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
{children}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
Card.displayName = 'Card';
|
||||||
|
|
||||||
|
export function CustomRemoteCacheAnimation(): ReactElement {
|
||||||
|
const containerRef = useRef<HTMLDivElement>(null);
|
||||||
|
const gitHubRef = useRef<HTMLDivElement>(null);
|
||||||
|
const gitlabRef = useRef<HTMLDivElement>(null);
|
||||||
|
const nxRef = useRef<HTMLDivElement>(null);
|
||||||
|
const computerRef = useRef<HTMLDivElement>(null);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="relative flex h-full w-full" ref={containerRef}>
|
||||||
|
<div className="flex w-full flex-col items-center justify-center gap-24">
|
||||||
|
<div className="flex w-full justify-center">
|
||||||
|
<Card ref={nxRef} className="size-18 relative">
|
||||||
|
<NxIcon
|
||||||
|
aria-hidden="true"
|
||||||
|
className="size-10 text-slate-900 dark:text-white"
|
||||||
|
/>
|
||||||
|
<CircleStackIcon
|
||||||
|
aria-hidden="true"
|
||||||
|
className="absolute bottom-1 right-1 size-5 text-slate-900 dark:text-white"
|
||||||
|
/>
|
||||||
|
</Card>
|
||||||
|
</div>
|
||||||
|
<div className="grid w-full grid-cols-3 items-stretch gap-4">
|
||||||
|
<Card ref={gitlabRef}>
|
||||||
|
<div className="text-center text-sm text-slate-900 dark:text-white">
|
||||||
|
AWS
|
||||||
|
</div>
|
||||||
|
<div className="mt-2 text-center text-2xl font-semibold">S3</div>
|
||||||
|
|
||||||
|
<ButtonLink
|
||||||
|
href="/nx-api/powerpack-s3-cache"
|
||||||
|
title="Learn how to configure AWS S3 caching"
|
||||||
|
variant="secondary"
|
||||||
|
size="small"
|
||||||
|
className="mt-4"
|
||||||
|
>
|
||||||
|
Get started
|
||||||
|
</ButtonLink>
|
||||||
|
</Card>
|
||||||
|
<Card ref={computerRef}>
|
||||||
|
<div className="text-center text-sm text-slate-900 dark:text-white">
|
||||||
|
Network drive
|
||||||
|
</div>
|
||||||
|
<ServerIcon aria-hidden="true" className="size-6" />
|
||||||
|
|
||||||
|
<ButtonLink
|
||||||
|
href="/nx-api/powerpack-shared-fs-cache"
|
||||||
|
title="Learn how to configure network drive caching"
|
||||||
|
variant="secondary"
|
||||||
|
size="small"
|
||||||
|
className="mt-4"
|
||||||
|
>
|
||||||
|
Get started
|
||||||
|
</ButtonLink>
|
||||||
|
</Card>
|
||||||
|
<Card ref={gitHubRef}>
|
||||||
|
<div className="text-center text-sm text-slate-900 dark:text-white">
|
||||||
|
More soon!
|
||||||
|
</div>
|
||||||
|
<CalendarDaysIcon aria-hidden="true" className="size-6" />
|
||||||
|
<div className="mt-4 size-8" />
|
||||||
|
</Card>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<AnimatedAngledBeam
|
||||||
|
containerRef={containerRef}
|
||||||
|
fromRef={gitlabRef}
|
||||||
|
toRef={nxRef}
|
||||||
|
endYOffset={0}
|
||||||
|
bidirectional={true}
|
||||||
|
duration={3}
|
||||||
|
/>
|
||||||
|
<AnimatedAngledBeam
|
||||||
|
containerRef={containerRef}
|
||||||
|
fromRef={computerRef}
|
||||||
|
toRef={nxRef}
|
||||||
|
startYOffset={0}
|
||||||
|
endYOffset={0}
|
||||||
|
startXOffset={0}
|
||||||
|
endXOffset={0}
|
||||||
|
bidirectional={true}
|
||||||
|
duration={3}
|
||||||
|
delay={1}
|
||||||
|
/>
|
||||||
|
<AnimatedAngledBeam
|
||||||
|
containerRef={containerRef}
|
||||||
|
fromRef={gitHubRef}
|
||||||
|
toRef={nxRef}
|
||||||
|
endYOffset={0}
|
||||||
|
bidirectional={true}
|
||||||
|
duration={3}
|
||||||
|
delay={2}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
74
nx-dev/ui-powerpack/src/lib/powerpack-pricing.tsx
Normal file
74
nx-dev/ui-powerpack/src/lib/powerpack-pricing.tsx
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
'use client';
|
||||||
|
import { ArrowRightIcon } from '@heroicons/react/24/outline';
|
||||||
|
import { ButtonLink } from '@nx/nx-dev/ui-common';
|
||||||
|
|
||||||
|
export function PowerpackPricing() {
|
||||||
|
return (
|
||||||
|
<aside>
|
||||||
|
{/*<h4 className="text-lg font-medium leading-6 text-slate-900 dark:text-slate-100">*/}
|
||||||
|
{/* Nx Powerpack license subscription*/}
|
||||||
|
{/*</h4>*/}
|
||||||
|
|
||||||
|
<div className="flex flex-col gap-2">
|
||||||
|
<div className="group relative flex w-full items-center justify-between gap-8 rounded-md border border-slate-200 bg-white px-6 py-4 transition hover:bg-white/90 hover:shadow dark:border-slate-800/60 dark:bg-slate-900/60 dark:hover:bg-slate-900/100">
|
||||||
|
<a
|
||||||
|
href="https://cloud.nx.app/powerpack/purchase?utm_source=nx.dev&utm_medium=referral&utm_campaign=nx-powerpackurl"
|
||||||
|
title="Buy your license"
|
||||||
|
className="flex items-center gap-2"
|
||||||
|
>
|
||||||
|
<span className="absolute inset-0" />
|
||||||
|
|
||||||
|
<ArrowRightIcon aria-hidden="true" className="size-4" />
|
||||||
|
<span className="text-sm font-medium leading-none text-slate-900 dark:text-slate-50">
|
||||||
|
Billed annually
|
||||||
|
</span>
|
||||||
|
<span className="inline-flex items-center gap-x-1 whitespace-nowrap rounded-md bg-blue-50 px-2 py-1 text-xs font-medium text-blue-900 ring-1 ring-inset ring-blue-500/30 dark:bg-blue-400/10 dark:text-blue-400 dark:ring-blue-400/30">
|
||||||
|
Save 20%
|
||||||
|
</span>
|
||||||
|
</a>
|
||||||
|
<p className="text-base">
|
||||||
|
<span className="font-semibold text-slate-950 dark:text-white">
|
||||||
|
$250
|
||||||
|
</span>
|
||||||
|
<span className="text-xs text-slate-500 dark:text-slate-400">
|
||||||
|
/seat
|
||||||
|
</span>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="mt-4 flex flex-col gap-2">
|
||||||
|
<div className="group relative flex w-full items-center justify-between gap-8 rounded-md border border-slate-200 bg-white px-6 py-4 transition hover:bg-white/90 hover:shadow dark:border-slate-800/60 dark:bg-slate-900/60 dark:hover:bg-slate-900/100">
|
||||||
|
<a
|
||||||
|
href="https://cloud.nx.app/powerpack/purchase?utm_source=nx.dev&utm_medium=referral&utm_campaign=nx-powerpackurl"
|
||||||
|
title="Buy your license"
|
||||||
|
className="flex items-center gap-2"
|
||||||
|
>
|
||||||
|
<span className="absolute inset-0" />
|
||||||
|
<ArrowRightIcon aria-hidden="true" className="size-4" />
|
||||||
|
<span className="text-sm font-medium leading-none text-slate-900 dark:text-slate-50">
|
||||||
|
Billed monthly
|
||||||
|
</span>
|
||||||
|
</a>
|
||||||
|
<p className="text-base">
|
||||||
|
<span className="font-semibold text-slate-950 dark:text-white">
|
||||||
|
$26
|
||||||
|
</span>
|
||||||
|
<span className="text-xs text-slate-500 dark:text-slate-400">
|
||||||
|
/seat
|
||||||
|
</span>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="mt-4 flex flex-col gap-2">
|
||||||
|
<ButtonLink
|
||||||
|
href="https://cloud.nx.app/powerpack/purchase?utm_source=nx.dev&utm_medium=referral&utm_campaign=nx-powerpackurl"
|
||||||
|
title="Talk to the engineering team"
|
||||||
|
variant="primary"
|
||||||
|
size="default"
|
||||||
|
>
|
||||||
|
Buy your Nx Powerpack license
|
||||||
|
</ButtonLink>
|
||||||
|
</div>
|
||||||
|
</aside>
|
||||||
|
);
|
||||||
|
}
|
||||||
1
nx-dev/ui-powerpack/src/server.ts
Normal file
1
nx-dev/ui-powerpack/src/server.ts
Normal file
@ -0,0 +1 @@
|
|||||||
|
// Use this file to export React server components
|
||||||
17
nx-dev/ui-powerpack/tsconfig.json
Normal file
17
nx-dev/ui-powerpack/tsconfig.json
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"jsx": "react-jsx",
|
||||||
|
"allowJs": false,
|
||||||
|
"esModuleInterop": false,
|
||||||
|
"allowSyntheticDefaultImports": true,
|
||||||
|
"strict": true
|
||||||
|
},
|
||||||
|
"files": [],
|
||||||
|
"include": [],
|
||||||
|
"references": [
|
||||||
|
{
|
||||||
|
"path": "./tsconfig.lib.json"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"extends": "../../tsconfig.base.json"
|
||||||
|
}
|
||||||
23
nx-dev/ui-powerpack/tsconfig.lib.json
Normal file
23
nx-dev/ui-powerpack/tsconfig.lib.json
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
{
|
||||||
|
"extends": "./tsconfig.json",
|
||||||
|
"compilerOptions": {
|
||||||
|
"outDir": "../../dist/out-tsc",
|
||||||
|
"types": [
|
||||||
|
"node",
|
||||||
|
"@nx/react/typings/cssmodule.d.ts",
|
||||||
|
"@nx/react/typings/image.d.ts"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"exclude": [
|
||||||
|
"jest.config.ts",
|
||||||
|
"src/**/*.spec.ts",
|
||||||
|
"src/**/*.test.ts",
|
||||||
|
"src/**/*.spec.tsx",
|
||||||
|
"src/**/*.test.tsx",
|
||||||
|
"src/**/*.spec.js",
|
||||||
|
"src/**/*.test.js",
|
||||||
|
"src/**/*.spec.jsx",
|
||||||
|
"src/**/*.test.jsx"
|
||||||
|
],
|
||||||
|
"include": ["src/**/*.js", "src/**/*.jsx", "src/**/*.ts", "src/**/*.tsx"]
|
||||||
|
}
|
||||||
16
nx.json
16
nx.json
@ -234,6 +234,15 @@
|
|||||||
"targetName": "e2e-macos-local",
|
"targetName": "e2e-macos-local",
|
||||||
"ciTargetName": "e2e-macos-ci"
|
"ciTargetName": "e2e-macos-ci"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"plugin": "@nx/next/plugin",
|
||||||
|
"options": {
|
||||||
|
"startTargetName": "next:start",
|
||||||
|
"buildTargetName": "next:build",
|
||||||
|
"devTargetName": "dev",
|
||||||
|
"serveStaticTargetName": "serve-static"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"nxCloudId": "62d013ea0852fe0a2df74438",
|
"nxCloudId": "62d013ea0852fe0a2df74438",
|
||||||
@ -241,5 +250,10 @@
|
|||||||
"parallel": 1,
|
"parallel": 1,
|
||||||
"cacheDirectory": "/tmp/nx-cache",
|
"cacheDirectory": "/tmp/nx-cache",
|
||||||
"bust": 8,
|
"bust": 8,
|
||||||
"defaultBase": "master"
|
"defaultBase": "master",
|
||||||
|
"generators": {
|
||||||
|
"@nx/react": {
|
||||||
|
"library": {}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -108,6 +108,7 @@
|
|||||||
"@nx/nx-dev/ui-markdoc": ["nx-dev/ui-markdoc/src/index.ts"],
|
"@nx/nx-dev/ui-markdoc": ["nx-dev/ui-markdoc/src/index.ts"],
|
||||||
"@nx/nx-dev/ui-member-card": ["nx-dev/ui-member-card/src/index.ts"],
|
"@nx/nx-dev/ui-member-card": ["nx-dev/ui-member-card/src/index.ts"],
|
||||||
"@nx/nx-dev/ui-podcast": ["nx-dev/ui-podcast/src/index.ts"],
|
"@nx/nx-dev/ui-podcast": ["nx-dev/ui-podcast/src/index.ts"],
|
||||||
|
"@nx/nx-dev/ui-powerpack": ["nx-dev/ui-powerpack/src/index.ts"],
|
||||||
"@nx/nx-dev/ui-pricing": ["nx-dev/ui-pricing/src/index.ts"],
|
"@nx/nx-dev/ui-pricing": ["nx-dev/ui-pricing/src/index.ts"],
|
||||||
"@nx/nx-dev/ui-primitives": ["nx-dev/ui-primitives/src/index.ts"],
|
"@nx/nx-dev/ui-primitives": ["nx-dev/ui-primitives/src/index.ts"],
|
||||||
"@nx/nx-dev/ui-references": ["nx-dev/ui-references/src/index.ts"],
|
"@nx/nx-dev/ui-references": ["nx-dev/ui-references/src/index.ts"],
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user