{"id":24730943,"url":"https://github.com/alfredoperez/ngx-dev-toolbar","last_synced_at":"2026-04-10T14:05:33.121Z","repository":{"id":270379659,"uuid":"906796519","full_name":"alfredoperez/ngx-dev-toolbar","owner":"alfredoperez","description":"A powerful development toolbar for Angular applications to improve your developer productivity directly in the browser.","archived":false,"fork":false,"pushed_at":"2026-03-08T00:50:33.000Z","size":46114,"stargazers_count":34,"open_issues_count":2,"forks_count":2,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-03-08T00:53:09.966Z","etag":null,"topics":["angular","angular-library","dev-tools","developer-tools","development","frontend","typescript","web-dev","web-development"],"latest_commit_sha":null,"homepage":"https://alfredoperez.github.io/ngx-dev-toolbar/","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/alfredoperez.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2024-12-21T23:37:47.000Z","updated_at":"2026-03-07T23:32:19.000Z","dependencies_parsed_at":"2024-12-30T18:31:07.829Z","dependency_job_id":"30227cd2-4f1b-4dc4-b420-eb9c63f6de37","html_url":"https://github.com/alfredoperez/ngx-dev-toolbar","commit_stats":null,"previous_names":["alfredoperez/ngx-dev-toolbar"],"tags_count":32,"template":false,"template_full_name":null,"purl":"pkg:github/alfredoperez/ngx-dev-toolbar","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alfredoperez%2Fngx-dev-toolbar","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alfredoperez%2Fngx-dev-toolbar/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alfredoperez%2Fngx-dev-toolbar/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alfredoperez%2Fngx-dev-toolbar/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/alfredoperez","download_url":"https://codeload.github.com/alfredoperez/ngx-dev-toolbar/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alfredoperez%2Fngx-dev-toolbar/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30279765,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-08T20:45:49.896Z","status":"ssl_error","status_checked_at":"2026-03-08T20:45:49.525Z","response_time":56,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["angular","angular-library","dev-tools","developer-tools","development","frontend","typescript","web-dev","web-development"],"created_at":"2025-01-27T16:01:32.400Z","updated_at":"2026-03-09T01:01:17.755Z","avatar_url":"https://github.com/alfredoperez.png","language":"TypeScript","funding_links":[],"categories":["Recently Updated","Development Utilities"],"sub_categories":["[Jan 30, 2025](/content/2025/01/30/README.md)","Debugging"],"readme":"# Angular Toolbar\n\n[![npm version](https://badge.fury.io/js/ngx-dev-toolbar.svg)](https://www.npmjs.com/package/ngx-dev-toolbar)\n[![Downloads](https://img.shields.io/npm/dm/ngx-dev-toolbar.svg)](https://www.npmjs.com/package/ngx-dev-toolbar)\n[![License](https://img.shields.io/npm/l/ngx-dev-toolbar.svg)](https://github.com/alfredoperez/ngx-dev-toolbar/blob/main/LICENSE)\n[![Angular](https://img.shields.io/badge/Angular-19%2B-red)](https://angular.io/)\n\nA development toolbar for Angular 19+ applications that helps developers interact with the application more efficiently.\n\n![Toolbar Demo](./docs/images/demo.gif)\n\n## Why ngx-dev-toolbar?\n\n- Toggle feature flags without backend changes\n- Simulate complete i18n environments (locale, timezone, currency, RTL)\n- Test product features and subscription tiers\n- Switch themes on the fly\n- Change user sessions effortlessly\n- Mock network requests in real-time\n- Test permission-based UI without backend changes\n\nNo more context switching or backend dependencies - everything you need is right in your browser!\n\n## Installation\n\n```bash\nnpm install ngx-dev-toolbar\n```\n\n## Quick Start\n\nAdd the toolbar to your `app.config.ts` alongside your other providers:\n\n```typescript\n// app.config.ts\nimport { ApplicationConfig, isDevMode } from '@angular/core';\nimport { provideRouter } from '@angular/router';\nimport { provideToolbar } from 'ngx-dev-toolbar';\n\nexport const appConfig: ApplicationConfig = {\n  providers: [\n    provideRouter(appRoutes),\n    provideToolbar({\n      enabled: isDevMode(),\n    }),\n  ],\n};\n```\n\n```typescript\n// main.ts\nimport { bootstrapApplication } from '@angular/platform-browser';\nimport { AppComponent } from './app/app.component';\nimport { appConfig } from './app/app.config';\n\nbootstrapApplication(AppComponent, appConfig);\n```\n\nThat's it! No template changes needed. The toolbar automatically attaches to the DOM.\n\n## Available Tools\n\n| Tool | Description |\n|------|-------------|\n| Feature Flags | Toggle feature flags on/off during development |\n| Permissions | Test permission-based UI without backend changes |\n| App Features | Test product features and subscription tiers |\n| i18n | Advanced i18n simulation — locale, timezone, currency, pseudo-localization, RTL |\n| Presets | Save and restore tool configurations |\n| Network Mocker | Mock HTTP requests in real-time |\n\n## Feature Flags\n\n```typescript\nimport { ToolbarFeatureFlagService } from 'ngx-dev-toolbar';\n\n@Component({...})\nexport class AppComponent {\n  private featureFlagsService = inject(ToolbarFeatureFlagService);\n\n  constructor() {\n    this.featureFlagsService.setAvailableOptions([\n      { id: 'darkMode', name: 'Dark Mode', isEnabled: false },\n      { id: 'betaFeatures', name: 'Beta Features', isEnabled: true },\n    ]);\n  }\n}\n```\n\nSubscribe to forced values:\n\n```typescript\nthis.featureFlagsService.getForcedValues().subscribe((flags) =\u003e {\n  // Apply forced flag states\n});\n```\n\n## Permissions\n\n```typescript\nimport { ToolbarPermissionsService } from 'ngx-dev-toolbar';\n\n@Component({...})\nexport class AppComponent {\n  private permissionsService = inject(ToolbarPermissionsService);\n\n  constructor() {\n    this.permissionsService.setAvailableOptions([\n      { id: 'can-edit', name: 'Can Edit', isGranted: false },\n      { id: 'is-admin', name: 'Admin Access', isGranted: false },\n    ]);\n  }\n}\n```\n\n## App Features\n\nTest product-level feature availability like license tiers and subscription features:\n\n```typescript\nimport { ToolbarAppFeaturesService } from 'ngx-dev-toolbar';\n\n@Component({...})\nexport class AppComponent {\n  private appFeaturesService = inject(ToolbarAppFeaturesService);\n\n  constructor() {\n    this.appFeaturesService.setAvailableOptions([\n      { id: 'analytics', name: 'Advanced Analytics', isEnabled: false },\n      { id: 'multi-user', name: 'Multi-User Support', isEnabled: true },\n    ]);\n  }\n}\n```\n\n## i18n\n\nSimulate complete internationalization environments — locale, timezone, currency, unit system, pseudo-localization, and RTL:\n\n```typescript\nimport { ToolbarI18nService } from 'ngx-dev-toolbar';\n\n@Component({...})\nexport class AppComponent {\n  private i18nService = inject(ToolbarI18nService);\n\n  constructor() {\n    // Set available locales\n    this.i18nService.setAvailableOptions([\n      { code: 'en', name: 'English' },\n      { code: 'es', name: 'Spanish' },\n      { code: 'ar', name: 'Arabic' },\n    ]);\n\n    // React to locale changes\n    this.i18nService.getForcedValues().subscribe((locales) =\u003e {\n      // Apply forced locale\n    });\n\n    // React to timezone, currency, and other i18n settings\n    this.i18nService.getForcedTimezone().subscribe((tz) =\u003e { /* e.g. 'Asia/Tokyo' */ });\n    this.i18nService.getForcedCurrency().subscribe((cur) =\u003e { /* e.g. 'JPY' */ });\n  }\n}\n```\n\nThe i18n tool also supports pseudo-localization for spotting hardcoded strings and RTL simulation for layout testing. See the [full docs](https://alfredoperez.github.io/ngx-dev-toolbar/ngx-dev-toolbar/i18n) for the complete API reference.\n\n## Creating Custom Tools\n\nBuild your own toolbar tools using the exported UI components. Here's a complete Notes tool:\n\n```typescript\nimport { ChangeDetectionStrategy, Component, inject, signal } from '@angular/core';\nimport { Injectable } from '@angular/core';\nimport {\n  ToolbarToolComponent,\n  ToolbarWindowOptions,\n  ToolbarButtonComponent,\n  ToolbarInputComponent,\n  ToolbarListComponent,\n  ToolbarListItemComponent,\n  ToolbarStepViewComponent,\n  ToolbarStepDirective,\n} from 'ngx-dev-toolbar';\n\n// 1. Define your model\ninterface Note {\n  id: string;\n  title: string;\n  content: string;\n}\n\n// 2. Create a service with signal-based state\n@Injectable({ providedIn: 'root' })\nclass NotesService {\n  private readonly _notes = signal\u003cNote[]\u003e([]);\n  readonly notes = this._notes.asReadonly();\n\n  add(title: string, content: string): void {\n    this._notes.update(notes =\u003e [\n      ...notes,\n      { id: crypto.randomUUID(), title, content },\n    ]);\n  }\n\n  remove(id: string): void {\n    this._notes.update(notes =\u003e notes.filter(n =\u003e n.id !== id));\n  }\n}\n\n// 3. Build the component\n@Component({\n  selector: 'app-notes-tool',\n  standalone: true,\n  imports: [\n    ToolbarToolComponent,\n    ToolbarButtonComponent,\n    ToolbarInputComponent,\n    ToolbarListComponent,\n    ToolbarListItemComponent,\n    ToolbarStepViewComponent,\n    ToolbarStepDirective,\n  ],\n  template: `\n    \u003cndt-toolbar-tool [options]=\"windowOptions\" title=\"Notes\" icon=\"edit\"\u003e\n      \u003cndt-step-view\n        [currentStep]=\"viewMode()\"\n        defaultStep=\"list\"\n        (back)=\"viewMode.set('list')\"\n      \u003e\n        \u003c!-- List view --\u003e\n        \u003cng-template ngtStep=\"list\"\u003e\n          \u003cndt-button (click)=\"viewMode.set('create')\" icon=\"edit\"\u003e\n            Add Note\n          \u003c/ndt-button\u003e\n          \u003cndt-list\n            [hasItems]=\"notesService.notes().length \u003e 0\"\n            emptyMessage=\"No notes yet\"\n            emptyHint=\"Click 'Add Note' to create one\"\n          \u003e\n            @for (note of notesService.notes(); track note.id) {\n              \u003cndt-list-item [label]=\"note.title\"\u003e\n                \u003cndt-button\n                  variant=\"icon\"\n                  icon=\"trash\"\n                  ariaLabel=\"Delete\"\n                  (click)=\"notesService.remove(note.id)\"\n                /\u003e\n              \u003c/ndt-list-item\u003e\n            }\n          \u003c/ndt-list\u003e\n        \u003c/ng-template\u003e\n\n        \u003c!-- Create view --\u003e\n        \u003cng-template ngtStep=\"create\" stepTitle=\"New Note\"\u003e\n          \u003cndt-input [(value)]=\"newTitle\" placeholder=\"Title\" ariaLabel=\"Note title\" /\u003e\n          \u003cndt-input [(value)]=\"newContent\" placeholder=\"Content\" ariaLabel=\"Note content\" /\u003e\n          \u003cndt-button (click)=\"onCreate()\" label=\"Save\" /\u003e\n        \u003c/ng-template\u003e\n      \u003c/ndt-step-view\u003e\n    \u003c/ndt-toolbar-tool\u003e\n  `,\n  changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class NotesToolComponent {\n  protected readonly notesService = inject(NotesService);\n\n  viewMode = signal\u003c'list' | 'create'\u003e('list');\n  newTitle = signal('');\n  newContent = signal('');\n\n  readonly windowOptions: ToolbarWindowOptions = {\n    id: 'notes',\n    title: 'Notes',\n    description: 'Quick development notes',\n    size: 'medium',\n  };\n\n  onCreate(): void {\n    if (this.newTitle()) {\n      this.notesService.add(this.newTitle(), this.newContent());\n      this.newTitle.set('');\n      this.newContent.set('');\n      this.viewMode.set('list');\n    }\n  }\n}\n```\n\n### Exported UI Components\n\n| Component | Selector | Purpose |\n|-----------|----------|---------|\n| `ToolbarToolComponent` | `ndt-toolbar-tool` | Window wrapper with positioning and animations |\n| `ToolbarButtonComponent` | `ndt-button` | Buttons with optional icon |\n| `ToolbarInputComponent` | `ndt-input` | Text inputs with two-way binding |\n| `ToolbarSelectComponent` | `ndt-select` | Dropdown selection |\n| `ToolbarListComponent` | `ndt-list` | List with empty/no-results states |\n| `ToolbarListItemComponent` | `ndt-list-item` | List items with optional badge |\n| `ToolbarCardComponent` | `ndt-card` | Content container |\n| `ToolbarClickableCardComponent` | `ndt-clickable-card` | Interactive card with icon |\n| `ToolbarStepViewComponent` | `ndt-step-view` | Multi-step view switcher |\n| `ToolbarIconComponent` | `ndt-icon` | 30+ SVG icons |\n| `ToolbarLinkButtonComponent` | `ndt-link-button` | External link button |\n\nFor a complete guide, see: [Create a Custom Tool](https://alfredoperez.github.io/ngx-dev-toolbar/docs/guides/custom-tool)\n\n## Configuration\n\nConfigure which tools are visible:\n\n```typescript\nprovideToolbar({\n  enabled: isDevMode(),\n  showI18nTool: true,\n  showFeatureFlagsTool: true,\n  showAppFeaturesTool: true,\n  showPermissionsTool: true,\n  showPresetsTool: true,\n})\n```\n\n## Keyboard Shortcuts\n\n- **Ctrl+Shift+D**: Toggle toolbar visibility\n\n## Features\n\n- **Zero Bundle Impact**: Dynamic imports exclude toolbar from production builds\n- **Persistent State**: Settings persist across page reloads\n- **No Template Changes**: Toolbar attaches automatically to the DOM\n- **Extensible**: Create custom tools to fit your workflow\n\n## Documentation\n\nFor full documentation, visit: [https://alfredoperez.github.io/ngx-dev-toolbar/](https://alfredoperez.github.io/ngx-dev-toolbar/)\n\n## Contributing\n\nWe welcome contributions! Please see our [contributing guidelines](https://github.com/alfredoperez/ngx-dev-toolbar/blob/main/CONTRIBUTING.md) for details.\n\n## Support\n\n- [Documentation](https://alfredoperez.github.io/ngx-dev-toolbar/)\n- [Issue Tracker](https://github.com/alfredoperez/ngx-dev-toolbar/issues)\n- [Discussions](https://github.com/alfredoperez/ngx-dev-toolbar/discussions)\n\n## License\n\nThis project is licensed under the MIT License - see the [LICENSE](https://github.com/alfredoperez/ngx-dev-toolbar/blob/main/LICENSE) file for details.\n\n---\n\n[![LinkedIn](https://img.shields.io/badge/LinkedIn-Connect-blue)](https://www.linkedin.com/in/alfredo-perez/)\n[![Bluesky](https://img.shields.io/badge/Bluesky-Follow-1DA1F2)](https://bsky.app/profile/alfredo-perez.bsky.social)\n[![GitHub Stars](https://img.shields.io/github/stars/alfredoperez/ngx-dev-toolbar?style=social)](https://github.com/alfredoperez/ngx-dev-toolbar)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Falfredoperez%2Fngx-dev-toolbar","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Falfredoperez%2Fngx-dev-toolbar","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Falfredoperez%2Fngx-dev-toolbar/lists"}