> Canonical URL: https://codingcat.dev/post/adding-angular-components-to-your-static-site

# Adding Angular Components to your static site

✏️ Blog PostSeptember 12, 2019

# Adding Angular Components to your static site

![CodingCat.dev tutorial cover image](https://cdn.sanity.io/images/hfh83o0w/production/ccbc8203df1de782371c3ee852dbc5f647c83225-1920x1080.png?w=1920&q=82&fit=max&auto=format)[![Alex Patterson](https://cdn.sanity.io/images/hfh83o0w/production/a606dfaa381aab08ddbe16a33fe1d3e1fb37c927-400x400.jpg?w=96&h=96&q=82&fit=max&auto=format)Alex Patterson](/author/alex-patterson)✏️ Visual Architecture Diagram

## how this post connects together.

Follow AJ from first principles to production-ready architecture.

Let’s build it!✏️ Visual Diagram: Adding Angular Components to your static site✓ Good PatternVISUAL DIAGRAM[Diagram Walkthrough]Step-by-step diagram breakdown for Adding Angular Components to your static site: start with Adding Angular Compone, implement Hands-On Implementation, and ship to production.AAA Contrast Verified

**Adding Angular Components to your static site ** is a technical guide on CodingCat.dev by Alex Patterson focused on Angular, Stripe, HTML. Utilizing Web Components within Hugo Static Site Generator (or any static site), to take Stripe/PayPal payments and more!.

## Why Angular Components

Because the people want it!

![](https://cdn.sanity.io/images/hfh83o0w/production/5e5ccb5f62d1f24899ae5bf75025bdaad8e046da-1080x2160.png?w=1080&q=82&fit=max&auto=format)

### Demo

I plan to share a more in depth course on how to build all of this! For now I thought it would be cool just to see it all in action. Notice how after the site loads Firebase kicks in and checks to see if you are a pro member then dynamically hides items using a webcomponent that understands user state. The great part here is that I have many of the Angular items that access firebase already created and I don't have to reinvent the wheel!

[https://youtu.be/iyvVtOsMThI](https://youtu.be/iyvVtOsMThI)

Who do I have to thank for teaching all of this to me? [Jeff Delaney](https://fireship.io/contributors/jeff-delaney/) at [https://fireship.io/courses/stripe-payments/](https://fireship.io/courses/stripe-payments/)

## Allowing User

It is as easy as using `` to wrap around any element and then use display none within that component.

### No more ads

An example of this is when a user registers and becomes a `Pro` member of AJonP, they will no longer see ads.For this I can just wrap my Hugo Go Partial:

Copied! 🐾

```

						googletag.cmd.push(function () {
							googletag.display('div-gpt-ad-xxxxxxxxxxxxxx-0');
						});

```

## Angular Parts

The template is pretty straight forward, Angular either shows the component or removes it based on the `*ngIf`.

Copied! 🐾

```

```

### Angular Component

Some things to note are the code decorations. This allows for you to pass in all of these different items as attributes on the `ajonp-allow-if` component. In our example above I pass in `level="not-user"` to the `@Input level` decorator.What is wonderful about using Angular is that you get all the nice dependency injection that you would normally get with a standard Angular component!

Copied! 🐾

```
import {
	Component,
	ViewEncapsulation,
	ChangeDetectorRef,
	Input,
	AfterViewInit,
	ElementRef
} from '@angular/core';
import { AuthService } from '../../core/services/auth.service';

@Component({ templateUrl: './allow-if.component.html', encapsulation: ViewEncapsulation.ShadowDom })
export class AllowIfComponent implements AfterViewInit {
	@Input() selector;
	@Input() level: 'pro' | 'user' | 'not-pro' | 'not-user' | 'not-user-not-pro';
	@Input() reverse = false;
	@Input() product;
	constructor(private cd: ChangeDetectorRef, public auth: AuthService, private el: ElementRef) {}
	ngAfterViewInit() {
		this.el.nativeElement.style.visibility = 'visible';
	}
	allowed() {
		const u = this.auth.userDoc;
		const products = u && u.products && Object.keys(u.products);

		// Handle Product
		if (products && products.includes(this.product)) {
			return true;
		}
		// Handle Level
		switch (this.level) {
			case 'user':
				return u;
			case 'pro':
				return u && u.is_pro;
			case 'not-pro':
				return u && !u.is_pro;
			case 'not-user':
				return !u;
			case 'not-user-not-pro':
				return !u || !u.is_pro;
			default:
				return false;
		}
	}
}
```

Here you can see I am utilizing the full firebase library for authentication, which is sweet!

Copied! 🐾

```
import { Injectable, ApplicationRef } from '@angular/core';
import * as firebase from 'firebase/app';
import { user } from 'rxfire/auth';
import { docData } from 'rxfire/firestore';

import { Observable, of } from 'rxjs';
import { switchMap, take, tap, isEmpty } from 'rxjs/operators';

import { AjonpUser } from '../models/ajonp-user';
import { AngularfirebaseService } from './angularfirebase.service';

@Injectable({
  providedIn: 'root'
})
export class AuthService {

  authClient = firebase.auth();

  user$: Observable;
  userDoc$: Observable;

  user;
  userDoc;

  constructor(private app: ApplicationRef, private db: AngularfirebaseService) {
    // Why service subsciptions? Maintain state between route changes with change detection.
    this.user$ = user(this.authClient)
      .pipe(tap(u => {
        this.user = u;
        this.app.tick();
      }));

    this.userDoc$ = this.getUserDoc$('users').pipe(tap(u => {
      this.userDoc = u;
      this.app.tick();
    }));

    this.userDoc$.pipe(take(1)).subscribe((u: AjonpUser) => {
      if (u && Object.keys(u).length) {
        const ajonpUser: AjonpUser = { uid: u.uid };
        this.updateUserData(ajonpUser).catch(error => {
          console.log(error);
        });
      } else {
        if (this.user && Object.keys(this.user).length) {
          const data: AjonpUser = {
            uid: this.user.uid,
            email: this.user.email,
            emailVerified: this.user.emailVerified,
            displayName: this.user.displayName || this.user.email || this.user.phoneNumber,
            phoneNumber: this.user.phoneNumber,
            photoURL: this.user.photoURL,
            roles: {
              subscriber: true
            }
          };
          this.setUserData(data).catch(error => {
            console.log(error);
          });
        }
      }
    });

    this.user$.subscribe();
    this.userDoc$.subscribe();
  }

  getUserDoc$(col) {
    return user(this.authClient).pipe(
      switchMap(u => {
        return u ? docData(firebase.firestore().doc(${col}/${(u as any).uid})) : of(null);
      })
    );
  }

  ///// Role-based Authorization //////

  canCreate(u: AjonpUser): boolean {
    const allowed = ['admin', 'editor'];
    return this.checkAuthorization(u, allowed);
  }

  canDelete(u: AjonpUser): boolean {
    const allowed = ['admin'];
    return this.checkAuthorization(u, allowed);
  }

  canEdit(u: AjonpUser): boolean {
    const allowed = ['admin', 'editor'];
    return this.checkAuthorization(u, allowed);
  }

  canRead(u: AjonpUser): boolean {
    const allowed = ['admin', 'editor', 'subscriber'];
    return this.checkAuthorization(u, allowed);
  }

  // determines if user has matching role
  private checkAuthorization(u: AjonpUser, allowedRoles: string[]): boolean {
    if (!u) {
      return false;
    }
    for (const role of allowedRoles) {
      if (u.roles[role]) {
        return true;
      }
    }
    return false;
  }

  public setUserData(u: AjonpUser) {
    return this.db.set(users/${u.uid}, u);
  }

  // Sets user data to firestore after succesful signin
  private updateUserData(u: AjonpUser) {
    return this.db.update(users/${u.uid}, u);
  }
  signOut() {
    this.authClient.signOut();
    location.href = '/pro';
  }
}
```

## Resources, Links & Official Documentation

- [**Angular Developer Guide:**](https://angular.dev/overview) Signals, standalone components, and enterprise Angular workflows
- [**Stripe Developer Documentation:**](https://docs.stripe.com/) Payment intents, webhooks, subscriptions, and billing architecture
- [**MDN HTML Reference:**](https://developer.mozilla.org/en-US/docs/Web/HTML) Semantic markup, accessibility attributes, and document structure

## Related CodingCat.dev Tutorials & Podcast Episodes

- [**Scully - Angular Static Site Generator**](/post/scully-io-angular-static-site-generator): In the Static Site Generator (SSG) space, ReactJs has Gatsby and VueJs has Vuepress/Gridsome. This left for a space to be filled for Angular, introducing Scully...
- [**Angular CLI Deploying**](/post/angular-cli-deploying): Demonstrating how to quickly deploy using Angular CLI to 6 places. Then how to setup CI/CD in Azure, AWS, and Google Cloud Platform.
- [**RxFire in Svelte 3 using Firebase Firestore and Authentication**](/post/rxfire-in-svelte-3-using-firebase-firestore-and-authentication): Introduction to Svelte3, Firebase, and RxFire. RxFire provides a set of observable creation methods. You simply call a function with some parameters to receive ...

## Frequently Asked Questions (FAQ)

### What are the main takeaways from Adding Angular Components to your static site?

Utilizing Web Components within Hugo Static Site Generator (or any static site), to take Stripe/PayPal payments and more!. Adding Angular Components to your static site explores practical patterns for Angular, Stripe, HTML in modern software engineering. Throughout this post, Alex Patterson breaks down real-world implementation details for Angular, Stripe, HTML so developers can apply these patterns directly in production.

### How do you implement Angular best practices in production?

When adopting Angular and Stripe in a production stack, start by validating your configuration against the [**Angular Developer Guide**](https://angular.dev/overview) (Signals, standalone components, and enterprise Angular workflows). Focus on incremental adoption, automated testing, and observability so your team can measure performance and developer velocity improvements at each stage.

### Where can I watch the full Adding Angular Components to your static site walkthrough and find related code resources?

You can explore the complete write-up and code examples right here on CodingCat.dev, and subscribe to the [**CodingCat.dev YouTube channel**](https://www.youtube.com/@CodingCatDev?sub_confirmation=1) for weekly video tutorials. For a deeper dive into Angular, check out our related guide: [**Scully - Angular Static Site Generator**](/post/scully-io-angular-static-site-generator).

## recent blog posts.

[All Blog Posts&rarr;](/blog)[![The Heads of AI wearing black company logo t-shirts and shaking hands in a circular web of cloud and GPU investments](https://cdn.sanity.io/images/hfh83o0w/production/d1d83d596ce5899d797cd3aaf1bd0142038f282a-1376x768.jpg?w=1376&q=82&fit=max&auto=format)](/post/anthropic-s1-ipo-circular-ai-economy-etf-risk)October 26, 2026[![](/logos/amplify/amplify.svg)![](/logos/amplify/amplify.svg)AWS Amplify](/topic/amplify)[AI & MCP Agents](/topic/ai)

### [Anthropic's S-1, $518B in cloud commitments, and circular AI capex](/post/anthropic-s1-ipo-circular-ai-economy-etf-risk)

Anthropic just filed its Form S-1 for a Nasdaq IPO under ticker ANT, revealing $518B in take-or-pay cloud commitments to Google, AWS, and Microsoft. Here is how Mark Zuckerberg, Elon Musk, Jensen Huang, Sundar Pichai, Satya Nadella, Tim Cook, and Dario Amodei built a circular revenue machine, and what happens to your S&P 500 ETF if it stalls.

[![Alex Patterson](https://cdn.sanity.io/images/hfh83o0w/production/a606dfaa381aab08ddbe16a33fe1d3e1fb37c927-400x400.jpg?w=96&h=96&q=82&fit=max&auto=format)Alex Patterson](/author/alex-patterson)[![PHP2Shell (CVE-2026-109618): How AI Found a Decade-Old Bug in 70% of the Web](https://cdn.sanity.io/images/hfh83o0w/production/e83065d0a4e2f841ce64d3f4aea8ddbbf07e5cb9-1376x768.jpg?w=1376&q=82&fit=max&auto=format)](/post/php2shell-cve-2026-109618-ai-php-security-scramble)October 22, 2026[![](/logos/amplify/amplify.svg)![](/logos/amplify/amplify.svg)AWS Amplify](/topic/amplify)[AI & MCP Agents](/topic/ai)

### [PHP2Shell (CVE-2026-109618): How AI Found a Decade-Old Bug in 70% of the Web](/post/php2shell-cve-2026-109618-ai-php-security-scramble)

Two critical pre-authentication RCE flaws in PHP (CVE-2026-109618 and CVE-2026-109619), uncovered by AI models from OpenAI and Google Gemini, sparked a global patching scramble across 70% of the web. Here is how PHP2Shell works and how to patch your servers.

[![Alex Patterson](https://cdn.sanity.io/images/hfh83o0w/production/a606dfaa381aab08ddbe16a33fe1d3e1fb37c927-400x400.jpg?w=96&h=96&q=82&fit=max&auto=format)Alex Patterson](/author/alex-patterson)