diff --git a/docs/docs/misc/comparison/ampt.mdx b/docs/docs/misc/comparison/ampt.mdx
deleted file mode 100644
index 6219202c8..000000000
--- a/docs/docs/misc/comparison/ampt.mdx
+++ /dev/null
@@ -1,71 +0,0 @@
----
-description: 'Comparison to Ampt'
-noindex: true
----
-
-# Ampt vs. Nitric
-
-Nitric is a framework that empowers developers to build complete cloud applications on their preferred cloud platform, combining infrastructure declaration and application code in one place. Ampt is a development platform tailored for rapidly building cloud applications using JavaScript or TypeScript. Both serve the purpose of simplifying cloud application development but operate in different ways and cater to different specific needs.
-These are the main differences between the two:
-
-1. **Cloud Provider Support:** Nitric is provider-agnostic, capable of deploying to multiple cloud providers such as AWS, Google Cloud, and Azure. Ampt is a platform, which currently runs on AWS.
-2. **Language Support:** Nitric provides multiple libraries for TypeScript/JavaScript, Python, Go, C# .NET and Java, allowing developers to choose their preferred language. Currently Ampt supports TypeScript and JavaScript.
-3. **Infrastructure Provisioning:** Nitric uses Pulumi by default for provisioning cloud resources, but also allows the use of [custom providers](/providers/custom/create). Ampt uses a hosted provisioning engine via their online platform. While resources deployed with Nitric are statically determined at deployment, Ampt is able to reallocate resources between AWS services at runtime to optimize applications.
-4. **Local Simulation:** Nitric provides a fully offline local cloud simulation tool, allowing you to test your applications locally before deploying them. This is a feature that Ampt does not offer. However, for local development Ampt deploys and syncs your application to the cloud via a sandbox environment, allowing for rapid testing of local changes.
-5. **Open Source:** As an open-source framework, Nitric does not require a platform or subscription to deploy applications. Ampt is a hosted platform which requires an account and provides both free and paid offerings.
-
-## Code Comparison
-
-To get a deeper understanding of the differences, let's see the same app built in both Nitric and Ampt.
-
-
-
-
-
-**Nitric**
-
-```typescript title:hello.ts
-import { api } from '@nitric/sdk'
-
-const helloApi = api('main')
-
-helloApi.get('/hello/:name', async (ctx) => {
- const { name } = ctx.req.params
-
- ctx.res.body = `Hello ${name}`
-})
-```
-
-
-
-
-
-**Ampt (Experimental)**
-
-```typescript title:hello.ts
-import { api } from '@ampt/api'
-
-const helloApi = api('main').router('/hello')
-
-helloApi.get('/:name', async (event) => {
- const { name } = event.params
-
- return event.status(200).body(`Hello ${name}`)
-})
-```
-
-
-
-
-
-## Differences
-
-| | Nitric | Ampt |
-| -------------------- | ----------------------------------------------------------------------- | -------------------------------------------------------------------- |
-| Language | Your choice | JavaScript / TypeScript |
-| Lines of code | 9 | 9 |
-| Cloud Infrastructure | Inferred, Static | Inferred, Dynamic |
-| Extensibility | [Custom providers](/providers/custom/create) can be created | None |
-| Local development | Built-in local simulator with instant hot reloading and offline support | Active project synchronization to a cloud sandbox with a local proxy |
-| Cloud providers | AWS, Azure, GCP and [Custom providers](/providers/custom/create) | Ampt Platform (AWS) |
-| Provisioning engine | Pulumi by default, other custom providers can be created | Hosted provisioning engine |
diff --git a/docs/docs/misc/comparison/aws-cdk.mdx b/docs/docs/misc/comparison/aws-cdk.mdx
deleted file mode 100644
index a3a80793e..000000000
--- a/docs/docs/misc/comparison/aws-cdk.mdx
+++ /dev/null
@@ -1,101 +0,0 @@
----
-description: 'Comparison to AWS CDK'
-noindex: true
----
-
-# AWS CDK vs. Nitric
-
-Nitric and AWS Cloud Development Kit (CDK) both provide developer-friendly approaches to cloud resource management, but they operate on different philosophies.
-Nitric uses an "Infrastructure from Code" approach, focusing on deriving the necessary infrastructure from the application code.
-This stands in contrast to AWS CDK's "Infrastructure as Code" methodology, which requires explicit definition of cloud resources.
-These are the main differences between the two:
-
-1. **Cloud Provider Support:** Nitric is provider-agnostic, capable of deploying to multiple cloud providers such as AWS, Google Cloud, and Azure. AWS CDK is primarily designed for AWS services.
-2. **Abstraction Level:** Nitric provides a high level of abstraction, allowing developers to focus more on writing application code. AWS CDK, while also abstracting over raw CloudFormation, requires a more detailed understanding of AWS services and their interactions.
-3. **Infrastructure Provisioning:** Nitric uses Pulumi by default for provisioning cloud resources, but also allows the use of [custom providers](/providers/custom/create). AWS CDK uses AWS CloudFormation for provisioning.
-4. **Local Simulation:** Nitric provides a local cloud simulation tool, allowing you to test your applications locally before deploying them. This is a feature that AWS CDK does not offer, you are required to deploy your application to the cloud.
-
-## Code Comparison
-
-To get a deeper understanding of the differences, let's see the same app built in both Nitric and AWS CDK. This simple cloud app uses a Function to retrieve a hello world message using a path parameter.
-
-
-
-
-
-**Nitric**
-
-```typescript title:hello.ts
-import { api } from '@nitric/sdk'
-
-const helloApi = api('main')
-
-helloApi.get('/hello/:name', async (ctx) => {
- const { name } = ctx.req.params
-
- ctx.res.body = `Hello ${name}`
-})
-```
-
-
-
-
-
-**AWS CDK**
-
-```javascript title:src/index.js
-exports.handler = async function (event = {}) {
- const name = event.pathParameters.name
-
- return {
- statusCode: 200,
- body: `Hello ${name}`,
- }
-}
-```
-
-```typescript title:lib/hello-stack.ts
-import * as cdk from 'aws-cdk-lib'
-import { Construct } from 'constructs'
-import * as apigateway from 'aws-cdk-lib/aws-apigateway'
-import * as lambda from 'aws-cdk-lib/aws-lambda'
-
-export class HelloWorldStack extends cdk.Stack {
- constructor(scope: Construct, id: string, props?: cdk.StackProps) {
- super(scope, id, props)
-
- const handler = new lambda.Function(this, 'HelloworldHandler', {
- runtime: lambda.Runtime.NODEJS_18_X,
- code: lambda.Code.fromAsset('src'),
- handler: 'index.handler',
- })
-
- const api = new apigateway.RestApi(this, 'hello-world-api', {
- restApiName: 'Hello World Service',
- description: 'A hello world API.',
- })
-
- const resource = api.root.addResource('hello').addResource('{name}')
-
- resource.addMethod('GET', new apigateway.LambdaIntegration(handler))
- }
-}
-```
-
-
-
-
-
-Nitric offers a simplified, user-friendly way to define APIs with the added benefit of being able to use custom providers for greater control and flexibility, while maintaining cloud neutrality. On the other hand, AWS CDK, with its verbose and explicit syntax, provides deep customization and control specifically within the AWS ecosystem, but might be more complex for beginners.
-
-## Differences
-
-| | Nitric | AWS CDK |
-| -------------------- | ---------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------- |
-| Language | Your choice | Your choice |
-| Lines of code | 9 | 33 |
-| Cloud Infrastructure | Inferred | Explicit |
-| Extensibility | [Custom providers](/providers/custom/create) can be created | Custom Constructs / Resource Providers |
-| Local simulation | Built-in local simulator with instant hot reloading | No |
-| Cloud providers | AWS, Azure, GCP and [Custom providers](/providers/custom/create) | AWS |
-| Provisioning engine | Pulumi by default, other custom providers can be created | CloudFormation (CDKTF is used for Terraform, but you cannot compile the same code to different engines) |
diff --git a/docs/docs/misc/comparison/aws-sam.mdx b/docs/docs/misc/comparison/aws-sam.mdx
deleted file mode 100644
index df7007abf..000000000
--- a/docs/docs/misc/comparison/aws-sam.mdx
+++ /dev/null
@@ -1,91 +0,0 @@
----
-description: 'Comparison to AWS Serverless Application Model (SAM)'
-noindex: true
----
-
-# AWS SAM vs. Nitric
-
-AWS Serverless Application Model (SAM) is an abstraction layer for CloudFormation that makes it simpler to write serverless applications in AWS.
-
-Although both AWS SAM and Nitric are in the same problem space, there are major differences in the way that Nitric solves simplifying serverless application development compared with SAM.
-
-## TLDR
-
-The major differences with SAM are:
-
-- Only supports AWS.
-- Configuration is defined in lengthy yaml files.
-- Only supports functions, apis, and tables.
-- IAM implementation is the responsibility of the developer.
-
-## Building
-
-To build with AWS SAM you need a template yaml, an OpenAPI spec yaml, as well as the actual lambda code.
-
-[Here](https://docs.aws.amazon.com/apigateway/latest/developerguide/http-api-open-api.html#http-api-import.example) is the example OpenAPI spec AWS uses to demonstrate the simplicity of SAM. That file is over 200 lines long.
-
-Nitric does the spec in 0 lines.
-
-Any Nitric config you write is done as code, keeping the architecture of your application in one place, rather than three.
-
-```typescript
-const newApi = api('test-api')
-
-newApi.get('/hello', (ctx) => {
- return ctx.text('Hello World')
-})
-```
-
-Building resources other than lambdas, apis, or tables requires separate CloudFormation extensions to your SAM template files.
-
-Nitric has first-class support for these other resources, and its only one extra line.
-
-```typescript
-const newBucket = bucket('test-bucket')
-```
-
-## IAM Policy
-
-SAM's least-privilege permissions are written explicitly in the template configuration. The responsibility (and burden) is on the developer to make sure the lambda policies chosen follow security best practices.
-
-This is done through more yaml configuration, which points to an AWS policy.
-
-```yaml
----
-Resources:
- MyFunction:
- Type: 'AWS::Serverless::Function'
- Properties:
- Handler: index.handler
- Runtime: nodejs8.10
- CodeUri: 's3://my-bucket/function.zip'
- Policies:
- - SQSPollerPolicy:
- QueueName: !GetAtt MyQueue.QueueName
-```
-
-On the other hand, Nitric handles the implementation of least-privilege policies for you. All that is needed is to specify how you want to use a resource, and the function will be assigned the relevant policy.
-
-```typescript
-const newBucket = bucket('tester').allow('read', 'write', 'delete')
-```
-
-## Testing
-
-Both the SAM and Nitric frameworks have local testing environments that closely resemble the cloud environment. This means testing that your functions work is as simple as making a request to the local endpoint.
-
-The difference comes when writing automated unit or integration tests.
-
-| | AWS SAM | Nitric |
-| ----------- | ------- | ------ |
-| Unit | AWS SDK | BYO |
-| Integration | AWS SDK | BYO |
-| Mocking | AWS SDK | BYO |
-
-AWS SAM can't configure all the resources, so when you use the local test environment none of the external resources are going to be mocked. This means for a decent integration testing experience, you have to use the AWS SDK or CLI, which attempts to solve this problem.
-
-Nitric's testing works with any testing framework, as resource creation and calling can be mocked. When running the local test environment, other resources like buckets are created using the file system. This makes the integration testing super smooth, as the files you create and events you push are actually there.
-
-## Deploying
-
-The deployment experience between the frameworks is very similar, where a single command will deploy the entire stack. The big difference however, is that AWS SAM only deploys to AWS, while Nitric will deploy to AWS, GCP, or Azure.
diff --git a/docs/docs/misc/comparison/bicep.mdx b/docs/docs/misc/comparison/bicep.mdx
deleted file mode 100644
index 665643ad7..000000000
--- a/docs/docs/misc/comparison/bicep.mdx
+++ /dev/null
@@ -1,80 +0,0 @@
----
-description: 'Comparison to Bicep'
-noindex: true
----
-
-# Bicep vs. Nitric
-
-[Bicep](https://docs.microsoft.com/en-us/azure/azure-resource-manager/bicep/overview?tabs=bicep) is an infrastructure as code solution for deploying stacks to Azure. It acts as an abstraction layer for Azure Resource Manager ([ARM](https://docs.microsoft.com/en-us/azure/azure-resource-manager/templates/overview)) templates.
-
-## TLDR
-
-The major differences with Bicep are:
-
-- Only supports Azure.
-- Configuration is defined in `.bicep` files.
-- IAM implementation is the responsibility of the developer.
-
-## Building
-
-Building with bicep involves creating a `.bicep` file and defining your resources in there. You can also add parameters, so properties like locations and names can be defined at deployment time.
-
-The API gateway resource [definitions](https://docs.microsoft.com/en-us/azure/templates/microsoft.apimanagement/service?tabs=bicep) can take up to 100 lines to define your API properties, before writing any function code or defining your API routes.
-
-The way you assign these routes and function code depends upon whether you are using logic apps, container apps, or something else. Each solution will require further configuration as well code or container deployments.
-
-Nitric's solution to these lengthy configuration files and processes is to have all your config as code.
-
-```typescript
-const newApi = api('test-api')
-
-newApi.get('/hello', (ctx) => {
- return ctx.text('Hello World')
-})
-```
-
-## IAM Policy
-
-Implementing least-privilege with bicep requires defining role definitions and/or role assignments in the bicep file.
-
-```bicep
-resource symbolicname 'Microsoft.Authorization/roleAssignments@2020-10-01-preview' = {
- name: 'string'
- scope: resourceSymbolicName or tenant()
- properties: {
- condition: 'string'
- conditionVersion: 'string'
- delegatedManagedIdentityResourceId: 'string'
- description: 'string'
- principalId: 'string'
- principalType: 'string'
- roleDefinitionId: 'string'
- }
-}
-```
-
-You choose the role assignment by either picking from the [long list](https://docs.microsoft.com/en-us/azure/role-based-access-control/built-in-roles) of default roles, or creating a more granular role based on the specific actions and data actions you want.
-
-On the other hand, Nitric handles the implementation of least-privilege policies for you. All that is needed is to specify how you want to use a resource, and the function will be assigned the relevant policy.
-
-```typescript
-const newQueue = bucket('tester').allow('read', 'write')
-```
-
-## Testing
-
-Azure functions can use any testing framework, including any mocking library. The same goes for Nitric testing. Both Nitric and Azure also have local testing environments using the Nitric CLI and the Azure Function CLI respectively. These will start local api gateways that can be used for integration tests.
-
-| | Bicep | Nitric |
-| ----------- | ----- | ------ |
-| Unit | BYO | BYO |
-| Integration | BYO | BYO |
-| Mocking | BYO | BYO |
-
-However, the Azure Function CLI does not mock or create test resources that the function will interact with. This makes it difficult to test complex functions locally.
-
-## Deploying
-
-When deploying to Azure using bicep files, there are two options. The first is via the command line with powershell, cloud shell, or the Azure CLI. The other is via the template deployment manager on Azure. Both offer similar experiences, prompting for parameters and then deploying the resources. However, some things such as functions and containers might require external configuration.
-
-Nitric's deployment experience is a single command that deploys the entire stack. Due to the config as code approach, the deployment will containerize your functions, push them privately to Azure Container Registry, and map your routes without any manual config.
diff --git a/docs/docs/misc/comparison/encore.mdx b/docs/docs/misc/comparison/encore.mdx
deleted file mode 100644
index d4cc8c30f..000000000
--- a/docs/docs/misc/comparison/encore.mdx
+++ /dev/null
@@ -1,88 +0,0 @@
----
-description: 'Comparison to Encore'
-noindex: true
----
-
-# Encore vs. Nitric
-
-Nitric is a framework that empowers developers to build complete cloud applications on their preferred cloud platform, combining infrastructure declaration and application code in one place. On the other hand, Encore is a development platform tailored for building cloud backend applications using the Go language, with deployment options for AWS or Google Cloud Platform. Both serve the purpose of simplifying cloud application development but operate in slightly different ways and cater to different specific needs.
-
-These are the main differences between the two:
-
-1. **Cloud Provider Support:** Nitric is provider-agnostic, capable of deploying to multiple cloud providers such as AWS, Google Cloud, and Azure. Encore currently deploys to AWS or Google Cloud.
-2. **Language Support:** Nitric provides libraries for TypeScript/JavaScript, Python, Go, and Dart. Additional languages can be supported using Nitric's gRPC API, allowing developers to choose their preferred language. Currently Encore supports Go and TypeScript.
-3. **Infrastructure Provisioning:** Nitric uses Pulumi or Terraform by default for provisioning cloud resources, but also allows the use of [custom providers](/providers/custom/create). Encore uses a hosted provisioning engine via their online platform.
-4. **Open Source:** As an open-source framework, Nitric does not require a platform or subscription to deploy applications. Encore's language frameworks are provided as open-source software, however infrastructure provisioning requires users to create their own IaC scripts or sign-up to Encore's hosted platform, which may incur additional costs.
-
-## Code Comparison
-
-To get a deeper understanding of the differences, let's see the same app built in both Nitric and Encore.
-
-
-
-
-
-**Nitric**
-
-```go title:services/hello/main.go
-package main
-
-import (
- "context"
-
- "github.com/nitrictech/go-sdk/nitric"
- "github.com/nitrictech/go-sdk/nitric/apis"
-)
-
-func main() {
- api := nitric.NewApi("main")
-
- api.Get("/hello/:name", func(ctx *apis.Ctx) {
- ctx.Response.Body = []byte("Hello " + ctx.Request.PathParams()["name"])
- })
-
- nitric.Run()
-}
-```
-
-
-
-
-
-**Encore**
-
-```go title:hello.go
-package hello
-
-import (
- "context"
-)
-
-//encore:api public path=/hello/:name
-func Hello(ctx context.Context, name string) (*Response, error) {
- msg := "Hello " + name
- return &Response{Message: msg}, nil
-}
-
-type Response struct {
- Message string
-}
-```
-
-
-
-
-
-The Nitric example shows an API where HTTP request handling is achieved using `apis.Ctx`, providing control over the request and response objects. The Encore example demonstrates an API where HTTP request handling is reflected through the function parameters and return types, with defined structs for responses.
-
-## Differences
-
-| | Nitric | Encore |
-| -------------------- | ---------------------------------------------------------------- | -------------------------- |
-| Language | Your choice | Go, TypeScript |
-| Lines of code | 26 | 15 |
-| Cloud Infrastructure | Inferred | Inferred |
-| Extensibility | [Custom providers](/providers/custom/create) can be created | No |
-| Local simulation | Built-in local simulator | Built-in local simulator |
-| Cloud providers | AWS, Azure, GCP and [Custom providers](/providers/custom/create) | AWS and GCP |
-| Provisioning engine | Pulumi by default, other custom providers can be created | Hosted provisioning engine |
diff --git a/docs/docs/misc/comparison/gcp-deployment-manager.mdx b/docs/docs/misc/comparison/gcp-deployment-manager.mdx
deleted file mode 100644
index 5089d4271..000000000
--- a/docs/docs/misc/comparison/gcp-deployment-manager.mdx
+++ /dev/null
@@ -1,129 +0,0 @@
----
-description: 'Comparison to Google Cloud Deployment Manager'
-noindex: true
----
-
-# Google Cloud Deployment Manager vs. Nitric
-
-[Google Cloud Deployment Manager](https://cloud.google.com/deployment-manager/docs#docs) is an infrastructure as code offering for creating and managing deployments on GCP.
-
-## TLDR
-
-The major differences between Nitric and Google Cloud Deployment Manager are:
-
-- Only supports GCP.
-- Configuration is defined in yaml, jinja, or python files.
-- IAM implementation is the responsibility of the developer.
-
-## Building
-
-To build with Google Cloud Deployment Manager you can build a template yaml file. For deploying a virtual machine, the file may look like:
-
-```yaml
-resources:
- - type: compute.v1.instance
- name: quickstart-deployment-vm
- properties:
- zone: us-central1-f
- machineType: https://www.googleapis.com/compute/v1/projects/[MY_PROJECT]/zones/us-central1-f/machineTypes/f1-micro
- disks:
- - deviceName: boot
- type: PERSISTENT
- boot: true
- autoDelete: true
- initializeParams:
- sourceImage: https://www.googleapis.com/compute/v1/projects/debian-cloud/global/images/family/debian-9
- networkInterfaces:
- - network: https://www.googleapis.com/compute/v1/projects/[MY_PROJECT]/global/networks/default
-s accessConfigs:
- - name: External NAT
- type: ONE_TO_ONE_NAT
-```
-
-However, there are also options provided to write these config files in python. This code must supply a `GenerateConfig(context)` or `generate_config(context)` function that returns a dictionary.
-
-```python
-def generate_config(context):
- resources = []
- resources.append({
- 'name': 'vm-template',
- 'type': 'compute.v1.instance',
- 'properties': {
- 'zone': 'us-central1-a',
- 'machineType': 'zones/us-central1-a/machineTypes/n1-standard-1',
- 'disks': [{
- 'deviceName': 'boot',
- 'type': 'PERSISTENT',
- 'boot': True,
- 'autoDelete': True,
- 'initializeParams': {
- 'sourceImage':
- 'projects/debian-cloud/global/images/family/debian-9'
- }
- }],
- 'networkInterfaces': [{
- 'network': 'global/networks/default'
- }]
- }
- })
-```
-
-On the contrary, any Nitric config you write is done as code, keeping the architecture and logic of your code in one place. This means when deployment happens, both the architecture and logic are deployed.
-
-```typescript
-const newApi = api('test-api')
-
-newApi.get('/hello', (ctx) => {
- return ctx.text('Hello World')
-})
-```
-
-Nitric also has first-class support for other resources. Creating these resources is a one line definition.
-
-```typescript
-const newBucket = bucket('test-bucket')
-```
-
-## IAM Policy
-
-Google Cloud Deployment Manager templates have property keys for defining or assigning roles. This puts the responsibility on the developer to make sure the policies defined in the file are following best practices.
-
-On the other hand, Nitric handles the implementation of least-privilege policies for you. All that is needed is to specify how you want to use a resource, and the function will be assigned the relevant policy.
-
-```typescript
-const newQueue = queue('tester').allow('dequeue', 'enqueue')
-```
-
-## Testing
-
-The decoupling of architecture and logic means testing for Google Cloud Deployment Manager is more about testing the function code then the templates themselves. This means the test process will be writing unit and integration tests using a test framework which works for your services. The issue with this is your integration tests will be run against your deployed resources.
-
-GCP has a few ways of emulating the cloud locally, either through a visual code extension, their CLI, or docker. Nitric has a local test environment that will mock other resources like buckets, as well as containerizing and running your services. This means you can easily write automated integration tests using any test framework you want, without worrying about side effects to production.
-
-Nitric's unit testing can also be done using any test framework and any mocking library, as all the architecture and config is defined as code.
-
-| | GCP DM | Nitric |
-| ----------- | ------ | ------ |
-| Unit | BYO | BYO |
-| Integration | BYO | BYO |
-| Mocking | BYO | BYO |
-
-## Deployment
-
-When deploying the stack to the cloud the big difference is that for GCP deployment manager, you will also have to deploy the function code separately. Deployment manager is also (obviously) only going to deploy to GCP. The commands for deployment are as follows:
-
-Deploying the stack.
-
-```
-gcloud deployment-manager deployments create quickstart-deployment --config vm.yaml
-
-nitric up
-```
-
-Deleting the stack.
-
-```
-gcloud deployment-manager deployments delete quickstart-deployment
-
-nitric down
-```
diff --git a/docs/docs/misc/comparison/pulumi.mdx b/docs/docs/misc/comparison/pulumi.mdx
deleted file mode 100644
index 7378de6eb..000000000
--- a/docs/docs/misc/comparison/pulumi.mdx
+++ /dev/null
@@ -1,180 +0,0 @@
----
-description: 'Comparison to Pulumi'
-noindex: true
----
-
-# Pulumi vs. Nitric
-
-
- Nitric is not designed to replace IaC tools like Pulumi, but instead
- introduces a method of bringing developer self service for infrastructure
- directly into the developer application (Nitric's default deployment engines
- are built with Pulumi). Nitric can be augmented through use of tools like
- Pulumi and even be fully customized using such tools see [Custom
- Providers](/providers/custom/create) for more details
-
-
-Nitric is a framework designed to aid developers in building full cloud applications, including declaring their infrastructure and application code in one place. Pulumi is an Infrastructure as Code tool that enables developers to define infrastructure using traditional programming languages or YAML (Cuelang). The main differences between these are:
-
-1. Nitric is cloud-agnostic, code that is written using Nitric constructs can be deployed to any cloud. Pulumi supports many clouds, infrastructure declarations are explicitly defined for the provider that a resource is provided by.
-
-1. Nitric defines not only the infrastructure but how it is interacted with at runtime, so infrastructure can be automatically inferred from application code to ensure best practice deployments and least privilege security.
-
-1. Nitric uses Pulumi under the hood for the Out of the Box providers. Pulumi is a great option for extending infrastructure deployed by Nitric or for deploying Nitric applications to clouds not supported by Nitric by default.
-
-1. Nitric provides tools for locally simulating a cloud environment (using the Nitric CLI), to allow applications to be tested locally. Pulumi programs can be unit tested but applications written to be deployed will need a separate solution for local development such as LocalStack.
-
-# Side by Side
-
-To showcase the power of the abstraction provided by Nitric here is a showcase of a Nitric program with an equivalent Pulumi program with application code.
-
-
-
-
-
-**Nitric**
-
-```javascript title:handle.js
-import * as nitric from '@nitric/sdk'
-
-const bucket = nitric.bucket('my-bucket').allow('read', 'write')
-
-bucket.on('create', '*', async (ctx) => {
- console.log(ctx.file.key, 'was created')
-})
-```
-
-
-
-
-
-**Pulumi**
-
-```javascript title:src/index.js
-const AWS = require('aws-sdk')
-
-exports.handler = async (event) => {
- const {
- s3: { object },
- } = event
- console.log(object.key, 'was created')
-}
-```
-
-```javascript title:lib/handle-stack.js
-import * as pulumi from '@pulumi/pulumi'
-import * as aws from '@pulumi/aws'
-import * as fs from 'fs'
-import * as mime from 'mime'
-import * as path from 'path'
-
-const config = new pulumi.Config()
-const region = config.require('aws:region')
-
-const bucket = new aws.s3.Bucket('s3-bucket')
-
-const role = new aws.iam.Role('lambdaRole', {
- assumeRolePolicy: JSON.stringify({
- Version: '2012-10-17',
- Statement: [
- {
- Action: 'sts:AssumeRole',
- Effect: 'Allow',
- Principal: {
- Service: 'lambda.amazonaws.com',
- },
- },
- ],
- }),
-})
-
-const policy = new aws.iam.RolePolicy('lambdaPolicy', {
- role: role,
- policy: JSON.stringify({
- Version: '2012-10-17',
- Statement: [
- {
- Action: [
- 'logs:CreateLogGroup',
- 'logs:CreateLogStream',
- 'logs:PutLogEvents',
- ],
- Effect: 'Allow',
- Resource: 'arn:aws:logs:*:*:*',
- },
- {
- Action: ['s3:PutObject'],
- Effect: 'Allow',
- Resource: `${bucket.arn}/*`,
- },
- ],
- }),
-})
-
-const lambdaFunction = new aws.lambda.Function('s3UploaderLambda', {
- runtime: 'nodejs14.x',
- code: new pulumi.asset.AssetArchive({
- '.': new pulumi.asset.FileArchive('./'),
- }),
- timeout: 10,
- handler: 'index.handler',
- role: role.arn,
- environment: {
- variables: {
- BUCKET_NAME: bucket.bucket,
- },
- },
-})
-
-const allowBucket = new aws.lambda.Permission('allowBucket', {
- action: 'lambda:InvokeFunction',
- function: lambdaFunction.arn,
- principal: 's3.amazonaws.com',
- sourceArn: bucket.arn,
-})
-
-const bucketNotification = new aws.s3.BucketNotification(
- 'bucketNotification',
- {
- bucket: bucket.id,
- lambdaFunctions: [
- {
- lambdaFunctionArn: func.arn,
- events: ['s3:ObjectCreated:*'],
- },
- ],
- },
- {
- dependsOn: [allowBucket],
- },
-)
-
-export const bucketName = bucket.bucket
-export const lambdaFunctionName = lambdaFunction.name
-```
-
-
-
-
-
-
- In the pulumi example we get control over absolutely every facet of our
- infrastructure which is great, but for the majority of use cases a repeatable
- pattern of deployment is enough and scales much better than applying fine
- grained configuration every time we need to define a new deployment (with
- Pulumi this would typically be done by sharing infrastructure as libraries
- e.g. Pulumi Crosswalks).
-
-
-The below table contains the main differences that you can see in the code examples, and also some that cannot fit in such a small app, but we still would like you to know about :)
-
-| Feature | Nitric | Pulumi |
-| -------------------- | -------------------------------------------------------------------------- | ------------------------------------------------------ |
-| Language | Your choice | YAML + your choice |
-| Lines of code | 7 | 69 |
-| Cloud Infrastructure | Inferred | Explicit |
-| Extensibility | Custom providers | Custom/dynamic providers |
-| Local Simulation | Built-in to CLI | N/A |
-| Cross-cloud support | Same code compiles to different clouds | No (need to write different code for different clouds) |
-| Provisioning engine | Custom providers can be written with any IaC tech (e.g. Terraform/AWS CDK) | Proprietary |
-| Testing | Same tests run on local simulator and cloud, without mocks | Need mocks for local testing |
diff --git a/docs/docs/misc/comparison/sst.mdx b/docs/docs/misc/comparison/sst.mdx
deleted file mode 100644
index 1c33038c8..000000000
--- a/docs/docs/misc/comparison/sst.mdx
+++ /dev/null
@@ -1,91 +0,0 @@
----
-description: 'Comparison to SST'
-noindex: true
----
-
-# SST vs. Nitric
-
-Nitric is a framework designed to aid developers in building full cloud applications on the Cloud of their choice, including declaring their infrastructure and application code in one place.
-SST is a framework that makes it easy to build modern full-stack JavaScript/TypeScript applications on AWS.
-
-These are the main differences between the two:
-
-1. **Cloud Provider Support:** Nitric is provider-agnostic, capable of deploying to multiple cloud providers such as AWS, Google Cloud, and Azure. SST is primarily designed for AWS services.
-2. **Language Support:** Nitric provides multiple libraries for TypeScript/JavaScript, Python, Go, C# .NET and Java, allowing developers to choose their preferred language. Currently SST only supports TypeScript and JavaScript.
-3. **Infrastructure Provisioning:** Nitric uses Pulumi by default for provisioning cloud resources, but also allows the use of [custom providers](/providers/custom/create). SST uses the AWS CDK, which uses AWS CloudFormation for provisioning.
-4. **Local Simulation:** Nitric provides a fully offline local cloud simulation tool, allowing you to test your applications locally before deploying them. This is a feature that SST does not offer, for local development SST deploys your application to the cloud and uses a proxy to sync with your local code.
-
-## Code Comparison
-
-To get a deeper understanding of the differences, let's see the same app built in both Nitric and SST. The SST App in this example is standalone without the frontend code.
-
-
-
-
-
-**Nitric**
-
-```javascript title:hello.js
-import { api } from '@nitric/sdk'
-
-const helloApi = api('main')
-
-helloApi.get('/hello/:name', async (ctx) => {
- const { name } = ctx.req.params
-
- ctx.res.body = `Hello ${name}`
-})
-```
-
-
-
-
-
-**SST**
-
-```javascript title:packages/functions/hello.ts
-import { ApiHandler, usePathParam } from 'sst/node/api'
-
-export const handler = ApiHandler(async (evt) => {
- const name = usePathParam('name')
-
- return {
- statusCode: 200,
- body: `Hello ${name}`,
- }
-})
-```
-
-```javascript title: stacks/hello-stack.ts
-import { StackContext, Api } from 'sst/constructs'
-
-export function API({ stack }: StackContext) {
- const api = new Api(stack, 'api', {
- routes: {
- 'GET /hello/{name}': 'packages/functions/src/hello.handler',
- },
- })
-
- stack.addOutputs({
- ApiEndpoint: api.url,
- })
-}
-```
-
-
-
-
-
-One key difference between Nitric and SST examples is while Nitric allows defining the API route handler inline which streamlines and simplifies the code, SST separates the route definition and the handler into different files for modularity. Another difference is that Nitric is cloud-neutral while SST is designed specifically for AWS.
-
-## Differences
-
-| | Nitric | SST |
-| -------------------- | ----------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------- |
-| Language | Your choice | JavaScript / TypeScript |
-| Lines of code | 9 | 23 |
-| Cloud Infrastructure | Inferred | Explicit |
-| Extensibility | [Custom providers](/providers/custom/create) can be created | Yes, you can fallback to using the underlying AWS CDK constructs. |
-| Local simulation | Built-in local simulator with instant hot reloading and offline support | No, provides proxy to a deployed app |
-| Cloud providers | AWS, Azure, GCP and [Custom providers](/providers/custom/create) | AWS |
-| Provisioning engine | Pulumi by default, other custom providers can be created | CloudFormation via AWS CDK (CDKTF is used for Terraform, but you cannot compile the same code to different engines) |
diff --git a/docs/docs/misc/comparison/terraform.mdx b/docs/docs/misc/comparison/terraform.mdx
deleted file mode 100644
index 519c9103d..000000000
--- a/docs/docs/misc/comparison/terraform.mdx
+++ /dev/null
@@ -1,204 +0,0 @@
----
-description: 'Comparison to Terraform'
-noindex: true
----
-
-# Terraform vs. Nitric
-
-
- Nitric is not designed to replace IaC tools like Terraform but instead
- introduces a method of bringing developer self-service for infrastructure
- directly into the developer application (Nitric's default deployment engines
- are built with Pulumi). Nitric can be augmented through use of tools like
- Pulumi or Terraform and even be fully customized using such tools see [Custom
- Providers](/providers/custom/create) for more details.
-
-
-Nitric is a framework designed to aid developers in building full cloud applications, including infrastructure. [Terraform](https://www.terraform.io/) is an Infrastructure as Code (IaC) tool that enables explicit definition of infrastructure using HCL (or programming languages using [CDKTF](https://developer.hashicorp.com/terraform/cdktf)). The main differences between these are:
-
-1. Nitric is cloud-agnostic, code that is written using Nitric constructs can be deployed to any cloud. Terraform supports many clouds, infrastructure declarations are explicitly defined for the provider that a resource is provided by.
-
-2. Nitric defines not only the infrastructure but how it is interacted with at runtime, so infrastructure can be automatically inferred from application code to ensure best practice deployments and least privilege security.
-
-3. Nitric provides tools for locally simulating a cloud environment (using the Nitric CLI), to allow an application to be tested locally. Terraform can be validated and linted as well as contract tested using terraform specific tooling.
-
-## Code Comparison
-
-To showcase the power of the abstraction provided by Nitric here is a showcase of a Nitric program with an equivalent Terraform configuration with application code.
-
-
-
-
-
-**Nitric**
-
-```javascript title:handle.js
-import * as nitric from '@nitric/sdk'
-
-const bucket = nitric.bucket('my-bucket').allow('read', 'write')
-
-bucket.on('create', '*', async (ctx) => {
- console.log(ctx.file.key, 'was created')
-})
-```
-
-
-
-
-
-**Terraform**
-
-```javascript title:src/index.js
-const AWS = require('aws-sdk')
-
-exports.handler = async (event) => {
- const {
- s3: { object },
- } = event
- console.log(object.key, 'was created')
-}
-```
-
-```hcl title:main.tf
-terraform {
- required_providers {
- aws = {
- source = "hashicorp/aws"
- version = "~> 3.0"
- }
- }
-}
-
-provider "aws" {
- region = "us-west-2"
-}
-
-locals {
- lambda_function_name = "upload_hello_txt_lambda"
-}
-
-resource "aws_s3_bucket" "this" {
- bucket = "my-s3-bucket"
- acl = "private"
-}
-
-data "archive_file" "lambda_zip" {
- type = "zip"
- source_file = "index.js"
- output_path = "${path.module}/lambda.zip"
-}
-
-resource "aws_lambda_function" "this" {
- function_name = local.lambda_function_name
- role = aws_iam_role.lambda_role.arn
- handler = "index.handler"
- runtime = "nodejs14.x"
- filename = data.archive_file.lambda_zip.output_path
- timeout = 10
-
- environment {
- variables = {
- BUCKET_NAME = aws_s3_bucket.this.bucket
- }
- }
-}
-
-resource "aws_lambda_permission" "allow_bucket" {
- statement_id = "AllowExecutionFromS3Bucket"
- action = "lambda:InvokeFunction"
- function_name = aws_lambda_function.func.arn
- principal = "s3.amazonaws.com"
- source_arn = aws_s3_bucket.bucket.arn
-}
-
-resource "aws_s3_bucket_notification" "bucket_notification" {
- bucket = aws_s3_bucket.bucket.id
-
- lambda_function {
- lambda_function_arn = aws_lambda_function.func.arn
- events = ["s3:ObjectCreated:*"]
- filter_prefix = "AWSLogs/"
- filter_suffix = ".log"
- }
-
- depends_on = [aws_lambda_permission.allow_bucket]
-}
-
-resource "aws_iam_role" "lambda_role" {
- name = "lambda_role"
-
- assume_role_policy = jsonencode({
- Version = "2012-10-17"
- Statement = [
- {
- Action = "sts:AssumeRole"
- Effect = "Allow"
- Principal = {
- Service = "lambda.amazonaws.com"
- }
- }
- ]
- })
-}
-
-resource "aws_iam_role_policy" "lambda_policy" {
- name = "lambda_policy"
- role = aws_iam_role.lambda_role.id
-
- policy = jsonencode({
- Version = "2012-10-17"
- Statement = [
- {
- Action = [
- "logs:CreateLogGroup",
- "logs:CreateLogStream",
- "logs:PutLogEvents"
- ]
- Effect = "Allow"
- Resource = "arn:aws:logs:*:*:*"
- },
- {
- Action = [
- "s3:PutObject"
- ]
- Effect = "Allow"
- Resource = "${aws_s3_bucket.this.arn}/*"
- }
- ]
- })
-}
-
-output "bucket_name" {
- value = aws_s3_bucket.this.bucket
-}
-
-output "lambda_function_name" {
- value = aws_lambda_function.this.function_name
-}
-```
-
-
-
-
-
-
- In the Terraform example we get control over absolutely every facet of our
- infrastructure which is great, but for the majority of use cases, a repeatable
- pattern of deployment is enough and scales much better than applying
- fine-grained configuration every time we need to define a new deployment.
-
-
-## Differences
-
-The table below contains the main differences you can see in the code examples, and also some that cannot fit in such a small app, but we'd like you to know about 🙂
-
-| Feature | Nitric | Terraform |
-| -------------------- | -------------------------------------------------------------------------- | -------------------------------------------------------- |
-| Language | Your choice | HCL |
-| Lines of code | 7 | 123 |
-| Cloud Infrastructure | Inferred | Explicit |
-| Extensibility | Custom providers | Custom/dynamic providers |
-| Local Simulation | Built-in to CLI | N/A |
-| Cross-cloud support | Same code compiles to different clouds | No (need to write different config for different clouds) |
-| Provisioning engine | Custom providers can be written with any IaC tech (e.g. Terraform/AWS CDK) | Proprietary |
-| Testing | Same tests run on local simulator and cloud, without mocks | Need mocks for local testing |
diff --git a/docs/docs/misc/faq.mdx b/docs/docs/misc/faq.mdx
index a51ec1a75..8f53b1639 100644
--- a/docs/docs/misc/faq.mdx
+++ b/docs/docs/misc/faq.mdx
@@ -40,20 +40,6 @@ Yes, Nitric supports monorepos through the custom runtime feature, which allows
Nitric is designed with flexibility to avoid lock-in, including to Nitric. If the framework no longer serves you, you'll simply need to choose a new IaC and migrate your provisioning code. The Nitric framework and CLI are written in Go, and use the Pulumi Go Providers, so you may be able to avoid rewriting all of the provisioning code by lifting the provisioning code which Nitric has already built for you. If relevant, you'll also need to rebuild your CI pipelines to leverage the new IaC tooling you've chosen. Nitric doesn't have access to your data, so no data migration is needed.
-## Differences From Other Solutions
-
-Learn how Nitric compares to:
-
-- [AWS CDK](./comparison/aws-cdk)
-- [AWS SAM](./comparison/aws-sam)
-- [Google Cloud Deployment Manager](./comparison/gcp-deployment-manager)
-- [Azure Resource Manager](./comparison/bicep)
-- [Pulumi](./comparison/pulumi)
-- [Terraform](./comparison/terraform)
-- [SST](./comparison/sst)
-- [Encore](./comparison/encore)
-- [Ampt](./comparison/ampt)
-
## More questions?
Start a discussion on [GitHub](https://github.com/nitrictech/nitric/discussions) or come and chat on our community [Discord](https://nitric.io/chat).
diff --git a/docs/next.config.mjs b/docs/next.config.mjs
index a16c31ee0..1d3016a58 100644
--- a/docs/next.config.mjs
+++ b/docs/next.config.mjs
@@ -95,12 +95,18 @@ const nextConfig = {
permanent: true,
}),
),
- {
- source: '/docs/comparison/:slug',
- destination: '/docs/concepts/comparison/:slug',
+ ...[
+ '/docs/comparison/:slug',
+ '/docs/misc/comparison/:path*',
+ '/docs/concepts/comparison',
+ '/docs/concepts/comparison/:slug*',
+ '/docs/assets/comparison/:path*',
+ ].map((source) => ({
+ source: source,
+ destination: '/docs/',
basePath: false,
permanent: true,
- },
+ })),
{
source: '/docs/assets/faq',
destination: '/docs/faq',
@@ -149,12 +155,6 @@ const nextConfig = {
basePath: false,
permanent: true,
},
- {
- source: '/docs/assets/comparison/:path*',
- destination: '/docs/faq/comparison/:path*',
- basePath: false,
- permanent: true,
- },
{
source: '/docs/getting-started',
destination: '/docs/get-started/quickstart',
@@ -353,18 +353,6 @@ const nextConfig = {
basePath: false,
permanent: true,
},
- {
- source: '/docs/concepts/comparison',
- destination: '/docs/misc/faq#differences-from-other-solutions',
- basePath: false,
- permanent: true,
- },
- {
- source: '/docs/concepts/comparison/:slug*',
- destination: '/docs/misc/comparison/:slug*',
- basePath: false,
- permanent: true,
- },
{
source: '/docs/concepts/extensibility',
destination: '/docs/get-started/foundations/deployment#flexibility',
@@ -629,12 +617,6 @@ const nextConfig = {
basePath: false,
permanent: true,
},
- {
- source: '/docs/misc/comparison/winglang',
- destination: '/docs/',
- basePath: false,
- permanent: true,
- },
]
},
async headers() {
diff --git a/docs/src/app/(sitemaps)/sitemap-0.xml/route.ts b/docs/src/app/(sitemaps)/sitemap-0.xml/route.ts
index 150fd0706..a6d7dd19c 100644
--- a/docs/src/app/(sitemaps)/sitemap-0.xml/route.ts
+++ b/docs/src/app/(sitemaps)/sitemap-0.xml/route.ts
@@ -22,14 +22,12 @@ export async function GET() {
priority: 0.7,
}))
- const docPages: SitemapItem[] = allDocuments
- .filter((page) => !page.slug.startsWith('misc/comparison/'))
- .map((page) => ({
- loc: page.slug === '' ? URL : `${URL}/${page.slug}`,
- lastmod: new Date(page.lastModified).toISOString(),
- changefreq: 'daily',
- priority: 0.7,
- }))
+ const docPages: SitemapItem[] = allDocuments.map((page) => ({
+ loc: page.slug === '' ? URL : `${URL}/${page.slug}`,
+ lastmod: new Date(page.lastModified).toISOString(),
+ changefreq: 'daily',
+ priority: 0.7,
+ }))
const allPagesSorted = [...pages, ...docPages].sort((a, b) =>
a.loc < b.loc ? -1 : 1,