From 145158ff1729bcf78256fd689064863ea927e584 Mon Sep 17 00:00:00 2001 From: Jye Cusch Date: Wed, 4 Sep 2024 14:05:37 +1000 Subject: [PATCH 01/11] doc(homepage): new home/introduction page --- src/pages/index.mdx | 263 ++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 251 insertions(+), 12 deletions(-) diff --git a/src/pages/index.mdx b/src/pages/index.mdx index 9a800078b..415b55605 100644 --- a/src/pages/index.mdx +++ b/src/pages/index.mdx @@ -1,9 +1,5 @@ -import { Community } from '@/components/Community' import { HomeHeader } from '@/components/HomeHeader' -import { Libraries } from '@/components/Libraries' -import { Providers } from '@/components/Providers' -import { GettingStarted } from '@/components/GettingStarted' -import { Concepts } from '@/components/Concepts' +import { InstallNitric } from '@/components/InstallNitric' export const description = 'Documentation for the Nitric cloud application framework.' @@ -12,17 +8,260 @@ export const disableEditGithub = true - +Nitric is a cloud framework with common resources like APIs, webhooks, databases, queues, topics, buckets, and more. - +However, Nitric is unique - it doesn't just deploy the resources, it helps you interact with them. It also makes them plugable, so you can swap services or even whole clouds without changing your code. -{/* */} +It's what's missing between applications and infrastructure automation. - +Oh, and it supports basically any language, like JavaScript, TypeScript, Python, Go, you name it. - +## Services - +Services are the heart of nitric apps, they're the entrypoints to your code. They can serve as APIs, webhooks, schedule handlers, subscribers and a lot more. You create services by telling Nitric where to look for your code and how to run it. + +```yaml {{ label:"nitric.yaml" }} +name: example +services: + - match: services/*.ts + start: npm run dev:services $SERVICE_PATH +``` + +You might have one service that handles everything, or a service for each route. It's up to you. + +## Resources + +Resources are the building blocks of your apps. They're the databases, queues, buckets, etc. that your services interact with. If you want a resource, you just ask for it. + + + +```javascript +import { bucket } from '@nitric/sdk' + +const profiles = bucket('profiles').allow('read', 'write', 'delete') +``` + +```python +from nitric.resources import bucket +from nitric.application import Nitric + +profiles = bucket('profiles').allow('read', 'write', 'delete') + +Nitric.run() +``` + +```go +import ( + "fmt" + + "github.com/nitrictech/go-sdk/nitric" +) + +func main() { + profiles, _ := nitric.NewBucket("profiles").Allow(nitric.BucketRead, nitric.BucketWrite, nitric.BucketDelete) + + if err := nitric.Run(); err != nil { + fmt.Println(err) + } +} +``` + +```dart +import 'package:nitric_sdk/nitric.dart'; + +final profiles = Nitric.bucket("profiles").allow([ + BucketPermission.read, + BucketPermission.write, + BucketPermission.delete, +]); +``` + + + +Nitric collects everything your services request. When you deploy, the deployment plugin you choose creates the resources and services, then links it all together. + + + That probably sounds like magic, but it's more like a compiler for Infrastructure-as-Code - you can read about it in the [Concepts](/docs/concepts) section. + + +## Providers + +Nitric is designed to be independent of any platform, so you can run your apps anywhere. You can deploy to AWS, Azure, GCP, or even your own Kubernetes cluster. You can even deploy to multiple clouds at once. + +Seriously, is there really a difference between a bucket on AWS and a bucket on Azure? We doesn't think so. So why is the code different? + +Nitric abstracts away the differences, so you can focus on your app. The part that makes that possible is a plugin, we call a **Provider**. + + + +```yaml {{ label:"nitric.prod.yaml", title: "AWS Pulumi" }} +provider: nitric/aws@1.1.1 +region: us-east-1 +``` + +```yaml {{ label:"nitric.prod.yaml", title: "Azure Pulumi" }} +provider: nitric/azure@1.1.1 +region: East US +``` + +```yaml {{ label:"nitric.prod.yaml", title: "Google Pulumi" }} +provider: nitric/gcp@1.1.1 +region: us-east1 +``` + +```yaml {{ label:"nitric.prod.yaml", title: "AWS Terraform" }} +provider: nitric/awstf@1.1.1 +region: us-east-1 +``` + +```yaml {{ label:"nitric.prod.yaml", title: "Google Terraform" }} +provider: nitric/gcptf@1.1.1 +region: us-east1 +``` + +```yaml {{ label:"nitric.prod.yaml", title: "Custom" }} +# Build your own provider to deploy anywhere you like. +provider: custom/on-prem@1.0.0 +``` + + + +We have a few providers built-in with IaC from Pulumi or Terraform, but you can build your own with any tools you prefer and to anywhere you want. You can even deploy to multiple clouds at once. + +## Projects + +Projects built with Nitric don't have many restrictions. You can use most languages, most libraries, most tools, most clouds, most services, mostly anything you like. But, you need to have a `nitric.yaml` file in the root of your project. + +```yaml {{ label:"nitric.yaml" }} +name: example +services: + - match: services/*.ts + start: npm run dev:services $SERVICE_PATH +``` + +Nitric uses this to find your services, then it turns each service into a container, runs them in deployment mode to match the resources you requested and gives the result to the Provider - which either generates IaC (like Terraform) or automatically deploys your app. + +So, a project structure might look something like this: + + + +```plaintext {{ title:"JavaScript" }} +example/ +├── nitric.yaml +├── services/ +│ └── orders.ts +│ └── users.ts +└── package.json +``` + +```plaintext {{ title:"Python" }} +example/ +├── nitric.yaml +├── services/ +│ └── orders.py +│ └── users.py +└── Pipfile +``` + +```plaintext {{ title:"Go" }} +example/ +├── nitric.yaml +├── services/ +│ ├── orders/ +│ │ └── main.go +│ └── users/ +│ └── main.go +├── dockerfile +└── go.mod +``` + +```plaintext {{ title:"Dart" }} +example/ +├── nitric.yaml +├── services/ +│ └── orders.dart +│ └── users.dart +└── pubspec.yaml +``` + + + +## CLI + +Nitric has a CLI to help you create, manage, run and deploy your projects. We recommend installing it with a package manager: + + + +```bash {{ title: 'macOS' }} +brew install nitrictech/tap/nitric +``` + +```bash {{ title: 'Windows' }} +scoop bucket add nitric https://github.com/nitrictech/scoop-bucket.git +scoop install nitric +``` + +```bash {{ title: 'Linux' }} +curl -L "https://nitric.io/install?version=latest" | bash +``` + + + +### New + +You can create a new project from a template with the `new` command. + +```bash +nitric new +``` + +### Start + +You can run your project locally with the `start` command. + +```bash +nitric start +``` + + + Start also emulates the resources you requested, so you can test your app locally. And provides a Dashboard UI to interact with the resources. + + +### Deploy + +You can deploy your project with the `up` command, once you have a stack file (deployment target). + +```bash +nitric stack new + +nitric up +``` + + + Some providers don't deploy directly, instead they generate IaC files. In those cases you use the IaC tool to deploy (e.g. `terraform apply`). + + +### Tear Down + +You can tear down your project with the `down` command. + +```bash +nitric down +``` + +## Dashboard + +Nitric has a local Dashboard UI (hosted by the CLI) to help you interact with your resources. You can typically access it at [http://localhost:49152](http://localhost:49152/). + +screen shot of the local development dashboard + +## What now? + +If you're still not sure what to make of Nitric, maybe start with the [Concepts](/docs/concepts) section, otherwise the best way to learn is to dive into the [Guides](/docs/guides) and start building your first project. From da0893c369c5080b662e8af634856b1d94bbd8f5 Mon Sep 17 00:00:00 2001 From: Jye Cusch Date: Wed, 4 Sep 2024 14:11:48 +1000 Subject: [PATCH 02/11] add missing labels --- src/pages/index.mdx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/pages/index.mdx b/src/pages/index.mdx index 415b55605..9720bf909 100644 --- a/src/pages/index.mdx +++ b/src/pages/index.mdx @@ -38,13 +38,13 @@ Resources are the building blocks of your apps. They're the databases, queues, b -```javascript +```javascript {{ label:"services/example.js" }} import { bucket } from '@nitric/sdk' const profiles = bucket('profiles').allow('read', 'write', 'delete') ``` -```python +```python {{ label:"services/example.py" }} from nitric.resources import bucket from nitric.application import Nitric @@ -53,7 +53,7 @@ profiles = bucket('profiles').allow('read', 'write', 'delete') Nitric.run() ``` -```go +```go {{ label:"services/example/main.go" }} import ( "fmt" @@ -69,7 +69,7 @@ func main() { } ``` -```dart +```dart {{ label:"services/example.dart" }} import 'package:nitric_sdk/nitric.dart'; final profiles = Nitric.bucket("profiles").allow([ From ae593bcb7ba2a037ba1fbf9845ec66e0fc725add Mon Sep 17 00:00:00 2001 From: Jye Cusch Date: Thu, 5 Sep 2024 12:45:58 +1000 Subject: [PATCH 03/11] Apply suggestions from code review Co-authored-by: Ryan Cartwright <39504851+HomelessDinosaur@users.noreply.github.com> --- src/pages/index.mdx | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/src/pages/index.mdx b/src/pages/index.mdx index 9720bf909..b3b2ade42 100644 --- a/src/pages/index.mdx +++ b/src/pages/index.mdx @@ -11,9 +11,9 @@ export const disableEditGithub = true description="Build cloud backends that run anywhere, fast." /> -Nitric is a cloud framework with common resources like APIs, webhooks, databases, queues, topics, buckets, and more. +Nitric is a cloud framework with common resources like APIs, websockets, databases, queues, topics, buckets, and more. -However, Nitric is unique - it doesn't just deploy the resources, it helps you interact with them. It also makes them plugable, so you can swap services or even whole clouds without changing your code. +However, Nitric is unique - it doesn't just deploy the resources, it helps you interact with them. It also makes them pluggable, so you can swap services or even whole clouds without changing your code. It's what's missing between applications and infrastructure automation. @@ -21,7 +21,7 @@ Oh, and it supports basically any language, like JavaScript, TypeScript, Python, ## Services -Services are the heart of nitric apps, they're the entrypoints to your code. They can serve as APIs, webhooks, schedule handlers, subscribers and a lot more. You create services by telling Nitric where to look for your code and how to run it. +Services are the heart of Nitric apps, they're the entrypoints to your code. They can serve as APIs, websockets, schedule handlers, subscribers and a lot more. You create services by telling Nitric where to look for your code and how to run it. ```yaml {{ label:"nitric.yaml" }} name: example @@ -72,11 +72,13 @@ func main() { ```dart {{ label:"services/example.dart" }} import 'package:nitric_sdk/nitric.dart'; -final profiles = Nitric.bucket("profiles").allow([ - BucketPermission.read, - BucketPermission.write, - BucketPermission.delete, -]); +void main() { + final profiles = Nitric.bucket("profiles").allow([ + BucketPermission.read, + BucketPermission.write, + BucketPermission.delete, + ]); +} ``` @@ -91,7 +93,7 @@ Nitric collects everything your services request. When you deploy, the deploymen Nitric is designed to be independent of any platform, so you can run your apps anywhere. You can deploy to AWS, Azure, GCP, or even your own Kubernetes cluster. You can even deploy to multiple clouds at once. -Seriously, is there really a difference between a bucket on AWS and a bucket on Azure? We doesn't think so. So why is the code different? +Seriously, is there really a difference between a bucket on AWS and a bucket on Azure? We don't think so. So why should the code be different? Nitric abstracts away the differences, so you can focus on your app. The part that makes that possible is a plugin, we call a **Provider**. From 064b04ce8f3ae3514b86296b508bc4fea5049077 Mon Sep 17 00:00:00 2001 From: Jye Cusch Date: Thu, 5 Sep 2024 13:57:31 +1000 Subject: [PATCH 04/11] Auto stash before checking out "origin/docs/new-layout" --- src/components/Libraries.tsx | 28 +++++++++++++++++++++++++++- src/pages/index.mdx | 13 +++++++++++-- 2 files changed, 38 insertions(+), 3 deletions(-) diff --git a/src/components/Libraries.tsx b/src/components/Libraries.tsx index ca82b0a10..612e3a230 100644 --- a/src/components/Libraries.tsx +++ b/src/components/Libraries.tsx @@ -49,7 +49,33 @@ const libraries = [ }, ] -export function Libraries() { +export interface LibrariesProps { + minimal?: boolean +} + +export function Libraries({ minimal = false }: LibrariesProps) { + if (minimal) { + return ( +
+ {libraries.map((library) => ( + + {library.name + + ))} +
+ ) + } + return (
diff --git a/src/pages/index.mdx b/src/pages/index.mdx index b3b2ade42..89d7e0cdb 100644 --- a/src/pages/index.mdx +++ b/src/pages/index.mdx @@ -1,5 +1,6 @@ import { HomeHeader } from '@/components/HomeHeader' import { InstallNitric } from '@/components/InstallNitric' +import { Libraries } from '@/components/Libraries' export const description = 'Documentation for the Nitric cloud application framework.' @@ -19,6 +20,10 @@ It's what's missing between applications and infrastructure automation. Oh, and it supports basically any language, like JavaScript, TypeScript, Python, Go, you name it. +
+ +
+ ## Services Services are the heart of Nitric apps, they're the entrypoints to your code. They can serve as APIs, websockets, schedule handlers, subscribers and a lot more. You create services by telling Nitric where to look for your code and how to run it. @@ -131,7 +136,7 @@ provider: custom/on-prem@1.0.0 -We have a few providers built-in with IaC from Pulumi or Terraform, but you can build your own with any tools you prefer and to anywhere you want. You can even deploy to multiple clouds at once. +We have a few providers built-in with IaC from Pulumi or Terraform, but you can build your own with any tools you prefer and to anywhere you want. ## Projects @@ -256,7 +261,7 @@ nitric down ## Dashboard -Nitric has a local Dashboard UI (hosted by the CLI) to help you interact with your resources. You can typically access it at [http://localhost:49152](http://localhost:49152/). +Nitric has a local Dashboard UI (hosted by the CLI) to help you interact with your resources. You can typically access it at [http://localhost:49152](http://localhost:49152/) after running `nitric start` or `nitric run`. screen shot of the local development dashboard +## Extension + +TODO + ## What now? If you're still not sure what to make of Nitric, maybe start with the [Concepts](/docs/concepts) section, otherwise the best way to learn is to dive into the [Guides](/docs/guides) and start building your first project. From c46632cb26c987503cdfb68c66f59d42609e0b2b Mon Sep 17 00:00:00 2001 From: Jye Cusch Date: Thu, 5 Sep 2024 14:50:06 +1000 Subject: [PATCH 05/11] Add local dev and extension sections --- src/pages/index.mdx | 98 +++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 94 insertions(+), 4 deletions(-) diff --git a/src/pages/index.mdx b/src/pages/index.mdx index 89d7e0cdb..ad7351228 100644 --- a/src/pages/index.mdx +++ b/src/pages/index.mdx @@ -12,6 +12,8 @@ export const disableEditGithub = true description="Build cloud backends that run anywhere, fast." /> +--- + Nitric is a cloud framework with common resources like APIs, websockets, databases, queues, topics, buckets, and more. However, Nitric is unique - it doesn't just deploy the resources, it helps you interact with them. It also makes them pluggable, so you can swap services or even whole clouds without changing your code. @@ -24,6 +26,8 @@ Oh, and it supports basically any language, like JavaScript, TypeScript, Python,
+--- + ## Services Services are the heart of Nitric apps, they're the entrypoints to your code. They can serve as APIs, websockets, schedule handlers, subscribers and a lot more. You create services by telling Nitric where to look for your code and how to run it. @@ -37,6 +41,8 @@ services: You might have one service that handles everything, or a service for each route. It's up to you. +--- + ## Resources Resources are the building blocks of your apps. They're the databases, queues, buckets, etc. that your services interact with. If you want a resource, you just ask for it. @@ -94,6 +100,8 @@ Nitric collects everything your services request. When you deploy, the deploymen That probably sounds like magic, but it's more like a compiler for Infrastructure-as-Code - you can read about it in the [Concepts](/docs/concepts) section. +--- + ## Providers Nitric is designed to be independent of any platform, so you can run your apps anywhere. You can deploy to AWS, Azure, GCP, or even your own Kubernetes cluster. You can even deploy to multiple clouds at once. @@ -138,6 +146,8 @@ provider: custom/on-prem@1.0.0 We have a few providers built-in with IaC from Pulumi or Terraform, but you can build your own with any tools you prefer and to anywhere you want. +--- + ## Projects Projects built with Nitric don't have many restrictions. You can use most languages, most libraries, most tools, most clouds, most services, mostly anything you like. But, you need to have a `nitric.yaml` file in the root of your project. @@ -196,6 +206,8 @@ example/ +--- + ## CLI Nitric has a CLI to help you create, manage, run and deploy your projects. We recommend installing it with a package manager: @@ -259,9 +271,15 @@ You can tear down your project with the `down` command. nitric down ``` -## Dashboard +--- -Nitric has a local Dashboard UI (hosted by the CLI) to help you interact with your resources. You can typically access it at [http://localhost:49152](http://localhost:49152/) after running `nitric start` or `nitric run`. +## Local development + +Sometimes you just want to run your app locally and we let you do just that. And we don't mean "binds to a cloud environment and syncs your code, but doesn't work without Wifi" local, we mean "runs on your machine, on a desert island" local. + +`nitric start` hosts entrypoints like APIs, websockets, and schedules, as well as resources like databases, topics, queues, key/value stores and buckets. + +It also provides a Dashboard to interact with your resources, so you can trigger schedules without waiting, or topics without a publisher, or upload test files to a bucket. It even produces a real-time architecture diagram of your services and resources. screen shot of the local development dashboard -## Extension +--- + +## Extension & Escape Hatches + +The services of cloud providers are vast, we can't cover everything and we shouldn't. Many services are unique enough that abstraction would be a disservice. Nitric aims to make common "table stakes" services easy to use, but we never want to limit you. + +### Runtime + +If you need to access a service in a way Nitric doesn't support, you can always use the provider's SDK directly. Code like this will always work: + + + +```javascript +import { S3Client } from '@aws-sdk/client-s3' + +const s3 = new S3Client({ region: 'us-east-1' }) + +const { Contents } = await s3.listObjectsV2({ Bucket: 'my-bucket' }) +``` + +```python +from boto3 import client + +s3 = client('s3', region_name='us-east-1') + +response = s3.list_objects_v2(Bucket='my-bucket') +``` + +```go +import ( + "context" + + "github.com/aws/aws-sdk-go-v2/config" + "github.com/aws/aws-sdk-go-v2/service/s3" +) + +cfg, _ := config.LoadDefaultConfig(context.TODO()) +client := s3.NewFromConfig(cfg) + +output, _ := client.ListObjectsV2(context.TODO(), &s3.ListObjectsV2Input{ + Bucket: aws.String("my-bucket"), +}) +``` + +```dart +import 'package:aws_s3/aws_s3.dart'; + +final s3 = S3(region: 'us-east-1'); + +final response = await s3.listObjectsV2(Bucket: 'my-bucket'); + +print(response.contents); +``` + + + +### Overriding + +If you need to change how Nitric deploys a resources or how it interacts with a service at runtime, you can [extend or modify a provider](/reference/providers/custom/extend-standard-provider). + + + For example, here's a [project that swaps SNS for EventBridge](https://github.com/jyecusch/iac-ifc-comparison) on AWS. + + +### Full Customization + +If you need to deploy to a cloud or new set of services that Nitric doesn't support, you can [build your own provider](/reference/providers/custom/building-custom-provider). This is a bit more advanced, but it's the ultimate escape hatch. + +The included providers are written in Go and built using Terraform or Pulumi, but you can use any language or tool you like. + +### Additional Resources + +If you need to use a service that Nitric doesn't support, you just do that like you always would. Nitric doesn't get in the way of you using the cloud, it just makes it easier. -TODO +--- ## What now? From 08edead14142d76f9730a7d494960c3e5b3ba8db Mon Sep 17 00:00:00 2001 From: Jye Cusch Date: Thu, 5 Sep 2024 22:08:28 +1000 Subject: [PATCH 06/11] draft ifc concepts page --- .../concepts/infrastructure-from-code.mdx | 158 ++++++++++++++++++ 1 file changed, 158 insertions(+) create mode 100644 src/pages/concepts/infrastructure-from-code.mdx diff --git a/src/pages/concepts/infrastructure-from-code.mdx b/src/pages/concepts/infrastructure-from-code.mdx new file mode 100644 index 000000000..526ded246 --- /dev/null +++ b/src/pages/concepts/infrastructure-from-code.mdx @@ -0,0 +1,158 @@ +export const description = + 'Introducing the concept of Infrastructure from Code (IfC) and how Nitric uses it to automate infrastructure and deployment.' + +# Infrastructure from Code (IfC) + +Infrastructure from Code (IfC) is an extension of Infrastructure as Code (IaC) that takes runtime application code into consideration and enhances Separation of Concerns (SoC). + + + Several products describe themselves as "Infrastructure from Code" (IfC), but + they're not all like Nitric. Many are platforms/SaaS products, not a + framework. Those products have different benefits and trade-offs. + + +Nitric's Infrastructure from Code (IfC) automates the creation of infrastructure from your application code, ensuring a clear separation between application logic and deployment concerns. + +It abstracts the infrastructure layer, allowing developers to define what their application needs without getting bogged down in the specifics of cloud services or infrastructure configurations. + +Sometimes it's easier to explain IfC by exploring the benefits. + +--- + +## Rapid Development + +Nitric significantly reduces or removes cloud-specific code. For example, accessing a file in a cloud storage bucket with nitric is just a few lines of code, while the equivalent code using cloud provider SDKs is much more verbose and error prone: + + + +```javascript {{ title:"Nitric SDK" }} +import { bucket } from '@nitric/sdk' + +const profiles = bucket('profiles').allow('read') + +export const getProfilePic = async (filename) => { + return await profiles.file(filename).read() +}) +``` + +```javascript {{ title:"AWS SDK" }} +import { GetObjectCommand, S3Client } from '@aws-sdk/client-s3' + +const client = new S3Client({}) +const PROFILES_BUCKET = process.env.PROFILES_BUCKET + +if (!bucket) { + throw new Error('PROFILES_BUCKET environment variable not set') +} + +export const getProfilePic = async (filename) => { + const command = new GetObjectCommand({ + Bucket: PROFILES_BUCKET, + Key: filename, + }) + + const response = await client.send(command) + return await response.Body.transformToByteArray() +} +``` + + + +--- + +## Decoupled Applications and Infrastructure + +Nitric keeps application code independent of specific cloud services. Developers focus on designing the application architecture and building features, without first making long-term technology choices. + +For example this same code would work equally well backed by AWS SNS, AWS EventBridge, Google Cloud Pub/Sub, Azure EventGrid, Apache Kafka, or any other messaging service: + +```javascript +import { topic } from '@nitric/sdk' + +const myTopic = topic('my-topic').allow('publish') + +export const publishMessage = async (message) => { + await myTopic.publish(message) +} +``` + +We can change the underlying messaging service through a simple configuration change, without modifying the application code. + + + +```yaml {{ label:"nitric.prod.yaml", title:"AWS" }} +provider: nitric/aws@1.1.1 +``` + +```yaml {{ label:"nitric.prod.yaml", title:"Azure" }} +provider: nitric/azure@1.1.1 +``` + +```yaml {{ label:"nitric.prod.yaml", title:"Google Cloud" }} +provider: nitric/gcp@1.1.1 +``` + +```yaml {{ label:"nitric.prod.yaml", title:"Anything Else" }} +provider: your_namespace/custom@1.0.0 +``` + + + + + The runtime code for cloud services like SNS still exists, it's just isolated + to an independent module. It could be from a [nitric + provider](https://github.com/nitrictech/nitric/blob/main/cloud/aws/runtime/topic/sns.go) + or [something custom](/reference/providers/custom/building-custom-provider) + built by you or an independent team, such as platform engineers or DevOps + teams. + + +--- + +## Automate Application Infrastructure Requirements + +Using Infrastructure as Code (IaC) tools like Terraform, Pulumi, or AWS CDK, developers can define the infrastructure requirements for their application. You can even create reusable modules for common infrastructure patterns. For example, you could create a pattern for async messaging, which includes a topic, and a subscription bound to a compute function. + +The problem is that these tools in isolation require manual processes to keep the infrastructure in sync with the application code. Processes that are error-prone and time-consuming. + +Infrastructure lingers in production that's no longer in use, permissions are too broad creating security risks, or too strict causing application failures. Environment variables used to determine resource names can be can be broken by a simple typo. It's a mess. + +Nitric solves this by automatically generating a requirements specification from the application code. This specification describes the resources used by the application, their hierarchy, and how the application intends to use them at runtime. + +If you want to see the spec for your application you can run `nitric spec`: + +```bash +nitric spec +``` + +### No Rogue Resources or Permissions + +Resources and access requirements are defined as close as possible to where they're used - so it's easy to see when they're no longer needed or permissions are too broad. + +```javascript +import { queue } from '@nitric/sdk' + +// Delete this line and the queue disappears from the IaC +const myQueue = queue('my-queue').allow('enqueue') + +// It's easy to tell when `enqueue` is no longer needed +export const enqueueMessage = async (message) => { + await myQueue.enqueue(message) +} +``` + +### No Broken Environment Variables + +The name of a resource is defined **_once_** (in the code), instead of twice (in the code and the IaC). IaC configuration is generated, so it's never out of sync with the application code. + +```javascript +sql('profiles') +``` + +and the framework maps the requirements specification to plugins written with existing IaC tools. These tools are still responsible for provisioning the resources, roles, and permissions. + +### Don't Change App Code for Infrastructure Changes + +You haven't imported the AWS SDK, Google Cloud SDK, or Azure SDK. You haven't written any cloud-specific code. You haven't written any mocks or tests for these cloud services, or anything that makes your code less portable. + +So when changes are needed for performance, cost, or compliance, you can make them instantly. It's just a line of config. From 217dce49fe44bea6a05ffe462a3b18493e949dbf Mon Sep 17 00:00:00 2001 From: Jye Cusch Date: Mon, 23 Sep 2024 11:08:26 +1000 Subject: [PATCH 07/11] intro page edits and link fixes --- src/pages/index.mdx | 89 +++++++++++++++++++++++++++++---------------- 1 file changed, 58 insertions(+), 31 deletions(-) diff --git a/src/pages/index.mdx b/src/pages/index.mdx index ad7351228..9e331e1e5 100644 --- a/src/pages/index.mdx +++ b/src/pages/index.mdx @@ -14,18 +14,20 @@ export const disableEditGithub = true --- -Nitric is a cloud framework with common resources like APIs, websockets, databases, queues, topics, buckets, and more. +Nitric is a declarative cloud framework with common resources like APIs, websockets, databases, queues, topics, buckets, and more. -However, Nitric is unique - it doesn't just deploy the resources, it helps you interact with them. It also makes them pluggable, so you can swap services or even whole clouds without changing your code. +However, Nitric doesn't just deploy the resources, it helps you interact with them. It also makes them pluggable, so you can swap services or even whole clouds without changing your code. It's what's missing between applications and infrastructure automation. Oh, and it supports basically any language, like JavaScript, TypeScript, Python, Go, you name it.
- +
+If you're familiar Nitric already, you might want to jump to the [Installation](/getting-started/installation), [Guides](/guides) or [Resources](/apis) sections. Otherwise, keep reading to learn more about Nitric. + --- ## Services @@ -35,17 +37,17 @@ Services are the heart of Nitric apps, they're the entrypoints to your code. The ```yaml {{ label:"nitric.yaml" }} name: example services: - - match: services/*.ts - start: npm run dev:services $SERVICE_PATH + - match: services/*.ts + start: npm run dev:services $SERVICE_PATH ``` -You might have one service that handles everything, or a service for each route. It's up to you. +You might have one service that handles everything, or a service for each route. It's up to you. Every matched services becomes a container, so you can scale them independently. --- ## Resources -Resources are the building blocks of your apps. They're the databases, queues, buckets, etc. that your services interact with. If you want a resource, you just ask for it. +Resources are the building blocks of your apps. They're the databases, queues, buckets, etc. that your services interact with. To request a resource, import the resource type and create one with a name. @@ -94,21 +96,23 @@ void main() { -Nitric collects everything your services request. When you deploy, the deployment plugin you choose creates the resources and services, then links it all together. +Nitric collects everything your services request. When you deploy, the deployment plugin you choose creates the resources and services, then links them all together. - That probably sounds like magic, but it's more like a compiler for Infrastructure-as-Code - you can read about it in the [Concepts](/docs/concepts) section. + That might sound like magic, but it's more like a compiler for + Infrastructure-as-Code - you can read about it in the [Concepts](/concepts) + section. --- -## Providers +## Deployment Plugins (Providers) -Nitric is designed to be independent of any platform, so you can run your apps anywhere. You can deploy to AWS, Azure, GCP, or even your own Kubernetes cluster. You can even deploy to multiple clouds at once. +Nitric is designed to be independent of any platform, so you can run your apps anywhere. You can deploy to AWS, Azure, GCP, your own Kubernetes cluster or a single server. You could even deploy to multiple clouds at once. -Seriously, is there really a difference between a bucket on AWS and a bucket on Azure? We don't think so. So why should the code be different? +Are the differences between a bucket on AWS and a bucket on Azure important to most apps? We don't think so. So why should the code be different? -Nitric abstracts away the differences, so you can focus on your app. The part that makes that possible is a plugin, we call a **Provider**. +Nitric abstracts away API layer differences, so you can focus on your app. The part that makes that possible is a plugin, we call a **Provider**. @@ -144,19 +148,19 @@ provider: custom/on-prem@1.0.0 -We have a few providers built-in with IaC from Pulumi or Terraform, but you can build your own with any tools you prefer and to anywhere you want. +We have several providers built-in with IaC from [Pulumi](https://www.pulumi.com/) or [Terraform](https://www.terraform.io/), but you can build your own with any tools you prefer and **deploy anywhere**. --- ## Projects -Projects built with Nitric don't have many restrictions. You can use most languages, most libraries, most tools, most clouds, most services, mostly anything you like. But, you need to have a `nitric.yaml` file in the root of your project. +Projects built with Nitric don't have many restrictions. You can use most languages, libraries, tools, clouds, services, mostly anything you like. But, you need to have a `nitric.yaml` file in the root of your project. ```yaml {{ label:"nitric.yaml" }} name: example services: - - match: services/*.ts - start: npm run dev:services $SERVICE_PATH + - match: services/*.ts + start: npm run dev:services $SERVICE_PATH ``` Nitric uses this to find your services, then it turns each service into a container, runs them in deployment mode to match the resources you requested and gives the result to the Provider - which either generates IaC (like Terraform) or automatically deploys your app. @@ -229,6 +233,11 @@ curl -L "https://nitric.io/install?version=latest" | bash + + Nitric has a few dependencies, like Docker, which you can read about in the + [Installation](/getting-started/installation) section. + + ### New You can create a new project from a template with the `new` command. @@ -246,7 +255,8 @@ nitric start ``` - Start also emulates the resources you requested, so you can test your app locally. And provides a Dashboard UI to interact with the resources. + Start also emulates the resources you requested, so you can test your app + locally. And provides a Dashboard UI to interact with the resources. ### Deploy @@ -254,13 +264,19 @@ nitric start You can deploy your project with the `up` command, once you have a stack file (deployment target). ```bash +# Create a new stack (deployment target) nitric stack new - +# Deploy to the stack, using the provider in the stack file nitric up ``` - Some providers don't deploy directly, instead they generate IaC files. In those cases you use the IaC tool to deploy (e.g. `terraform apply`). + Some providers deploy directly, others generate IaC files for existing tools + (like HCL for Terraform). In the cases where IaC is generated you use the + chosen IaC tool to deploy (e.g. `terraform apply`). + +Currently, all Pulumi providers deploy directly, while Terraform providers generate IaC. + ### Tear Down @@ -271,15 +287,20 @@ You can tear down your project with the `down` command. nitric down ``` + + If you used a provider that generates IaC, use the IaC tool to tear down (e.g. + `terraform destroy`). + + --- ## Local development -Sometimes you just want to run your app locally and we let you do just that. And we don't mean "binds to a cloud environment and syncs your code, but doesn't work without Wifi" local, we mean "runs on your machine, on a desert island" local. +Sometimes you'll want to run your app locally. We don't mean "binds to a cloud environment and syncs your code, but doesn't work without Wifi" local, we mean "runs on your machine, on a desert island" local. `nitric start` hosts entrypoints like APIs, websockets, and schedules, as well as resources like databases, topics, queues, key/value stores and buckets. -It also provides a Dashboard to interact with your resources, so you can trigger schedules without waiting, or topics without a publisher, or upload test files to a bucket. It even produces a real-time architecture diagram of your services and resources. +It also provides a Dashboard to interact with your resources, so you can trigger schedules without waiting, or topics without a publisher, or upload test files to a bucket. It even produces a live architecture diagram of your services and resources as your code updates. ```javascript +// Import the AWS SDK import { S3Client } from '@aws-sdk/client-s3' +// Use it like you normally would const s3 = new S3Client({ region: 'us-east-1' }) - const { Contents } = await s3.listObjectsV2({ Bucket: 'my-bucket' }) ``` ```python +# Import the boto3 (AWS) SDK from boto3 import client +# Use it like you normally would s3 = client('s3', region_name='us-east-1') - response = s3.list_objects_v2(Bucket='my-bucket') ``` ```go import ( "context" - + // Import the AWS SDK "github.com/aws/aws-sdk-go-v2/config" "github.com/aws/aws-sdk-go-v2/service/s3" ) +// Use it like you normally would cfg, _ := config.LoadDefaultConfig(context.TODO()) client := s3.NewFromConfig(cfg) @@ -332,12 +358,12 @@ output, _ := client.ListObjectsV2(context.TODO(), &s3.ListObjectsV2Input{ ``` ```dart +// Import the AWS SDK import 'package:aws_s3/aws_s3.dart'; +// Use it like you normally would final s3 = S3(region: 'us-east-1'); - final response = await s3.listObjectsV2(Bucket: 'my-bucket'); - print(response.contents); ``` @@ -348,21 +374,22 @@ print(response.contents); If you need to change how Nitric deploys a resources or how it interacts with a service at runtime, you can [extend or modify a provider](/reference/providers/custom/extend-standard-provider). - For example, here's a [project that swaps SNS for EventBridge](https://github.com/jyecusch/iac-ifc-comparison) on AWS. + For example, here's a [project that swaps SNS for + EventBridge](https://github.com/jyecusch/iac-ifc-comparison) on AWS. ### Full Customization -If you need to deploy to a cloud or new set of services that Nitric doesn't support, you can [build your own provider](/reference/providers/custom/building-custom-provider). This is a bit more advanced, but it's the ultimate escape hatch. +If you need to deploy to a new platform or new set of services that Nitric doesn't support, you can [build your own provider](/reference/providers/custom/building-custom-provider). This is a bit more advanced, but it's the ultimate escape hatch. The included providers are written in Go and built using Terraform or Pulumi, but you can use any language or tool you like. ### Additional Resources -If you need to use a service that Nitric doesn't support, you just do that like you always would. Nitric doesn't get in the way of you using the cloud, it just makes it easier. +If you need to use a service/resource that Nitric doesn't support, you do that like you always would. Nitric doesn't get in the way of you using the cloud, it just makes it easier. --- ## What now? -If you're still not sure what to make of Nitric, maybe start with the [Concepts](/docs/concepts) section, otherwise the best way to learn is to dive into the [Guides](/docs/guides) and start building your first project. +If you're still not sure what to make of Nitric, maybe start with the [Concepts](/concepts) section, otherwise the best way to learn is to dive into the [Guides](/guides) and start building your first project. From 2b45bb0048ebcbb6929096ff9e6415b612825faa Mon Sep 17 00:00:00 2001 From: David Moore Date: Mon, 23 Sep 2024 11:59:37 +1000 Subject: [PATCH 08/11] format --- src/components/Libraries.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/components/Libraries.tsx b/src/components/Libraries.tsx index 612e3a230..ac0d0342c 100644 --- a/src/components/Libraries.tsx +++ b/src/components/Libraries.tsx @@ -56,13 +56,13 @@ export interface LibrariesProps { export function Libraries({ minimal = false }: LibrariesProps) { if (minimal) { return ( -
+
{libraries.map((library) => ( Date: Mon, 23 Sep 2024 13:04:22 +1000 Subject: [PATCH 09/11] update hr styles --- typography.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/typography.js b/typography.js index 05f150473..1448fd268 100644 --- a/typography.js +++ b/typography.js @@ -27,7 +27,7 @@ module.exports = ({ theme }) => ({ '--tw-prose-invert-bold': theme('colors.white'), '--tw-prose-invert-counters': theme('colors.zinc.400'), '--tw-prose-invert-bullets': theme('colors.zinc.600'), - '--tw-prose-invert-hr': theme('colors.white / 0.05'), + '--tw-prose-invert-hr': theme('colors.white / 0.10'), '--tw-prose-invert-quotes': theme('colors.zinc.100'), '--tw-prose-invert-quote-borders': theme('colors.zinc.700'), '--tw-prose-invert-captions': theme('colors.zinc.400'), @@ -143,8 +143,8 @@ module.exports = ({ theme }) => ({ hr: { borderColor: 'var(--tw-prose-hr)', borderTopWidth: 1, - marginTop: theme('spacing.16'), - marginBottom: theme('spacing.16'), + marginTop: theme('spacing.8'), + marginBottom: theme('spacing.8'), maxWidth: 'none', marginLeft: `calc(-1 * ${theme('spacing.4')})`, marginRight: `calc(-1 * ${theme('spacing.4')})`, From a8491bd7fc1dae2e4e2fbd5bbe92ec1967a5a194 Mon Sep 17 00:00:00 2001 From: Jye Cusch Date: Mon, 23 Sep 2024 13:08:37 +1000 Subject: [PATCH 10/11] fix links with redirects --- src/pages/index.mdx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/pages/index.mdx b/src/pages/index.mdx index 9e331e1e5..8e30cf46d 100644 --- a/src/pages/index.mdx +++ b/src/pages/index.mdx @@ -100,8 +100,8 @@ Nitric collects everything your services request. When you deploy, the deploymen That might sound like magic, but it's more like a compiler for - Infrastructure-as-Code - you can read about it in the [Concepts](/concepts) - section. + Infrastructure-as-Code - you can read about it in the + [Concepts](/concepts/introduction) section. --- @@ -392,4 +392,4 @@ If you need to use a service/resource that Nitric doesn't support, you do that l ## What now? -If you're still not sure what to make of Nitric, maybe start with the [Concepts](/concepts) section, otherwise the best way to learn is to dive into the [Guides](/guides) and start building your first project. +If you're still not sure what to make of Nitric, maybe start with the [Concepts](/concepts/introduction) section, otherwise the best way to learn is to dive into the [Guides](/guides) and start building your first project. From bfea125c7acdd21c59c56d292153d8a976c53cac Mon Sep 17 00:00:00 2001 From: Jye Cusch Date: Mon, 23 Sep 2024 14:59:07 +1000 Subject: [PATCH 11/11] review feedback applied --- src/pages/concepts/infrastructure-from-code.mdx | 4 ++-- src/pages/index.mdx | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/pages/concepts/infrastructure-from-code.mdx b/src/pages/concepts/infrastructure-from-code.mdx index 526ded246..d88f04450 100644 --- a/src/pages/concepts/infrastructure-from-code.mdx +++ b/src/pages/concepts/infrastructure-from-code.mdx @@ -21,7 +21,7 @@ Sometimes it's easier to explain IfC by exploring the benefits. ## Rapid Development -Nitric significantly reduces or removes cloud-specific code. For example, accessing a file in a cloud storage bucket with nitric is just a few lines of code, while the equivalent code using cloud provider SDKs is much more verbose and error prone: +Nitric significantly reduces or removes cloud-specific code. For example, accessing a file in a cloud storage bucket with Nitric is just a few lines of code, while the equivalent code using cloud provider SDKs is much more verbose and error prone: @@ -100,7 +100,7 @@ provider: your_namespace/custom@1.0.0 The runtime code for cloud services like SNS still exists, it's just isolated - to an independent module. It could be from a [nitric + to an independent module. It could be from a [Nitric provider](https://github.com/nitrictech/nitric/blob/main/cloud/aws/runtime/topic/sns.go) or [something custom](/reference/providers/custom/building-custom-provider) built by you or an independent team, such as platform engineers or DevOps diff --git a/src/pages/index.mdx b/src/pages/index.mdx index 8e30cf46d..6a78076a1 100644 --- a/src/pages/index.mdx +++ b/src/pages/index.mdx @@ -41,7 +41,7 @@ services: start: npm run dev:services $SERVICE_PATH ``` -You might have one service that handles everything, or a service for each route. It's up to you. Every matched services becomes a container, so you can scale them independently. +You might have one service that handles everything, or a service for each route. It's up to you. Every matched service becomes a container, allowing them run and scale independently. --- @@ -173,8 +173,8 @@ So, a project structure might look something like this: example/ ├── nitric.yaml ├── services/ -│ └── orders.ts -│ └── users.ts +│ └── orders.js +│ └── users.js └── package.json ```