Skip to content

Repository files navigation

Toni-Hoffmann.com

Open Source has always a passion, so why not open sourcing my personal portfolio website.

The website is hosted at toni-hoffmann.com.

The base idea is to have a portfolio, that represents me in different kind of ways. On one site, it is the contents, like the photography, projects and music that I created. But then it's also the minimalistic bright design, the animation contents or the tons of images I fit in on the pages.

alt text

To-Do´s

  • Increase banner image quality, based on the browser size

Technologies used

  • Angular is the root framework of this application
  • Bootstrap is used for the layout, buttons and navigation
  • ng-xGallerify is my gallery component that hosts the photography portfolio

Everything else is developed from scratch. The languages that have been used are TypeScript, SCSS and HTML.

Branching should be done like the git flow, with a master, develop and feature branches, while master represents the production state of the database.

Depending on the project, my favorite set up is to work with a seperate terminal and a nice clean editor, which I both can upgrade with plug ins and adjust to my needs. I also tried to code much of this project by using GitHub Codespaces, which was a great success.

Setup

  • Install Node.js version 24 (the version is pinned in .nvmrc)
  • Clone the Repository via git clone git@github.com:xremix/toni-hoffmann-com.git
  • If using nvm, run nvm install and nvm use in the repository to select Node 24.
  • Run npm install in your local repository

Run

  • Run npm start to get the dev server started with SSR enabled
  • Navigate to http://localhost:4200/
  • The app will automatically reload if you change any of the source files

Deploy

Prerequisites

  • Make sure you have rewrite rules set up on the webserver
  • Make sure deploy the api in the folder /api on the same level than the angular application. The API is part of a private repository

Build and Prerender

  • Run nvm use in the deployment terminal before building (or otherwise ensure Node 24 is selected).
  • Run npm run prerender to generate the sitemap and prerender every route in routes.txt. This produces route-specific HTML and metadata for search engines.
  • Upload the complete contents of dist/toni-hoffmann-com/browser (including all prerendered subfolders and the root files) to the web server.
  • Browser navigation, SSR, and prerendering use the same routes and generate URLs with a trailing slash. Old /. URLs are still accepted.
  • For Node hosting instead of static hosting, run npm run build:ssr and then npm run serve:ssr.

Gallery image indexing

  • Gallery HTML includes full-size image sources, descriptive alternative text and captions, and direct image links that also work without JavaScript. Small screens use thumbnails; normal clicks still open the lightbox.
  • Each gallery page includes ImageGallery / ImageObject structured data with full-size URLs and photographer attribution. This helps describe the images; it does not guarantee rankings or rich results.
  • npm run prerender generates image sitemap entries and gallery routes from api/images/*.json. Pagination is shared with the gallery through src/app/models/gallery-config.json; update the metadata before building whenever photos change.
  • Prerendering reads gallery metadata from the live API. Deploy matching api/images/*.json files and image files before building so prerendered gallery pages and the locally generated sitemap describe the same photos.
  • The sitemap deliberately omits lastmod rather than reporting the build date as a content change date. robots.txt advertises the sitemap, and pages allow large image previews.
  • After deployment, submit https://www.toni-hoffmann.com/sitemap.xml in Google Search Console and inspect a gallery URL's crawled HTML. Ensure /images/ still serves actual image files without authentication or crawler-blocking headers. Google needs time to recrawl, and inclusion in image search is not guaranteed.
  • Run node --test generate-sitemap.test.js to check sitemap pagination and XML escaping.

Individual photo pages

  • Every gallery photo has a permanent /photography/<album>/photo/<id>/ landing page with its own title, heading, canonical URL, full-size image, visible description, and primary-image structured data. Gallery captions link to these pages on hover or keyboard focus, without adding text below the images; lightboxes include an "About this photo" link. Photo pages link to their gallery page and adjacent photos.
  • The existing api/images/*.json files are the single source of photo metadata. Readable slugs are generated automatically from each title with a deterministic filename-based suffix to distinguish identical titles. Gallery order and pagination do not affect URLs.
  • Existing titles provide alternative text and subject-specific descriptions with collection and photographer attribution automatically. Optional description, alt, and permanent slug fields can be added directly to a photo's existing JSON entry; no separate metadata file is needed. Do not invent locations or conditions.
  • Editing a title or filename changes its automatic URL. To preserve a published URL before editing, save its current generated ID in the entry's optional slug field, or add a permanent redirect from the old URL.
  • npm run prerender also includes all photo pages in routes.txt and the image sitemap. Node 24 runs the shared TypeScript URL helpers directly, keeping sitemap URLs consistent with the application.
  • After building, run node --test generate-sitemap.test.js verify-photo-pages.test.js to verify that every image has a unique landing page and that the generated HTML actually contains the photo, description, metadata and gallery links.

Google Search Console follow-up

After deploying, sign in to the verified property for https://www.toni-hoffmann.com/:

  1. Submit sitemap.xml in Sitemaps and check its processing status.
  2. Use URL inspection on a gallery and an individual photo page (copy its URL from the gallery caption or lightbox). Check the live test and rendered HTML for the image, caption, canonical URL and image metadata. Request indexing for representative pages, rather than all photos manually.
  3. Check Page indexing for blocked, duplicate or crawled-but-not-indexed pages. Google's selected canonical should match each photo page, not its gallery.
  4. In Performance, set Search type: Image and track impressions, clicks, queries and pages after recrawling. Structured data and sitemap submission do not guarantee inclusion or rankings.

About

Open Source has always a passion, so why not open sourcing my personal portfolio website

Topics

Resources

Stars

2 stars

Watchers

1 watching

Forks

Contributors

Languages