|
| 1 | +# LaunchDarkly Dev Toolbar with URL-Shareable Overrides |
| 2 | + |
| 3 | +[](https://opensource.org/licenses/Apache-2.0) |
| 4 | + |
| 5 | +A simple HTML5 application that provides a visual interface for viewing and managing LaunchDarkly feature flags with URL-shareable overrides. |
| 6 | + |
| 7 | +> **LaunchDarkly Labs**: This repository is maintained by LaunchDarkly Labs. While we try to keep it up to date, it is not officially supported by LaunchDarkly. For officially supported SDKs and tools, visit [launchdarkly.com](https://launchdarkly.com). |
| 8 | +
|
| 9 | +## Features |
| 10 | + |
| 11 | +### 🎯 Flag Visualization |
| 12 | +- Real-time display of all feature flags |
| 13 | +- Shows flag values, evaluation reasons, and variation indices |
| 14 | +- Visual indicators for flags with active overrides |
| 15 | +- Auto-updates when flags change |
| 16 | + |
| 17 | +### 🔗 URL-Shareable Overrides |
| 18 | +- Flag overrides automatically sync to URL parameters |
| 19 | +- Share URLs with specific flag configurations |
| 20 | +- Overrides persist across page reloads |
| 21 | +- Load overrides directly from URL query parameters |
| 22 | + |
| 23 | +### 🛠️ Interactive Dev Toolbar |
| 24 | +- Built-in LaunchDarkly developer toolbar integration |
| 25 | +- Override flag values locally without affecting other team members |
| 26 | +- Test different flag variations instantly |
| 27 | +- Event interception for debugging |
| 28 | + |
| 29 | +### 📊 SDK Logging |
| 30 | +- Custom logger displays all SDK events in real-time |
| 31 | +- Color-coded log levels (debug, info, warn, error) |
| 32 | +- Auto-scrolling log viewer |
| 33 | +- Timestamps for all log entries |
| 34 | + |
| 35 | +## Getting Started |
| 36 | + |
| 37 | +### Prerequisites |
| 38 | +- A LaunchDarkly account with a client-side ID |
| 39 | +- A modern web browser with ES module support |
| 40 | + |
| 41 | +### Usage |
| 42 | + |
| 43 | +1. **Open the application** |
| 44 | + ``` |
| 45 | + https://your-github-username.github.io/repo-name/ |
| 46 | + ``` |
| 47 | + |
| 48 | +2. **Enter your LaunchDarkly Client-Side ID** |
| 49 | + - Paste your client-side ID in the configuration form |
| 50 | + - Click "Load SDK" |
| 51 | + - The SDK will initialize and display all your flags |
| 52 | + |
| 53 | +3. **View and Override Flags** |
| 54 | + - All flags are displayed with their current values |
| 55 | + - Flags with overrides show an orange "OVERRIDE" badge |
| 56 | + - Use the toolbar to modify flag values |
| 57 | + |
| 58 | +4. **Share Flag Configurations** |
| 59 | + - Override flags using the toolbar |
| 60 | + - Copy the URL from your address bar |
| 61 | + - Share with teammates - they'll see the same flag overrides |
| 62 | + |
| 63 | +## URL Parameter Format |
| 64 | + |
| 65 | +Overrides are stored in the URL with the format: |
| 66 | +``` |
| 67 | +?clientSideId=YOUR_ID&ld_override_flagname=value |
| 68 | +``` |
| 69 | + |
| 70 | +**Example:** |
| 71 | +``` |
| 72 | +?clientSideId=abc123&ld_override_enable-feature=true&ld_override_max-items=10 |
| 73 | +``` |
| 74 | + |
| 75 | +Values are JSON-encoded, supporting: |
| 76 | +- Booleans: `true`, `false` |
| 77 | +- Numbers: `42`, `3.14` |
| 78 | +- Strings: `"hello"` |
| 79 | +- JSON objects: `{"key":"value"}` |
| 80 | + |
| 81 | +## Architecture |
| 82 | + |
| 83 | +### Files |
| 84 | + |
| 85 | +- **`index.html`** - Main application UI and styles |
| 86 | +- **`app.js`** - Core application logic, flag display, and SDK integration |
| 87 | +- **`flag-url-override-plugin.js`** - Reusable plugin for URL-based override management |
| 88 | + |
| 89 | +### Flag URL Override Plugin |
| 90 | + |
| 91 | +The `flag-url-override-plugin.js` module provides a reusable wrapper around LaunchDarkly's `FlagOverridePlugin` that adds URL synchronization. |
| 92 | + |
| 93 | +#### API |
| 94 | + |
| 95 | +```javascript |
| 96 | +import { createFlagUrlOverridePlugin } from './flag-url-override-plugin.js'; |
| 97 | + |
| 98 | +const plugin = createFlagUrlOverridePlugin({ |
| 99 | + parameterPrefix: 'ld_override_', // URL parameter prefix |
| 100 | + overrideOptions: {}, // Options for FlagOverridePlugin |
| 101 | + logger: console // Logger instance |
| 102 | +}); |
| 103 | + |
| 104 | +// Register callback for override changes |
| 105 | +plugin.onOverrideChange((flagKey, action) => { |
| 106 | + // Handle override changes |
| 107 | + // action: 'set', 'remove', or 'clear' |
| 108 | +}); |
| 109 | + |
| 110 | +// Sync current overrides to URL |
| 111 | +plugin.syncInitialOverrides(); |
| 112 | +``` |
| 113 | + |
| 114 | +## Development |
| 115 | + |
| 116 | +### Local Development |
| 117 | + |
| 118 | +1. **Clone the repository** |
| 119 | + ```bash |
| 120 | + git clone https://github.com/your-username/repo-name.git |
| 121 | + cd repo-name |
| 122 | + ``` |
| 123 | + |
| 124 | +2. **Start a local server** |
| 125 | + ```bash |
| 126 | + # Using Python |
| 127 | + python -m http.server 8080 |
| 128 | + |
| 129 | + # Or using Node.js |
| 130 | + npx http-server -p 8080 |
| 131 | + ``` |
| 132 | + |
| 133 | +3. **Open in browser** |
| 134 | + ``` |
| 135 | + http://localhost:8080 |
| 136 | + ``` |
| 137 | + |
| 138 | +### Deployment |
| 139 | + |
| 140 | +The repository includes a GitHub Actions workflow that automatically deploys to GitHub Pages on every push to `main`. |
| 141 | + |
| 142 | +#### Setup GitHub Pages |
| 143 | + |
| 144 | +1. Go to **Settings → Pages** |
| 145 | +2. Under "Build and deployment", select **Source: GitHub Actions** |
| 146 | +3. Push to `main` branch to trigger deployment |
| 147 | + |
| 148 | +The site will be available at: |
| 149 | +``` |
| 150 | +https://your-username.github.io/repo-name/ |
| 151 | +``` |
| 152 | + |
| 153 | +## How It Works |
| 154 | + |
| 155 | +### Initialization Flow |
| 156 | + |
| 157 | +1. **URL Parameters Parsed** |
| 158 | + - Client-side ID extracted from `clientSideId` parameter |
| 159 | + - Flag overrides loaded from `ld_override_*` parameters |
| 160 | + |
| 161 | +2. **SDK Initialization** |
| 162 | + - LaunchDarkly client initialized with custom logger |
| 163 | + - Flag override and event interception plugins registered |
| 164 | + - Plugins configured with URL sync capabilities |
| 165 | + |
| 166 | +3. **Override Loading** |
| 167 | + - URL overrides automatically applied on initialization |
| 168 | + - Display updated to show override badges |
| 169 | + |
| 170 | +4. **Real-time Sync** |
| 171 | + - Override changes immediately sync to URL |
| 172 | + - Flag display updates to show/hide badges |
| 173 | + - URL updates without page reload (using `replaceState`) |
| 174 | + |
| 175 | +### Override Synchronization |
| 176 | + |
| 177 | +The plugin monkey-patches three key methods: |
| 178 | + |
| 179 | +- **`setOverride(flagKey, value)`** - Sets override, syncs to URL, updates display |
| 180 | +- **`removeOverride(flagKey)`** - Removes override, syncs to URL, updates display |
| 181 | +- **`clearAllOverrides()`** - Clears all overrides, syncs to URL, refreshes display |
| 182 | + |
| 183 | +All changes are immediately reflected in: |
| 184 | +1. The URL (via `history.replaceState`) |
| 185 | +2. The flag display (badges appear/disappear) |
| 186 | +3. The flag values (updates in real-time) |
| 187 | + |
| 188 | +## Configuration |
| 189 | + |
| 190 | +### Customizing the Parameter Prefix |
| 191 | + |
| 192 | +Edit `app.js` to change the URL parameter prefix: |
| 193 | + |
| 194 | +```javascript |
| 195 | +const flagOverridePlugin = createFlagUrlOverridePlugin({ |
| 196 | + parameterPrefix: 'myapp_flag_', // Use custom prefix |
| 197 | + overrideOptions: {}, |
| 198 | + logger: logger |
| 199 | +}); |
| 200 | +``` |
| 201 | + |
| 202 | +### Custom Logger Options |
| 203 | + |
| 204 | +The logger supports multiple log levels and can be customized: |
| 205 | + |
| 206 | +```javascript |
| 207 | +class CustomLogger { |
| 208 | + debug(...args) { /* ... */ } |
| 209 | + info(...args) { /* ... */ } |
| 210 | + warn(...args) { /* ... */ } |
| 211 | + error(...args) { /* ... */ } |
| 212 | +} |
| 213 | +``` |
| 214 | + |
| 215 | +## Troubleshooting |
| 216 | + |
| 217 | +### SDK Not Initializing |
| 218 | + |
| 219 | +- **Check client-side ID**: Ensure your client-side ID is correct |
| 220 | +- **Check browser console**: Look for error messages |
| 221 | +- **Verify SDK logs**: Check the logs panel for initialization errors |
| 222 | + |
| 223 | +### Overrides Not Working |
| 224 | + |
| 225 | +- **Check toolbar settings**: Ensure the toolbar isn't set to refresh on override changes |
| 226 | +- **Verify plugin registration**: Check that both plugins are passed to the SDK |
| 227 | +- **Check console logs**: Look for `[setOverride]` log messages |
| 228 | + |
| 229 | +### URL Not Updating |
| 230 | + |
| 231 | +- **Check browser compatibility**: Ensure your browser supports `history.replaceState` |
| 232 | +- **Check console logs**: Look for `[syncOverridesToUrl]` messages |
| 233 | +- **Verify no errors**: Check for JavaScript errors in console |
| 234 | + |
| 235 | +## Resources |
| 236 | + |
| 237 | +- [LaunchDarkly Documentation](https://docs.launchdarkly.com/) |
| 238 | +- [Developer Toolbar Guide](https://launchdarkly.com/docs/home/getting-started/dev-toolbar) |
| 239 | +- [Client-Side JavaScript SDK](https://docs.launchdarkly.com/sdk/client-side/javascript) |
| 240 | + |
| 241 | +## License |
| 242 | + |
| 243 | +This project is licensed under the Apache License 2.0 - see the [LICENSE](LICENSE) file for details. |
0 commit comments