Commit 1f1fafd
chore: Static URL Support for Applications and Pages (#41312)
## 🎯 Overview
This PR implements **Static URL** functionality for Appsmith
applications and pages, allowing users to create clean, URLs without
auto-generated IDs. This feature is gated behind the
`release_static_url_enabled` feature flag.
## 🚀 Key Features
### 1. **Application-Level Static URLs**
- **Enable/Disable Static URLs**: Toggle static URLs on/off at the
application level
- **Custom Application Slug**: Set a unique, human-readable slug for the
entire application (e.g., `my-app` instead of `untitled-application-5`)
- **Real-time Validation**: Client-side and server-side validation for
slug format (lowercase letters, numbers, hyphens only)
- **Availability Check**: Real-time checking if a slug is available or
already taken
- **Slug Suggestions**: Auto-generate slug suggestions based on
application name
### 2. **Page-Level Static URLs**
- **Custom Page Slugs**: Set unique slugs for individual pages (e.g.,
`dashboard` instead of `page1-68fb0a086001f8101c93e34q`)
- **Per-Page Configuration**: Each page can have its own static slug
- **Validation & Uniqueness**: Real-time validation and uniqueness
checking for page slugs
### 3. **URL Format Changes**
**Before (Legacy Format):**
```
/app/application-slug/page-name-<pageId>
```
**After (Static URL Format):**
```
/app/app-slug/page-slug
```
## 🏗️ Technical Implementation
### **New Routes**
- `BUILDER_PATH_STATIC`:
`/app/:staticApplicationSlug/:staticPageSlug/edit`
- `VIEWER_PATH_STATIC`: `/app/:staticApplicationSlug/:staticPageSlug`
### **New Redux Actions**
- `ENABLE_STATIC_URL` / `DISABLE_STATIC_URL`: Toggle static URL feature
- `PERSIST_APP_SLUG` / `PERSIST_PAGE_SLUG`: Save application/page slugs
- `VALIDATE_APP_SLUG` / `VALIDATE_PAGE_SLUG`: Validate slug availability
- `FETCH_APP_SLUG_SUGGESTION`: Get auto-generated suggestions
### **New API Endpoints**
#### Application APIs
- `POST /api/v1/applications/:applicationId/static-url` - Enable static
URL with initial slug
- `PUT /api/v1/applications/:applicationId/static-url` - Update
application slug
- `DELETE /api/v1/applications/:applicationId/static-url` - Disable
static URL
- `GET /api/v1/applications/:applicationId/static-url/:uniqueSlug` -
Validate application slug availability
- `GET /api/v1/applications/:applicationId/static-url/suggest-app-slug`
- Get slug suggestion
#### Page APIs
- `PATCH /api/v1/pages/static-url` - Update page slug
- `GET /api/v1/pages/:pageId/static-url/verify/:uniqueSlug` - Validate
page slug availability
### **URL Assembly Enhancements**
- Extended `URLAssembly` to support static URL generation
- Added `URL_TYPE.STATIC` for static URL routing
- Static URLs only apply in **published/viewer mode** (edit mode uses
regular URLs)
- Automatic fallback: If `staticPageSlug` is not set, falls back to
regular `pageSlug`
## 🎨 UI Components
### **General Settings (Application Level)**
- **Static URL Toggle**: Enable/disable static URLs for the application
- **Application Slug Input**:
- Real-time validation with error messages
- Loading states during validation
- Success/error indicators
- URL preview showing the final URL
- **Apply/Cancel Buttons**: Persist or discard changes
- **Confirmation Modal**: Shows before/after URLs when changing or
disabling
### **Page Settings (Page Level)**
- **Page Slug Input**: Similar to application slug with validation
- **URL Preview**: Shows the complete page URL
- **Apply/Cancel Actions**: Per-page slug management
### **StaticURLConfirmationModal**
- Displays "From" and "To" URLs
- Warning message about breaking existing links
- Different modes: "Change" vs "Disable"
- Bold formatting for app/page slugs in URLs
## 🔄 State Management
### **Application Reducer**
- `uniqueSlug`: Stores the application's static slug
- `staticUrlEnabled`: Boolean flag for static URL status
### **Page List Reducer**
- `uniqueSlug`: Stores each page's static slug
- Updates only the specific page when slug is persisted
### **Applications UI Reducer**
- `isValidatingAppSlug`: Validation in progress
- `isApplicationSlugValid`: Validation result
- `isFetchingAppSlugSuggestion`: Fetching suggestion
- `appSlugSuggestion`: Auto-generated suggestion
- `isPersistingAppSlug`: Save in progress
## 🛡️ Validation Rules
**Application/Page Slug Requirements:**
- Only lowercase letters (a-z)
- Numbers (0-9)
- Hyphens (-)
- No spaces or special characters
- Must be unique across the workspace
- Cannot be empty
## 🔀 Navigation & Routing
### **Route Matching Updates**
- Extended `matchBuilderPath` to include `BUILDER_PATH_STATIC`
- Extended `matchViewerPath` to include `VIEWER_PATH_STATIC`
- Updated route params to include optional `staticApplicationSlug` and
`staticPageSlug`
### **Page Navigation**
- New hook: `useStaticUrlGeneration` for generating static URLs in
navigation
- Updated `useNavigateToAnotherPage` to support static URLs
- Menu items and navigation components updated to use static URLs when
available
## 📦 Key Files Changed
**Core Logic:**
- `URLAssembly.ts`: URL generation logic with static URL support
- `ApplicationSagas.tsx`: Sagas for enable/disable/persist operations
- `PageSagas.tsx`: Page-level slug persistence
- `appRoutes.ts`: New static URL routes
**UI Components:**
- `GeneralSettings.tsx`: Application-level static URL configuration
- `PageSettings.tsx`: Page-level static URL configuration
- `StaticURLConfirmationModal.tsx`: Confirmation dialog (new)
- `UrlPreview.tsx`: URL preview component (new)
**State Management:**
- `applicationsReducer.tsx`: Application UI state
- `appReducer.ts`: Application entity state
- `pageListReducer.tsx`: Page list state
## ⚙️ Feature Flag
- `release_static_url_enabled`: Controls visibility of static URL
features
## Automation
/ok-to-test tags="@tag.All"
### 🔍 Cypress test results
<!-- This is an auto-generated comment: Cypress test results -->
> [!TIP]
> 🟢 🟢 🟢 All cypress tests have passed! 🎉 🎉 🎉
> Workflow run:
<https://github.com/appsmithorg/appsmith/actions/runs/18936467359>
> Commit: a74b4ac
> <a
href="https://internal.appsmith.com/app/cypress-dashboard/rundetails-65890b3c81d7400d08fa9ee5?branch=master&workflowId=18936467359&attempt=1"
target="_blank">Cypress dashboard</a>.
> Tags: `@tag.All`
> Spec:
> <hr>Thu, 30 Oct 2025 10:56:15 UTC
<!-- end of auto-generated comment: Cypress test results -->
## Communication
Should the DevRel and Marketing teams inform users about this change?
- [ ] Yes
- [ ] No
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **New Features**
* Static URL support for apps and pages: enable/disable static URLs,
edit app/page slugs, validate and persist slugs, and receive slug
suggestions.
* URL preview with click-to-copy and a confirmation modal when changing
or disabling app slugs.
* **Bug Fixes / Improvements**
* Routing, editor and viewer flows updated for slug-based paths.
* Base page resolution and editor links now derive from application
state for more reliable navigation and loading.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
---------
Co-authored-by: Pedro Santos Rodrigues <pedro@appsmith.com>1 parent a30daa6 commit 1f1fafd
File tree
61 files changed
+2519
-233
lines changed- app/client/src
- PluginActionEditor/components/PluginActionResponse/components
- actions
- api
- services/ConsolidatedPageLoadApi
- ce
- IDE/constants
- actions
- api
- constants
- routes
- entities
- IDE/utils
- URLRedirect
- middlewares
- pages
- AppIDE/layout/routers/MainPane
- Editor/Explorer
- common
- reducers/uiReducers
- sagas
- selectors
- components/editorComponents/GlobalSearch
- ee/sagas
- entities
- Application
- Engine
- Page
- URLRedirect
- pages
- AppIDE
- components/AppSettings
- components
- layouts
- components
- routers
- UISegmentLeftPane
- AppViewer
- Editor
- DataSourceEditor
- SaaSEditor
- WidgetsEditor/components
- reducers
- entityReducers
- uiReducers
- sagas
- __tests__
- selectors
- utils
Some content is hidden
Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
61 files changed
+2519
-233
lines changedLines changed: 3 additions & 2 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
17 | 17 | | |
18 | 18 | | |
19 | 19 | | |
| 20 | + | |
20 | 21 | | |
21 | 22 | | |
22 | 23 | | |
| |||
247 | 248 | | |
248 | 249 | | |
249 | 250 | | |
250 | | - | |
251 | 251 | | |
252 | 252 | | |
253 | 253 | | |
254 | 254 | | |
| 255 | + | |
255 | 256 | | |
256 | 257 | | |
257 | 258 | | |
| |||
346 | 347 | | |
347 | 348 | | |
348 | 349 | | |
349 | | - | |
| 350 | + | |
350 | 351 | | |
351 | 352 | | |
352 | 353 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
14 | 14 | | |
15 | 15 | | |
16 | 16 | | |
| 17 | + | |
| 18 | + | |
17 | 19 | | |
18 | 20 | | |
19 | 21 | | |
| |||
26 | 28 | | |
27 | 29 | | |
28 | 30 | | |
29 | | - | |
| 31 | + | |
30 | 32 | | |
31 | 33 | | |
| 34 | + | |
| 35 | + | |
32 | 36 | | |
33 | 37 | | |
34 | 38 | | |
| |||
37 | 41 | | |
38 | 42 | | |
39 | 43 | | |
| 44 | + | |
| 45 | + | |
40 | 46 | | |
41 | 47 | | |
42 | 48 | | |
| |||
45 | 51 | | |
46 | 52 | | |
47 | 53 | | |
| 54 | + | |
| 55 | + | |
48 | 56 | | |
49 | 57 | | |
50 | 58 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
705 | 705 | | |
706 | 706 | | |
707 | 707 | | |
| 708 | + | |
| 709 | + | |
| 710 | + | |
| 711 | + | |
| 712 | + | |
| 713 | + | |
| 714 | + | |
| 715 | + | |
| 716 | + | |
| 717 | + | |
| 718 | + | |
| 719 | + | |
| 720 | + | |
| 721 | + | |
| 722 | + | |
| 723 | + | |
| 724 | + | |
| 725 | + | |
| 726 | + | |
| 727 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
89 | 89 | | |
90 | 90 | | |
91 | 91 | | |
| 92 | + | |
92 | 93 | | |
93 | 94 | | |
94 | 95 | | |
| |||
97 | 98 | | |
98 | 99 | | |
99 | 100 | | |
| 101 | + | |
100 | 102 | | |
101 | 103 | | |
102 | 104 | | |
| |||
300 | 302 | | |
301 | 303 | | |
302 | 304 | | |
| 305 | + | |
| 306 | + | |
| 307 | + | |
| 308 | + | |
| 309 | + | |
| 310 | + | |
| 311 | + | |
| 312 | + | |
| 313 | + | |
| 314 | + | |
| 315 | + | |
| 316 | + | |
| 317 | + | |
| 318 | + | |
303 | 319 | | |
304 | 320 | | |
305 | 321 | | |
Lines changed: 2 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
2 | 2 | | |
3 | 3 | | |
4 | 4 | | |
| 5 | + | |
| 6 | + | |
5 | 7 | | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
14 | 14 | | |
15 | 15 | | |
16 | 16 | | |
| 17 | + | |
17 | 18 | | |
18 | 19 | | |
19 | 20 | | |
| |||
27 | 28 | | |
28 | 29 | | |
29 | 30 | | |
| 31 | + | |
30 | 32 | | |
31 | 33 | | |
32 | 34 | | |
| |||
135 | 137 | | |
136 | 138 | | |
137 | 139 | | |
| 140 | + | |
| 141 | + | |
| 142 | + | |
138 | 143 | | |
139 | 144 | | |
140 | 145 | | |
| |||
175 | 180 | | |
176 | 181 | | |
177 | 182 | | |
178 | | - | |
179 | 183 | | |
180 | 184 | | |
181 | 185 | | |
182 | 186 | | |
183 | 187 | | |
184 | 188 | | |
185 | 189 | | |
| 190 | + | |
186 | 191 | | |
187 | 192 | | |
188 | 193 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
5 | 5 | | |
6 | 6 | | |
7 | 7 | | |
| 8 | + | |
8 | 9 | | |
9 | 10 | | |
10 | 11 | | |
| |||
40 | 41 | | |
41 | 42 | | |
42 | 43 | | |
43 | | - | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
44 | 50 | | |
45 | 51 | | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
79 | 79 | | |
80 | 80 | | |
81 | 81 | | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
82 | 110 | | |
83 | 111 | | |
84 | 112 | | |
| |||
290 | 318 | | |
291 | 319 | | |
292 | 320 | | |
| 321 | + | |
| 322 | + | |
| 323 | + | |
| 324 | + | |
| 325 | + | |
| 326 | + | |
| 327 | + | |
| 328 | + | |
| 329 | + | |
| 330 | + | |
| 331 | + | |
| 332 | + | |
| 333 | + | |
| 334 | + | |
| 335 | + | |
| 336 | + | |
| 337 | + | |
| 338 | + | |
| 339 | + | |
| 340 | + | |
| 341 | + | |
| 342 | + | |
| 343 | + | |
| 344 | + | |
| 345 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
35 | 35 | | |
36 | 36 | | |
37 | 37 | | |
| 38 | + | |
38 | 39 | | |
39 | 40 | | |
40 | 41 | | |
| |||
517 | 518 | | |
518 | 519 | | |
519 | 520 | | |
| 521 | + | |
| 522 | + | |
| 523 | + | |
| 524 | + | |
| 525 | + | |
| 526 | + | |
| 527 | + | |
| 528 | + | |
| 529 | + | |
| 530 | + | |
| 531 | + | |
| 532 | + | |
| 533 | + | |
| 534 | + | |
| 535 | + | |
| 536 | + | |
| 537 | + | |
| 538 | + | |
| 539 | + | |
| 540 | + | |
| 541 | + | |
| 542 | + | |
| 543 | + | |
| 544 | + | |
| 545 | + | |
| 546 | + | |
| 547 | + | |
| 548 | + | |
| 549 | + | |
| 550 | + | |
| 551 | + | |
| 552 | + | |
| 553 | + | |
| 554 | + | |
| 555 | + | |
| 556 | + | |
| 557 | + | |
| 558 | + | |
| 559 | + | |
| 560 | + | |
| 561 | + | |
| 562 | + | |
| 563 | + | |
| 564 | + | |
| 565 | + | |
| 566 | + | |
520 | 567 | | |
521 | 568 | | |
522 | 569 | | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
636 | 636 | | |
637 | 637 | | |
638 | 638 | | |
| 639 | + | |
| 640 | + | |
| 641 | + | |
| 642 | + | |
639 | 643 | | |
640 | 644 | | |
641 | 645 | | |
| 646 | + | |
| 647 | + | |
| 648 | + | |
| 649 | + | |
| 650 | + | |
| 651 | + | |
| 652 | + | |
| 653 | + | |
| 654 | + | |
| 655 | + | |
| 656 | + | |
| 657 | + | |
| 658 | + | |
| 659 | + | |
| 660 | + | |
642 | 661 | | |
643 | 662 | | |
644 | 663 | | |
| |||
670 | 689 | | |
671 | 690 | | |
672 | 691 | | |
| 692 | + | |
| 693 | + | |
| 694 | + | |
673 | 695 | | |
674 | 696 | | |
675 | 697 | | |
| |||
0 commit comments