Before you begin, ensure you have met the following requirements:
- Git
- Node.js The
.nvmrc
file contains the required Node.js version. - VSCode Recommended code editor with the following extensions:
- DavidAnson.vscode-markdownlint
- EditorConfig.EditorConfig
- esbenp.prettier-vscode
- formulahendry.auto-rename-tag
- github.vscode-github-actions
- SimonSiefke.svg-preview
- svelte.svelte-vscode
Clone or fork this repository.
Key steps of the profile creation which take place locally on your computer.
This repo uses Node.js's built-in package manager command-line tool npm. There are other package managers, we will warn you when you may encounter one of them.
The package.json
contains the required JavaScript packages which are hosted at npm. To install these dependencies run the following script at the root of this repository:
npm install
Upon executing this step, a node_modules
folder is generated within your repo's root directory, housing all installed packages and their dependencies. Node.js subsequently locates and loads these packages as needed by your application.
In case of installation issues or dependency reinstallation, simply delete the node_modules
folder and install the dependencies again.
Once you have installed the dependencies, start a development server:
npm run dev
# or start the server and open the app in a new browser tab
npm run dev -- --open
Press Ctrl + D
to terminate the development server.
When you run npm run dev
for the first time, it creates the .svelte-kit
folder, which the development server uses for storing build artifacts and cache. As you continue working on this repo, the development server relies on this folder for a faster development experience.
If unexpected issues arise during development, you can delete the .svelte-kit
folder to remove the existing cache and build artifacts. Once deleted, restart the development server, which will generate a new .svelte-kit
folder with a fresh cache, potentially resolving any problems you encountered.
You might be wondering what we mean by Development in the context of this repo. We will cover the Customization options in more detail later in this document.
Perform type checking to ensure that src/custom/database.ts
aligns with src/database.d.ts
, and fix any errors or warnings that arise:
npm run check
Check the code for syntax and style issues, and fix any errors or warnings that arise:
npm run lint
The original src/custom/example.database.ts
can be helpful for comparing it with the modified src/custom/database.ts
to troubleshoot and resolve any errors.
To create a production version of your app:
npm run build
Fix any errors or warnings that arise.
A known warning can be left unresolved before deployment. It is related to older SvelteKit versions and involves the adapter-auto package. The warning reads:
Unable to detect a supported production environment. Visit https://kit.svelte.dev/docs/adapters to learn how to configure your app for your chosen platform.
To preview the production build in the browser:
npm run preview
You can now use Git commands to push your changes to GitHub.
If you accidentally push a commit that fails β, don't worry. Simply start over the Local Workflow and address the issues.
After pushing your changes to GitHub, the automated processes take over. Automation significantly improves software development by providing consistent validation through Continuous Integration (CI) and facilitating automated deployment via Continuous Delivery (CD).
This repository contains a GitHub Workflow located at .github/workflows/ci.yml
, which executes installation, validation, and build processes on GitHub. The workflow runs can be viewed under the Actions
tab.
In our case, we utilize Vercel as the hosting platform for our static website, enabling an automated and seamless release process into production. The deployments can be viewed under the Deployments
tab.
But first, we need to set up CD by importing our Git repo from GitHub to Vercel. Complete this one-time task once you have a successfully βοΈ pushed commit on GitHub:
- Sign in to vercel.com with your GitHub account.
- Go to the Dashboard
- Click
Add New
and chooseProject
- In the
Import Git repository
section, you'll see your imported Git repositories. To import a new one, clickAdjust GitHub App Permissions β
next toMissing Git repository?
question. - In the popup, click
Configure
next to your GitHub username - Optional If you enabled 2FA on GitHub, you'll need to authorize yourself.
- Enlarge the window, and you'll see it landed on GitHub. Scroll down to
Repository access
, select the repository, and clickSave
. This authorizes Vercel to access your repository and create a static site from it. - The popup will be closed automatically, and you'll see the authorized repository in the Vercel Dashboard. Click
Import
next to it. - Look for
Node.js Version
and select18.x
, the rest of the settings can remain as they are, then click the wideDeploy
button. - If you see "Congratulations", your site is live!
- Click
Continue to Dashboard
to set the domain for the site. - Click
Settings
at the top, thenDomains
on the left panel. - Add your domain name if you have one, or
Edit
the name provided by Vercel. - Visit your site on the domain π
The deployed site from this repository can be viewed at dalum.vercel.app.
From this point forward, every time you push to the main
branch (or create a pull request), GitHub CI processes will automatically test, validate, and build your code changes to ensure seamless integration with the existing codebase. Subsequently, Vercel CD processes will deploy the updated code automatically from the main
branch. If the checks pass βοΈ, your live site will be updated smoothly. However, if the checks fail β, the deployment will not proceed, and your live site will remain unchanged, preserving the last successful deployment.
Three key areas for customization include:
package.json
The core of every Node.js application, it is used to manage dependencies for the project. You can install or uninstall dependencies using thenpm
CLI.src/custom/
A directory for the database, the Markdown files, and styling.static/
A directory containing static assets, such as favicon and images.
This repository does not have a backend or a persistent database, so all information must be stored in files located in the src/custom/
folder. Customize the database.ts
file with your own information to display your personal content on the website.
example.database.ts
: This file serves as a reference for the website's data. Do not delete or modify it; keep it for future reference. Initially thedatabase.ts
is a copy of this example.
src/database.d.ts
: This file outlines the structure and data types for the{example.}database.ts
files, ensuring they are accurate and conform to the expected format, thus preventing errors. The types utilized in the Type-checking and Linting section rely on this file.
The following trees provide an alternative representation of the type definitions found in src/database.d.ts
to help you better understand the structure and connections between different fields. In these trees, optional fields are marked with a β
symbol. You can remove or comment out these subtrees from the database.ts
as needed.
- profile
βββ sidebar
βββ pages
βββ about
βββ resume β
βββ portfolio β
βββ blog β
- sidebar
βββ name
βββ profession
β
βββ img
β βββ src
β βββ alt
β
βββ showContacts
β βββ text
β βββ icon
β
βββ contacts[] β
β βββ title
β βββ icon
β βββ link
β βββ text
β β
β <or>
β β
β βββ title
β βββ icon
β βββ address
β
βββ socials[] β
βββ link
βββ icon
- about
βββ nav
βββ title
β
βββ seo
β βββ title
β βββ description
β βββ keywords
β
βββ paragraphs[] β
β
βββ services β
β βββ title
β βββ items[]
β βββ title
β βββ text
β βββ icon
β
βββ testimonials β
β βββ title
β βββ items[]
β βββ name
β βββ date
β βββ text
β βββ qoute
β β βββ src
β β βββ alt
β βββ img
β βββ src
β βββ alt
β
βββ clients β
βββ title
βββ items[]
βββ link
βββ img
βββ src
βββ alt
- resume β
βββ nav
βββ title
β
βββ seo
β βββ title
β βββ description
β βββ keywords
β
βββ education β
β βββ title
β βββ icon
β βββ items[]
β βββ title
β βββ year
β βββ text
β
βββ experience β
β βββ title
β βββ icon
β βββ items[]
β βββ title
β βββ year
β βββ text
β
βββ skills β
βββ title
βββ items[]
βββ name
βββ percentage
- portfolio β
βββ nav
βββ title
β
βββ seo
β βββ title
β βββ description
β βββ keywords
β
βββ imageIcon
β
βββ categoryFilter β
β βββ instruction
β βββ icon
β βββ allCategory
β
βββ projects[]
βββ slug
βββ title
βββ category β
βββ client β
βββ description
βββ img
βββ src
βββ alt
- blog β
βββ nav
βββ title
β
βββ seo
β βββ title
β βββ description
β βββ keywords
β
βββ categoryFilter β
β βββ instruction
β βββ icon
β βββ allCategory
β
βββ posts[]
βββ slug
βββ title
βββ category β
βββ date β
βββ description
βββ img
βββ src
βββ alt
Each Page - page.about
, page.resume
, page.portfolio
- has an seo
section that will be rendered as meta content in the <head>
of your site.
Example <head>
for the Resume page:
<head>
<title>Richard Hanrick Β· Resume</title>
<meta name="description" content="Richard Hanrick's profile: Explore services, view client work, and read testimonials to see how Richard Hanrick can elevate your project.">
<meta name="keywords" content="freelancer, data science, analytics">
</head>
Each Project page - portfolio.projects[]
- has a dynamically generated SEO meta content based on the following rules:
Meta | Content |
---|---|
title |
sidebar.name Β· page.portfolio.projects[].title |
description |
page.portfolio.projects[].description |
keywords |
page.portfolio.seo.keywords, page.portfolio.projects[].category |
Example <head>
for a Project page:
<head>
<title>Richard Hanrick Β· Finance</title>
<meta name="description" content="A short (max. 155 charaters) description which can be nicely appear in SEO">
<meta name="keywords" content="freelancer, data science, analytics, Statistics">
</head>
The content of the individual Project pages on your site comes from the Markdown files located in the src/custom/projects/
folder.
To establish a connection between the Markdown files and the database.ts
, specifically the items in the portfolio.projects[]
array, ensure that the filename of each Markdown file and the slug
field of each item in the portfolio.projects[]
array are identical. By doing this, the projects/{slug}.md
Markdown file corresponds to a single item in the portfolio.projects[]
array which has the same slug
value, and the Markdown file will be rendered on the page at the URL https://example.com/portfolio/{slug}.
You may notice that there are only two items in the projects/
folder, while there are more items in the portfolio.projects[]
array. When rendering a Project page with a specific slug
, the site first looks for a Markdown file to be rendered from projects/{slug}.md
. If it is missing, the site will render the corresponding item from the portfolio.projects[]
array.
On the contrary, if a Markdown file exists with some slug
but there is no corresponding item in the portfolio.projects[]
array, then nothing will be rendered, and the Markdown file will not be accessible to visitors.
The projects/_markdown_syntax.md
file outlines the supported syntax for Markdown files in this repository. This file is vital for future reference, so avoid to delete it. Instead, remove or comment out the corresponding item in the portfolio.projects[]
array, so the projects/_markdown_syntax.md
will not appear on your site.
Adjust image width in Markdown using |full
postfix in the image alt text. This stretches the image to the full width of the container. Without |full
, the image retains its actual size. Below are two examples from projects/_markdown_syntax.md
demonstrating both cases:


Place any static assets that should be served as-is, such as images, in the static/
folder. You can organize this folder as you see fit, but make sure to:
- Keep the
robots.txt
file in its current location, as it is related to SEO, and - Keep a
favicon.ico
file in its current location, as it is related tosrc/app.html
.
When referencing an image, for example in database.ts
or within a Project Markdown file, omit the static
prefix and use the next folder, starting with a /
.
The static/example_images/
folder contains the images used in example.database.ts
(and initialy in database.ts
). You can keep this folder and create a new static/images/
folder for your personal images, which can then be used in database.ts
.
The customizable colors can be found in src/custom/colors.css
.
Start the development server, and modify the colors in VSCode. You will see the changes right away in the browser.
-
Choose a font family from Google Fonts, such as Open Sans.
-
Select the following styles, these will then appear in the
Selected family
panel on the right:- Light 300
- Regular 400
- Medium 500
- SemiBold 600
- Bold 700
- ExtraBold 800
-
In the
Use on the web
section of the right panel, find and copy the following configuration into thesrc/custom/fonts.css
file:-
Choose the
@import
option and copy the URL contained within the<style>
tags. -
Under the
CSS rules to specify families
section copy the name of the font family:
@import url('https://fonts.googleapis.com/css2?family=Open+Sans:wght@300;400;500;600;700;800&display=swap'); :root { --ff-custom: "Open Sans"; }
-
-
Save the
src/custom/fonts.css
, start the development server if it is not running, and view the changes in the browser.
-
Terminate the development server if it is running.
-
Select an icon set from Iconify Design, such as Material Symbols.
-
The URL should resemble
icon-sets.iconify.design/material-symbols/
, with the last part, in this casematerial-symbols
, identifying the icon set. Run the installation script at the root of the repository:npm install @iconify-icons/material-symbols --save-dev
After executing this script, the
devDependencies
in thepackage.json
file will be updated. -
Restart the development server to observe the replacement of the default IonIcon phone with a new Material Design phone in the Sidebar. Open the
src/custom/icons.js
file in VSCode. -
On the Iconify site, locate the desired icon, such as phone-android-outline. Near the icon, in the first input, there will be text like
material-symbols:phone-android-outline
. Copy this text. -
In the
src/custom/icons.js
file, edit the line and verify the changes in the browser:... import phone from "@iconify-icons/ion/phone-portrait-outline.js"; ...
The result should look like (replacing
:
with/
):... import phone from "@iconify-icons/material-symbols/phone-android-outline.js"; ...
-
If all icons in the
src/custom/icons.js
file have been replaced and you no longer use Font Awesome icons, uninstall the icon set:npm uninstall @iconify-icons/fa6-solid npm uninstall @iconify-icons/fa6-brands
Once again, you will see the changes reflected in the
devDependencies
of thepackage.json
file.
- Optional fields: Refer to the type definitions in
src/database.d.ts
to see which fields are marked as optional with a?
. - Required fields: If you see the word
undefined
somewhere on your site it indicates a missing required field indatabase.ts
. - What can you do if a field is required but you do not need it:
- Examine its ancestors; if one of them is optional, you might not need the entire subtree.
- You can try setting the field to an empty string
""
, an empty array[]
, ornull
, and then preview the changes in the browser to see if the value appears asundefined
or not. However, this approach is considered a hack and may not always produce the desired results.
- Broken images: Avoid using the
static
prefix in theimg.src
fields, but ensure the path starts with/
. - Broken Markdown: Refer to the
projects/_markdown_syntax.md
for the supported syntax.