Skip to content

📋 Angular Material & RxJS Observables are used to display my data. A Google Cloud Firestore NoSQL database stores the blog posts & website data. Anyone can read the blog posts.

License

AndrewJBateman/angular-material-portfolio

Repository files navigation

⚡ Angular Material Portfolio

  • Angular app using standalone components and Angular Material to create a fully-responsive portfolio website with a Firebase Firestore database.
  • Note: to open web links in a new window use: ctrl+click on link

GitHub repo size GitHub pull requests GitHub Repo stars GitHub last commit

📄 Table of contents

📚 General info

  • Responsive: grid of Angular Material mat-cards using Breakpoint detection
  • Navbars: Top/side navbars with page routing & links to Github & LinkedIn. Dark mode can be selected
  • Footer with date & link to Build information page
  • Build Data info. on main app dependencies
  • Home: Angular Tab Groups/Material card grid to display data, using data-binding from an array of 'areas' based on an Area model.
  • Projects: card grid to display project data using data-binding from an array of projects based on a Project model.
  • Skills: card grid to display project data using data-binding from an array of skills based on a Skill model.
  • Contact: Simple form that user can fill in with name, email and comment. Input validation is included - Send button disabled if form incomplete/incorrect. Buttons to navigate to previous page and to clear the form. The data is sent to the app Firestore backend using angularfire-lite and a success message is returned once sending is complete. Large buttons allow user to return to Home page or send another message (which actually navigates 'back' to the same page presenting a clear form).
  • Posts: Posts are stored in the app Firebase DB and displayed using mat-tabs. Mat-cards now display Post title, subtitle, content, time to read (calculated using a simple Angular pipe) and how old the post is (another pipe using the npm module Day.js). The Post Detail page includes the post image, Blog Detail and the footer includes an image credit with web link to the authors page and date published info.
  • Not Found: In the event of the user trying to route to any page address that is not listed in the router-module a single Mat-card will display a message to the user. There is a simple button to reroute the user to the Home page.

📷 Screenshots

Example screenshot Example screenshot Example screenshot Example screenshot

📶 Technologies

💾 Setup

  • ng serve for a dev server. Navigate to http://localhost:4200/. The app will automatically reload if you change any of the source files
  • npm run build to create build file with Ahead of Time (AOT) compilation. Source map explorer set to false
  • If source map explorer was set to true when build folder created: npm run explore to run the webpack-bundle-analyzer - opens bundle analysis drawing
  • http-server -g -b -p 8080 dist/angular-material-portfolio/browser to run build files on test server port 8080 using the GZip & Brottli files
  • firebase deploy to deploy build file to firebase hosting
  • firebase login --reauth if firebase deploy not working and it shows you are logged in but in fact login token is stale

💻 Code Examples

  • core/services/breakpoint.service.ts extracted BreakpointObserver service to provide breakpoint information to components
/**
 * BreakpointService provides information about current viewport size breakpoints.
 * It uses Angular CDK BreakpointObserver to get breakpoint state, and maps it to
 * a number of grid columns to use for grid layouts.
 */
export class BreakpointService {
  breakpointObserver = inject(BreakpointObserver);

  // return number of grid columns based on user screen size breakpoint, default 4
  breakpointColumnNr$ = this.breakpointObserver
    .observe([Breakpoints.XSmall, Breakpoints.Small, Breakpoints.Medium])
    .pipe(
      map(state =>
        state.breakpoints[Breakpoints.XSmall]
          ? BreakpointSize.XSmall
          : state.breakpoints[Breakpoints.Small]
            ? BreakpointSize.Small
            : state.breakpoints[Breakpoints.Medium]
              ? BreakpointSize.Medium
              : BreakpointSize.Large
      ),
      shareReplay(1)
    );
}

🆒 Features

  • common Grid card layouts with data from a shared firebase database service
  • latest Angular 17 control flows replace '*ngIf' and '*ngFor'
  • local storage dark mode and post mat-tab active settings stored so still there after refresh

📋 Status & To-Do List

  • Status: Working, deployed to Firebase. ighthouse performance 90%, accessibility 100%, Best Practises: 100%, SEO 100% & working PWA
  • To-Do: General: fix index CSP, add text compression, reduce unused JS, cache policy 1 year?
  • To-Do: Skills: add more skills, PLC programming Beckhoff...
  • To-Do: Improve lighthouse performance score: remove unused CSS and redo small images.
  • To-Do: Projects: Terracota project, add to Node projects, add Docker/Java/IoT.. projects. Serve static assets with an efficient cache policy
  • To-Do: Posts: Unsplash images - use sizing website.
  • To-Do: SCSS - reorganise
  • To-Do: Colors: Add to styles SCSS to reduce repeated scss throughout app.
  • To-Do: overview drg

👏 Inspiration

📁 License

  • This project is licensed under the terms of the MIT license.

✉️ Contact