Skip to content

Commit e7894f5

Browse files
authored
docs(build-a-backend): add AWS Blocks integration section (#8606)
* docs(build-a-backend): add AWS Blocks integration section Add an "AWS Blocks" section under Build a Backend covering how to add AWS Blocks to an existing Amplify Gen 2 project, how the integration works, connecting a frontend, and task-based guides for adding an AI agent and using BasicAuth. Add a Blocks integration steering-file recipe for AI coding assistants. - New pages under src/pages/[platform]/build-a-backend/aws-blocks/ - Register pages in directory.mjs (top of Build a Backend, New badge) - Extend develop-with-ai/steering-files with an AWS Blocks section - Add Blocks terminology to cspell dictionary * docs(build-a-backend): fix Connect your frontend link in Blocks how-it-works Add the missing build-a-backend/ path segment so the Next steps link resolves instead of 404ing. * chore: update yarn.lock to v10 format for Yarn 4.17 CI's set_yarn_berry action runs 'yarn set version berry', which resolves to the latest Yarn (now 4.17.0) and rewrites the lockfile to __metadata version 10. The committed lockfile was version 9, so the immutable install step failed on every PR. Regenerate the lockfile and bump packageManager to match what CI resolves. * feat(modal): introduce AWS Blocks in the announcement modal Repurpose the site announcement modal from 'Introducing Amplify Gen 2' to 'Introducing AWS Blocks', since Gen 2 is now established and AWS Blocks is the new capability. Add two feature highlights, an internal link to the Blocks docs section, and an external link to AWS Blocks on AWS. Use a new dismissal key so the announcement re-shows. Remove the now-unused Gen 1 back-link, isGen1 prop, and orphaned useGen1Path helper. * docs(aws-blocks): correct verified API usage in Agent and AuthBasic guides Verified all code examples against the aws-blocks source repo: - add-an-agent: expose getChannel() on the backend API namespace. The frontend useChat subscribe() calls api.getChannel(), but it is not auto-generated and must be defined explicitly (matches the bb-agent README end-to-end example and test-apps/comprehensive). - use-basic-auth: setAuthState() does not throw; it returns an AuthState with errorName. Replace the try/catch + isBlocksError pattern with hasAuthError(next, ...), per the bb-auth-basic README rule of thumb. - get-started: list all four scaffolded npm scripts (sandbox, sandbox:delete, blocks:dev, blocks:generate-client). * fix(modal): add spacing between modal action label and icon The 'AWS Blocks on AWS' button's external-link icon overlapped its label because .modal-action had no inline-flex layout or gap. Add inline-flex + gap (matching .modal-heading) so text and trailing icons are spaced. * feat(modal): differentiate Blocks CTA labels and feature examples - Rename actions so they read distinctly: primary "Explore Blocks with Amplify" (left, into the Amplify docs) and secondary "AWS Blocks documentation" (right, external). Previously both said "AWS Blocks". - Swap feature examples that overlapped Amplify's own categories (AI agents, auth, storage) for differentiated Blocks capabilities: PostgreSQL databases, realtime messaging, metrics, logging. * feat(modal): rename secondary CTA to "Get Started with Blocks" Keeps the external-link icon to signal it opens a new page (the AWS Blocks docs). Pairs with the primary "Explore Blocks with Amplify" action. * docs(build-a-backend): move steering-file recipe to a separate PR The AWS Blocks steering-file section now lives in #8608. Restore steering-files/index.mdx to its main version here so this PR is scoped to the Blocks docs only. * docs(aws-blocks): address PR review feedback on Agent guide Verified against current aws-blocks/main (local clone was 31 commits stale, which is how these were missed): - useChat adapter now compiles: backend returns { conversationId } and { messages } and sendMessage accepts channelId, matching the UseChatOptions interface and the bb-agent README end-to-end example. - Replace deprecated BedrockModels.DEFAULT with BALANCED; note model is optional (defaults to BALANCED). - Move Realtime to a Real-time & async category (matches the Blocks reference), leaving EmailClient under Communication. - Reword the useChat factory callout ("Despite the name..."). * docs(aws-blocks): re-verify examples against latest aws-blocks main Pulled aws-blocks to HEAD e8f3854 and re-verified all examples: - Agent sendMessage now passes userId to agent.stream(); without it the Agent throws PersistenceRequired at runtime (bb-agent agent.ts:407). - Revert Realtime to the Communication category and restore Compute & background (AsyncJob/CronJob) to match the aws-blocks root README grouping (the authoritative in-repo source). - Drop blocks:dev from the scaffolded-scripts list: the CLI points it at aws-blocks/scripts/server.ts, which the amplify template does not ship, so it is non-functional for Amplify projects.
1 parent 6cf6e76 commit e7894f5

16 files changed

Lines changed: 904 additions & 146 deletions

File tree

cspell.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -889,6 +889,7 @@
889889
"multienv",
890890
"Multifactor",
891891
"multipart",
892+
"Multiplatform",
892893
"multiPartConcurrencyLimit",
893894
"multishells",
894895
"Mutation.createTodo",

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -129,5 +129,5 @@
129129
"overrides": {
130130
"tmp": "^0.2.4"
131131
},
132-
"packageManager": "yarn@4.14.1"
132+
"packageManager": "yarn@4.17.0"
133133
}

src/components/Layout/Layout.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -312,7 +312,7 @@ export const Layout = ({
312312
>
313313
<IconsProvider icons={defaultIcons}>
314314
<ApiModalProvider>
315-
<Modal isGen1={isGen1} />
315+
<Modal />
316316
<View
317317
className={classNames(
318318
'layout-wrapper',

src/components/Modal/Modal.tsx

Lines changed: 47 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -6,30 +6,33 @@ import {
66
Text,
77
View
88
} from '@aws-amplify/ui-react';
9-
import { IconChevron, IconStar, IconX, IconTSBoxed } from '@/components/Icons';
9+
import {
10+
IconChevron,
11+
IconStar,
12+
IconX,
13+
IconAWS,
14+
IconExternalLink
15+
} from '@/components/Icons';
1016
import { useEffect, useId, useState } from 'react';
1117
import { InternalLinkButton } from '@/components/InternalLinkButton';
1218
import { useCurrentPlatform } from '@/utils/useCurrentPlatform';
1319
import { DEFAULT_PLATFORM } from '@/data/platforms';
14-
import { useGen1Path } from './useGen1Path';
1520

16-
interface ModalProps extends ViewProps {
17-
isGen1?: boolean;
18-
}
21+
const AWS_BLOCKS_URL =
22+
'https://docs.aws.amazon.com/blocks/latest/devguide/what-is-blocks.html';
1923

20-
export const Modal = ({ isGen1 }: ModalProps) => {
24+
export const Modal = (_props: ViewProps) => {
2125
const headingId = useId();
2226
const [isVisible, setIsVisible] = useState(false);
2327
const platform = useCurrentPlatform() || DEFAULT_PLATFORM;
2428
const handleDialogAction = () => {
25-
localStorage.setItem('gen2ModalDismissed', 'true');
29+
localStorage.setItem('awsBlocksModalDismissed', 'true');
2630
setIsVisible(false);
2731
};
28-
const gen1Path = useGen1Path(platform);
2932

3033
useEffect(() => {
31-
const hasDismissedGen2Modal = localStorage.getItem('gen2ModalDismissed');
32-
if (!hasDismissedGen2Modal) {
34+
const hasDismissedModal = localStorage.getItem('awsBlocksModalDismissed');
35+
if (!hasDismissedModal) {
3336
setIsVisible(true);
3437
}
3538
}, []);
@@ -43,79 +46,82 @@ export const Modal = ({ isGen1 }: ModalProps) => {
4346
>
4447
<Flex className="modal-header">
4548
<Flex as="h2" className="modal-heading" id={headingId}>
46-
<IconStar /> Introducing Amplify Gen 2
49+
<IconStar /> Introducing AWS Blocks
4750
</Flex>
4851
<Button
4952
onClick={() => handleDialogAction()}
5053
variation="link"
5154
className="modal-dismiss"
5255
>
53-
<VisuallyHidden>Dismiss Gen 2 introduction dialog</VisuallyHidden>
56+
<VisuallyHidden>Dismiss AWS Blocks introduction dialog</VisuallyHidden>
5457
<IconX />
5558
</Button>
5659
</Flex>
57-
Amplify has re-imagined the way frontend developers build fullstack
58-
applications. Develop and deploy without the hassle.
60+
Extend your Amplify Gen 2 app with AWS Blocks — self-contained backend
61+
capabilities you compose into your existing backend.
5962
<Flex className="modal-key-points">
6063
<Flex className="modal-key-point">
61-
<View className="modal-key-point-left" aria-hidden="true">
62-
<IconTSBoxed />
64+
<View
65+
aria-hidden="true"
66+
className="modal-key-point-left"
67+
textAlign="center"
68+
fontSize="xxxl"
69+
>
70+
🧩
6371
</View>
6472
<Flex className="modal-key-point-right">
6573
<Text as="h3" className="modal-key-point-heading">
66-
Fullstack TypeScript
74+
Composable backend capabilities
6775
</Text>
6876
<Text className="modal-key-point-text">
69-
Write your app&apos;s data model, auth, storage, and functions in
70-
TypeScript; Amplify will do the rest.
77+
Add the Blocks you need — PostgreSQL databases, realtime
78+
messaging, metrics, logging, and more — alongside your existing
79+
Amplify resources.
7180
</Text>
7281
</Flex>
7382
</Flex>
7483
<Flex className="modal-key-point">
75-
<View
76-
aria-hidden="true"
77-
className="modal-key-point-left"
78-
textAlign="center"
79-
fontSize="xxxl"
80-
>
81-
🚀
84+
<View className="modal-key-point-left" aria-hidden="true">
85+
<IconAWS />
8286
</View>
8387
<Flex className="modal-key-point-right">
8488
<Text as="h3" className="modal-key-point-heading">
85-
Built with the AWS CDK
89+
Local-first, built on the AWS CDK
8690
</Text>
8791
<Text className="modal-key-point-text">
88-
Use any cloud resource your app needs. Never worry about scale.
92+
Run your whole app locally with no AWS account, then deploy the
93+
same code to AWS with the AWS CDK.
8994
</Text>
9095
</Flex>
9196
</Flex>
9297
</Flex>
9398
<Flex className="modal-actions">
94-
{isGen1 ? null : (
95-
<InternalLinkButton
96-
as="a"
97-
size="small"
98-
href={gen1Path}
99-
onClick={() => handleDialogAction()}
100-
className="modal-action modal-action--secondary"
101-
>
102-
Back to Gen 1 Docs
103-
</InternalLinkButton>
104-
)}
10599
<InternalLinkButton
106100
as="a"
107101
size="small"
108102
href={{
109-
pathname: '/[platform]/how-amplify-works',
103+
pathname: '/[platform]/build-a-backend/aws-blocks',
110104
query: { platform: platform }
111105
}}
112106
onClick={() => handleDialogAction()}
113107
variation="primary"
114108
className="modal-action modal-action--primary"
115109
>
116-
Learn more about Gen 2
110+
Explore Blocks with Amplify
117111
<IconChevron className="icon-rotate-270" />
118112
</InternalLinkButton>
113+
<Button
114+
as="a"
115+
size="small"
116+
href={AWS_BLOCKS_URL}
117+
target="_blank"
118+
rel="noopener noreferrer"
119+
onClick={() => handleDialogAction()}
120+
className="modal-action modal-action--secondary"
121+
>
122+
Get Started with Blocks
123+
<IconExternalLink />
124+
</Button>
119125
</Flex>
120126
</Flex>
121127
);

src/components/Modal/__tests__/Modal.test.tsx

Lines changed: 18 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -45,16 +45,16 @@ describe('Modal', () => {
4545
render(<Modal />);
4646

4747
const modal = screen.getByRole('dialog', {
48-
name: 'Introducing Amplify Gen 2'
48+
name: 'Introducing AWS Blocks'
4949
});
5050

5151
expect(modal).toBeInTheDocument();
5252
expect(modal).toHaveAttribute('open');
5353
});
5454

55-
it('should render Modal with no open attribute when gen2ModalDismissed exists in localStorage', async () => {
55+
it('should render Modal with no open attribute when awsBlocksModalDismissed exists in localStorage', async () => {
5656
window.localStorage.setItem(
57-
'gen2ModalDismissed',
57+
'awsBlocksModalDismissed',
5858
JSON.stringify({ data: 'true' })
5959
);
6060

@@ -67,34 +67,37 @@ describe('Modal', () => {
6767
expect(modal).not.toHaveAttribute('open');
6868
});
6969

70-
it('should set gen2ModalDismissed in localStorage when close button clicked', async () => {
70+
it('should set awsBlocksModalDismissed in localStorage when close button clicked', async () => {
7171
render(<Modal />);
7272

7373
const closeButton = await screen.findByRole('button', {
74-
name: 'Dismiss Gen 2 introduction dialog'
74+
name: 'Dismiss AWS Blocks introduction dialog'
7575
});
7676

7777
userEvent.click(closeButton);
78-
expect(localStorage.getItem('gen2ModalDismissed')).toEqual('true');
78+
expect(localStorage.getItem('awsBlocksModalDismissed')).toEqual('true');
7979
});
8080

81-
it('should render Gen 1 link if isGen1 is false (default)', async () => {
81+
it('should render an internal link to the AWS Blocks docs section', async () => {
8282
render(<Modal />);
8383

84-
const gen1Link = screen.getByRole('link', {
85-
name: 'Back to Gen 1 Docs'
84+
const blocksLink = screen.getByRole('link', {
85+
name: /Explore Blocks with Amplify/
8686
});
8787

88-
expect(gen1Link).toBeInTheDocument();
88+
expect(blocksLink).toBeInTheDocument();
8989
});
9090

91-
it('should not render Gen 1 link if isGen1 is true', async () => {
92-
render(<Modal isGen1={true} />);
91+
it('should render an external link to get started with Blocks', async () => {
92+
render(<Modal />);
9393

94-
const gen1Link = screen.queryByRole('link', {
95-
name: 'Back to Gen 1 Docs'
94+
const awsLink = screen.getByRole('link', {
95+
name: /Get Started with Blocks/
9696
});
9797

98-
expect(gen1Link).toBeNull();
98+
expect(awsLink).toHaveAttribute(
99+
'href',
100+
'https://docs.aws.amazon.com/blocks/latest/devguide/what-is-blocks.html'
101+
);
99102
});
100103
});

src/components/Modal/__tests__/useGen1Path.test.ts

Lines changed: 0 additions & 63 deletions
This file was deleted.

src/components/Modal/useGen1Path.ts

Lines changed: 0 additions & 24 deletions
This file was deleted.

src/directory/directory.mjs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,33 @@ export const directory = {
6666
path: 'src/pages/[platform]/build-a-backend/index.mdx',
6767
section: 'backend',
6868
children: [
69+
{
70+
path: 'src/pages/[platform]/build-a-backend/aws-blocks/index.mdx',
71+
section: 'backend',
72+
isNew: true,
73+
children: [
74+
{
75+
path: 'src/pages/[platform]/build-a-backend/aws-blocks/get-started/index.mdx',
76+
section: 'backend'
77+
},
78+
{
79+
path: 'src/pages/[platform]/build-a-backend/aws-blocks/how-it-works/index.mdx',
80+
section: 'backend'
81+
},
82+
{
83+
path: 'src/pages/[platform]/build-a-backend/aws-blocks/connect-your-frontend/index.mdx',
84+
section: 'backend'
85+
},
86+
{
87+
path: 'src/pages/[platform]/build-a-backend/aws-blocks/add-an-agent/index.mdx',
88+
section: 'backend'
89+
},
90+
{
91+
path: 'src/pages/[platform]/build-a-backend/aws-blocks/use-basic-auth/index.mdx',
92+
section: 'backend'
93+
}
94+
]
95+
},
6996
{
7097
path: 'src/pages/[platform]/build-a-backend/auth/index.mdx',
7198
section: 'backend',

0 commit comments

Comments
 (0)