Files
langgraphjs/examples/ai-elements
github-actions[bot] 31261c3be5 chore: version packages (#2558)
This PR was opened by the [Changesets
release](https://github.com/changesets/action) GitHub action. When
you're ready to do a release, you can merge this and the packages will
be published to npm automatically. If you're not ready to do a release
yet, that's fine, whenever you add more changesets to main, this PR will
be updated.


# Releases
## @langchain/langgraph-checkpoint-mongodb@1.4.0

### Minor Changes

- [#1928](https://github.com/langchain-ai/langgraphjs/pull/1928)
[`3d7fcea`](https://github.com/langchain-ai/langgraphjs/commit/3d7fcea7d7ea7f1203d24be9df607d5a8e8717bc)
Thanks [@Mihailoff](https://github.com/Mihailoff)! - Add TTL support for
automatic checkpoint expiration

    -   Add optional `ttl` parameter to MongoDBSaver (value in seconds)
    -   Add `setup()` method to create TTL indexes on collections
    -   Add `upserted_at` timestamp to documents when TTL is enabled
- Each write refreshes TTL (expires after inactivity, not creation)

### Patch Changes

- [#2556](https://github.com/langchain-ai/langgraphjs/pull/2556)
[`bee3c91`](https://github.com/langchain-ai/langgraphjs/commit/bee3c91d0adc315ebde0622d8c4b1fff041c1bfd)
Thanks [@mohamedkhaled4053](https://github.com/mohamedkhaled4053)! - Fix
`MongoDBSaver.putWrites` throwing `MongoServerError: Invalid
BulkOperation, Batch cannot be empty` when called with an empty `writes`
array. This is reached by human-in-the-loop / `interrupt()` flows, where
a task can complete producing zero channel writes and LangGraph calls
`putWrites(config, [], taskId)`. `putWrites` now no-ops on empty writes,
matching the behavior of the postgres and sqlite savers (which iterate
and naturally skip empty batches).

- [#2550](https://github.com/langchain-ai/langgraphjs/pull/2550)
[`2b8cc2f`](https://github.com/langchain-ai/langgraphjs/commit/2b8cc2f3fd5c9d3c33b56e013292daf5d936428e)
Thanks [@lazydiv](https://github.com/lazydiv)! -
feat(checkpoint-mongodb): add setup() to create required indexes

## @langchain/langgraph-api@1.4.0

### Minor Changes

- [#2559](https://github.com/langchain-ai/langgraphjs/pull/2559)
[`48cbdd2`](https://github.com/langchain-ai/langgraphjs/commit/48cbdd23fdf29277530f6aa05c397c9902e81206)
Thanks [@christian-bromann](https://github.com/christian-bromann)! -
feat(langgraph-cli): add `deploy` command for LangSmith Deployment

Port the Python CLI's `langgraph deploy` workflow to
`@langchain/langgraph-cli`, including local and remote build paths,
deployment lifecycle subcommands (`list`, `revisions list`, `delete`,
`logs`), and host-backend client utilities with tests.

### Patch Changes

- [#2557](https://github.com/langchain-ai/langgraphjs/pull/2557)
[`b1e856d`](https://github.com/langchain-ai/langgraphjs/commit/b1e856d987ac16148dc0872d1fecf70e659ef28e)
Thanks [@christian-bromann](https://github.com/christian-bromann)! -
fix(langgraph-api): preserve non-empty response_metadata on protocol-v2
state messages

The protocol-v2 state normalizer stripped `response_metadata` from
messages,
dropping data that HITL flows rely on — an interrupt's card is carried
on
    `AIMessage.response_metadata` (e.g. `{ cards: ... }`). Non-empty
    `response_metadata` is now retained so the card reaches the client.

- [#2557](https://github.com/langchain-ai/langgraphjs/pull/2557)
[`b1e856d`](https://github.com/langchain-ai/langgraphjs/commit/b1e856d987ac16148dc0872d1fecf70e659ef28e)
Thanks [@christian-bromann](https://github.com/christian-bromann)! -
fix(sdk): apply state update and goto alongside interrupt resume

    `respond(decision, { update, goto })` now maps to LangGraph's
`Command(resume, update, goto)`, so a human-in-the-loop UI can commit a
state
update (e.g. push the interrupt card into state) in the **same
superstep** as
the resume — one checkpoint, no separate `updateState` write, no
flicker.
`@langchain/langgraph-api` forwards `update`/`goto` through
`input.respond`,
and `@langchain/core` message instances in `update` are serialized to
dicts
before transport, exactly like `submit()`. Bumps `@langchain/protocol`
to
    `^0.0.18` for the `Goto` type.

`respond`/`respondAll` also apply `update` **optimistically** (mirroring
`submit()`): the pushed messages paint immediately, with stable ids
minted so
the resumed run's echo reconciles them in place. Without this the
interrupt is
cleared the instant `respond()` dispatches while the pushed card only
reappears
a server round-trip later — so the card would flicker in that gap. The
optimistic state settles on the resumed run's terminal (pending → sent,
or
    rolled back on a failure before any echo).

User-initiated optimistic writes (`submit()` / `respond()` /
`respondAll()`) now
commit to the store **synchronously**, in the same tick as the
triggering event,
instead of being coalesced onto the next macrotask. This lets a
framework render
the pushed message in the **same commit** as any local UI state the
caller flips
alongside it (e.g. a HITL form swapping its inputs for the resolved
card), so the
card no longer blinks out for the one-macrotask window before the flush
lands.
    High-frequency streaming writes keep their macrotask coalescing.

- Updated dependencies
\[[`48cbdd2`](https://github.com/langchain-ai/langgraphjs/commit/48cbdd23fdf29277530f6aa05c397c9902e81206)]:
    -   @langchain/langgraph-ui@1.4.0

## @langchain/langgraph-cli@1.4.0

### Minor Changes

- [#2559](https://github.com/langchain-ai/langgraphjs/pull/2559)
[`48cbdd2`](https://github.com/langchain-ai/langgraphjs/commit/48cbdd23fdf29277530f6aa05c397c9902e81206)
Thanks [@christian-bromann](https://github.com/christian-bromann)! -
feat(langgraph-cli): add `deploy` command for LangSmith Deployment

Port the Python CLI's `langgraph deploy` workflow to
`@langchain/langgraph-cli`, including local and remote build paths,
deployment lifecycle subcommands (`list`, `revisions list`, `delete`,
`logs`), and host-backend client utilities with tests.

### Patch Changes

- Updated dependencies
\[[`48cbdd2`](https://github.com/langchain-ai/langgraphjs/commit/48cbdd23fdf29277530f6aa05c397c9902e81206),
[`b1e856d`](https://github.com/langchain-ai/langgraphjs/commit/b1e856d987ac16148dc0872d1fecf70e659ef28e),
[`b1e856d`](https://github.com/langchain-ai/langgraphjs/commit/b1e856d987ac16148dc0872d1fecf70e659ef28e)]:
    -   @langchain/langgraph-api@1.4.0

## @langchain/langgraph-ui@1.4.0

### Minor Changes

- [#2559](https://github.com/langchain-ai/langgraphjs/pull/2559)
[`48cbdd2`](https://github.com/langchain-ai/langgraphjs/commit/48cbdd23fdf29277530f6aa05c397c9902e81206)
Thanks [@christian-bromann](https://github.com/christian-bromann)! -
feat(langgraph-cli): add `deploy` command for LangSmith Deployment

Port the Python CLI's `langgraph deploy` workflow to
`@langchain/langgraph-cli`, including local and remote build paths,
deployment lifecycle subcommands (`list`, `revisions list`, `delete`,
`logs`), and host-backend client utilities with tests.

## @langchain/langgraph@1.4.5

### Patch Changes

- [#2557](https://github.com/langchain-ai/langgraphjs/pull/2557)
[`b1e856d`](https://github.com/langchain-ai/langgraphjs/commit/b1e856d987ac16148dc0872d1fecf70e659ef28e)
Thanks [@christian-bromann](https://github.com/christian-bromann)! -
fix(sdk): apply state update and goto alongside interrupt resume

    `respond(decision, { update, goto })` now maps to LangGraph's
`Command(resume, update, goto)`, so a human-in-the-loop UI can commit a
state
update (e.g. push the interrupt card into state) in the **same
superstep** as
the resume — one checkpoint, no separate `updateState` write, no
flicker.
`@langchain/langgraph-api` forwards `update`/`goto` through
`input.respond`,
and `@langchain/core` message instances in `update` are serialized to
dicts
before transport, exactly like `submit()`. Bumps `@langchain/protocol`
to
    `^0.0.18` for the `Goto` type.

`respond`/`respondAll` also apply `update` **optimistically** (mirroring
`submit()`): the pushed messages paint immediately, with stable ids
minted so
the resumed run's echo reconciles them in place. Without this the
interrupt is
cleared the instant `respond()` dispatches while the pushed card only
reappears
a server round-trip later — so the card would flicker in that gap. The
optimistic state settles on the resumed run's terminal (pending → sent,
or
    rolled back on a failure before any echo).

User-initiated optimistic writes (`submit()` / `respond()` /
`respondAll()`) now
commit to the store **synchronously**, in the same tick as the
triggering event,
instead of being coalesced onto the next macrotask. This lets a
framework render
the pushed message in the **same commit** as any local UI state the
caller flips
alongside it (e.g. a HITL form swapping its inputs for the resolved
card), so the
card no longer blinks out for the one-macrotask window before the flush
lands.
    High-frequency streaming writes keep their macrotask coalescing.

- Updated dependencies
\[[`b1e856d`](https://github.com/langchain-ai/langgraphjs/commit/b1e856d987ac16148dc0872d1fecf70e659ef28e)]:
    -   @langchain/langgraph-sdk@1.9.24

## @langchain/langgraph-sdk@1.9.24

### Patch Changes

- [#2557](https://github.com/langchain-ai/langgraphjs/pull/2557)
[`b1e856d`](https://github.com/langchain-ai/langgraphjs/commit/b1e856d987ac16148dc0872d1fecf70e659ef28e)
Thanks [@christian-bromann](https://github.com/christian-bromann)! -
fix(sdk): apply state update and goto alongside interrupt resume

    `respond(decision, { update, goto })` now maps to LangGraph's
`Command(resume, update, goto)`, so a human-in-the-loop UI can commit a
state
update (e.g. push the interrupt card into state) in the **same
superstep** as
the resume — one checkpoint, no separate `updateState` write, no
flicker.
`@langchain/langgraph-api` forwards `update`/`goto` through
`input.respond`,
and `@langchain/core` message instances in `update` are serialized to
dicts
before transport, exactly like `submit()`. Bumps `@langchain/protocol`
to
    `^0.0.18` for the `Goto` type.

`respond`/`respondAll` also apply `update` **optimistically** (mirroring
`submit()`): the pushed messages paint immediately, with stable ids
minted so
the resumed run's echo reconciles them in place. Without this the
interrupt is
cleared the instant `respond()` dispatches while the pushed card only
reappears
a server round-trip later — so the card would flicker in that gap. The
optimistic state settles on the resumed run's terminal (pending → sent,
or
    rolled back on a failure before any echo).

User-initiated optimistic writes (`submit()` / `respond()` /
`respondAll()`) now
commit to the store **synchronously**, in the same tick as the
triggering event,
instead of being coalesced onto the next macrotask. This lets a
framework render
the pushed message in the **same commit** as any local UI state the
caller flips
alongside it (e.g. a HITL form swapping its inputs for the resolved
card), so the
card no longer blinks out for the one-macrotask window before the flush
lands.
    High-frequency streaming writes keep their macrotask coalescing.

## @langchain/angular@1.0.25

### Patch Changes

- [#2557](https://github.com/langchain-ai/langgraphjs/pull/2557)
[`b1e856d`](https://github.com/langchain-ai/langgraphjs/commit/b1e856d987ac16148dc0872d1fecf70e659ef28e)
Thanks [@christian-bromann](https://github.com/christian-bromann)! -
fix(sdk): apply state update and goto alongside interrupt resume

    `respond(decision, { update, goto })` now maps to LangGraph's
`Command(resume, update, goto)`, so a human-in-the-loop UI can commit a
state
update (e.g. push the interrupt card into state) in the **same
superstep** as
the resume — one checkpoint, no separate `updateState` write, no
flicker.
`@langchain/langgraph-api` forwards `update`/`goto` through
`input.respond`,
and `@langchain/core` message instances in `update` are serialized to
dicts
before transport, exactly like `submit()`. Bumps `@langchain/protocol`
to
    `^0.0.18` for the `Goto` type.

`respond`/`respondAll` also apply `update` **optimistically** (mirroring
`submit()`): the pushed messages paint immediately, with stable ids
minted so
the resumed run's echo reconciles them in place. Without this the
interrupt is
cleared the instant `respond()` dispatches while the pushed card only
reappears
a server round-trip later — so the card would flicker in that gap. The
optimistic state settles on the resumed run's terminal (pending → sent,
or
    rolled back on a failure before any echo).

User-initiated optimistic writes (`submit()` / `respond()` /
`respondAll()`) now
commit to the store **synchronously**, in the same tick as the
triggering event,
instead of being coalesced onto the next macrotask. This lets a
framework render
the pushed message in the **same commit** as any local UI state the
caller flips
alongside it (e.g. a HITL form swapping its inputs for the resolved
card), so the
card no longer blinks out for the one-macrotask window before the flush
lands.
    High-frequency streaming writes keep their macrotask coalescing.

- Updated dependencies
\[[`b1e856d`](https://github.com/langchain-ai/langgraphjs/commit/b1e856d987ac16148dc0872d1fecf70e659ef28e)]:
    -   @langchain/langgraph-sdk@1.9.24

## @langchain/react@1.0.25

### Patch Changes

- [#2557](https://github.com/langchain-ai/langgraphjs/pull/2557)
[`b1e856d`](https://github.com/langchain-ai/langgraphjs/commit/b1e856d987ac16148dc0872d1fecf70e659ef28e)
Thanks [@christian-bromann](https://github.com/christian-bromann)! -
fix(sdk): apply state update and goto alongside interrupt resume

    `respond(decision, { update, goto })` now maps to LangGraph's
`Command(resume, update, goto)`, so a human-in-the-loop UI can commit a
state
update (e.g. push the interrupt card into state) in the **same
superstep** as
the resume — one checkpoint, no separate `updateState` write, no
flicker.
`@langchain/langgraph-api` forwards `update`/`goto` through
`input.respond`,
and `@langchain/core` message instances in `update` are serialized to
dicts
before transport, exactly like `submit()`. Bumps `@langchain/protocol`
to
    `^0.0.18` for the `Goto` type.

`respond`/`respondAll` also apply `update` **optimistically** (mirroring
`submit()`): the pushed messages paint immediately, with stable ids
minted so
the resumed run's echo reconciles them in place. Without this the
interrupt is
cleared the instant `respond()` dispatches while the pushed card only
reappears
a server round-trip later — so the card would flicker in that gap. The
optimistic state settles on the resumed run's terminal (pending → sent,
or
    rolled back on a failure before any echo).

User-initiated optimistic writes (`submit()` / `respond()` /
`respondAll()`) now
commit to the store **synchronously**, in the same tick as the
triggering event,
instead of being coalesced onto the next macrotask. This lets a
framework render
the pushed message in the **same commit** as any local UI state the
caller flips
alongside it (e.g. a HITL form swapping its inputs for the resolved
card), so the
card no longer blinks out for the one-macrotask window before the flush
lands.
    High-frequency streaming writes keep their macrotask coalescing.

- Updated dependencies
\[[`b1e856d`](https://github.com/langchain-ai/langgraphjs/commit/b1e856d987ac16148dc0872d1fecf70e659ef28e)]:
    -   @langchain/langgraph-sdk@1.9.24

## @langchain/svelte@1.0.25

### Patch Changes

- [#2557](https://github.com/langchain-ai/langgraphjs/pull/2557)
[`b1e856d`](https://github.com/langchain-ai/langgraphjs/commit/b1e856d987ac16148dc0872d1fecf70e659ef28e)
Thanks [@christian-bromann](https://github.com/christian-bromann)! -
fix(sdk): apply state update and goto alongside interrupt resume

    `respond(decision, { update, goto })` now maps to LangGraph's
`Command(resume, update, goto)`, so a human-in-the-loop UI can commit a
state
update (e.g. push the interrupt card into state) in the **same
superstep** as
the resume — one checkpoint, no separate `updateState` write, no
flicker.
`@langchain/langgraph-api` forwards `update`/`goto` through
`input.respond`,
and `@langchain/core` message instances in `update` are serialized to
dicts
before transport, exactly like `submit()`. Bumps `@langchain/protocol`
to
    `^0.0.18` for the `Goto` type.

`respond`/`respondAll` also apply `update` **optimistically** (mirroring
`submit()`): the pushed messages paint immediately, with stable ids
minted so
the resumed run's echo reconciles them in place. Without this the
interrupt is
cleared the instant `respond()` dispatches while the pushed card only
reappears
a server round-trip later — so the card would flicker in that gap. The
optimistic state settles on the resumed run's terminal (pending → sent,
or
    rolled back on a failure before any echo).

User-initiated optimistic writes (`submit()` / `respond()` /
`respondAll()`) now
commit to the store **synchronously**, in the same tick as the
triggering event,
instead of being coalesced onto the next macrotask. This lets a
framework render
the pushed message in the **same commit** as any local UI state the
caller flips
alongside it (e.g. a HITL form swapping its inputs for the resolved
card), so the
card no longer blinks out for the one-macrotask window before the flush
lands.
    High-frequency streaming writes keep their macrotask coalescing.

- Updated dependencies
\[[`b1e856d`](https://github.com/langchain-ai/langgraphjs/commit/b1e856d987ac16148dc0872d1fecf70e659ef28e)]:
    -   @langchain/langgraph-sdk@1.9.24

## @langchain/vue@1.0.25

### Patch Changes

- [#2557](https://github.com/langchain-ai/langgraphjs/pull/2557)
[`b1e856d`](https://github.com/langchain-ai/langgraphjs/commit/b1e856d987ac16148dc0872d1fecf70e659ef28e)
Thanks [@christian-bromann](https://github.com/christian-bromann)! -
fix(sdk): apply state update and goto alongside interrupt resume

    `respond(decision, { update, goto })` now maps to LangGraph's
`Command(resume, update, goto)`, so a human-in-the-loop UI can commit a
state
update (e.g. push the interrupt card into state) in the **same
superstep** as
the resume — one checkpoint, no separate `updateState` write, no
flicker.
`@langchain/langgraph-api` forwards `update`/`goto` through
`input.respond`,
and `@langchain/core` message instances in `update` are serialized to
dicts
before transport, exactly like `submit()`. Bumps `@langchain/protocol`
to
    `^0.0.18` for the `Goto` type.

`respond`/`respondAll` also apply `update` **optimistically** (mirroring
`submit()`): the pushed messages paint immediately, with stable ids
minted so
the resumed run's echo reconciles them in place. Without this the
interrupt is
cleared the instant `respond()` dispatches while the pushed card only
reappears
a server round-trip later — so the card would flicker in that gap. The
optimistic state settles on the resumed run's terminal (pending → sent,
or
    rolled back on a failure before any echo).

User-initiated optimistic writes (`submit()` / `respond()` /
`respondAll()`) now
commit to the store **synchronously**, in the same tick as the
triggering event,
instead of being coalesced onto the next macrotask. This lets a
framework render
the pushed message in the **same commit** as any local UI state the
caller flips
alongside it (e.g. a HITL form swapping its inputs for the resolved
card), so the
card no longer blinks out for the one-macrotask window before the flush
lands.
    High-frequency streaming writes keep their macrotask coalescing.

- Updated dependencies
\[[`b1e856d`](https://github.com/langchain-ai/langgraphjs/commit/b1e856d987ac16148dc0872d1fecf70e659ef28e)]:
    -   @langchain/langgraph-sdk@1.9.24

## @example/ai-elements@0.1.41

### Patch Changes

- Updated dependencies
\[[`b1e856d`](https://github.com/langchain-ai/langgraphjs/commit/b1e856d987ac16148dc0872d1fecf70e659ef28e)]:
    -   @langchain/react@1.0.25
    -   @langchain/langgraph@1.4.5

## @examples/assistant-ui-claude@0.1.41

### Patch Changes

- Updated dependencies
\[[`b1e856d`](https://github.com/langchain-ai/langgraphjs/commit/b1e856d987ac16148dc0872d1fecf70e659ef28e)]:
    -   @langchain/react@1.0.25
    -   @langchain/langgraph@1.4.5

## @examples/ui-angular@0.0.51

### Patch Changes

- Updated dependencies
\[[`b1e856d`](https://github.com/langchain-ai/langgraphjs/commit/b1e856d987ac16148dc0872d1fecf70e659ef28e)]:
    -   @langchain/langgraph-sdk@1.9.24
    -   @langchain/angular@1.0.25
    -   @langchain/langgraph@1.4.5

## @examples/ui-multimodal@0.0.27

### Patch Changes

- Updated dependencies
\[[`b1e856d`](https://github.com/langchain-ai/langgraphjs/commit/b1e856d987ac16148dc0872d1fecf70e659ef28e)]:
    -   @langchain/react@1.0.25
    -   @langchain/langgraph@1.4.5

## @examples/ui-react@0.0.27

### Patch Changes

- Updated dependencies
\[[`b1e856d`](https://github.com/langchain-ai/langgraphjs/commit/b1e856d987ac16148dc0872d1fecf70e659ef28e)]:
    -   @langchain/langgraph-sdk@1.9.24
    -   @langchain/react@1.0.25
    -   @langchain/langgraph@1.4.5

## langgraph@1.0.45

### Patch Changes

- Updated dependencies
\[[`b1e856d`](https://github.com/langchain-ai/langgraphjs/commit/b1e856d987ac16148dc0872d1fecf70e659ef28e)]:
    -   @langchain/langgraph@1.4.5

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-06-22 11:40:07 -07:00
..
2026-06-22 11:40:07 -07:00
2026-06-22 11:40:07 -07:00

AI Elements — Tool-Calling Agent Example

A self-contained chat interface built with AI Elements components and @langchain/react. It demonstrates how to build a production-quality agentic UI using AI Elements' composable component library.

What it shows

  • Tool call rendering — each tool invocation is displayed with Tool + ToolHeader + ToolContent + ToolInput + ToolOutput, updating live as the agent streams tool input and then the result.
  • Reasoning display — when the model emits reasoning tokens, a collapsible Reasoning block auto-opens during streaming and collapses when done.
  • Streaming messagesMessage + MessageContent + MessageResponse renders streaming markdown via Streamdown with full GFM support.
  • Loading skeleton — a Shimmer placeholder appears between the user's message and the first assistant token.
  • Conversation scrollConversation + ConversationContent + ConversationScrollButton auto-scrolls and shows a jump-to-bottom button when you scroll up.
  • Message actionsMessageActions + MessageAction with a copy button appears below the last assistant message once streaming completes.
  • Prompt inputPromptInput + PromptInputBody + PromptInputTextarea + PromptInputFooter + PromptInputSubmit provides a full-featured input bar.
  • SuggestionsSuggestions + Suggestion shows preset prompts before the first message.

Agent

The backing LangGraph agent (packages/agents/src/agents/ai-elements.ts) is a createReactAgent with two simulated tools:

Tool Description
get_weather Returns deterministic simulated weather data for any city
web_search Returns three simulated search result objects for any query

No external API keys are required for the tools.

Setup

Create a .env file in this folder (optional — defaults are provided):

VITE_LANGGRAPH_API_URL=http://localhost:2024   # default when running locally
VITE_LANGGRAPH_ASSISTANT_ID=ai_elements         # matches langgraph.json

Run

Start the LangGraph agent server first:

bun run dev --filter=@langchain/playground-agents

Then start this preview app:

bun run dev --filter=@langchain/playground-preview-ai-elements

Open http://localhost:4600.

AI Elements components used

Component Source file
Conversation, ConversationContent, ConversationScrollButton src/components/ai-elements/conversation.tsx
Message, MessageContent, MessageResponse, MessageActions, MessageAction src/components/ai-elements/message.tsx
PromptInput, PromptInputBody, PromptInputTextarea, PromptInputFooter, PromptInputSubmit src/components/ai-elements/prompt-input.tsx
Tool, ToolHeader, ToolContent, ToolInput, ToolOutput src/components/ai-elements/tool.tsx
Reasoning, ReasoningTrigger, ReasoningContent src/components/ai-elements/reasoning.tsx
Suggestions, Suggestion src/components/ai-elements/suggestion.tsx
Shimmer src/components/ai-elements/shimmer.tsx

Components live in src/components/ai-elements/ and are owned by this package (shadcn/AI Elements registry style — copy-paste, not a node_modules import).

Vite path alias

AI Elements components use bare src/ imports (e.g. import { cn } from "src/lib/utils"). The vite.config.ts maps src./src to resolve these correctly in both dev and production builds.