Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
192 changes: 153 additions & 39 deletions docs/capabilities/server/media-uploads.mdx
Original file line number Diff line number Diff line change
@@ -1,15 +1,12 @@
import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';

# Media Uploads

:::warning
Apps can only display images hosted on Reddit
Apps can only display media hosted on Reddit
:::

You can upload images to Reddit at runtime using the `media` capability. This is different than static images, which are part of your [assets](../blocks/app_image_assets.md).
You can upload media to Reddit at runtime using the `media` capability. This is different than static images, which are part of your [assets](../blocks/app_image_assets.md).

Runtime images are useful for embedding images in RTJSON (Posts and Comments) as well as displaying them within an interactive post app.
Runtime media is useful for embedding media in RTJSON (Posts and Comments) as well as displaying it within an interactive post app.

## Enabling media uploads
Enable the `media` permission in your `devvit.json` file.
Expand All @@ -21,32 +18,152 @@ Enable the `media` permission in your `devvit.json` file.
}
```

## Using media uploads
On the server, you can pass the URL of any remotely hosted image (even if its not hosted on Reddit) to the `media.upload` function. This function will return a Reddit URL. Both HTTP and data URLs are supported.

<Tabs>
<TabItem value="web" label="Devvit Web">
```ts title="server/index.ts"
import { media } from '@devvit/media';
function submitImage() {
const response = await media.upload({
url: 'https://media2.giphy.com/media/xTiN0CNHgoRf1Ha7CM/giphy.gif',
type: 'gif',
## Media uploads (Devvit Web)
On the server, pass a remote URL or data URL to `media.upload()` to upload an image, GIF, or video and get a Reddit-hosted asset you can safely render in posts, comments, and rich text.

### Response type
`media.upload()` returns:

```ts
type MediaAsset = {
mediaId: string;
mediaUrl: string;
};
```

- `mediaId`: Reddit media asset ID.
- `mediaUrl`: Reddit CDN URL (use this in rich text or UI).

### `media.upload()` input
`media.upload()` expects an object with:

- `url`: The media URL (remote URL or data URL).
- `type`: The media kind (`'image'`, `'gif'`, or `'video'`).

```ts
type UploadMediaOptions = {
url: string; // remote URL or data URL
type: 'image' | 'gif' | 'video';
};
```

Use `type: 'image'` for PNG, JPEG, and WEBP uploads.

### Basic server usage
```ts title="server/index.ts"
import { media } from '@devvit/web/server';

const uploaded = await media.upload({
url: 'https://example.com/my-image.png',
type: 'image',
});

// uploaded.mediaId
// uploaded.mediaUrl
```

### Example: API endpoint returning upload response
```ts title="server/index.ts"
import { media } from '@devvit/web/server';

app.post('/api/upload', async (c) => {
const { url, type } = await c.req.json<{
url: string;
type: 'image' | 'gif' | 'video';
}>();

const uploaded = await media.upload({ url, type });

return c.json({
mediaId: uploaded.mediaId,
mediaUrl: uploaded.mediaUrl,
});
});
```

### Example: submit a post with uploaded media using RichTextBuilder
```ts title="server/index.ts"
import { media } from '@devvit/web/server';
import { reddit, RichTextBuilder } from '@devvit/reddit';

const uploaded = await media.upload({
url: 'https://example.com/cover.png',
type: 'image',
});

const richtext = new RichTextBuilder()
.paragraph((p) => {
p.text({ text: 'Uploaded image:' });
})
.paragraph((p) => {
p.image({
mediaUrl: uploaded.mediaUrl,
caption: 'Rendered from media.upload()',
});
}
```
</TabItem>
<TabItem value="blocks" label="Devvit Blocks / Mod Tools">
```ts
import { Devvit } from '@devvit/public-api';
});

const response = await media.upload({
url: 'https://media2.giphy.com/media/xTiN0CNHgoRf1Ha7CM/giphy.gif',
type: 'gif',
await reddit.submitPost({
subredditName: 'my_subreddit',
title: 'Post with uploaded media',
richtext,
});
```

### Example: submit a comment with uploaded media using RichTextBuilder
```ts title="server/index.ts"
import { media } from '@devvit/web/server';
import { reddit, RichTextBuilder } from '@devvit/reddit';

// Parent can be a post id (t3_...) or comment id (t1_...)
const parentId = 't3_abc123';

const uploaded = await media.upload({
url: 'https://example.com/reply-image.png',
type: 'image',
});

const commentRichtext = new RichTextBuilder()
.paragraph((p) => {
p.text({ text: 'Here is the image:' });
})
.paragraph((p) => {
p.image({ mediaUrl: uploaded.mediaUrl });
});
```
</TabItem>
</Tabs>

await reddit.submitComment({
id: parentId,
richtext: commentRichtext,
});
```

### Example: raw RTJSON (without RichTextBuilder)
If you prefer raw RTJSON, pass an object directly to `richtext`:

```ts title="server/index.ts"
import { media } from '@devvit/web/server';
import { reddit } from '@devvit/reddit';

const uploaded = await media.upload({
url: 'https://example.com/raw-rtjson.png',
type: 'image',
});

await reddit.submitComment({
id: 't3_abc123',
richtext: {
document: [
{
e: 'par',
c: [{ e: 'text', t: 'Raw RTJSON image:' }],
},
{
e: 'par',
c: [{ e: 'img', mediaUrl: uploaded.mediaUrl, c: 'RTJSON image node' }],
},
],
},
});
```


## Canvas screenshots
Expand All @@ -68,25 +185,22 @@ const response = await fetch('/api/upload-screenshot', {
```

```ts title="server/index.ts"
import { media } from '@devvit/media';
import { media } from '@devvit/web/server';

app.post('/api/upload-screenshot', async (c) => {
const { image } = await c.req.json();

const response = await media.upload({
url: image, // data URL from canvas
type: 'png',
url: image, // data URL from canvas
type: 'image',
});

return c.json({ url: response.mediaUrl });
});
```

## Limitations

- The formats supported are PNG, JPEG, WEBP, and GIF.
- The maximum file size allowed is 20 MB.

### Notes
## Notes and limits

- When uploading a WEBP image, it will be converted to JPEG. As such, the Reddit URL returned points to a JPEG image.
- Supported image upload formats: PNG, JPEG, WEBP, and GIF.
- Maximum upload size: 20 MB.
- WEBP uploads may be converted to JPEG in the returned Reddit URL.
Loading
Loading