Skip to content

Commit 3468b2e

Browse files
authored
Synchronize Devvit documentation with current behavior (#160)
<!-- If this pull request closes an issue, please mention the issue number below --> Closes #159 ## 💸 TL;DR This PR synchronizes Devvit’s configuration, CLI, launch-screen, and Redis documentation with the current implementation. It corrects invalid or outdated examples, documents additional supported configuration fields, and applies equivalent updates to both the current and versioned `0.13` documentation. It also centralizes the latest published documentation version through `versions.json`. ## 📜 Details Design Doc: Not applicable Jira: Not applicable This documentation-only PR: * Corrects the documented server build path, app-name limit, and default custom-post height. * Expands the `devvit.json` reference to cover additional schema-supported settings, permissions, triggers, assets, payments, and server options. * Updates CLI documentation for `init`, `publish`, `logs`, `playtest`, `upload`, and `view`. * Removes references to the nonexistent `devvit build` command and `--here` option. * Replaces deprecated launch-screen mode-listener examples with the current focus-based approach. * Corrects stale Redis links and repairs a malformed transaction example. * Removes a duplicated sidebar entry and fixes minor changelog errors. * Derives `LATEST_DEVVIT_VERSION` from the first entry in `versions.json` rather than duplicating the version in `docusaurus.config.ts`. * Mirrors applicable changes in both `docs/` and `versioned_docs/version-0.13/`. This PR does not change Devvit runtime behavior, generated API references, Blob Storage permission behavior, or Reddit subscription identity APIs. ## 🧪 Testing Steps / Validation The following checks were completed against the current repository snapshot: 1. Applied the patch successfully with: ```bash git apply --check devvit-docs-patch-1-docs-sync.patch ``` 2. Checked the resulting diff for whitespace errors: ```bash git diff --check ``` 3. Parsed all JSON code blocks changed in the configuration guides. 4. Verified that relative documentation links in the changed files resolve. 5. Checked that Markdown code fences remain balanced. 6. Checked the changed documentation for unexpected control characters. 7. Confirmed that equivalent updates were made to the current and versioned `0.13` documentation where applicable. A complete local Docusaurus build was not run because installed dependencies were not included in the supplied repository snapshot. Repository CI should run the full documentation build. > **CI note:** The `Build Documentation` workflow is currently marked `action_required` because this pull request originates from a fork. A repository maintainer must approve the workflow before the CI jobs can run. No CI failures have been reported at this stage. ## ✅ Checks * [ ] CI tests (if present) are passing * [x] Adheres to code style for repo * [x] Contributor License Agreement (CLA) completed if not a Reddit employee
1 parent b0666d2 commit 3468b2e

13 files changed

Lines changed: 514 additions & 173 deletions

File tree

docs/capabilities/devvit-web/devvit_web_configuration.md

Lines changed: 101 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
# Configure your app
1+
# Configure your app
22

3-
The devvit.json file serves as your app's configuration file. Use it to specify entry points, configure features like [event triggers](../server/triggers) and [scheduled actions](../server/scheduler.mdx), and enable app functionality such as [image uploads](../server/media-uploads.mdx). This page covers all available devvit.json configuration options. A complete devvit.json example file is provided [here](#complete-example).
3+
The `devvit.json` file serves as your app's configuration file. Use it to specify entry points, configure features like [event triggers](../server/triggers) and [scheduled actions](../server/scheduler.mdx), and enable app functionality such as [image uploads](../server/media-uploads.mdx). This page summarizes the schema-supported configuration options; the published JSON Schema remains authoritative. A representative `devvit.json` example is provided [here](#complete-example).
44

55
## devvit.json
66

@@ -18,7 +18,7 @@ All configuration files should include a `$schema` property which many IDEs will
1818

1919
Your `devvit.json` must include:
2020

21-
- **`name`** (required): App account name and Community URL slug. Must be 3-16 characters, start with a letter, and contain only lowercase letters, numbers, and hyphens.
21+
- **`name`** (required): App account name and Community URL slug. Must be 3-20 characters, start with a letter, and contain only lowercase letters, numbers, and hyphens.
2222

2323
Additionally, you must include at least one of:
2424

@@ -31,7 +31,7 @@ Additionally, you must include at least one of:
3131

3232
| Property | Type | Description | Required |
3333
| --------- | ------ | ------------------------------------------------------------------------- | ---------------- |
34-
| `name` | string | App account name and Community URL slug (3-16 chars, `^[a-z][a-z0-9-]*$`) | Yes |
34+
| `name` | string | App account name and Community URL slug (3-20 chars, `^[a-z][a-z0-9-]*$`) | Yes |
3535
| `$schema` | string | Schema version for IDE support | No (recommended) |
3636

3737
### App components
@@ -58,17 +58,19 @@ Additionally, you must include at least one of:
5858

5959
### UI & interaction
6060

61-
| Property | Type | Description | Required |
62-
| -------- | ------ | ----------------------------------------- | -------- |
63-
| `menu` | object | Menu items in posts, comments, subreddits | No |
64-
| `forms` | object | Form submission endpoints | No |
61+
| Property | Type | Description | Required |
62+
| ---------- | ------ | ------------------------------------------------ | -------- |
63+
| `menu` | object | Menu items in posts, comments, and subreddits | No |
64+
| `forms` | object | Form submission endpoints | No |
65+
| `settings` | object | Global and per-subreddit app settings definitions | No |
6566

6667
### Development
6768

68-
| Property | Type | Description | Required |
69-
| --------- | ------ | --------------------------------------------------- | -------- |
70-
| `dev` | object | Development configuration | No |
71-
| `scripts` | object | Build commands run by the Devvit CLI (optional) | No |
69+
| Property | Type | Description | Required |
70+
| --------------- | ------ | ------------------------------------------------------- | -------- |
71+
| `dev` | object | Development configuration | No |
72+
| `scripts` | object | Build commands run by the Devvit CLI | No |
73+
| `sourceIgnores` | array | Source files excluded from packages submitted for review | No |
7274

7375
## Detailed configuration
7476

@@ -96,7 +98,7 @@ Configure web views for custom post types:
9698
- `entrypoints` (object): Map of named entrypoints for post rendering
9799
- Must include a `"default"` entrypoint
98100
- `entry` (string): HTML file path or `/api/` endpoint
99-
- `height` (enum): `"regular"` or `"tall"` (default: `"regular"`)
101+
- `height` (enum): `"regular"` or `"tall"` (default: `"tall"`)
100102

101103
### Server configuration
102104

@@ -105,14 +107,17 @@ Configure Node.js server functionality:
105107
```json
106108
{
107109
"server": {
108-
"entry": "src/server/index.js"
110+
"dir": "dist/server",
111+
"entry": "index.js"
109112
}
110113
}
111114
```
112115

113116
**Properties:**
114117

115-
- `entry` (string): Server bundle filename (default: `"src/server/index.js"`)
118+
- `dir` (string): Server bundle directory relative to the project root (default: `"dist/server"`)
119+
- `entry` (string): Server bundle filename within `server.dir` (default: `"index.js"`)
120+
- `externalEndpoints` (object): Named `/external/` routes available to approved outside callers. See [External Endpoints](../server/external-endpoints.mdx).
116121

117122
Server bundles must be compiled to CommonJS (`cjs`). ES module output is not supported by the Devvit Web runtime.
118123

@@ -131,6 +136,7 @@ Control what your app can access:
131136
"payments": false,
132137
"realtime": false,
133138
"redis": true,
139+
"chromeless": false,
134140
"reddit": {
135141
"enable": true,
136142
"asUser": ["SUBMIT_POST", "SUBMIT_COMMENT"]
@@ -153,9 +159,11 @@ Control what your app can access:
153159
**Other permissions:**
154160

155161
- `media` (boolean): Enable media uploads (default: `false`)
156-
- `payments` (boolean): Enable payments plugin (default: `false`)
162+
- `payments` (boolean): Enable the payments plugin (default: `false`)
157163
- `realtime` (boolean): Enable realtime messaging (default: `false`)
158164
- `redis` (boolean): Enable Redis storage (default: `false`)
165+
- `chromeless` (boolean): Allow supported custom posts to render without standard post chrome when highlighted (default: `false`)
166+
- `blob` (boolean): Reserved for the experimental Blob Storage capability and not yet publicly available. Follow the current [Blob Storage](../server/blob-storage.mdx) setup instructions rather than enabling this field unless directed by Reddit.
159167

160168
### Triggers configuration
161169

@@ -176,6 +184,7 @@ Handle Reddit events:
176184
- `onAppInstall`, `onAppUpgrade`
177185
- `onPostCreate`, `onPostDelete`, `onPostSubmit`, `onPostUpdate`, `onPostReport`, `onPostFlairUpdate`, `onPostNsfwUpdate`, `onPostSpoilerUpdate`
178186
- `onCommentCreate`, `onCommentDelete`, `onCommentSubmit`, `onCommentUpdate`, `onCommentReport`
187+
- `onMentionInCommentCreate` (limited access; see [Global Triggers](../server/global-triggers.mdx))
179188
- `onModAction`, `onModMail`
180189
- `onAutomoderatorFilterPost`, `onAutomoderatorFilterComment`
181190

@@ -264,6 +273,66 @@ Map form identifiers to submission endpoints:
264273
}
265274
```
266275

276+
### Static asset configuration
277+
278+
Configure a directory of static assets that is available to both the app client and server:
279+
280+
```json
281+
{
282+
"media": {
283+
"dir": "assets"
284+
}
285+
}
286+
```
287+
288+
- `dir` (string): Static asset directory relative to the project root (default: `"assets"`)
289+
290+
This top-level `media` object is separate from `permissions.media`, which enables runtime media uploads.
291+
292+
### Settings configuration
293+
294+
Define settings that apply globally or can be configured separately for each subreddit installation:
295+
296+
```json
297+
{
298+
"settings": {
299+
"global": {
300+
"featureEnabled": {
301+
"type": "boolean",
302+
"label": "Enable feature",
303+
"defaultValue": true
304+
}
305+
},
306+
"subreddit": {
307+
"welcomeMessage": {
308+
"type": "paragraph",
309+
"label": "Welcome message"
310+
}
311+
}
312+
}
313+
}
314+
```
315+
316+
At least one of `global` or `subreddit` is required. Supported setting types include strings, paragraphs, numbers, booleans, selects, and multi-selects. See [Settings and Secrets](../server/settings-and-secrets.mdx) for validation and access patterns.
317+
318+
### Payments configuration
319+
320+
The top-level `payments` object declares products and the internal endpoints used to fulfill or refund orders. It is separate from `permissions.payments`, which enables the payments plugin.
321+
322+
```json
323+
{
324+
"payments": {
325+
"productsFile": "products.json",
326+
"endpoints": {
327+
"fulfillOrder": "/internal/payments/fulfill-order",
328+
"refundOrder": "/internal/payments/refund-order"
329+
}
330+
}
331+
}
332+
```
333+
334+
Provide either inline `products` or a `productsFile`, and always configure `endpoints.fulfillOrder`. See [Add Payments](../../earn-money/payments/payments_add.mdx) for the complete product schema and implementation steps.
335+
267336
### Marketing assets
268337

269338
Configure app presentation:
@@ -298,6 +367,18 @@ Configure build commands run by the Devvit CLI. These commands run relative to t
298367
- `dev` (string): Command run by `devvit playtest` to build or watch your client/server artifacts
299368
- `build` (string): Command run by `devvit upload` to build your client/server artifacts
300369

370+
### Source packaging exclusions
371+
372+
Use `sourceIgnores` to exclude files from the source archive submitted during `devvit publish`. Patterns use `.gitignore` syntax and are evaluated after the root `.gitignore` file.
373+
374+
```json
375+
{
376+
"sourceIgnores": ["coverage/", "*.log", "fixtures/private/"]
377+
}
378+
```
379+
380+
Patterns are relative to the project root. Some paths, including `node_modules/`, `.env`, and `.git/`, are always excluded.
381+
301382
### Development configuration
302383

303384
Configure development settings:
@@ -316,7 +397,7 @@ Configure development settings:
316397

317398
## Validation rules
318399

319-
The `devvit.json` configuration is validated against the JSON Schema at build time. Many IDEs will also underline errors as you write. Common validation errors include:
400+
The Devvit CLI validates `devvit.json` against the JSON Schema before playtest, upload, and publish operations. Many IDEs will also underline errors as you write. Common validation errors include:
320401

321402
- **JSON Syntax:** Adding comments or trailing commas (unsupported by JSON)
322403
- **Required Properties:** Missing the required `name` property
@@ -333,7 +414,7 @@ The `devvit.json` configuration is validated against the JSON Schema at build ti
333414
3. **Set appropriate menu scopes.** Consider whether features should be available to all users or just moderators.
334415
4. **Validate endpoints.** Ensure all internal endpoints start with `/internal/`.
335416
5. **Use meaningful names.** Choose descriptive names for entrypoints, tasks, and forms.
336-
6. **Test configurations.** Validate your config with `devvit build` before deployment.
417+
6. **Test configurations.** Use `devvit playtest` during development; `devvit playtest`, `devvit upload`, and `devvit publish` validate the configuration before packaging.
337418

338419
## Environment variables
339420

@@ -356,7 +437,8 @@ The `devvit.json` configuration is validated against the JSON Schema at build ti
356437
}
357438
},
358439
"server": {
359-
"entry": "src/server/index.js"
440+
"dir": "dist/server",
441+
"entry": "index.js"
360442
},
361443
"permissions": {
362444
"http": {

docs/capabilities/server/launch_screen_and_entry_points/launch_screen_customization.md

Lines changed: 24 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,9 @@ import { requestExpandedMode } from '@devvit/web/client';
2828
document.addEventListener('DOMContentLoaded', () => {
2929
const playButton = document.getElementById('play-button');
3030

31-
playButton.addEventListener('click', async (event) => {
31+
playButton.addEventListener('click', (event) => {
3232
try {
33-
await requestExpandedMode(event, 'game');
33+
requestExpandedMode(event, 'game');
3434
} catch (error) {
3535
console.error('Failed to enter expanded mode:', error);
3636
}
@@ -47,13 +47,13 @@ Requests expanded mode for the web view. This displays the web view in a larger
4747
```tsx
4848
import { requestExpandedMode } from '@devvit/web/client';
4949

50-
// Must be called from a trusted event (click, touch, etc.)
51-
await requestExpandedMode(event, 'game');
50+
// Must be called synchronously from a trusted click event.
51+
requestExpandedMode(event, 'game');
5252
```
5353

5454
**Parameters**
5555

56-
- `event` (PointerEvent): The gesture that triggered the request, must be a trusted event
56+
- `event` (MouseEvent): The trusted `click` event that triggered the request
5757
- `entry` (string): The destination URI name (e.g., `splash` or `game`). Entry names are the `devvit.json post.entrypoints` keys
5858

5959
### getWebViewMode()
@@ -72,23 +72,21 @@ if (currentMode === 'expanded') {
7272
}
7373
```
7474

75-
### Mode Change Events
75+
### Returning to inline mode
7676

77-
Listen for mode changes to update your UI.
77+
The legacy `addWebViewModeListener()` and `removeWebViewModeListener()` APIs are deprecated. Listen for the window `focus` event to detect when an expanded web view returns to inline mode, then read the current mode again.
7878

7979
```tsx
80-
import { addWebViewModeListener, removeWebViewModeListener } from '@devvit/web/client';
80+
import { getWebViewMode } from '@devvit/web/client';
8181

8282
function useWebViewMode() {
8383
const [mode, setMode] = useState(getWebViewMode());
8484

8585
useEffect(() => {
86-
const handleModeChange = (newMode: 'inline' | 'expanded') => {
87-
setMode(newMode);
88-
};
86+
const handleFocus = () => setMode(getWebViewMode());
8987

90-
addWebViewModeListener(handleModeChange);
91-
return () => removeWebViewModeListener(handleModeChange);
88+
window.addEventListener('focus', handleFocus);
89+
return () => window.removeEventListener('focus', handleFocus);
9290
}, []);
9391

9492
return mode;
@@ -103,42 +101,42 @@ import {
103101
getWebViewMode,
104102
requestExpandedMode,
105103
exitExpandedMode,
106-
addWebViewModeListener,
107-
removeWebViewModeListener,
108104
} from '@devvit/web/client';
109105

110106
export function GameApp() {
111107
const [mode, setMode] = useState(getWebViewMode());
112108
const [gameStarted, setGameStarted] = useState(false);
113109

114110
useEffect(() => {
115-
const handleModeChange = (newMode: 'inline' | 'expanded') => {
116-
setMode(newMode);
111+
const handleFocus = () => {
112+
const nextMode = getWebViewMode();
113+
setMode(nextMode);
117114

118-
// Pause game when exiting expanded mode
119-
if (newMode === 'inline' && gameStarted) {
115+
// Pause game when returning to inline mode.
116+
if (nextMode === 'inline' && gameStarted) {
120117
pauseGame();
121118
}
122119
};
123120

124-
addWebViewModeListener(handleModeChange);
125-
return () => removeWebViewModeListener(handleModeChange);
121+
window.addEventListener('focus', handleFocus);
122+
return () => window.removeEventListener('focus', handleFocus);
126123
}, [gameStarted]);
127124

128-
const handlePlayClick = async (event: React.MouseEvent) => {
125+
const handlePlayClick = (event: React.MouseEvent<HTMLButtonElement>) => {
129126
try {
130-
await requestExpandedMode(event.nativeEvent, 'game');
127+
requestExpandedMode(event.nativeEvent, 'game');
128+
setMode('expanded');
131129
setGameStarted(true);
132130
} catch (error) {
133131
console.error('Could not enter expanded mode:', error);
134-
// Fallback: start game inline
132+
// Fallback: start game inline.
135133
setGameStarted(true);
136134
}
137135
};
138136

139-
const handleExitClick = async (event: React.MouseEvent) => {
137+
const handleExitClick = (event: React.MouseEvent<HTMLButtonElement>) => {
140138
try {
141-
await exitExpandedMode(event.nativeEvent);
139+
exitExpandedMode(event.nativeEvent);
142140
} catch (error) {
143141
console.error('Could not exit expanded mode:', error);
144142
}

0 commit comments

Comments
 (0)