[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M71BXTPAH8TWJ69V6KJ0RJS2":3,"skill-same:01M71BXTPAH8TWJ69V6KJ0RJS2":80},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":16,"sourceHtmlUrl":17,"categories":18,"keywords":19,"publishedAt":40,"linkOnly":41,"markdownContent":42,"markdownBody":43,"frontMatter":44,"refName":50,"commitSha":51,"skillDirectory":5,"forksCount":14,"repositoryHtmlUrl":52,"repositoryHomepageUrl":6,"ownerHtmlUrl":53,"ownerBlogUrl":54,"ownerDescription":55,"updatedAt":56,"install":57,"resources":70},"01M71BXTPAH8TWJ69V6KJ0RJS2","angular-routing",null,"Implement routing in Angular v20+ applications with lazy loading, functional guards, resolvers, and route parameters. Use for navigation setup, protected routes, route-based data loading, and nested routing. Triggers on route configuration, adding authentication guards, implementing lazy loading, or reading route parameters with signals.","agency-black\u002FSkills","agency-black","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F234862658?v=4","01M6HWVFPNGNR5N2CX9ECSAD57","agencia.black","01M719WF77BF3HN0N9FK1APEFY",0,"MIT","https:\u002F\u002Fgithub.com\u002Fagency-black\u002FSkills\u002Fblob\u002Fmain\u002Fangular-routing\u002FLICENSE","https:\u002F\u002Fgithub.com\u002Fagency-black\u002FSkills\u002Fblob\u002Fmain\u002Fangular-routing\u002FSKILL.md",[],[20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39],"angular routing","routing","angular","functional","nested","route","with","implement","use","guards","triggers","license","implementing","applications","authentication","loading","for","development","lazy","resolvers","2026-11-10 10:12:30",false,"---\nname: angular-routing\ndescription: >-\n  Implement routing in Angular v20+ applications with lazy loading, functional\n  guards, resolvers, and route parameters. Use for navigation setup, protected\n  routes, route-based data loading, and nested routing. Triggers on route\n  configuration, adding authentication guards, implementing lazy loading, or\n  reading route parameters with signals.\nmetadata:\n  category: development\n  source:\n    repository: 'https:\u002F\u002Fgithub.com\u002Fanalogjs\u002Fangular-skills'\n    path: skills\u002Fangular-routing\n    license_path: LICENSE\n---\n\n# Angular Routing\n\nConfigure routing in Angular v20+ with lazy loading, functional guards, and signal-based route parameters.\n\n## Basic Setup\n\n```typescript\n\u002F\u002F app.routes.ts\nimport { Routes } from '@angular\u002Frouter';\n\nexport const routes: Routes = [\n  { path: '', redirectTo: '\u002Fhome', pathMatch: 'full' },\n  { path: 'home', component: Home },\n  { path: 'about', component: About },\n  { path: '**', component: NotFound },\n];\n\n\u002F\u002F app.config.ts\nimport { ApplicationConfig } from '@angular\u002Fcore';\nimport { provideRouter } from '@angular\u002Frouter';\nimport { routes } from '.\u002Fapp.routes';\n\nexport const appConfig: ApplicationConfig = {\n  providers: [\n    provideRouter(routes),\n  ],\n};\n\n\u002F\u002F app.component.ts\nimport { Component } from '@angular\u002Fcore';\nimport { RouterOutlet, RouterLink, RouterLinkActive } from '@angular\u002Frouter';\n\n@Component({\n  selector: 'app-root',\n  imports: [RouterOutlet, RouterLink, RouterLinkActive],\n  template: `\n    \u003Cnav>\n      \u003Ca routerLink=\"\u002Fhome\" routerLinkActive=\"active\">Home\u003C\u002Fa>\n      \u003Ca routerLink=\"\u002Fabout\" routerLinkActive=\"active\">About\u003C\u002Fa>\n    \u003C\u002Fnav>\n    \u003Crouter-outlet \u002F>\n  `,\n})\nexport class App {}\n```\n\n## Lazy Loading\n\nLoad feature modules on demand:\n\n```typescript\n\u002F\u002F app.routes.ts\nexport const routes: Routes = [\n  { path: '', redirectTo: '\u002Fhome', pathMatch: 'full' },\n  { path: 'home', component: Home },\n  \n  \u002F\u002F Lazy load entire feature\n  {\n    path: 'admin',\n    loadChildren: () => import('.\u002Fadmin\u002Fadmin.routes').then(m => m.adminRoutes),\n  },\n  \n  \u002F\u002F Lazy load single component\n  {\n    path: 'settings',\n    loadComponent: () => import('.\u002Fsettings\u002Fsettings.component').then(m => m.Settings),\n  },\n];\n\n\u002F\u002F admin\u002Fadmin.routes.ts\nexport const adminRoutes: Routes = [\n  { path: '', component: AdminDashboard },\n  { path: 'users', component: AdminUsers },\n  { path: 'settings', component: AdminSettings },\n];\n```\n\n## Route Parameters\n\n### With Signal Inputs (Recommended)\n\n```typescript\n\u002F\u002F Route config\n{ path: 'users\u002F:id', component: UserDetail }\n\n\u002F\u002F Component - use input() for route params\nimport { Component, input, computed } from '@angular\u002Fcore';\n\n@Component({\n  selector: 'app-user-detail',\n  template: `\n    \u003Ch1>User {{ id() }}\u003C\u002Fh1>\n  `,\n})\nexport class UserDetail {\n  \u002F\u002F Route param as signal input\n  id = input.required\u003Cstring>();\n  \n  \u002F\u002F Computed based on route param\n  userId = computed(() => parseInt(this.id(), 10));\n}\n```\n\nEnable with `withComponentInputBinding()`:\n\n```typescript\n\u002F\u002F app.config.ts\nimport { provideRouter, withComponentInputBinding } from '@angular\u002Frouter';\n\nexport const appConfig: ApplicationConfig = {\n  providers: [\n    provideRouter(routes, withComponentInputBinding()),\n  ],\n};\n```\n\n### Query Parameters\n\n```typescript\n\u002F\u002F Route: \u002Fsearch?q=angular&page=1\n\n@Component({...})\nexport class Search {\n  \u002F\u002F Query params as inputs\n  q = input\u003Cstring>('');\n  page = input\u003Cstring>('1');\n  \n  currentPage = computed(() => parseInt(this.page(), 10));\n}\n```\n\n### With ActivatedRoute (Alternative)\n\n```typescript\nimport { Component, inject } from '@angular\u002Fcore';\nimport { ActivatedRoute } from '@angular\u002Frouter';\nimport { toSignal } from '@angular\u002Fcore\u002Frxjs-interop';\nimport { map } from 'rxjs';\n\n@Component({...})\nexport class UserDetail {\n  private route = inject(ActivatedRoute);\n  \n  \u002F\u002F Convert route params to signal\n  id = toSignal(\n    this.route.paramMap.pipe(map(params => params.get('id'))),\n    { initialValue: null }\n  );\n  \n  \u002F\u002F Query params\n  query = toSignal(\n    this.route.queryParamMap.pipe(map(params => params.get('q'))),\n    { initialValue: '' }\n  );\n}\n```\n\n## Functional Guards\n\n### Auth Guard\n\n```typescript\n\u002F\u002F guards\u002Fauth.guard.ts\nimport { inject } from '@angular\u002Fcore';\nimport { CanActivateFn, Router } from '@angular\u002Frouter';\n\nexport const authGuard: CanActivateFn = (route, state) => {\n  const authService = inject(Auth);\n  const router = inject(Router);\n  \n  if (authService.isAuthenticated()) {\n    return true;\n  }\n  \n  \u002F\u002F Redirect to login with return URL\n  return router.createUrlTree(['\u002Flogin'], {\n    queryParams: { returnUrl: state.url },\n  });\n};\n\n\u002F\u002F Usage in routes\n{\n  path: 'dashboard',\n  component: Dashboard,\n  canActivate: [authGuard],\n}\n```\n\n### Role Guard\n\n```typescript\nexport const roleGuard = (allowedRoles: string[]): CanActivateFn => {\n  return (route, state) => {\n    const authService = inject(Auth);\n    const router = inject(Router);\n    \n    const userRole = authService.currentUser()?.role;\n    \n    if (userRole && allowedRoles.includes(userRole)) {\n      return true;\n    }\n    \n    return router.createUrlTree(['\u002Funauthorized']);\n  };\n};\n\n\u002F\u002F Usage\n{\n  path: 'admin',\n  component: Admin,\n  canActivate: [authGuard, roleGuard(['admin', 'superadmin'])],\n}\n```\n\n### Can Deactivate Guard\n\n```typescript\nexport interface CanDeactivate {\n  canDeactivate: () => boolean | Promise\u003Cboolean>;\n}\n\nexport const unsavedChangesGuard: CanDeactivateFn\u003CCanDeactivate> = (component) => {\n  if (component.canDeactivate()) {\n    return true;\n  }\n  \n  return confirm('You have unsaved changes. Leave anyway?');\n};\n\n\u002F\u002F Component implementation\n@Component({...})\nexport class Edit implements CanDeactivate {\n  form = inject(FormBuilder).group({...});\n  \n  canDeactivate(): boolean {\n    return !this.form.dirty;\n  }\n}\n\n\u002F\u002F Route\n{\n  path: 'edit\u002F:id',\n  component: Edit,\n  canDeactivate: [unsavedChangesGuard],\n}\n```\n\n## Resolvers\n\nPre-fetch data before route activation:\n\n```typescript\n\u002F\u002F resolvers\u002Fuser.resolver.ts\nimport { inject } from '@angular\u002Fcore';\nimport { ResolveFn } from '@angular\u002Frouter';\n\nexport const userResolver: ResolveFn\u003CUser> = (route) => {\n  const userService = inject(User);\n  const id = route.paramMap.get('id')!;\n  return userService.getById(id);\n};\n\n\u002F\u002F Route config\n{\n  path: 'users\u002F:id',\n  component: UserDetail,\n  resolve: { user: userResolver },\n}\n\n\u002F\u002F Component - access resolved data via input\n@Component({...})\nexport class UserDetail {\n  user = input.required\u003CUser>();\n}\n```\n\n## Nested Routes\n\n```typescript\n\u002F\u002F Parent route with children\nexport const routes: Routes = [\n  {\n    path: 'products',\n    component: ProductsLayout,\n    children: [\n      { path: '', component: ProductList },\n      { path: ':id', component: ProductDetail },\n      { path: ':id\u002Fedit', component: ProductEdit },\n    ],\n  },\n];\n\n\u002F\u002F ProductsLayout\n@Component({\n  imports: [RouterOutlet],\n  template: `\n    \u003Ch1>Products\u003C\u002Fh1>\n    \u003Crouter-outlet \u002F> \u003C!-- Child routes render here -->\n  `,\n})\nexport class ProductsLayout {}\n```\n\n## Programmatic Navigation\n\n```typescript\nimport { Component, inject } from '@angular\u002Fcore';\nimport { Router } from '@angular\u002Frouter';\n\n@Component({...})\nexport class Product {\n  private router = inject(Router);\n  \n  \u002F\u002F Navigate to route\n  goToProducts() {\n    this.router.navigate(['\u002Fproducts']);\n  }\n  \n  \u002F\u002F Navigate with params\n  goToProduct(id: string) {\n    this.router.navigate(['\u002Fproducts', id]);\n  }\n  \n  \u002F\u002F Navigate with query params\n  search(query: string) {\n    this.router.navigate(['\u002Fsearch'], {\n      queryParams: { q: query, page: 1 },\n    });\n  }\n  \n  \u002F\u002F Navigate relative to current route\n  goToEdit() {\n    this.router.navigate(['edit'], { relativeTo: this.route });\n  }\n  \n  \u002F\u002F Replace current history entry\n  replaceUrl() {\n    this.router.navigate(['\u002Fnew-page'], { replaceUrl: true });\n  }\n}\n```\n\n## Route Data\n\n```typescript\n\u002F\u002F Static route data\n{\n  path: 'admin',\n  component: Admin,\n  data: {\n    title: 'Admin Dashboard',\n    roles: ['admin'],\n  },\n}\n\n\u002F\u002F Access in component\n@Component({...})\nexport class AdminCmpt {\n  title = input\u003Cstring>(); \u002F\u002F From route data\n  roles = input\u003Cstring[]>(); \u002F\u002F From route data\n}\n\n\u002F\u002F Or via ActivatedRoute\nprivate route = inject(ActivatedRoute);\ndata = toSignal(this.route.data);\n```\n\n## Router Events\n\n```typescript\nimport { Router, NavigationStart, NavigationEnd } from '@angular\u002Frouter';\nimport { filter } from 'rxjs';\n\n@Component({...})\nexport class AppMain {\n  private router = inject(Router);\n  \n  isNavigating = signal(false);\n  \n  constructor() {\n    this.router.events.pipe(\n      filter(e => e instanceof NavigationStart || e instanceof NavigationEnd)\n    ).subscribe(event => {\n      this.isNavigating.set(event instanceof NavigationStart);\n    });\n  }\n}\n```\n\nFor advanced patterns, see [references\u002Frouting-patterns.md](references\u002Frouting-patterns.md).\n","# Angular Routing\n\nConfigure routing in Angular v20+ with lazy loading, functional guards, and signal-based route parameters.\n\n## Basic Setup\n\n```typescript\n\u002F\u002F app.routes.ts\nimport { Routes } from '@angular\u002Frouter';\n\nexport const routes: Routes = [\n  { path: '', redirectTo: '\u002Fhome', pathMatch: 'full' },\n  { path: 'home', component: Home },\n  { path: 'about', component: About },\n  { path: '**', component: NotFound },\n];\n\n\u002F\u002F app.config.ts\nimport { ApplicationConfig } from '@angular\u002Fcore';\nimport { provideRouter } from '@angular\u002Frouter';\nimport { routes } from '.\u002Fapp.routes';\n\nexport const appConfig: ApplicationConfig = {\n  providers: [\n    provideRouter(routes),\n  ],\n};\n\n\u002F\u002F app.component.ts\nimport { Component } from '@angular\u002Fcore';\nimport { RouterOutlet, RouterLink, RouterLinkActive } from '@angular\u002Frouter';\n\n@Component({\n  selector: 'app-root',\n  imports: [RouterOutlet, RouterLink, RouterLinkActive],\n  template: `\n    \u003Cnav>\n      \u003Ca routerLink=\"\u002Fhome\" routerLinkActive=\"active\">Home\u003C\u002Fa>\n      \u003Ca routerLink=\"\u002Fabout\" routerLinkActive=\"active\">About\u003C\u002Fa>\n    \u003C\u002Fnav>\n    \u003Crouter-outlet \u002F>\n  `,\n})\nexport class App {}\n```\n\n## Lazy Loading\n\nLoad feature modules on demand:\n\n```typescript\n\u002F\u002F app.routes.ts\nexport const routes: Routes = [\n  { path: '', redirectTo: '\u002Fhome', pathMatch: 'full' },\n  { path: 'home', component: Home },\n  \n  \u002F\u002F Lazy load entire feature\n  {\n    path: 'admin',\n    loadChildren: () => import('.\u002Fadmin\u002Fadmin.routes').then(m => m.adminRoutes),\n  },\n  \n  \u002F\u002F Lazy load single component\n  {\n    path: 'settings',\n    loadComponent: () => import('.\u002Fsettings\u002Fsettings.component').then(m => m.Settings),\n  },\n];\n\n\u002F\u002F admin\u002Fadmin.routes.ts\nexport const adminRoutes: Routes = [\n  { path: '', component: AdminDashboard },\n  { path: 'users', component: AdminUsers },\n  { path: 'settings', component: AdminSettings },\n];\n```\n\n## Route Parameters\n\n### With Signal Inputs (Recommended)\n\n```typescript\n\u002F\u002F Route config\n{ path: 'users\u002F:id', component: UserDetail }\n\n\u002F\u002F Component - use input() for route params\nimport { Component, input, computed } from '@angular\u002Fcore';\n\n@Component({\n  selector: 'app-user-detail',\n  template: `\n    \u003Ch1>User {{ id() }}\u003C\u002Fh1>\n  `,\n})\nexport class UserDetail {\n  \u002F\u002F Route param as signal input\n  id = input.required\u003Cstring>();\n  \n  \u002F\u002F Computed based on route param\n  userId = computed(() => parseInt(this.id(), 10));\n}\n```\n\nEnable with `withComponentInputBinding()`:\n\n```typescript\n\u002F\u002F app.config.ts\nimport { provideRouter, withComponentInputBinding } from '@angular\u002Frouter';\n\nexport const appConfig: ApplicationConfig = {\n  providers: [\n    provideRouter(routes, withComponentInputBinding()),\n  ],\n};\n```\n\n### Query Parameters\n\n```typescript\n\u002F\u002F Route: \u002Fsearch?q=angular&page=1\n\n@Component({...})\nexport class Search {\n  \u002F\u002F Query params as inputs\n  q = input\u003Cstring>('');\n  page = input\u003Cstring>('1');\n  \n  currentPage = computed(() => parseInt(this.page(), 10));\n}\n```\n\n### With ActivatedRoute (Alternative)\n\n```typescript\nimport { Component, inject } from '@angular\u002Fcore';\nimport { ActivatedRoute } from '@angular\u002Frouter';\nimport { toSignal } from '@angular\u002Fcore\u002Frxjs-interop';\nimport { map } from 'rxjs';\n\n@Component({...})\nexport class UserDetail {\n  private route = inject(ActivatedRoute);\n  \n  \u002F\u002F Convert route params to signal\n  id = toSignal(\n    this.route.paramMap.pipe(map(params => params.get('id'))),\n    { initialValue: null }\n  );\n  \n  \u002F\u002F Query params\n  query = toSignal(\n    this.route.queryParamMap.pipe(map(params => params.get('q'))),\n    { initialValue: '' }\n  );\n}\n```\n\n## Functional Guards\n\n### Auth Guard\n\n```typescript\n\u002F\u002F guards\u002Fauth.guard.ts\nimport { inject } from '@angular\u002Fcore';\nimport { CanActivateFn, Router } from '@angular\u002Frouter';\n\nexport const authGuard: CanActivateFn = (route, state) => {\n  const authService = inject(Auth);\n  const router = inject(Router);\n  \n  if (authService.isAuthenticated()) {\n    return true;\n  }\n  \n  \u002F\u002F Redirect to login with return URL\n  return router.createUrlTree(['\u002Flogin'], {\n    queryParams: { returnUrl: state.url },\n  });\n};\n\n\u002F\u002F Usage in routes\n{\n  path: 'dashboard',\n  component: Dashboard,\n  canActivate: [authGuard],\n}\n```\n\n### Role Guard\n\n```typescript\nexport const roleGuard = (allowedRoles: string[]): CanActivateFn => {\n  return (route, state) => {\n    const authService = inject(Auth);\n    const router = inject(Router);\n    \n    const userRole = authService.currentUser()?.role;\n    \n    if (userRole && allowedRoles.includes(userRole)) {\n      return true;\n    }\n    \n    return router.createUrlTree(['\u002Funauthorized']);\n  };\n};\n\n\u002F\u002F Usage\n{\n  path: 'admin',\n  component: Admin,\n  canActivate: [authGuard, roleGuard(['admin', 'superadmin'])],\n}\n```\n\n### Can Deactivate Guard\n\n```typescript\nexport interface CanDeactivate {\n  canDeactivate: () => boolean | Promise\u003Cboolean>;\n}\n\nexport const unsavedChangesGuard: CanDeactivateFn\u003CCanDeactivate> = (component) => {\n  if (component.canDeactivate()) {\n    return true;\n  }\n  \n  return confirm('You have unsaved changes. Leave anyway?');\n};\n\n\u002F\u002F Component implementation\n@Component({...})\nexport class Edit implements CanDeactivate {\n  form = inject(FormBuilder).group({...});\n  \n  canDeactivate(): boolean {\n    return !this.form.dirty;\n  }\n}\n\n\u002F\u002F Route\n{\n  path: 'edit\u002F:id',\n  component: Edit,\n  canDeactivate: [unsavedChangesGuard],\n}\n```\n\n## Resolvers\n\nPre-fetch data before route activation:\n\n```typescript\n\u002F\u002F resolvers\u002Fuser.resolver.ts\nimport { inject } from '@angular\u002Fcore';\nimport { ResolveFn } from '@angular\u002Frouter';\n\nexport const userResolver: ResolveFn\u003CUser> = (route) => {\n  const userService = inject(User);\n  const id = route.paramMap.get('id')!;\n  return userService.getById(id);\n};\n\n\u002F\u002F Route config\n{\n  path: 'users\u002F:id',\n  component: UserDetail,\n  resolve: { user: userResolver },\n}\n\n\u002F\u002F Component - access resolved data via input\n@Component({...})\nexport class UserDetail {\n  user = input.required\u003CUser>();\n}\n```\n\n## Nested Routes\n\n```typescript\n\u002F\u002F Parent route with children\nexport const routes: Routes = [\n  {\n    path: 'products',\n    component: ProductsLayout,\n    children: [\n      { path: '', component: ProductList },\n      { path: ':id', component: ProductDetail },\n      { path: ':id\u002Fedit', component: ProductEdit },\n    ],\n  },\n];\n\n\u002F\u002F ProductsLayout\n@Component({\n  imports: [RouterOutlet],\n  template: `\n    \u003Ch1>Products\u003C\u002Fh1>\n    \u003Crouter-outlet \u002F> \u003C!-- Child routes render here -->\n  `,\n})\nexport class ProductsLayout {}\n```\n\n## Programmatic Navigation\n\n```typescript\nimport { Component, inject } from '@angular\u002Fcore';\nimport { Router } from '@angular\u002Frouter';\n\n@Component({...})\nexport class Product {\n  private router = inject(Router);\n  \n  \u002F\u002F Navigate to route\n  goToProducts() {\n    this.router.navigate(['\u002Fproducts']);\n  }\n  \n  \u002F\u002F Navigate with params\n  goToProduct(id: string) {\n    this.router.navigate(['\u002Fproducts', id]);\n  }\n  \n  \u002F\u002F Navigate with query params\n  search(query: string) {\n    this.router.navigate(['\u002Fsearch'], {\n      queryParams: { q: query, page: 1 },\n    });\n  }\n  \n  \u002F\u002F Navigate relative to current route\n  goToEdit() {\n    this.router.navigate(['edit'], { relativeTo: this.route });\n  }\n  \n  \u002F\u002F Replace current history entry\n  replaceUrl() {\n    this.router.navigate(['\u002Fnew-page'], { replaceUrl: true });\n  }\n}\n```\n\n## Route Data\n\n```typescript\n\u002F\u002F Static route data\n{\n  path: 'admin',\n  component: Admin,\n  data: {\n    title: 'Admin Dashboard',\n    roles: ['admin'],\n  },\n}\n\n\u002F\u002F Access in component\n@Component({...})\nexport class AdminCmpt {\n  title = input\u003Cstring>(); \u002F\u002F From route data\n  roles = input\u003Cstring[]>(); \u002F\u002F From route data\n}\n\n\u002F\u002F Or via ActivatedRoute\nprivate route = inject(ActivatedRoute);\ndata = toSignal(this.route.data);\n```\n\n## Router Events\n\n```typescript\nimport { Router, NavigationStart, NavigationEnd } from '@angular\u002Frouter';\nimport { filter } from 'rxjs';\n\n@Component({...})\nexport class AppMain {\n  private router = inject(Router);\n  \n  isNavigating = signal(false);\n  \n  constructor() {\n    this.router.events.pipe(\n      filter(e => e instanceof NavigationStart || e instanceof NavigationEnd)\n    ).subscribe(event => {\n      this.isNavigating.set(event instanceof NavigationStart);\n    });\n  }\n}\n```\n\nFor advanced patterns, see [references\u002Frouting-patterns.md](references\u002Frouting-patterns.md).\n",{"name":5,"metadata":45,"description":7},{"source":46,"category":37},{"path":47,"repository":48,"license_path":49},"skills\u002Fangular-routing","https:\u002F\u002Fgithub.com\u002Fanalogjs\u002Fangular-skills","LICENSE","main","681496e0662f4c45c4758fae9d4510ae87311bf2","https:\u002F\u002Fgithub.com\u002Fagency-black\u002FSkills","https:\u002F\u002Fgithub.com\u002Fagency-black","http:\u002F\u002Fwww.dogma.black","Las grandes ideas merecen una ejecución impecable. Construimos plataformas web, aplicaciones y ecosistemas digitales completos. Esta Trinidad es nuestro dogma.","2026-05-29 16:13:55",{"source":8,"skillName":5,"commands":58,"prompt":68,"zipAvailable":69},[59,62,65],{"tool":60,"command":61},"npx","npx skills add agency-black\u002FSkills --skill angular-routing",{"tool":63,"command":64},"bunx","bunx skills add agency-black\u002FSkills --skill angular-routing",{"tool":66,"command":67},"pnpm","pnpm dlx skills add agency-black\u002FSkills --skill angular-routing","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002Fagency-black\u002FSkills\u002Fblob\u002Fmain\u002Fangular-routing\u002FSKILL.md",true,[71,74],{"path":49,"resourceType":49,"resourceTypeDesc":72,"sizeBytes":73,"sourceHtmlUrl":16},"许可证",1072,{"path":75,"resourceType":76,"resourceTypeDesc":77,"sizeBytes":78,"sourceHtmlUrl":79},"references\u002Frouting-patterns.md","REFERENCE","参考文档",10527,"https:\u002F\u002Fgithub.com\u002Fagency-black\u002FSkills\u002Fblob\u002Fmain\u002Fangular-routing\u002Freferences\u002Frouting-patterns.md",[81,106,136,165,189,212],{"skillNo":82,"name":83,"nameZh":6,"description":84,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":85,"categories":86,"keywords":87,"publishedAt":40},"01M71JZVZ0TVW7Z5DQBRWSBG8A","zarr-python","Chunked N-D arrays for cloud storage (Zarr-Python 3). Compressed arrays, parallel I\u002FO, S3\u002FGCS via fsspec, NumPy\u002FDask\u002FXarray compatible, for large-scale scientific computing pipelines.","https:\u002F\u002Fgithub.com\u002Fagency-black\u002FSkills\u002Fblob\u002Fmain\u002Fzarr-python\u002FSKILL.md",[],[88,89,90,91,92,93,94,95,96,97,98,99,100,36,101,28,102,103,104,105],"zarr python","python","zarr","arrays","Cloud Storage","remote","workflows","scientific","read","write","edit","parallel","dask","s3fs","numpy","s3","scientific computing","scale",{"skillNo":107,"name":108,"nameZh":6,"description":109,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":110,"sourceHtmlUrl":111,"categories":112,"keywords":118,"publishedAt":40},"01M71JYXC5VAEJT8KXN5GRK32S","xvary-stock-research","Thesis-driven equity analysis from public SEC EDGAR and market data; \u002Fanalyze, \u002Fscore, \u002Fcompare workflows with bundled Python tools (Claude Code, Cursor, Codex).","https:\u002F\u002Fgithub.com\u002Fagency-black\u002FSkills\u002Fblob\u002Fmain\u002Fxvary-stock-research\u002FLICENSE","https:\u002F\u002Fgithub.com\u002Fagency-black\u002FSkills\u002Fblob\u002Fmain\u002Fxvary-stock-research\u002FSKILL.md",[113],{"categoryNo":114,"categoryName":115,"taxonomyType":116,"taxonomyTypeDesc":117},"01JBSEEDCAT000000000000021","资料检索与研究","SCENARIO","使用场景",[119,120,121,122,123,124,125,89,126,94,127,128,129,130,131,132,26,133,134,135],"xvary","stock","research","xvary stock research","sec edgar","community","equity","thesis","analysis","code","Market","compare","market data","analyze","codex","cursor","2026",{"skillNo":137,"name":138,"nameZh":6,"description":139,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":140,"licenseFileUrl":141,"sourceHtmlUrl":142,"categories":143,"keywords":150,"publishedAt":40},"01M71JVSDPDQ5040YBN6J1ASKY","webapp-testing","Toolkit for interacting with and testing local web applications using Playwright. Supports verifying frontend functionality, debugging UI behavior, capturing browser screenshots, and viewing browser logs.","Apache-2.0","https:\u002F\u002Fgithub.com\u002Fagency-black\u002FSkills\u002Fblob\u002Fmain\u002Fwebapp-testing\u002FLICENSE.txt","https:\u002F\u002Fgithub.com\u002Fagency-black\u002FSkills\u002Fblob\u002Fmain\u002Fwebapp-testing\u002FSKILL.md",[144,147],{"categoryNo":145,"categoryName":146,"taxonomyType":116,"taxonomyTypeDesc":117},"01JBSEEDCAT000000000000008","测试与质量",{"categoryNo":148,"categoryName":149,"taxonomyType":116,"taxonomyTypeDesc":117},"01JBSEEDCAT000000000000009","前端开发",[151,152,153,36,33,154,155,156,157,158,159,26,160,161,162,163,164],"webapp","testing","webapp testing","local","frontend","debugging","toolkit","logs","browser","playwright","web","behavior","ui","screenshots",{"skillNo":166,"name":167,"nameZh":6,"description":168,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":140,"licenseFileUrl":169,"sourceHtmlUrl":170,"categories":171,"keywords":173,"publishedAt":40},"01M71JV64CW7R6FYYK9JWWGW0X","web-artifacts-builder","Suite of tools for creating elaborate, multi-component claude.ai HTML artifacts using modern frontend web technologies (React, Tailwind CSS, shadcn\u002Fui). Use for complex artifacts requiring state management, routing, or shadcn\u002Fui components - not for simple single-file HTML\u002FJSX artifacts.","https:\u002F\u002Fgithub.com\u002Fagency-black\u002FSkills\u002Fblob\u002Fmain\u002Fweb-artifacts-builder\u002FLICENSE.txt","https:\u002F\u002Fgithub.com\u002Fagency-black\u002FSkills\u002Fblob\u002Fmain\u002Fweb-artifacts-builder\u002FSKILL.md",[172],{"categoryNo":148,"categoryName":149,"taxonomyType":116,"taxonomyTypeDesc":117},[174,175,176,161,177,178,179,36,180,181,155,182,28,183,184,185,186,187,21,188],"builder","artifacts builder","artifacts","web artifacts builder","single-file","css","Tailwind","ui components","single","file","components","react","multi","state","state management",{"skillNo":190,"name":191,"nameZh":6,"description":192,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":193,"categories":194,"keywords":196,"publishedAt":40},"01M71JS4X2FRY41DE84DEP06MN","vercel-react-view-transitions","Guide for implementing smooth, native-feeling animations using React's View Transition API (`\u003CViewTransition>` component, `addTransitionType`, and CSS view transition pseudo-elements). Use this skill whenever the user wants to add page transitions, animate route changes, create shared element animations, animate enter\u002Fexit of components, animate list reorder, implement directional (forward\u002Fback) navigation animations, or integrate view transitions in Next.js. Also use when the user mentions view transitions, `startViewTransition`, `ViewTransition`, transition types, or asks about animating between UI states in React without third-party animation libraries.","https:\u002F\u002Fgithub.com\u002Fagency-black\u002FSkills\u002Fblob\u002Fmain\u002Fvercel-react-view-transitions\u002FSKILL.md",[195],{"categoryNo":148,"categoryName":149,"taxonomyType":116,"taxonomyTypeDesc":117},[185,197,198,199,200,201,202,203,204,179,205,206,207,32,208,184,209,25,210,211],"vercel react view transitions","view","react view transitions","vercel","transitions","shared","back","Animation","types","states","element","when","api","create","libraries",{"skillNo":213,"name":214,"nameZh":6,"description":215,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":216,"categories":217,"keywords":219,"publishedAt":40},"01M71JS1WZ1J4F9YVC2203JBJW","vercel-react-native-skills","React Native and Expo best practices for building performant mobile apps. Use when building React Native components, optimizing list performance, implementing animations, or working with native modules. Triggers on tasks involving React Native, Expo, mobile performance, or native platform APIs.","https:\u002F\u002Fgithub.com\u002Fagency-black\u002FSkills\u002Fblob\u002Fmain\u002Fvercel-react-native-skills\u002FSKILL.md",[218],{"categoryNo":148,"categoryName":149,"taxonomyType":116,"taxonomyTypeDesc":117},[200,220,185,221,222,223,224,225,226,36,227,32,30,28,228,229,208,230,231,184],"vercel react native skills","react native","native","react native skills","modules","platform","animations","performance","react native components","apps","best practices","tasks"]