> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://uploadcare.com/docs/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://uploadcare.com/docs/_mcp/server.

# File Uploader installation

> Learn how to install and start using the File Uploader in your project in a few minutes.

#### Integrate File Uploader with one prompt

# Integrate Uploadcare File Uploader

You are integrating file uploads into an existing project using **Uploadcare's modern File
Uploader**. This instruction is framework-agnostic. Analyze the project first, then follow the
matching path below.

Your primary objective is to inspect the repository, determine the correct integration strategy,
collect any missing configuration from the user, implement the smallest safe change, and verify that
file uploads work correctly.

**Do not generate implementation code before completing the repository analysis and resolving all
required configuration questions.**

---

## Step 1: Analyze the project

Before writing any code, inspect the repository and determine:

1. **Integration type**: frontend (browser UI), backend (server-side / API), or full-stack?
2. **Framework / stack**: React, Next.js, Vue, Angular, Svelte, vanilla JS, Node.js, Python, Ruby,
   PHP, Go, etc.
3. **Package manager**: npm, yarn, pnpm, pip, gem, composer, etc.
4. **Existing patterns**:
   * where third-party UI components are added
   * where global and component-level CSS is imported
   * how environment variables and configuration values are managed
   * how HTTP/API clients are implemented
   * how upload results and errors are handled
5. **Target location**: the page, route, component, form, API endpoint, or server module where the
   uploader should be integrated.

Do not modify the project yet. First, report the detected stack and the proposed integration
location.

If the integration type or the target location is ambiguous, **ask the user for clarification and
STOP**. Do not generate code until the ambiguity is resolved.

Once the framework is identified, use the corresponding `userAgentIntegration` value in every
uploader configuration you write:

| Detected framework | `userAgentIntegration` value |
| ------------------ | ---------------------------- |
| React              | `llm-react`                  |
| Next.js            | `llm-nextjs`                 |
| Vue                | `llm-Vue`                    |
| Angular            | `llm-angular`                |
| Svelte             | `llm-svelte`                 |
| Vanilla JS / other | `llm-js`                     |

Use the exact value consistently throughout the implementation.

---

## Step 2: Collect required configuration

Before writing implementation code, determine the settings below and use the answers in every code
example you produce.

* If the user has already provided a value, do not ask for it again.
* If one or more required values are missing, **ask all missing questions in a single message and
  STOP**. Do not generate code while waiting for the user's answers.
* Use the documented defaults only when the user explicitly asks to use defaults (or explicitly
  declines to choose).

### Step 2.1: Public key (`pubkey`)

Ask: **"What is your Uploadcare public key?"**

Every uploader and upload request must be configured with your project's public key. The user can
find it in the Uploadcare dashboard under
[API keys](https://app.uploadcare.com/projects/-/api-keys/).

* If the user provides a public key, use that exact value everywhere a key is required: `pubkey`
  (frontend prop/attribute), `publicKey` (SDKs), and `UPLOADCARE_PUB_KEY` (raw HTTP).
* The public key is safe to expose in frontend code. Never request, use, or place the **secret key**
  in frontend code.
* Only if the user explicitly asks to use defaults (or wants to try it without an account), fall
  back to the demo key `demopublickey`. Warn that files uploaded with the demo key are public and
  periodically purged, so it must not be used in production.

| Setting    | Frontend prop / attribute | Backend field                      | Default (demo only) |
| ---------- | ------------------------- | ---------------------------------- | ------------------- |
| Public key | `pubkey`                  | `publicKey` / `UPLOADCARE_PUB_KEY` | `demopublickey`     |

Substitute the chosen public key for `demopublickey` in every code example you generate.

---

### Step 2.2: Uploader mode

Ask: **"How should the uploader appear in your UI?"**

| Mode               | Description                                                                                        | React component                              | Web Component tag                           |
| ------------------ | -------------------------------------------------------------------------------------------------- | -------------------------------------------- | ------------------------------------------- |
| **Regular**        | Button that opens a modal dialog (default)                                                         | `FileUploaderRegular`                        | `<uc-file-uploader-regular>`                |
| **Dynamic Button** | Compact state-aware button: source picker, drag-and-drop, progress, and upload list in one control | `FileUploaderRegular` + `dynamicButton` prop | `<uc-file-uploader-regular dynamic-button>` |
| **Inline**         | Uploader embedded directly on the page, no dialog window                                           | `FileUploaderInline`                         | `<uc-file-uploader-inline>`                 |
| **Minimal**        | Compact drag-and-drop area, minimal UI chrome                                                      | `FileUploaderMinimal`                        | `<uc-file-uploader-minimal>`                |

**Dynamic Button** is a variant of the Regular mode
([docs](https://uploadcare.com/docs/file-uploader/dynamic-button/)): it uses the same component,
tag, and CSS as Regular, plus:

* React: add the `dynamicButton` prop: `<FileUploaderRegular dynamicButton ... />`
* Web Components: add the `dynamic-button` attribute:
  `<uc-file-uploader-regular ctx-name="my-uploader" dynamic-button></uc-file-uploader-regular>`
* Optional tuning attributes on `<uc-config>`: `dynamic-button-view-mode` (`auto` | `menu` |
  `toolbar` | `compact`) and `dynamic-button-show-first-icon` (default `true`). Do not set these
  unless the user explicitly asks for custom Dynamic Button behavior.

It fits toolbars, forms, chat composers, and other space-constrained interfaces.

The CSS import also changes per mode:

| Mode           | React (always)                        | Web Components (npm)                                             | Web Components (CDN)               |
| -------------- | ------------------------------------- | ---------------------------------------------------------------- | ---------------------------------- |
| Regular        | `@uploadcare/react-uploader/core.css` | `@uploadcare/file-uploader/web/uc-file-uploader-regular.min.css` | `uc-file-uploader-regular.min.css` |
| Inline         | `@uploadcare/react-uploader/core.css` | `@uploadcare/file-uploader/web/uc-file-uploader-inline.min.css`  | `uc-file-uploader-inline.min.css`  |
| Minimal        | `@uploadcare/react-uploader/core.css` | `@uploadcare/file-uploader/web/uc-file-uploader-minimal.min.css` | `uc-file-uploader-minimal.min.css` |
| Dynamic Button | `@uploadcare/react-uploader/core.css` | `@uploadcare/file-uploader/web/uc-file-uploader-regular.min.css` | `uc-file-uploader-regular.min.css` |

Default if the user explicitly asks to use defaults: **Regular**.

Use the component name, tag name, CSS path, and (for Dynamic Button) the extra prop/attribute that
match the chosen mode in every code example.

---

### Step 2.3: Upload sources (`sourceList` / `source-list`)

#### Step 2.3.1: Ask: **"Which upload sources should users see?"**

Present the following options and let the user pick one or more:

| Option       | Description                                    |
| ------------ | ---------------------------------------------- |
| **Local**    | Files from the device (`local`)                |
| **URL**      | Upload from a URL (`url`)                      |
| **Camera**   | Device camera (`camera`)                       |
| **External** | Cloud storage services (see sub-options below) |

#### Step 2.3.2: If the user selects **External**, ask them to choose one or more of the following external sources:

| Source        | Value      |
| ------------- | ---------- |
| Dropbox       | `dropbox`  |
| OneDrive      | `onedrive` |
| Google Drive  | `gdrive`   |
| Google Photos | `gphotos`  |
| Box           | `box`      |

Build the final `sourceList` / `source-list` value from **exactly** the sources selected by the
user: the selected top-level sources (`local`, `url`, `camera`) combined with the selected external
source values (e.g. `dropbox`, `onedrive`). Do not add unrequested sources.

Always ask which sources to use, and wait for the user's answer. Only if the user explicitly asks to
use defaults (or declines to choose), fall back to: `local, url, camera, dropbox, gdrive`.

### Step 2.4: Multiple file upload (`multiple` / `multipleMax`)

Ask: **"Should users be able to upload more than one file at a time?"**

* If **yes**, also ask whether there is a maximum number of files (leave `multipleMax` at `0` for
  no limit).
* If **no**, set `multiple="false"` (Web Components attribute) or `multiple={false}` (React prop).

| Option        | Attribute / prop | Default | Notes                      |
| ------------- | ---------------- | ------- | -------------------------- |
| `multiple`    | `multiple`       | `true`  | `false` = single-file mode |
| `multipleMax` | `multiple-max`   | `0`     | `0` = no limit             |

Apply both answers before generating code. If the user explicitly asks to use defaults, use
`multiple = true` and `multipleMax = 0`.

**Important:** in every code example you generate, set `sourceList` / `source-list` to exactly the
comma-separated list of sources the user chose (or the default). Do not hard-code a fixed list in
the template. Always reflect the user's actual selection.

---

## Frontend integration

### Package selection

| Framework                           | Package to install                    | Import path                                        |
| ----------------------------------- | ------------------------------------- | -------------------------------------------------- |
| React                               | `@uploadcare/react-uploader ≥ 1.16.0` | `@uploadcare/react-uploader`                       |
| Next.js                             | `@uploadcare/react-uploader ≥ 1.16.0` | `@uploadcare/react-uploader/next` + `"use client"` |
| Vue / Angular / Svelte / Vanilla JS | `@uploadcare/file-uploader@1`         | npm or CDN                                         |

**Never use legacy packages:** `uploadcare-widget`, `@uploadcare/react-widget`,
`uploadcare.full.min.js`, or any jQuery-based Uploadcare package.

### Respect the existing package manager

Install packages with the package manager detected in the repository (`npm install <package>`,
`pnpm add <package>`, `yarn add <package>`, etc.). Do not default to npm when the repository clearly
uses another package manager, and do not introduce a second package manager or generate an
unnecessary lockfile.

---

### React

```bash
npm install @uploadcare/react-uploader
```

```tsx
// Use the component name from the mode table in Step 2 (e.g. FileUploaderRegular)
import { FileUploaderRegular } from '@uploadcare/react-uploader';
import '@uploadcare/react-uploader/core.css';

export default function Uploader() {
  return (
    // Replace FileUploaderRegular with the component that matches the chosen mode
    <FileUploaderRegular
      pubkey='demopublickey' // replace with the public key from Step 2.1
      sourceList='<comma-separated sources from Step 2>'
      multiple={true} // set to false for single-file mode
      multipleMax={0} // set to user's limit; 0 = no limit
      userAgentIntegration='llm-react'
    />
  );
}
```

Add this component to the target page (ask the user which page if unclear).

---

### Next.js (App Router)

```bash
npm install @uploadcare/react-uploader
```

```tsx
'use client';
// Use the component name from the mode table in Step 2 (e.g. FileUploaderRegular)
import { FileUploaderRegular } from '@uploadcare/react-uploader/next';
import '@uploadcare/react-uploader/core.css';

export default function Uploader() {
  return (
    // Replace FileUploaderRegular with the component that matches the chosen mode
    <FileUploaderRegular
      pubkey='demopublickey' // replace with the public key from Step 2.1
      sourceList='<comma-separated sources from Step 2>'
      multiple={true} // set to false for single-file mode
      multipleMax={0} // set to user's limit; 0 = no limit
      userAgentIntegration='llm-nextjs'
    />
  );
}
```

The uploader component must be a Client Component (`'use client'`). Do not import browser-only
uploader code directly into a Next.js Server Component.

---

### Vue / Angular / Svelte — Web Components via npm

```bash
npm install @uploadcare/file-uploader
```

Register components once (e.g. in your app entry point or the component file):

```js
import * as UC from '@uploadcare/file-uploader';
// Use the CSS filename that matches the chosen mode from Step 2
// e.g. uc-file-uploader-regular.min.css / uc-file-uploader-inline.min.css / uc-file-uploader-minimal.min.css
import '@uploadcare/file-uploader/web/uc-file-uploader-regular.min.css';
UC.defineComponents(UC);
```

Add to your template:

```html
<uc-config
  ctx-name="my-uploader"
  pubkey="demopublickey"
  source-list="<comma-separated sources from Step 2>"
  multiple="true"
  multiple-max="0"
  userAgentIntegration="llm-Vue"
></uc-config>

<!-- Use the tag that matches the chosen mode from Step 2 -->
<!-- e.g. uc-file-uploader-regular / uc-file-uploader-inline / uc-file-uploader-minimal -->
<uc-file-uploader-regular ctx-name="my-uploader"></uc-file-uploader-regular>
```

Use `llm-angular` or `llm-svelte` instead when the detected framework is Angular or Svelte.

**Angular**: add `CUSTOM_ELEMENTS_SCHEMA` to the component's `schemas` array:

```ts
import { Component, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';

@Component({
  selector: 'file-uploader',
  standalone: true,
  templateUrl: './file-uploader.component.html',
  schemas: [CUSTOM_ELEMENTS_SCHEMA],
})
export class FileUploaderComponent {}
```

---

### Vanilla JS (no bundler — CDN)

```html
<!-- Use the CSS filename that matches the chosen mode from Step 2 -->
<!-- e.g. uc-file-uploader-regular.min.css / uc-file-uploader-inline.min.css / uc-file-uploader-minimal.min.css -->
<link
  rel="stylesheet"
  href="https://cdn.jsdelivr.net/npm/@uploadcare/file-uploader@1/web/uc-file-uploader-regular.min.css"
/>
<script type="module">
  import * as UC from 'https://cdn.jsdelivr.net/npm/@uploadcare/file-uploader@1/web/file-uploader.min.js';
  UC.defineComponents(UC);
</script>

<uc-config
  ctx-name="my-uploader"
  pubkey="demopublickey"
  source-list="<comma-separated sources from Step 2>"
  multiple="true"
  multiple-max="0"
  userAgentIntegration="llm-js"
></uc-config>

<!-- Use the tag that matches the chosen mode from Step 2 -->
<!-- e.g. uc-file-uploader-regular / uc-file-uploader-inline / uc-file-uploader-minimal -->
<uc-file-uploader-regular ctx-name="my-uploader"></uc-file-uploader-regular>
```

---

## Implement the integration

After analyzing the repository, identifying the target integration location, collecting the required
configuration, and resolving all ambiguity, implement the **smallest safe change**:

* Follow the existing project architecture and coding conventions.
* Do not perform unrelated refactoring, modify unrelated files, or replace existing components or
  infrastructure unless necessary.
* Use the user's exact uploader configuration: selected mode, selected upload sources, multiple-file
  setting, maximum file count.

---

## Handle upload results

The integration must provide a way to confirm successful uploads. Use the appropriate Uploadcare
uploader event or callback mechanism for the detected framework and package, and on successful
upload make the resulting file information available to the application.

At minimum, capture:

* the file **UUID**
* the **CDN URL**

### Canonical pattern

All uploader events are dispatched on the `<uc-upload-ctx-provider>` tag (not on the uploader
element), so add that tag alongside `<uc-config>` and subscribe to the `change` event. Its payload is
an `OutputCollectionState`; read its `successEntries` field, which is already filtered to
successfully uploaded files and typed as `OutputFileEntry<'success'>[]` (no manual `allEntries`
filtering or type narrowing needed). Adapt this single pattern to the detected framework.

**Web Components (Vue / Angular / Svelte / vanilla JS)**: add the provider tag next to `<uc-config>`
and listen for `change`:

```html
<uc-upload-ctx-provider ctx-name="my-uploader"></uc-upload-ctx-provider>

<script type="module">
  const ctx = document.querySelector('uc-upload-ctx-provider[ctx-name="my-uploader"]');
  ctx.addEventListener('change', (e) => {
    // e.detail is an OutputCollectionState
    e.detail.successEntries.forEach((f) => {
      // expose f.uuid and f.cdnUrl to your app (state, form field, API call)
      console.log('UUID:', f.uuid, 'CDN URL:', f.cdnUrl);
    });
  });
</script>
```

**React / Next.js**: the same event is exposed as the `onChange` prop, but the callback receives the
`OutputCollectionState` payload **directly** (there is no `e.detail`):

```tsx
<FileUploaderRegular
  // ...config from Step 2...
  onChange={(state) => {
    state.successEntries.forEach((f) => {
      // f.uuid, f.cdnUrl
    });
  }}
/>
```

Follow the existing application pattern when deciding whether to update component state, update a
form field, call an application callback, send the file information to an API, or store the result
elsewhere. If the expected application behavior is ambiguous, implement the smallest non-destructive
behavior that exposes the successful upload result and clearly document the assumption.

---

## Backend integration

For server-side or API-only projects, do not immediately generate upload code. **Confirm the
intended upload architecture with the user before writing code.** Determine:

* where the uploaded file originates
* whether uploads should go directly from the browser to Uploadcare, or pass through the application
  backend
* whether signed uploads are required
* whether the resulting UUID or CDN URL must be persisted
* whether the application already has a storage or database abstraction

Never expose private credentials or secret keys to frontend code. Prefer direct
browser-to-Uploadcare uploads when appropriate rather than unnecessarily proxying large files
through the application server.

After confirming the architecture, upload files via an official SDK when one is available for the
detected language; otherwise use the Uploadcare Upload API via HTTP.

### Official SDKs (use if available for the detected language)

| Language | Package                     |
| -------- | --------------------------- |
| Node.js  | `@uploadcare/upload-client` |
| Python   | `pyuploadcare`              |
| Ruby     | `uploadcare-ruby`           |
| PHP      | `uploadcare/uploadcare-php` |

If no official SDK exists, fall back to raw HTTP (see below).

### Node.js example

```bash
npm install @uploadcare/upload-client
```

```js
import { UploadClient } from '@uploadcare/upload-client';
import { readFileSync } from 'fs';

const client = new UploadClient({ publicKey: 'demopublickey' });
const buffer = readFileSync('test-file.jpg');
const result = await client.uploadFile(new Blob([buffer]), { fileName: 'test-file.jpg' });
console.log('Uploaded:', result.cdnUrl);
```

### Raw HTTP fallback (any language / curl)

```bash
curl -X POST https://upload.uploadcare.com/base/ \
  -F "UPLOADCARE_PUB_KEY=demopublickey" \
  -F "UPLOADCARE_STORE=1" \
  -F "file=@test-file.jpg"
```

A successful response returns JSON with a `file` UUID. Build the CDN URL as
`https://<your-subdomain>.ucarecd.net/<uuid>/`, where `<your-subdomain>` is your project's delivery
subdomain. Do not use the legacy `ucarecdn.com` domain.

The subdomain is derived deterministically from the public key, so compute it instead of asking the
user. In any JavaScript / TypeScript / Node context, use the official
[`@uploadcare/cname-prefix`](https://github.com/uploadcare/uploadcare-js-api-clients/tree/master/packages/cname-prefix)
package:

```js
import { getPrefixedCdnBaseSync } from '@uploadcare/cname-prefix';

const cdnBase = getPrefixedCdnBaseSync('demopublickey', 'https://ucarecd.net'); // use the key from Step 2.1
// => 'https://1s4oyld5dc.ucarecd.net'
const cdnUrl = `${cdnBase}/${uuid}/`;
```

Outside a JavaScript environment, look up the delivery subdomain in the Uploadcare dashboard under
**Settings → Delivery**. Either way, never fall back to `ucarecdn.com`.

---

## Verification

After placing the code, verify the integration.

* **If the agent can run the project**:
  1. Install dependencies using the existing package manager.
  2. Run relevant static checks: type checking, linting, and tests when applicable.
  3. Start the dev server, open the target page, and trigger the uploader.
  4. Upload a test file and confirm there are no relevant browser or server errors.
  5. Confirm the upload returns a file UUID and a CDN URL, and that the file is accessible through
     the resulting CDN URL.
  If verification fails: inspect the actual error, diagnose the root cause, apply the smallest
  appropriate fix, and repeat verification. Do not mark the task complete while known integration
  errors remain.

* **If the agent cannot run the project** (sandboxed or browser-based agent): place the code,
  perform all available static verification, then give the user this checklist and wait for their
  confirmation before diagnosing further:
  * [ ] Install dependencies if not already installed
  * [ ] Start the dev server (`npm run dev` or equivalent)
  * [ ] Open the page that contains the uploader
  * [ ] Upload any file using the uploader UI
  * [ ] Confirm the browser console shows no errors and a success response containing a file UUID
  * [ ] Open the CDN URL and confirm the uploaded file is accessible
  * [ ] Open `https://app.uploadcare.com/projects/<public-key>/files/` (substitute the public key from
    Step 2.1): the uploaded file should appear there

Surface the file URL from the Uploadcare dashboard as proof of success. **Never claim that runtime
verification succeeded unless an actual upload was performed successfully.**

---

## Final response format

After completing the implementation, provide a concise report with the following sections:

1. **Detected Project**: integration type, framework/stack, package manager, target integration
   location.
2. **Configuration Used**: uploader mode, upload sources, multiple upload setting, maximum file
   count;
3. **Files Changed**: every modified or created file and briefly why.
4. **Implementation Summary**: which Uploadcare package was used, how the uploader was integrated,
   how successful upload results are handled, and how the UUID and CDN URL are exposed to the
   application.
5. **Verification**: exactly what was verified, clearly distinguishing checks actually performed by
   the agent from checks that still require manual user verification.
6. **Remaining Assumptions**: any assumptions or unresolved issues; if there are none, explicitly
   state: "No remaining assumptions."

---

## Guardrails

* Analyze before coding. Ask only for information that cannot be reliably determined from the
  repository, ask all missing configuration questions in one message, and stop and wait after
  asking. Do not generate implementation code before the required answers are available.
* Use defaults only when the user explicitly requests defaults.
* Do not rely on memorized package names, component names, attributes, or legacy Uploadcare examples
  when the project context is incomplete. Local or smaller models may have outdated or insufficient
  Uploadcare knowledge.
* Prefer the tables and rules in this prompt over model memory. If a required value is not defined
  in this prompt or cannot be confirmed from the repository, ask the user instead of guessing.
* When uncertain, generate the smallest safe change first and clearly list any assumptions that
  still need user confirmation.
* Follow the repository's existing architecture and package manager. Do not perform unrelated
  refactoring.
* Use only `@uploadcare/file-uploader@1` (Web Components) or `@uploadcare/react-uploader ≥ 1.16.0`
  (React wrapper).
* Pin CDN URLs to major `@1` (e.g. `@uploadcare/file-uploader@1`).
* Never install or reference: `uploadcare-widget`, `@uploadcare/react-widget`, or any jQuery-based
  Uploadcare package.
* Never expose secret credentials in frontend code.
* Capture successful upload results, including UUID and CDN URL, and verify the implementation when
  the environment allows it. Clearly distinguish completed verification from manual verification
  steps.

## From CDN

We recommend using one of the modern code distribution services, such as:

* [https://jsdelivr.com/](https://jsdelivr.com/)
* [https://esm.sh/](https://esm.sh/)
* [https://skypack.dev/](https://skypack.dev/)
* etc

Import the File Uploader library into your JavaScript code:

```html
<script type="module">
  import * as UC from 'https://cdn.jsdelivr.net/npm/@uploadcare/file-uploader@v1/web/file-uploader.min.js';
  UC.defineComponents(UC);
</script>
```

Note that we distribute the library as ES modules, so you need to use the `type="module"` attribute on the `<script>` tag.

We're also providing IIFE bundle, but it's not recommended to use it directly.

```html
<script src="https://cdn.jsdelivr.net/npm/@uploadcare/file-uploader@v1/web/file-uploader.iife.min.js" async></script>
<script>
  UC.defineComponents(UC);
</script>
```

## From NPM

Install the npm package:

```sh
npm i @uploadcare/file-uploader
```

Then register the File Uploader components for usage:

```js
import * as UC from '@uploadcare/file-uploader';

UC.defineComponents(UC);
```

## React Uploader

This [library](https://www.npmjs.com/package/@uploadcare/react-uploader) allows
you to easily integrate the File Uploader into your React applications:

```sh
npm i @uploadcare/react-uploader
```

## Framework examples

Ready-to-run examples are available in our examples repository:

* [All examples (GitHub)](https://github.com/uploadcare/file-uploader-examples)
* [JavaScript](https://github.com/uploadcare/file-uploader-examples/tree/main/examples/js-uploader)
* [React (Web Components)](https://github.com/uploadcare/file-uploader-examples/tree/main/examples/react-uploader)
* [React (adapter)](https://github.com/uploadcare/file-uploader-examples/tree/main/examples/react-uploader-adapter)
* [Vue](https://github.com/uploadcare/file-uploader-examples/tree/main/examples/vue-uploader)
* [Angular](https://github.com/uploadcare/file-uploader-examples/tree/main/examples/angular-uploader)
* [Svelte](https://github.com/uploadcare/file-uploader-examples/tree/main/examples/svelte-uploader)
* [Next.js (Web Components)](https://github.com/uploadcare/file-uploader-examples/tree/main/examples/next-uploader)
* [Next.js (adapter)](https://github.com/uploadcare/file-uploader-examples/tree/main/examples/next-uploader-adapter)

For setup paths by framework, see [framework integrations](/docs/integrations/frameworks-file-uploader/).

## Dynamic script connection

There is an alternative way if your project meets the following criteria:

* Does not support new language features (such as nullish coalescing operator,
  static class properties) — for instance, this might apply to projects built
  with frameworks such as Nuxt 2. (Note that Nuxt 3 supports modern JavaScript
  features and works as needed).
* Has SSR and does not support node conditional exports.

Then you can use this workaround to import the uploader only at the browser
runtime, bypassing your project's build system and obtaining a working type
system. This can be achieved without the need to manually configure the build
process (using tools such as Babel) or disabling SSR for a specific package.

First, install the npm package:

```sh
npm i @uploadcare/file-uploader
```

Then import `loadFileUploaderFrom` function to connect the library dynamically and
avoid errors:

```js
import { loadFileUploaderFrom } from '@uploadcare/file-uploader/abstract/loadFileUploaderFrom.js';

loadFileUploaderFrom('https://cdn.jsdelivr.net/npm/@uploadcare/file-uploader@v1/web/file-uploader.iife.min.js');
```

You may need to implement some logic that depends on connected uploader or get
access directly to the imported components. Since `loadFileUploaderFrom` returns
`Promise`, use `.then()`

```js
import { loadFileUploaderFrom } from '@uploadcare/file-uploader/abstract/loadFileUploaderFrom.js';

loadFileUploaderFrom('https://cdn.jsdelivr.net/npm/@uploadcare/file-uploader@v1/web/file-uploader.iife.min.js').then(
  (UC) => {
    if (!UC) {
      return; // To avoid errors in SSR case
    }

    // Now you can realize your logic, e.g.:
    const uploader = new UC.FileUploaderRegular();
    document.body.appendChild(uploader);
  },
);
```

## Choose a solution

To use the File Uploader in your application markup, select the tag that best
fits your needs from the table below and place it in your HTML document:

| Mode         | Syntax                                                   |
| ------------ | -------------------------------------------------------- |
| Regular mode | `<uc-file-uploader-regular> </uc-file-uploader-regular>` |
| Minimal mode | `<uc-file-uploader-minimal> </uc-file-uploader-minimal>` |
| Inline mode  | `<uc-file-uploader-inline> </uc-file-uploader-inline>`   |

Look at the [File Uploader solutions](/docs/file-uploader/#solutions) for more.

Example:

```html
<link
  rel="stylesheet"
  href="https://cdn.jsdelivr.net/npm/@uploadcare/file-uploader@v1/web/uc-file-uploader-regular.min.css"
/>

<uc-config ctx-name="my-uploader" pubkey="YOUR_PUBLIC_KEY"></uc-config>

<uc-file-uploader-regular ctx-name="my-uploader"></uc-file-uploader-regular>
```

The `<uc-config>` block is used to configure the uploader. Take a look at
uploader [configuration](/docs/file-uploader/configuration/).

The `ctx-name` attribute is used to specify the name of the uploader context,
which allows blocks to be wired together. Required.

### Dynamic mode

The `dynamic-button` attribute can be used with the Regular File Uploader to
replace the default static upload button with a compact, state-aware control. It
shows configured upload sources, accepts drag and drop, and changes after files
are selected, uploaded, or failed.

```html
<uc-config
  ctx-name="my-uploader"
  pubkey="YOUR_PUBLIC_KEY"
  source-list="local, camera, url"
  dynamic-button-view-mode="auto"
></uc-config>

<uc-file-uploader-regular ctx-name="my-uploader" dynamic-button></uc-file-uploader-regular>
```

See [Dynamic button](/docs/file-uploader/dynamic-button/) for view modes, behavior,
and use cases.

### Headless mode

The `headless` attribute can be used with the Regular File Uploader to hide the default upload button. This is useful when you want to replace the default button with your own custom UI element and trigger the upload flow programmatically.

When headless mode is enabled, use the `initFlow()` method to start the upload process:

```html
<link
  rel="stylesheet"
  href="https://cdn.jsdelivr.net/npm/@uploadcare/file-uploader@v1/web/uc-file-uploader-regular.min.css"
/>

<uc-config ctx-name="my-uploader" pubkey="YOUR_PUBLIC_KEY"></uc-config>

<uc-upload-ctx-provider id="uploaderctx" ctx-name="my-uploader"></uc-upload-ctx-provider>

<uc-file-uploader-regular ctx-name="my-uploader" headless></uc-file-uploader-regular>

<button id="custom-upload-btn">Upload Files</button>

<script type="module">
  import * as UC from 'https://cdn.jsdelivr.net/npm/@uploadcare/file-uploader@v1/web/file-uploader.min.js';
  UC.defineComponents(UC);

  // Optional but safe: wait until the provider element is defined
  await customElements.whenDefined('uc-upload-ctx-provider');

  const ctx = document.querySelector('#uploaderctx');
  const button = document.getElementById('custom-upload-btn');

  const api = ctx.getAPI();
  button.addEventListener('click', () => api.initFlow()); // initFlow(): void
</script>
```

> **Note**
>
> **Note:** All examples assume you have configured your API keys. Replace `YOUR_PUBLIC_KEY` with your actual public key, or set it via environment variables. The component must be defined before calling `initFlow()`.