@dytsou/shorten-url 2.4.4 → 2.4.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # URL Shortener
2
2
 
3
- A URL shortener built with Cloudflare Workers, Cloudflare KV, and a responsive static web interface. The Worker creates short links, stores them in KV, and serves redirects; the `docs/` directory contains the website and OpenAPI reference.
3
+ A URL shortener built with Cloudflare Workers, Cloudflare KV, and a responsive React interface. The Worker serves the product UI and redirects, while `docs/` contains the documentation and OpenAPI reference.
4
4
 
5
5
  [![Built with Cloudflare](https://workers.cloudflare.com/built-with-cloudflare.svg)](https://cloudflare.com)
6
6
  [![Deploy to Cloudflare](https://deploy.workers.cloudflare.com/button)](https://deploy.workers.cloudflare.com/?url=https://github.com/dytsou/shorten-url)
@@ -10,7 +10,8 @@ A URL shortener built with Cloudflare Workers, Cloudflare KV, and a responsive s
10
10
  - **URL Shortening**: Create short links stored in Cloudflare KV and redirect with HTTP 302
11
11
  - **Custom Slugs**: Optionally choose a slug using letters, numbers, hyphens, or underscores
12
12
  - **Cloudflare Access**: The Worker checks for Cloudflare Access JWT and email headers before creating links
13
- - **Responsive Design**: Static shortening form supports desktop and mobile screens
13
+ - **Responsive Design**: Worker-hosted React interface supports desktop and mobile screens
14
+ - **Flagship Controls**: Shorten and protected Flagship views share one interface
14
15
  - **Unique Links**: Optionally reuse the same short key when the destination URL already exists
15
16
  - **URL Safety**: Validate submitted URLs and optionally check redirect destinations with Google Safe Browsing
16
17
  - **Copy Support**: Copy shortened URLs with a manual-selection fallback
@@ -22,6 +23,30 @@ The Worker does not implement click analytics, per-IP rate limiting, or blocked-
22
23
 
23
24
  ## Quick Start
24
25
 
26
+ ### Worker-hosted React frontend
27
+
28
+ The product UI is React source in `frontend/`, compiled to `frontend/dist`, and served by the Worker through its `ASSETS` binding. Worker routing and APIs remain in `src/`; the API reference from `docs/api/` is bundled into Worker assets at `/api/` and `/api/openapi.yaml`. The separate Cloudflare Pages site can publish the documentation landing page from `docs/`; `docs/index.html` is not a product asset.
29
+
30
+ For a clean local setup, install both declared packages and use the root commands:
31
+
32
+ ```bash
33
+ pnpm install --frozen-lockfile --ignore-scripts
34
+ pnpm --dir frontend install --frozen-lockfile --ignore-scripts
35
+ cp wrangler.toml.example wrangler.toml
36
+ # Set a real LINKS namespace and production-only Access values in wrangler.toml or secrets.
37
+ pnpm build
38
+ pnpm dev
39
+ ```
40
+
41
+ `pnpm dev`, `pnpm preview`, and `pnpm deploy` build `frontend/dist` before running Wrangler. The Worker serves the UI at `GET /`. Only the `production` branch mounts its product page at `/shorten`; other branch previews stay at `/`. Regardless of the page path, the UI sends API requests to `POST /` and `/settings/api/*`. Standalone settings pages are not exposed.
42
+
43
+ Production must use an Access-protected custom hostname, set `workers_dev = false`, and set `ACCESS_ALLOWED_HOSTS` to that hostname. Keep `CLOUDFLARE_API_TOKEN`, `FLAGSHIP_CSRF_SECRET`, and provider credentials in Cloudflare/GitHub secrets, never Vite metadata or tracked configuration. Optional `FRONTEND_URL` and `FRONTEND_PAGES_BASE` retain legacy error/interstitial pages only; they are not used to serve the normal UI.
44
+
45
+ The Worker deployment workflow reads the non-secret GitHub variables
46
+ `LINKS_KV_NAMESPACE_ID` and `ACCESS_ALLOWED_HOSTS`, plus the
47
+ `CLOUDFLARE_API_TOKEN` secret, to create its ignored `wrangler.toml` at build
48
+ time.
49
+
25
50
  ### Prerequisites
26
51
 
27
52
  - A Cloudflare account with Workers and Pages; the Deploy to Cloudflare button provisions the required KV namespace
@@ -35,7 +60,7 @@ The Worker does not implement click analytics, per-IP rate limiting, or blocked-
35
60
  2. Connect your Cloudflare and GitHub or GitLab accounts, then choose the destination repository and Worker name.
36
61
  3. Confirm the `LINKS` KV binding. Cloudflare provisions the namespace and deploys the Worker from the `main` branch.
37
62
 
38
- The button deploys the Worker; it does not publish the static homepage in `docs/`. Connect the created repository to Cloudflare Pages, leave the build command blank, and set the output directory to `docs`. Then set `frontend.url` in `config/config.js` to the Pages URL and push the change to redeploy the Worker. The Worker fetches the static homepage and serves it at `/`, so the form submits to `POST /` on the Worker.
63
+ The button deploys the Worker; it does not publish `docs/`. Connect the created repository to Cloudflare Pages, leave the build command blank, and set the output directory to `docs`. The React product UI is built into `frontend/dist` and served by the Worker through `ASSETS`; use the Worker deployment workflow or `pnpm deploy` to build and deploy those assets.
39
64
 
40
65
  ### 2. Alternative: Manual Worker Deployment
41
66
 
@@ -48,33 +73,25 @@ corepack enable
48
73
  pnpm install
49
74
  ```
50
75
 
51
- Set `frontend.url` in `config/config.js` to the public URL where you host `docs/`. The Worker fetches this page for `GET /`:
52
-
53
- ```javascript
54
- const config = {
55
- frontend: {
56
- url: "https://your-project.pages.dev/",
57
- },
58
- // Configure worker options here
59
- };
60
- ```
61
-
62
- `src/worker.js` imports `config/config.js` directly. Keep API keys out of this file; configure the optional Google Safe Browsing key with a Wrangler secret.
63
-
64
- Install Wrangler, log in, and deploy:
76
+ The Worker serves the product UI from `ASSETS`. To deploy manually, install both packages, create the local Wrangler file from the tracked example, set the `LINKS` namespace ID and Access hostname, then build and deploy:
65
77
 
66
78
  ```bash
79
+ pnpm install --frozen-lockfile --ignore-scripts
80
+ pnpm --dir frontend install --frozen-lockfile --ignore-scripts
81
+ cp wrangler.toml.example wrangler.toml
82
+ # Set the LINKS namespace ID and ACCESS_ALLOWED_HOSTS.
83
+ pnpm build
67
84
  pnpm exec wrangler login
68
85
  pnpm deploy
69
86
  ```
70
87
 
71
88
  The `LINKS` binding in `wrangler.toml` omits an account-specific namespace ID so Wrangler can provision it. To use an existing KV namespace, create it with `pnpm exec wrangler kv namespace create LINKS` and set its ID in `wrangler.toml` before deploying.
72
89
 
73
- ### 3. Deploy the Frontend to Cloudflare Pages
90
+ ### 3. Deploy Documentation to Cloudflare Pages
74
91
 
75
- The `main` branch includes a sample page at `docs/index.html`. To create your own Pages site, connect your repository to Cloudflare Pages, set the production branch to the branch containing your homepage, leave the build command blank, and use `docs` as the output directory.
92
+ The `docs/` directory contains the API reference and documentation. To create a Pages site, connect your repository, set the production branch to the branch containing your documentation, leave the build command blank, and use `docs` as the output directory.
76
93
 
77
- This repository's Cloudflare Pages project publishes `docs/` from the `production` branch. The `main` branch remains the one-click Worker template. Set `frontend.url` to your Pages URL so the Worker can serve the hosted homepage at `/`.
94
+ This repository's Cloudflare Pages project publishes `docs/` from the `production` branch. The product UI is served by the Worker and does not depend on the Pages site.
78
95
 
79
96
  For custom error and interstitial pages, set `frontend.pagesBase` to the directory containing those files.
80
97
 
@@ -84,12 +101,13 @@ The Worker returns short URLs using the request's origin, so configure its publi
84
101
 
85
102
  ### Frontend Configuration
86
103
 
87
- | Option | Description | Default |
88
- | --------------------- | --------------------------------------------------------------------------- | -------- |
89
- | `frontend.url` | Static homepage URL fetched by the Worker for `GET /` | Required |
90
- | `frontend.pagesBase` | Base URL for hosted error and interstitial pages | `url` |
91
-
92
- The `frontend.displayDomain` and `frontend.theme` values in the configuration are not read by the current static page or Worker.
104
+ | Option | Description | Default |
105
+ | ------------------------ | ------------------------------------------------------- | ------- |
106
+ | `frontend.url` | Optional origin for legacy error and interstitial pages | `""` |
107
+ | `frontend.pagesBase` | Base URL for hosted error and interstitial pages | `url` |
108
+ | `frontend.workerOrigin` | Public Worker origin for a separately hosted frontend | `""` |
109
+ | `frontend.displayDomain` | Domain shown in UI (null = auto-detect) | `null` |
110
+ | `frontend.theme` | UI theme selection | `""` |
93
111
 
94
112
  ### Worker Configuration
95
113
 
@@ -99,7 +117,7 @@ The `frontend.displayDomain` and `frontend.theme` values in the configuration ar
99
117
  | `worker.cors` | Add wildcard CORS headers for API responses | `"on"` |
100
118
  | `worker.unique_link` | Reuse a key when the same URL has already been shortened | `true` |
101
119
  | `worker.custom_link` | Allow custom slugs | `true` |
102
- | `SAFE_BROWSING_API_KEY` | Optional Google Safe Browsing API key stored as a Worker secret | Unset |
120
+ | `SAFE_BROWSING_API_KEY` | Optional Google Safe Browsing API key stored as a Worker secret | Unset |
103
121
  | `worker.min_random_key_length` | Minimum length for generated keys | `6` |
104
122
  | `worker.random_chars` | Characters used for generated keys | See config |
105
123
  | `worker.max_custom_slug_length` | Maximum length for custom slugs | `50` |
@@ -107,12 +125,12 @@ The `frontend.displayDomain` and `frontend.theme` values in the configuration ar
107
125
 
108
126
  ### Security Configuration
109
127
 
110
- | Option | Description | Default |
111
- | ------------------------------------- | -------------------------------------------------------------------- | ------- |
112
- | `security.rate_limit` | Not implemented by the Worker | Unused |
113
- | `security.validate_urls` | URLs are always validated; this setting does not toggle validation | Unused |
114
- | `security.blocked_domains` | Domain blocklists are not implemented by the Worker | Unused |
115
- | `security.block_suspicious_domains` | Domain blocklists are not implemented by the Worker | Unused |
128
+ | Option | Description | Default |
129
+ | ----------------------------------- | ------------------------------------------------------------------ | ------- |
130
+ | `security.rate_limit` | Not implemented by the Worker | Unused |
131
+ | `security.validate_urls` | URLs are always validated; this setting does not toggle validation | Unused |
132
+ | `security.blocked_domains` | Domain blocklists are not implemented by the Worker | Unused |
133
+ | `security.block_suspicious_domains` | Domain blocklists are not implemented by the Worker | Unused |
116
134
 
117
135
  ### Storage Configuration
118
136
 
@@ -124,9 +142,9 @@ The `frontend.displayDomain` and `frontend.theme` values in the configuration ar
124
142
 
125
143
  ### Custom Domain
126
144
 
127
- 1. Add a custom domain to the Cloudflare Pages project for the static site.
128
- 2. Add a domain to the Cloudflare Worker separately for the shortening API.
129
- 3. Set `frontend.url` to the Cloudflare Pages URL; Pages and Worker domains are configured independently.
145
+ 1. Add a custom domain to the Cloudflare Worker and protect it with Cloudflare Access.
146
+ 2. Add a custom domain to the Cloudflare Pages project for documentation.
147
+ 3. Set `frontend.url` only when using separately hosted legacy error or interstitial pages.
130
148
 
131
149
  ### Google Safe Browsing
132
150
 
@@ -156,13 +174,13 @@ These files are not included in this repository. The Worker fetches their curren
156
174
 
157
175
  ## 📖 API Documentation
158
176
 
159
- The API reference is a static Swagger UI published from `docs/api/`; it is not served by the Worker at `/api`.
177
+ The API reference is a static Swagger UI built from `docs/api/` and bundled into Worker assets. `/api` redirects to `/api/`, where the interactive reference is served.
160
178
 
161
179
  ### OpenAPI Specification
162
180
 
163
181
  - **Format**: OpenAPI 3.1.0
164
182
  - **Location**: [docs/api/openapi.yaml](docs/api/openapi.yaml)
165
- - **Interactive UI**: [docs/api/index.html](docs/api/index.html), published at `/api/` under the Pages base URL
183
+ - **Interactive UI**: [docs/api/index.html](docs/api/index.html), bundled into Worker assets and served at `/api/`
166
184
  - **Offline Access**: [docs/api/index.html](docs/api/index.html) for local viewing
167
185
 
168
186
  ### Shorten URL
@@ -176,7 +194,7 @@ The API reference is a static Swagger UI published from `docs/api/`; it is not s
176
194
  }
177
195
  ```
178
196
 
179
- `custom_slug` is optional. The default Worker template requires Cloudflare Access headers before creating a link.
197
+ The endpoint stays at the origin root even when the production page is mounted at `/shorten`. `custom_slug` is optional. The default Worker template requires Cloudflare Access headers before creating a link.
180
198
 
181
199
  **Response (201 Created):**
182
200
 
@@ -203,9 +221,23 @@ Redirects to the stored destination with HTTP 302. Query parameters from the sho
203
221
 
204
222
  ### Additional Endpoints
205
223
 
206
- - **GET** `/` - Fetches the configured static homepage
224
+ - **GET** `/` - Serves the Worker-hosted React interface
207
225
  - **OPTIONS** - Returns a CORS preflight response
208
226
 
227
+ ### Flagship Management API
228
+
229
+ The authenticated control plane manages the `shorten-routing` flag under `/settings/api`. Requests require Cloudflare Access authentication. Fetch a CSRF token before sending a write; POST and PUT requests must include that token in `X-CSRF-Token`, use `application/json`, and come from the same origin as the UI.
230
+
231
+ | Method | Path | Purpose |
232
+ | ------ | -------------------------------------------- | --------------------------------------------------------- |
233
+ | `GET` | `/settings/api/csrf` | Get a CSRF token for the signed-in Access user and origin |
234
+ | `GET` | `/settings/api/flags` | Read the saved shortening flag |
235
+ | `POST` | `/settings/api/flag` | Create the `shorten-routing` flag |
236
+ | `PUT` | `/settings/api/flag/shorten-routing` | Save a draft with `expectedUpdatedAt` concurrency control |
237
+ | `POST` | `/settings/api/flag/shorten-routing/publish` | Publish the saved version |
238
+
239
+ Targeting rules are evaluated by ascending priority. Conditions in a rule are combined with AND and can target country, region, continent, timezone, browser language, or UTM source, medium, and campaign. Supported operators are `equals`, `not_equals`, `contains`, `starts_with`, `ends_with`, `in`, and `not_in`. A rule can also set `rolloutPercentage` from 0 to 100; the Worker uses a stable visitor key for the canary assignment. See the OpenAPI schema for request and response shapes.
240
+
209
241
  ## 🛠️ Development
210
242
 
211
243
  ### Local Development
@@ -223,23 +255,27 @@ curl -X POST http://localhost:8787/ \
223
255
  -d '{"url": "https://example.com"}'
224
256
  ```
225
257
 
226
- The Worker imports `config/config.js` directly. Run `pnpm test` to execute the Worker tests.
258
+ The Worker combines built-in defaults with non-secret Wrangler variables; keep credentials in Wrangler secrets. Run `pnpm test` to execute the Worker tests.
227
259
 
228
260
  ### File Structure
229
261
 
230
262
  ```
231
263
  shorten-url/
232
264
  ├── src/
233
- │ ├── lib/ # Validation, redirects, KV, responses, and observability
234
- │ └── worker.js # Worker entrypoint
265
+ │ ├── lib/ # Validation, routes, KV, assets, and observability
266
+ │ ├── worker.js # Production Worker entrypoint
267
+ │ └── worker.example.js # Example Worker entrypoint
268
+ ├── frontend/ # React product UI, about-page template, and build configuration
235
269
  ├── docs/
236
- │ ├── index.html # Sample homepage (POST /)
270
+ │ ├── index.html # Documentation site homepage
271
+ │ ├── about.md # Content rendered as the /about website page
237
272
  │ └── api/
238
273
  │ ├── index.html # Swagger UI for API docs
239
274
  │ └── openapi.yaml # OpenAPI 3.1.0 specification
240
275
  ├── config/
241
- │ └── config.js # Worker configuration
242
- ├── wrangler.toml # Wrangler configuration
276
+ │ ├── config.js # Existing deployment template
277
+ │ └── config.example.js # Configuration example
278
+ ├── wrangler.toml.example # Wrangler deployment template
243
279
  ├── .github/ # GitHub workflows and templates
244
280
  ├── .gitignore # Ignores local-only files
245
281
  └── README.md # This file
@@ -264,7 +300,8 @@ shorten-url/
264
300
 
265
301
  **Worker deployment fails:**
266
302
 
267
- - Confirm `src/worker.js` and `config/config.js` are present
303
+ - Confirm `src/worker.js`, `wrangler.toml.example`, and `frontend/` are present
304
+ - Build the frontend so `frontend/dist/index.html` exists
268
305
  - Ensure the `LINKS` KV namespace ID in `wrangler.toml` is valid
269
306
  - Ensure KV namespace ID is correct
270
307
  - Verify you're logged into the correct Cloudflare account
@@ -277,8 +314,8 @@ shorten-url/
277
314
 
278
315
  **Frontend not loading:**
279
316
 
280
- - Set `frontend.url` to the hosted static homepage URL
281
- - If the form returns an invalid-path response, check that its POST path matches the Worker route (`/` for the template)
317
+ - Check that the Worker has an `ASSETS` binding and `frontend/dist/index.html` was built
318
+ - If shortening returns an invalid-path response, check that the frontend POST path is `/`
282
319
  - Enable CORS if the frontend and Worker use different origins
283
320
 
284
321
  **Rate limiting issues:**
@@ -307,7 +344,8 @@ If you encounter any issues or have questions:
307
344
 
308
345
  ## Deployment Checklist
309
346
 
310
- - [ ] Set `frontend.url` and the `LINKS` KV namespace in the deployment configuration
347
+ - [ ] Set `LINKS_KV_NAMESPACE_ID` and `ACCESS_ALLOWED_HOSTS` for Worker deployment
348
+ - [ ] Build the React frontend into `frontend/dist`
311
349
  - [ ] Deployed `docs/` to Cloudflare Pages
312
350
  - [ ] Created Cloudflare KV namespace
313
351
  - [ ] Configured `wrangler.toml` with correct KV namespace ID
@@ -0,0 +1,137 @@
1
+ /**
2
+ * URL Shortener Configuration Example
3
+ *
4
+ * Copy this file to config.js and modify the values according to your setup.
5
+ * This file should be committed to your repository as a template.
6
+ * The actual config.js file should be added to .gitignore to keep your secrets safe.
7
+ */
8
+
9
+ const config = {
10
+ // Frontend Configuration
11
+ frontend: {
12
+ // Leave empty when the Worker serves the React UI. Set this only for
13
+ // separately hosted legacy error/interstitial pages.
14
+ url: "",
15
+
16
+ // Public Worker origin used by frontend/index.html for shortening and
17
+ // protected settings APIs when the frontend is hosted separately. Keep it in
18
+ // sync with the HTML meta tag or VITE_WORKER_ORIGIN; leave empty when the
19
+ // Worker serves the page.
20
+ workerOrigin: "",
21
+
22
+ // Domain displayed in the custom slug input prefix
23
+ // If null, will use the current domain automatically
24
+ // Example: "short.ly" or "yourdomain.com"
25
+ displayDomain: null,
26
+
27
+ // Default theme for the frontend
28
+ theme: "", // Use empty string for default theme, or "theme/urlcool" for urlcool theme
29
+ },
30
+
31
+ // Worker Configuration
32
+ worker: {
33
+ // Control the HTTP referrer header
34
+ // Set to "on" to create anonymous links that hide the HTTP Referer header
35
+ no_ref: "off",
36
+
37
+ // Allow Cross-origin resource sharing for API requests
38
+ cors: "on",
39
+
40
+ // If true, the same long URL will be shortened into the same short URL
41
+ unique_link: true,
42
+
43
+ // Allow users to customize the short URL
44
+ custom_link: true,
45
+
46
+ // Google Safe Browsing API Key for URL safety check before redirect
47
+ // Get your API key from: https://developers.google.com/safe-browsing/v4/get-started
48
+ // Leave empty to disable safety checking
49
+ safe_browsing_api_key: "",
50
+
51
+ // Maximum length for custom slugs
52
+ max_custom_slug_length: 50,
53
+
54
+ // Minimum length for generated random keys
55
+ min_random_key_length: 6,
56
+
57
+ // Characters used for random key generation (removed confusing characters)
58
+ random_chars: "ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz2345678",
59
+
60
+ // Reserved slugs that cannot be used as custom URLs
61
+ reserved_slugs: [
62
+ "api",
63
+ "admin",
64
+ "www",
65
+ "mail",
66
+ "ftp",
67
+ "localhost",
68
+ "password",
69
+ "help",
70
+ "support",
71
+ "contact",
72
+ "about",
73
+ "settings",
74
+ ],
75
+ },
76
+
77
+ // KV Storage Configuration (Cloudflare Workers)
78
+ storage: {
79
+ // KV namespace binding name (must match wrangler.toml)
80
+ binding_name: "LINKS",
81
+ },
82
+
83
+ // Flagship Configuration (optional until the binding and secrets are provisioned)
84
+ flagship: {
85
+ // Wrangler binding name. The Worker expects the official `env.FLAGS` binding.
86
+ binding_name: "FLAGS",
87
+ // Set in the Flagship binding block in wrangler.toml; do not put credentials here.
88
+ app_id: "",
89
+ // Worker secrets/variables used only by protected settings management:
90
+ // CLOUDFLARE_ACCOUNT_ID, FLAGSHIP_APP_ID, FLAGSHIP_API_TOKEN,
91
+ // FLAGSHIP_CSRF_SECRET, CF_ACCESS_ISSUER, CF_ACCESS_AUDIENCE,
92
+ // and optionally CF_ACCESS_JWKS_URL.
93
+ },
94
+
95
+ // Security Configuration
96
+ security: {
97
+ // Rate limiting (requests per minute per IP)
98
+ rate_limit: 10,
99
+
100
+ // Enable URL validation
101
+ validate_urls: true,
102
+
103
+ // Block suspicious domains
104
+ block_suspicious_domains: true,
105
+
106
+ // List of blocked domains (exact matches)
107
+ // Add domains you want to block from being shortened
108
+ blocked_domains: [
109
+ // "bit.ly",
110
+ // "tinyurl.com",
111
+ // "t.co"
112
+ ],
113
+ },
114
+
115
+ // Analytics Configuration (optional)
116
+ analytics: {
117
+ // Enable click tracking
118
+ enable_tracking: false,
119
+
120
+ // Google Analytics tracking ID (GA4)
121
+ // Example: "G-XXXXXXXXXX"
122
+ ga_tracking_id: "",
123
+
124
+ // Custom analytics endpoint for tracking clicks
125
+ analytics_endpoint: "",
126
+ },
127
+ };
128
+
129
+ // Export for use in other files
130
+ if (typeof module !== "undefined" && module.exports) {
131
+ module.exports = config;
132
+ }
133
+
134
+ // Make available globally for browser usage
135
+ if (typeof window !== "undefined") {
136
+ window.APP_CONFIG = config;
137
+ }
package/config/config.js CHANGED
@@ -12,6 +12,12 @@ const config = {
12
12
  // REQUIRED: Change this to your Cloudflare Pages URL or custom domain
13
13
  url: "https://your-project.pages.dev/",
14
14
 
15
+ // Public Worker origin used by frontend/index.html for shortening and
16
+ // protected settings when the frontend is hosted separately. Keep it in
17
+ // sync with the HTML meta tag or VITE_WORKER_ORIGIN; leave empty when the
18
+ // Worker serves the page.
19
+ workerOrigin: "",
20
+
15
21
  // Domain displayed in the custom slug input prefix
16
22
  // If null, will use the current domain automatically
17
23
  // Example: "short.ly" or "yourdomain.com"
@@ -63,6 +69,7 @@ const config = {
63
69
  "support",
64
70
  "contact",
65
71
  "about",
72
+ "settings",
66
73
  ],
67
74
  },
68
75
 
@@ -72,6 +79,18 @@ const config = {
72
79
  binding_name: "LINKS",
73
80
  },
74
81
 
82
+ // Flagship Configuration (optional until the binding and secrets are provisioned)
83
+ flagship: {
84
+ // Wrangler binding name. The Worker expects the official `env.FLAGS` binding.
85
+ binding_name: "FLAGS",
86
+ // Set in the Flagship binding block in wrangler.toml; do not put credentials here.
87
+ app_id: "",
88
+ // Worker secrets/variables used only by protected settings management:
89
+ // CLOUDFLARE_ACCOUNT_ID, FLAGSHIP_APP_ID, FLAGSHIP_API_TOKEN,
90
+ // FLAGSHIP_CSRF_SECRET, CF_ACCESS_ISSUER, CF_ACCESS_AUDIENCE,
91
+ // and optionally CF_ACCESS_JWKS_URL.
92
+ },
93
+
75
94
  // Security Configuration
76
95
  security: {
77
96
  // Rate limiting (requests per minute per IP)