diff --git a/src/directory/directory.mjs b/src/directory/directory.mjs
index c812c8d9894..b0d80164c6d 100644
--- a/src/directory/directory.mjs
+++ b/src/directory/directory.mjs
@@ -843,6 +843,9 @@ export const directory = {
}
]
},
+ {
+ path: 'src/pages/[platform]/frontend/local-context/index.mdx'
+ },
{
path: 'src/pages/[platform]/frontend/server-side-rendering/index.mdx',
children: [
diff --git a/src/pages/[platform]/frontend/connect-to-existing-resources/index.mdx b/src/pages/[platform]/frontend/connect-to-existing-resources/index.mdx
index 826899e520c..a29d35b0d2b 100644
--- a/src/pages/[platform]/frontend/connect-to-existing-resources/index.mdx
+++ b/src/pages/[platform]/frontend/connect-to-existing-resources/index.mdx
@@ -3,7 +3,7 @@ import { getCustomStaticPath } from '@/utils/getCustomStaticPath';
export const meta = {
title: 'Connect to existing AWS resources',
description:
- 'Use Amplify client libraries with your own AWS infrastructure. Configure Auth, Data, Storage, Analytics, Geo, and Notifications programmatically or via amplify_outputs.json — no Amplify backend required.',
+ 'Use Amplify client libraries with your own AWS infrastructure. Configure Auth, Data, Storage, Analytics, Geo, and Notifications programmatically or via amplify_outputs.json, with no Amplify backend required.',
platforms: [
'android',
'angular',
@@ -32,7 +32,7 @@ export function getStaticProps(context) {
Amplify client libraries can be used **independently** without the Amplify backend workflow. If you've provisioned AWS resources with CDK, Terraform, CloudFormation, or the AWS Console, you can connect Amplify libraries directly to those resources.
-This means you can adopt Amplify's client libraries for authentication, data, storage, and more — while keeping full control over your infrastructure.
+This means you can adopt Amplify's client libraries for authentication, data, storage, and more, while keeping full control over your infrastructure.
## When to use this approach
@@ -45,39 +45,90 @@ This means you can adopt Amplify's client libraries for authentication, data, st
-There are two ways to configure Amplify client libraries with your own resources:
+The default path is a generated `amplify_outputs.json` file that you hand to `Amplify.configure()`:
-### Option 1: Manual `amplify_outputs.json`
+```typescript
+import { Amplify } from 'aws-amplify';
+import outputs from './amplify_outputs.json';
-Create an `amplify_outputs.json` file in your project with the configuration for your resources. See the [full `amplify_outputs.json` specification](/[platform]/reference/amplify_outputs/) for all supported fields.
+Amplify.configure(outputs);
+```
-```json title="amplify_outputs.json"
-{
- "version": "1",
- "auth": {
- "aws_region": "us-east-1",
- "user_pool_id": "us-east-1_abc123",
- "user_pool_client_id": "abcdef123456"
- },
- "storage": {
- "aws_region": "us-east-1",
- "bucket_name": "my-app-bucket"
- }
-}
+When you own the infrastructure there is no generated file, so you provide the configuration yourself. There are three ways to do that:
+
+
+
+
+
+`createConfigurationBuilder`, exported from `aws-amplify`, assembles a `ResourcesConfig` step by step. Every method returns the builder, and `build()` produces a frozen `ResourcesConfig` that `Amplify.configure()` accepts:
+
+```typescript
+import { Amplify, createAmplifyContext, createConfigurationBuilder } from 'aws-amplify';
+
+const config = createConfigurationBuilder()
+ .auth({
+ Cognito: {
+ userPoolId: 'us-east-1_abc123',
+ userPoolClientId: 'abcdef123456'
+ }
+ })
+ .storage({ S3: { bucket: 'my-app-bucket', region: 'us-east-1' } })
+ .build();
+
+Amplify.configure(config);
+// or
+const ctx = createAmplifyContext(config);
```
-Then configure Amplify in your app:
+| Method | Description |
+|--------|-------------|
+| `from(seed)` | Merges an existing configuration in. Accepts anything `Amplify.configure()` accepts: a `ResourcesConfig`, a legacy `aws-exports` object, `amplify_outputs.json`, or **another builder**. Can be called repeatedly to accumulate, and is also available as `createConfigurationBuilder({ from })`. |
+| `add(category, value)` | Adds a category, **replacing** it entirely if already present. |
+| `patch(category, partial)` | Deep-merges a partial into a category, keeping nested values you don't mention. Creates the category if it doesn't exist. |
+| `auth()`, `api()`, `storage()`, `analytics()`, `geo()`, `notifications()`, `interactions()`, `predictions()` | Shorthands for `add()` with that category: `.auth(config)` is `.add('Auth', config)`. |
+| `build()` | Returns the finished, frozen `ResourcesConfig`. |
+
+**Configure part of a configuration.** `patch()` deep-merges into a category, so you can change one nested value and leave the rest of it alone. This is the difference between the two write methods: `add('Auth', …)` (and its `auth()` shorthand) discards whatever `Auth` held, while `patch()` keeps it.
```typescript
-import { Amplify } from 'aws-amplify';
-import outputs from './amplify_outputs.json';
+const config = createConfigurationBuilder({ from: outputs })
+ // Everything else under Auth.Cognito survives
+ .patch('Auth', { Cognito: { userPoolId: 'us-east-1_dev123' } })
+ // Add or overwrite a category outright, whether or not the outputs file carries it
+ .add('Storage', { S3: { bucket: 'my-platform-bucket', region: 'us-east-1' } })
+ .build();
+```
-Amplify.configure(outputs);
+**Extend a base builder.** A builder is itself a valid seed, so one shared base can produce environment-specific configurations without being mutated:
+
+```typescript
+// Owned by your platform team, never passed to configure() directly
+const base = createConfigurationBuilder({ from: outputs });
+
+const dev = createConfigurationBuilder({ from: base })
+ .patch('Auth', { Cognito: { userPoolId: 'us-east-1_dev123' } })
+ .build();
+
+const prod = createConfigurationBuilder({ from: base })
+ .patch('Auth', { Cognito: { userPoolId: 'us-east-1_prod789' } })
+ .build();
+```
+
+**Write generators.** Because `build()` returns a plain object, a function that closes over the shared base turns a single varying value into a whole configuration:
+
+```typescript
+const withUserPool = (userPoolId: string) =>
+ createConfigurationBuilder({ from: base })
+ .patch('Auth', { Cognito: { userPoolId } })
+ .build();
+
+Amplify.configure(withUserPool('us-east-1_dev123'));
```
-### Option 2: Direct `Amplify.configure()` with a `ResourcesConfig` object
+
+
-Pass the configuration directly without a JSON file:
+Pass a `ResourcesConfig` object straight to `Amplify.configure()`. Nothing is merged for you, so every call states the complete configuration:
```typescript
import { Amplify } from 'aws-amplify';
@@ -102,6 +153,45 @@ Amplify.configure({
});
```
+This is the most direct option when your app has exactly one configuration and it never varies at runtime.
+
+
+
+
+Keep the configuration in a file of your own and import it, the way a generated `amplify_outputs.json` is imported. Amplify only cares about the shape, so the file name is yours to choose. See the [full `amplify_outputs.json` specification](/[platform]/reference/amplify_outputs/) for every supported field:
+
+```json title="my_resources.json"
+{
+ "version": "1.5",
+ "auth": {
+ "aws_region": "us-east-1",
+ "user_pool_id": "us-east-1_abc123",
+ "user_pool_client_id": "abcdef123456"
+ },
+ "storage": {
+ "aws_region": "us-east-1",
+ "bucket_name": "my-app-bucket"
+ }
+}
+```
+
+```typescript
+import { Amplify, createAmplifyContext } from 'aws-amplify';
+import resources from './my_resources.json';
+
+Amplify.configure(resources);
+// or
+const ctx = createAmplifyContext(resources);
+```
+
+Because the file is checked in as data, this option keeps the configuration out of your application code while still letting you hold several of them: one file per environment, each imported where it is needed.
+
+
+
+
+
+The built `ResourcesConfig` is a plain object either way, so it works anywhere a configuration is accepted: pass it to `Amplify.configure()` to set it globally, or to `createAmplifyContext()` to create an isolated [local context](/[platform]/frontend/local-context/) instead of touching global state.
+
@@ -114,7 +204,7 @@ Create an `amplify_outputs.json` file in your Xcode project. See the [full speci
```json title="amplify_outputs.json"
{
- "version": "1",
+ "version": "1.5",
"auth": {
"aws_region": "us-east-1",
"user_pool_id": "us-east-1_abc123",
@@ -152,9 +242,9 @@ try Amplify.configure(config)
```
This approach is ideal for:
-- **Unit testing** — Configure Amplify without bundling JSON files
-- **Environment switching** — Build different configurations for dev/staging/prod
-- **Dynamic configuration** — Fetch configuration from a remote source at runtime
+- **Unit testing:** Configure Amplify without bundling JSON files
+- **Environment switching:** Build different configurations for dev/staging/prod
+- **Dynamic configuration:** Fetch configuration from a remote source at runtime
@@ -168,7 +258,7 @@ Create an `amplify_outputs.json` file in your `app/src/main/res/raw/` directory.
```json title="amplify_outputs.json"
{
- "version": "1",
+ "version": "1.5",
"auth": {
"aws_region": "us-east-1",
"user_pool_id": "us-east-1_abc123",
@@ -207,9 +297,9 @@ Amplify.configure(config, applicationContext)
```
This approach is ideal for:
-- **Unit testing** — Configure Amplify without bundling JSON files
-- **Environment switching** — Build different configurations for dev/staging/prod
-- **Dynamic configuration** — Fetch configuration from a remote source at runtime
+- **Unit testing:** Configure Amplify without bundling JSON files
+- **Environment switching:** Build different configurations for dev/staging/prod
+- **Dynamic configuration:** Fetch configuration from a remote source at runtime
@@ -223,7 +313,7 @@ Create an `amplify_outputs.json` file with your resource configuration. See the
```json title="amplify_outputs.json"
{
- "version": "1",
+ "version": "1.5",
"auth": {
"aws_region": "us-east-1",
"user_pool_id": "us-east-1_abc123",
@@ -267,9 +357,9 @@ await Amplify.configure(config);
```
This approach is ideal for:
-- **Unit testing** — Configure Amplify without bundling files
-- **Environment switching** — Build different configurations for dev/staging/prod
-- **Dynamic configuration** — Fetch configuration from a remote source at runtime
+- **Unit testing:** Configure Amplify without bundling files
+- **Environment switching:** Build different configurations for dev/staging/prod
+- **Dynamic configuration:** Fetch configuration from a remote source at runtime
@@ -279,7 +369,49 @@ Connect to an existing Cognito User Pool and Identity Pool.
+
+
+
+
+```typescript
+import { Amplify, createAmplifyContext, createConfigurationBuilder } from 'aws-amplify';
+
+const config = createConfigurationBuilder()
+ .auth({
+ Cognito: {
+ userPoolId: 'us-east-1_abc123',
+ userPoolClientId: 'abcdef123456',
+ identityPoolId: 'us-east-1:11111111-2222-3333-4444-555555555555',
+ loginWith: {
+ email: true
+ },
+ signUpVerificationMethod: 'code',
+ userAttributes: {
+ email: { required: true }
+ },
+ allowGuestAccess: true,
+ passwordFormat: {
+ minLength: 8,
+ requireLowercase: true,
+ requireUppercase: true,
+ requireNumbers: true,
+ requireSpecialCharacters: true
+ }
+ }
+ })
+ .build();
+
+Amplify.configure(config);
+// or
+const ctx = createAmplifyContext(config);
+```
+
+
+
+
```typescript
+import { Amplify } from 'aws-amplify';
+
Amplify.configure({
Auth: {
Cognito: {
@@ -306,6 +438,10 @@ Amplify.configure({
});
```
+
+
+
+
@@ -439,16 +575,33 @@ await Amplify.configure(config);
### Auth required fields
+
+
+Fields of `ResourcesConfig['Auth']`, the object both tabs above build:
+
+| Field | Required | Description |
+|-------|----------|-------------|
+| `Cognito.userPoolId` | With a user pool | Cognito User Pool ID |
+| `Cognito.userPoolClientId` | With a user pool | Cognito app client ID |
+| `Cognito.identityPoolId` | With an identity pool | Cognito Identity Pool ID, needed for guest access and for IAM-signed requests |
+
+There is no region field: the region is read from the user pool and identity pool IDs. `Cognito` accepts the user pool fields, the identity pool fields, or both, so an identity-pool-only configuration cannot carry `userPoolId`.
+
+Every other field is optional. See [`AuthConfig`](https://github.com/aws-amplify/amplify-js/blob/aws-amplify%406.22.0/packages/core/src/singleton/Auth/types.ts) for the full type.
+
+
+
+
+
| Field | Required | Description |
|-------|----------|-------------|
| `awsRegion` | Yes | AWS region (e.g. `us-east-1`) |
| `userPoolId` | Yes | Cognito User Pool ID |
| `userPoolClientId` | Yes | Cognito app client ID |
-| `identityPoolId` | No | Cognito Identity Pool ID (needed for guest access and IAM-based auth) |
-| `passwordPolicy` | No | Password requirements (min length, character types) |
-| `oauth` | No | OAuth/Hosted UI configuration (social sign-in) |
-| `mfaConfiguration` | No | MFA mode: `NONE`, `OPTIONAL`, or `REQUIRED` |
-| `mfaMethods` | No | MFA types: `SMS`, `TOTP` |
+
+Every other field is optional. See the [`amplify_outputs.json` schema](https://github.com/aws-amplify/amplify-backend/blob/%40aws-amplify%2Fclient-config%401.11.1/packages/client-config/src/client-config-schema/schema_v1.5.json) for the full shape.
+
+
## Configure Data (AWS AppSync)
@@ -456,26 +609,59 @@ Connect to an existing AppSync GraphQL API.
-```json title="amplify_outputs.json"
-{
- "version": "1",
- "data": {
- "aws_region": "us-east-1",
- "url": "https://abc123.appsync-api.us-east-1.amazonaws.com/graphql",
- "api_key": "da2-abcdefghijklmno",
- "default_authorization_type": "API_KEY",
- "authorization_types": ["API_KEY"]
- }
-}
+
+
+
+
+```typescript
+import { Amplify, createAmplifyContext, createConfigurationBuilder } from 'aws-amplify';
+
+const config = createConfigurationBuilder()
+ .api({
+ GraphQL: {
+ endpoint:
+ 'https://abc123.appsync-api.us-east-1.amazonaws.com/graphql',
+ region: 'us-east-1',
+ apiKey: 'da2-abcdefghijklmno',
+ defaultAuthMode: 'apiKey'
+ }
+ })
+ .build();
+
+Amplify.configure(config);
+// or
+const ctx = createAmplifyContext(config);
```
+
+
+
```typescript
import { Amplify } from 'aws-amplify';
-import outputs from './amplify_outputs.json';
-Amplify.configure(outputs);
+Amplify.configure({
+ API: {
+ GraphQL: {
+ endpoint:
+ 'https://abc123.appsync-api.us-east-1.amazonaws.com/graphql',
+ region: 'us-east-1',
+ apiKey: 'da2-abcdefghijklmno',
+ defaultAuthMode: 'apiKey'
+ }
+ }
+});
```
+
+
+
+
+
+
+In a `ResourcesConfig` object the AppSync API lives under `API.GraphQL`, and `defaultAuthMode` takes the client-side value, one of `apiKey`, `userPool`, `identityPool`, `oidc`, `lambda`, or `none`, rather than the `API_KEY` style used in `amplify_outputs.json`.
+
+
+
@@ -540,13 +726,34 @@ await Amplify.configure(config);
### Data required fields
+
+
+Fields of `ResourcesConfig['API']`, the object both tabs above build:
+
+| Field | Required | Description |
+|-------|----------|-------------|
+| `GraphQL.endpoint` | Yes | AppSync GraphQL endpoint URL |
+| `GraphQL.defaultAuthMode` | Yes | `apiKey`, `userPool`, `identityPool`, `oidc`, `lambda`, or `none`. `iam` is the deprecated spelling of `identityPool` |
+| `GraphQL.apiKey` | With `apiKey` auth | AppSync API key |
+| `GraphQL.region` | With `identityPool` auth | Region used to sign the request |
+
+Every other field is optional. See [`APIConfig`](https://github.com/aws-amplify/amplify-js/blob/aws-amplify%406.22.0/packages/core/src/singleton/API/types.ts) for the full type.
+
+
+
+
+
| Field | Required | Description |
|-------|----------|-------------|
| `awsRegion` | Yes | AWS region |
| `url` | Yes | AppSync GraphQL endpoint URL |
-| `defaultAuthorizationType` | Yes | Default auth mode: `API_KEY`, `AMAZON_COGNITO_USER_POOLS`, `AWS_IAM`, or `OPENID_CONNECT` |
-| `authorizationTypes` | Yes | All supported auth modes |
-| `apiKey` | No | Required if using `API_KEY` auth |
+| `defaultAuthorizationType` | Yes | Default auth mode: API key, Cognito user pools, IAM, Lambda, or OIDC |
+| `authorizationTypes` | Yes | Every auth mode the API accepts, from the same list |
+| `apiKey` | With API key auth | AppSync API key |
+
+Every other field is optional. See the [`amplify_outputs.json` schema](https://github.com/aws-amplify/amplify-backend/blob/%40aws-amplify%2Fclient-config%401.11.1/packages/client-config/src/client-config-schema/schema_v1.5.json) for the full shape.
+
+
## Configure Storage (Amazon S3)
@@ -554,7 +761,35 @@ Connect to an existing S3 bucket.
+
+
+
+
+```typescript
+import { Amplify, createAmplifyContext, createConfigurationBuilder } from 'aws-amplify';
+
+const config = createConfigurationBuilder()
+ .auth({
+ Cognito: {
+ userPoolId: 'us-east-1_abc123',
+ userPoolClientId: 'abcdef123456',
+ identityPoolId: 'us-east-1:11111111-2222-3333-4444-555555555555'
+ }
+ })
+ .storage({ S3: { bucket: 'my-app-bucket', region: 'us-east-1' } })
+ .build();
+
+Amplify.configure(config);
+// or
+const ctx = createAmplifyContext(config);
+```
+
+
+
+
```typescript
+import { Amplify } from 'aws-amplify';
+
Amplify.configure({
Auth: {
Cognito: {
@@ -572,6 +807,53 @@ Amplify.configure({
});
```
+
+
+
+
+### Multiple buckets
+
+
+
+
+
+```typescript
+const config = createConfigurationBuilder()
+ .storage({
+ S3: {
+ bucket: 'primary-bucket',
+ region: 'us-east-1',
+ buckets: {
+ media: { bucketName: 'my-media-bucket', region: 'us-east-1' },
+ logs: { bucketName: 'my-logs-bucket', region: 'us-west-2' }
+ }
+ }
+ })
+ .build();
+```
+
+
+
+
+```typescript
+Amplify.configure({
+ Storage: {
+ S3: {
+ bucket: 'primary-bucket',
+ region: 'us-east-1',
+ buckets: {
+ media: { bucketName: 'my-media-bucket', region: 'us-east-1' },
+ logs: { bucketName: 'my-logs-bucket', region: 'us-west-2' }
+ }
+ }
+ }
+});
+```
+
+
+
+
+
@@ -696,7 +978,7 @@ final config = AmplifyOutputs(
-
+
Storage requires Auth (Cognito Identity Pool) for authorization. Always configure Auth alongside Storage.
@@ -704,11 +986,31 @@ Storage requires Auth (Cognito Identity Pool) for authorization. Always configur
### Storage required fields
+
+
+Fields of `ResourcesConfig['Storage']`, the object both tabs above build:
+
+| Field | Required | Description |
+|-------|----------|-------------|
+| `S3.bucket` | For the default bucket | Bucket used by calls that do not name one |
+| `S3.region` | For the default bucket | Region of that bucket |
+| `S3.buckets[name].bucketName`, `S3.buckets[name].region` | With additional buckets | Each extra bucket is keyed by the friendly name you pass to the Storage APIs |
+
+Every other field is optional. See [`StorageConfig`](https://github.com/aws-amplify/amplify-js/blob/aws-amplify%406.22.0/packages/core/src/singleton/Storage/types.ts) for the full type.
+
+
+
+
+
| Field | Required | Description |
|-------|----------|-------------|
| `awsRegion` | Yes | AWS region |
| `bucketName` | Yes | Default S3 bucket name |
-| `buckets` | No | Additional named buckets for multi-bucket setups |
+| `buckets[].name`, `buckets[].bucketName`, `buckets[].awsRegion` | With additional buckets | All three are required on every entry |
+
+Every other field is optional. See the [`amplify_outputs.json` schema](https://github.com/aws-amplify/amplify-backend/blob/%40aws-amplify%2Fclient-config%401.11.1/packages/client-config/src/client-config-schema/schema_v1.5.json) for the full shape.
+
+
## Configure Analytics (Amazon Pinpoint)
@@ -716,18 +1018,47 @@ Connect to an existing Pinpoint application.
-```json title="amplify_outputs.json"
-{
- "version": "1",
- "analytics": {
- "amazon_pinpoint": {
- "aws_region": "us-east-1",
- "app_id": "abc123def456"
+
+
+
+
+```typescript
+import { Amplify, createAmplifyContext, createConfigurationBuilder } from 'aws-amplify';
+
+const config = createConfigurationBuilder()
+ .analytics({
+ Pinpoint: {
+ appId: 'abc123def456',
+ region: 'us-east-1'
+ }
+ })
+ .build();
+
+Amplify.configure(config);
+// or
+const ctx = createAmplifyContext(config);
+```
+
+
+
+
+```typescript
+import { Amplify } from 'aws-amplify';
+
+Amplify.configure({
+ Analytics: {
+ Pinpoint: {
+ appId: 'abc123def456',
+ region: 'us-east-1'
}
}
-}
+});
```
+
+
+
+
@@ -784,35 +1115,101 @@ await Amplify.configure(config);
+### Analytics required fields
+
+
+
+Fields of `ResourcesConfig['Analytics']`, the object both tabs above build:
+
+| Field | Required | Description |
+|-------|----------|-------------|
+| `Pinpoint.appId` | Yes | Pinpoint application (project) ID |
+| `Pinpoint.region` | Yes | Region of the Pinpoint project |
+
+Every other field is optional. See [`AnalyticsConfig`](https://github.com/aws-amplify/amplify-js/blob/aws-amplify%406.22.0/packages/core/src/singleton/Analytics/types.ts) for the full type.
+
+
+
+
+
+| Field | Required | Description |
+|-------|----------|-------------|
+| `amazonPinpoint.awsRegion` | Yes | AWS region of the Pinpoint project |
+| `amazonPinpoint.appId` | Yes | Pinpoint application (project) ID |
+
+Every other field is optional. See the [`amplify_outputs.json` schema](https://github.com/aws-amplify/amplify-backend/blob/%40aws-amplify%2Fclient-config%401.11.1/packages/client-config/src/client-config-schema/schema_v1.5.json) for the full shape.
+
+
+
## Configure Geo (Amazon Location Service)
Connect to existing Location Service resources.
-```json title="amplify_outputs.json"
-{
- "version": "1",
- "geo": {
- "aws_region": "us-east-1",
- "maps": {
- "items": {
- "myMap": { "style": "VectorEsriStreets" }
+
+
+
+
+```typescript
+import { Amplify, createAmplifyContext, createConfigurationBuilder } from 'aws-amplify';
+
+const config = createConfigurationBuilder()
+ .geo({
+ LocationService: {
+ region: 'us-east-1',
+ maps: {
+ items: { myMap: { style: 'VectorEsriStreets' } },
+ default: 'myMap'
},
- "default": "myMap"
- },
- "search_indices": {
- "items": ["myPlaceIndex"],
- "default": "myPlaceIndex"
- },
- "geofence_collections": {
- "items": ["myGeofenceCollection"],
- "default": "myGeofenceCollection"
+ searchIndices: {
+ items: ['myPlaceIndex'],
+ default: 'myPlaceIndex'
+ },
+ geofenceCollections: {
+ items: ['myGeofenceCollection'],
+ default: 'myGeofenceCollection'
+ }
+ }
+ })
+ .build();
+
+Amplify.configure(config);
+// or
+const ctx = createAmplifyContext(config);
+```
+
+
+
+
+```typescript
+import { Amplify } from 'aws-amplify';
+
+Amplify.configure({
+ Geo: {
+ LocationService: {
+ region: 'us-east-1',
+ maps: {
+ items: { myMap: { style: 'VectorEsriStreets' } },
+ default: 'myMap'
+ },
+ searchIndices: {
+ items: ['myPlaceIndex'],
+ default: 'myPlaceIndex'
+ },
+ geofenceCollections: {
+ items: ['myGeofenceCollection'],
+ default: 'myGeofenceCollection'
+ }
}
}
-}
+});
```
+
+
+
+
@@ -873,6 +1270,38 @@ Amplify.configure(config, applicationContext)
+### Geo required fields
+
+
+
+Fields of `ResourcesConfig['Geo']`, the object both tabs above build:
+
+| Field | Required | Description |
+|-------|----------|-------------|
+| `LocationService.region` | Yes | Region of the Location Service resources |
+| `LocationService.maps.items`, `LocationService.maps.default` | With `maps` | Maps keyed by name, plus the default map name |
+| `LocationService.searchIndices.items`, `LocationService.searchIndices.default` | With `searchIndices` | Place index names, plus the default index |
+| `LocationService.geofenceCollections.items`, `LocationService.geofenceCollections.default` | With `geofenceCollections` | Collection names, plus the default collection |
+
+Every other field is optional. See [`GeoConfig`](https://github.com/aws-amplify/amplify-js/blob/aws-amplify%406.22.0/packages/core/src/singleton/Geo/types.ts) for the full type.
+
+
+
+
+
+| Field | Required | Description |
+|-------|----------|-------------|
+| `awsRegion` | Yes | AWS region of the Location Service resources |
+| `maps.items`, `maps.default` | With `maps` | Maps keyed by name, plus the default map name |
+| `searchIndices.items`, `searchIndices.default` | With `searchIndices` | Place index names, plus the default index |
+| `geofenceCollections.items`, `geofenceCollections.default` | With `geofenceCollections` | Collection names, plus the default collection |
+
+Every other field is optional. See the [`amplify_outputs.json` schema](https://github.com/aws-amplify/amplify-backend/blob/%40aws-amplify%2Fclient-config%401.11.1/packages/client-config/src/client-config-schema/schema_v1.5.json) for the full shape.
+
+
+
+Each resource group is optional on its own, but configure the ones your app actually calls: the Geo APIs need a default for the resource type they use.
+
## Configure Notifications (Push)
Connect to an existing Pinpoint application for push notifications.
@@ -914,11 +1343,11 @@ Amplify.configure(config, applicationContext)
-
+
```json title="amplify_outputs.json"
{
- "version": "1",
+ "version": "1.5",
"notifications": {
"aws_region": "us-east-1",
"amazon_pinpoint_app_id": "abc123def456",
@@ -929,6 +1358,108 @@ Amplify.configure(config, applicationContext)
+
+
+
+
+
+
+```typescript
+import { Amplify, createAmplifyContext, createConfigurationBuilder } from 'aws-amplify';
+
+const config = createConfigurationBuilder()
+ .notifications({
+ PushNotification: {
+ Pinpoint: { appId: 'abc123def456', region: 'us-east-1' }
+ },
+ InAppMessaging: {
+ Pinpoint: { appId: 'abc123def456', region: 'us-east-1' }
+ }
+ })
+ .build();
+
+Amplify.configure(config);
+// or
+const ctx = createAmplifyContext(config);
+```
+
+
+
+
+```typescript
+import { Amplify } from 'aws-amplify';
+
+Amplify.configure({
+ Notifications: {
+ PushNotification: {
+ Pinpoint: { appId: 'abc123def456', region: 'us-east-1' }
+ },
+ InAppMessaging: {
+ Pinpoint: { appId: 'abc123def456', region: 'us-east-1' }
+ }
+ }
+});
+```
+
+
+
+
+
+
+
+### Notifications required fields
+
+
+
+Fields of `ResourcesConfig['Notifications']`, the object both tabs above build. At least one of `PushNotification` and `InAppMessaging` must be present:
+
+| Field | Required | Description |
+|-------|----------|-------------|
+| `PushNotification.Pinpoint.appId`, `PushNotification.Pinpoint.region` | For Pinpoint push | Pinpoint project backing push device registration |
+| `PushNotification.CustomerProfiles.endpoint`, `PushNotification.CustomerProfiles.region` | For Amazon Connect push | Amazon Connect Customer Profiles endpoint backing push device registration |
+| `InAppMessaging.Pinpoint.appId`, `InAppMessaging.Pinpoint.region` | For in-app messaging | Pinpoint project backing in-app messages |
+
+Every other field is optional. See [`NotificationsConfig`](https://github.com/aws-amplify/amplify-js/blob/aws-amplify%406.22.0/packages/core/src/singleton/Notifications/types.ts) for the full type.
+
+
+
+
+
+| Field | Required | Description |
+|-------|----------|-------------|
+| `awsRegion` | For Pinpoint | AWS region of the Pinpoint project |
+| `amazonPinpointAppId` | For Pinpoint | Pinpoint application ID |
+| `channels` | For Pinpoint | Channels to enable: APNS, FCM, in-app messaging, email, or SMS. At least one entry, no duplicates |
+
+A Pinpoint setup needs all three: the region, the app ID, and at least one channel.
+
+Every other field is optional. See the [`amplify_outputs.json` schema](https://github.com/aws-amplify/amplify-backend/blob/%40aws-amplify%2Fclient-config%401.11.1/packages/client-config/src/client-config-schema/schema_v1.5.json) for the full shape.
+
+
+
+
+
+Configure either a Pinpoint project or an Amazon Connect endpoint, or both:
+
+| Field | Required | Description |
+|-------|----------|-------------|
+| `awsRegion` | For Pinpoint | AWS region of the Pinpoint project |
+| `amazonPinpointAppId` | For Pinpoint | Pinpoint application ID |
+| `channels` | For Pinpoint | Channels to enable: APNS, FCM, in-app messaging, email, or SMS. At least one entry, no duplicates |
+| `amazonConnect.awsRegion`, `amazonConnect.endpoint` | For Amazon Connect | Amazon Connect Customer Profiles endpoint backing push device registration. Both are required on the entry |
+
+A Pinpoint setup needs all three Pinpoint fields: the region, the app ID, and at least one channel.
+
+Every other field is optional. See the [`amplify_outputs.json` schema](https://github.com/aws-amplify/amplify-backend/blob/%40aws-amplify%2Fclient-config%401.11.1/packages/client-config/src/client-config-schema/schema_v1.5.json) for the full shape.
+
+
+
+
+
+In a `ResourcesConfig` object there is no `channels` list: which channels are active follows from the providers you configure, `PushNotification` and `InAppMessaging`. The `amazon_connect` block in `amplify_outputs.json` becomes `Notifications.PushNotification.CustomerProfiles` with `endpoint` and `region`.
+
+
+
## Multi-category configuration
You can configure multiple services together. This example sets up Auth, Data, and Storage in a single configuration.
@@ -1028,7 +1559,45 @@ await Amplify.configure(config);
+
+
+
+
+```typescript
+import { Amplify, createAmplifyContext, createConfigurationBuilder } from 'aws-amplify';
+
+const config = createConfigurationBuilder()
+ .auth({
+ Cognito: {
+ userPoolId: 'us-east-1_abc123',
+ userPoolClientId: 'abcdef123456',
+ identityPoolId: 'us-east-1:11111111-2222-3333-4444-555555555555'
+ }
+ })
+ .api({
+ GraphQL: {
+ endpoint:
+ 'https://abc123.appsync-api.us-east-1.amazonaws.com/graphql',
+ region: 'us-east-1',
+ defaultAuthMode: 'userPool'
+ }
+ })
+ .storage({ S3: { bucket: 'my-app-bucket', region: 'us-east-1' } })
+ .build();
+
+Amplify.configure(config);
+// or
+const ctx = createAmplifyContext(config);
+```
+
+Chaining also means a category can come from somewhere else entirely: seed the builder with a shared configuration and add only what this app owns.
+
+
+
+
```typescript
+import { Amplify } from 'aws-amplify';
+
Amplify.configure({
Auth: {
Cognito: {
@@ -1039,7 +1608,9 @@ Amplify.configure({
},
API: {
GraphQL: {
- endpoint: 'https://abc123.appsync-api.us-east-1.amazonaws.com/graphql',
+ endpoint:
+ 'https://abc123.appsync-api.us-east-1.amazonaws.com/graphql',
+ region: 'us-east-1',
defaultAuthMode: 'userPool'
}
},
@@ -1052,6 +1623,10 @@ Amplify.configure({
});
```
+
+
+
+
@@ -1182,7 +1757,28 @@ await Amplify.configure(config);
-You can maintain separate `amplify_outputs.json` files per environment:
+Keep one configuration per environment and select it at startup. With the builder, derive each one from a shared base so only the differing fields are restated. The generator pattern from [How it works](#how-it-works) applies directly:
+
+```typescript
+import { Amplify, createConfigurationBuilder } from 'aws-amplify';
+import outputs from './amplify_outputs.json';
+
+const base = createConfigurationBuilder({ from: outputs });
+
+const withUserPool = (userPoolId: string) =>
+ createConfigurationBuilder({ from: base })
+ .patch('Auth', { Cognito: { userPoolId } })
+ .build();
+
+const configs = {
+ dev: withUserPool('us-east-1_dev123'),
+ prod: withUserPool('us-east-1_prod789')
+};
+
+Amplify.configure(configs[selectedEnvironment]);
+```
+
+If the environments share nothing, keep a separate outputs file per environment instead:
```typescript
import devOutputs from './amplify_outputs.dev.json';
@@ -1192,6 +1788,21 @@ const outputs = process.env.NODE_ENV === 'production' ? prodOutputs : devOutputs
Amplify.configure(outputs);
```
+### Several environments at the same time
+
+`Amplify.configure()` sets one process-wide configuration, so selecting an environment this way means the whole app moves with it. To keep more than one environment live at once, pass each configuration to `createAmplifyContext()` instead of to `configure()`, then hand the resulting context to the category APIs:
+
+```typescript
+import { createAmplifyContext } from 'aws-amplify';
+
+const environments = {
+ dev: createAmplifyContext(withUserPool('us-east-1_dev123')),
+ prod: createAmplifyContext(withUserPool('us-east-1_prod789'))
+};
+```
+
+See [Local context](/[platform]/frontend/local-context/) for what a context isolates, how to use one, and why it is a client-side API.
+
## `amplify_outputs.json` schema reference
diff --git a/src/pages/[platform]/frontend/local-context/index.mdx b/src/pages/[platform]/frontend/local-context/index.mdx
new file mode 100644
index 00000000000..53f5bb0870c
--- /dev/null
+++ b/src/pages/[platform]/frontend/local-context/index.mdx
@@ -0,0 +1,203 @@
+import { getCustomStaticPath } from '@/utils/getCustomStaticPath';
+
+export const meta = {
+ title: 'Local context',
+ description:
+ 'Create an isolated, local AmplifyContext with createAmplifyContext and pass it directly to Amplify category APIs, without relying on global singleton configuration.',
+ platforms: [
+ 'angular',
+ 'javascript',
+ 'nextjs',
+ 'react',
+ 'react-native',
+ 'vue'
+ ]
+};
+
+export const getStaticPaths = async () => {
+ return getCustomStaticPath(meta.platforms);
+};
+
+export function getStaticProps(context) {
+ return {
+ props: {
+ platform: context.params.platform,
+ meta
+ }
+ };
+}
+
+By default, Amplify uses a single, process-wide configuration created by `Amplify.configure()`. Every category API call (for example `signIn`, `fetchAuthSession`, or `getCurrentUser`) reads from this global singleton. That is the right default when your app talks to exactly one backend as one user at a time, but it means there is only ever **one** configuration and **one** auth state in the process.
+
+`aws-amplify` exposes `createAmplifyContext` for everything else. It builds a **local** `AmplifyContext`: an isolated configuration and auth handle that you pass explicitly to category APIs as their **first argument**. Each context carries its own resource configuration and its own per-context auth instance, so contexts never share state with one another or with the global singleton.
+
+This is not a server-side API. For server-side runtimes, keep using the server exports and `runWithAmplifyServerContext`. See [Use a local context or a server context?](#use-a-local-context-or-a-server-context).
+
+## When to use a local context
+
+Reach for `createAmplifyContext` whenever a single global configuration is not enough:
+
+- **Multiple profiles signed in at once:** for example a work profile and a personal profile side by side, each with its own session, without signing one out to use the other.
+- **Tenant switching:** hold a context per tenant/organization so switching does not tear down and re-configure Amplify globally.
+- **Environment switching:** point a build at alpha, beta, pre-prod, or prod backends from the same running app, which is useful for internal tooling, QA harnesses, and dashboards that compare environments side by side.
+
+
+
+**Tip:** If your app talks to a single backend as one user at a time, keep using `Amplify.configure()` and call the APIs without a context argument. Nothing changes for you: the context parameter is optional and fully backward compatible.
+
+
+
+## Create and use a local context
+
+
+
+
+
+Import `createAmplifyContext` from `aws-amplify`, pass your backend outputs to create the context, then hand that context to any category API as its **first** positional argument. Unlike `Amplify.configure()`, creating a context does **not** set a global context and does **not** dispatch any Hub events: it returns a new, isolated context object, ready to use immediately.
+
+```typescript
+import { createAmplifyContext } from 'aws-amplify';
+import { signIn, getCurrentUser, fetchUserAttributes } from 'aws-amplify/auth';
+import outputs from './amplify_outputs.json';
+
+// Create the context
+const ctx = createAmplifyContext(outputs);
+
+// Sign in against the configuration carried by `ctx`
+await signIn(ctx, { username, password });
+
+// Read the current user from that same context
+const user = await getCurrentUser(ctx);
+const attributes = await fetchUserAttributes(ctx);
+```
+
+
+
+
+The context argument is optional. `Amplify.configure()` sets a single process-wide context, and calling an API without a leading context falls back to it, exactly as before local contexts existed. Nothing about this changes when you adopt `createAmplifyContext` elsewhere in your app.
+
+```typescript
+import { Amplify } from 'aws-amplify';
+import { signIn, getCurrentUser, fetchUserAttributes } from 'aws-amplify/auth';
+import outputs from './amplify_outputs.json';
+
+// Set the global context
+Amplify.configure(outputs);
+
+// Uses the global context, no context argument
+await signIn({ username, password });
+
+const user = await getCurrentUser();
+const attributes = await fetchUserAttributes();
+```
+
+
+
+
+
+### Library options are per context
+
+`createAmplifyContext` takes the same optional `libraryOptions` as `Amplify.configure()` as its second argument, and those options belong to that context alone. A custom token provider, credentials provider, or key-value storage passed here is used only by calls that receive this context: it is never shared with another context or with the global singleton.
+
+```typescript
+const ctx = createAmplifyContext(outputs, {
+ Auth: {
+ tokenProvider,
+ credentialsProvider
+ }
+});
+```
+
+If you do not pass any, the context resolves its own per-context Amazon Cognito token and credentials providers backed by `localStorage`. Either way the resulting token store is scoped to the context, which is what lets two contexts hold two signed-in users at the same time.
+
+## Use multiple isolated contexts
+
+Because each context is fully isolated, you can hold several at once and they will not share configuration or auth state. Each keeps its own session, so a user signed in through one context is unaffected by the others.
+
+### Multiple profiles signed in at once
+
+A user can be signed in to a work profile and a personal profile simultaneously, each with its own configuration and its own independent session.
+
+```typescript
+import { createAmplifyContext } from 'aws-amplify';
+import { signIn, getCurrentUser } from 'aws-amplify/auth';
+import workOutputs from './amplify_work_outputs.json';
+import personalOutputs from './amplify_personal_outputs.json';
+
+const workProfile = createAmplifyContext(workOutputs);
+const personalProfile = createAmplifyContext(personalOutputs);
+
+await signIn(workProfile, { username: workEmail, password: workPassword });
+await signIn(personalProfile, { username: personalEmail, password: personalPassword });
+
+// Both sessions are live and independent
+const workUser = await getCurrentUser(workProfile);
+const personalUser = await getCurrentUser(personalProfile);
+```
+
+### Switching environments
+
+Point the same running app at different backends, for example alpha, beta, pre-prod, and prod, without reconfiguring Amplify globally. This is useful for internal tools and QA dashboards that compare environments side by side.
+
+```typescript
+import { createAmplifyContext } from 'aws-amplify';
+import { fetchAuthSession } from 'aws-amplify/auth';
+import alphaOutputs from './outputs/alpha.json';
+import betaOutputs from './outputs/beta.json';
+import prodOutputs from './outputs/prod.json';
+
+const environments = {
+ alpha: createAmplifyContext(alphaOutputs),
+ beta: createAmplifyContext(betaOutputs),
+ prod: createAmplifyContext(prodOutputs)
+};
+
+// Select the environment at runtime, no global reconfiguration needed
+const ctx = environments[selectedEnvironment];
+const session = await fetchAuthSession(ctx);
+```
+
+
+
+**Note:** Before local contexts, switching backends at runtime meant calling `Amplify.configure()` again, which replaced the configuration for the whole app and reset the global auth state. Holding one context per environment avoids that.
+
+
+
+## Error handling
+
+Context resolution surfaces two typed errors with stable `name` values, so you can catch them uniformly:
+
+| Error | When it is thrown |
+| --- | --- |
+| `NoAmplifyContextError` | An API was called without a context AND `Amplify.configure()` has not been called yet (no global context exists), or `undefined` was passed as the leading context argument followed by other arguments. |
+| `InvalidAmplifyContextError` | A value that is not an `AmplifyContext` was passed as the first argument, or an `AmplifyContext` was passed in a position other than the first argument. |
+
+Catch them by `name`. The error classes are internal, so there is nothing to import, and a stable name keeps working even when two copies of a package end up in the same bundle:
+
+```typescript
+import { getCurrentUser } from 'aws-amplify/auth';
+
+try {
+ const user = await getCurrentUser(ctx);
+} catch (error) {
+ if (error instanceof Error && error.name === 'NoAmplifyContextError') {
+ // No context available: call configure() or create one with createAmplifyContext()
+ }
+ throw error;
+}
+```
+
+## Use a local context or a server context?
+
+Local contexts are for **client-side** code. Server-side runtimes have their own mechanism, and the two are not interchangeable:
+
+- **Client:** use `createAmplifyContext` from `aws-amplify` and pass the context to the standard category APIs, as shown above.
+- **Server:** use `runWithAmplifyServerContext` from `@aws-amplify/adapter-nextjs`, calling the APIs exported from the `aws-amplify//server` sub-paths inside the `operation` callback. See [Server-Side Rendering](/[platform]/frontend/server-side-rendering/).
+
+The server exports exist to constrain the API surface: only a subset of Amplify APIs is supported server-side, and the `/server` sub-paths are what make that subset explicit. Reaching for a local context on the server would sidestep that boundary and let you call APIs that are not supported in a server runtime. Use the server context instead: it also derives auth state from the incoming request's cookies, which a local context does not do.
+
+
+
+Need more than one Amplify configuration, or more than one signed-in identity, at the same time in your client app? A local `AmplifyContext` is the recommended pattern.
+
+
diff --git a/src/pages/[platform]/frontend/server-side-rendering/index.mdx b/src/pages/[platform]/frontend/server-side-rendering/index.mdx
index 21ffbac0bc0..46b04609498 100644
--- a/src/pages/[platform]/frontend/server-side-rendering/index.mdx
+++ b/src/pages/[platform]/frontend/server-side-rendering/index.mdx
@@ -78,6 +78,12 @@ You can use the exported `runWithAmplifyServerContext` function to call Amplify
**Tip:** You only need to call the `createServerRunner` function once and reuse the `runWithAmplifyServerContext` function throughout.
+
+
+**Note:** If your **client-side** code needs to hold several Amplify configurations at once, for example one per tenant or per environment, see [Local context](/[platform]/frontend/local-context/). For server-side code, use `runWithAmplifyServerContext` with the `/server` exports as described on this page.
+
+
+