Compare commits

..

No commits in common. "4e3068b8986e2538db53037dcc104858face78c3" and "2dac56f61d4863db0f2b706d3cdeb847b0cbe68d" have entirely different histories.

133 changed files with 42 additions and 18929 deletions

8
.gitattributes vendored Normal file
View File

@ -0,0 +1,8 @@
# Auto detect text files and perform LF normalization
* text eol=LF
*.ts text
*.spec.ts text
# Ignore binary files >:(
*.png binary
*.jpg binary

41
.gitignore vendored
View File

@ -1,41 +0,0 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
# dependencies
/node_modules
/.pnp
.pnp.js
.yarn/install-state.gz
# testing
/coverage
# next.js
/.next/
/out/
# production
/build
# misc
.DS_Store
*.pem
# debug
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# local env files
.env*.local
# vercel
.vercel
# typescript
*.tsbuildinfo
next-env.d.ts
# coverage
.coverage
.scannerwork

12
.vscode/settings.json vendored
View File

@ -1,12 +0,0 @@
{
"editor.codeActionsOnSave": {
"source.fixAll.eslint": "explicit"
},
"eslint.validate": [
"typescript"
],
"sonarlint.connectedMode.project": {
"connectionId": "nhcarrigan",
"projectKey": "nhcarrigan_portfolio"
}
}

3
CODE_OF_CONDUCT.md Normal file
View File

@ -0,0 +1,3 @@
# Code of Conduct
Our Code of Conduct can be found here: https://docs.nhcarrigan.com/#/coc

3
CONTRIBUTING.md Normal file
View File

@ -0,0 +1,3 @@
# Contributing
Our contributing guidelines can be found here: https://docs.nhcarrigan.com/#/contributing

5
LICENSE.md Normal file
View File

@ -0,0 +1,5 @@
# License
This software is licensed under our [global software license](https://docs.nhcarrigan.com/#/license).
Copyright held by Naomi Carrigan.

3
PRIVACY.md Normal file
View File

@ -0,0 +1,3 @@
# Privacy Policy
Our privacy policy can be found here: https://docs.nhcarrigan.com/#/privacy

View File

@ -1,10 +1,20 @@
# Portfolio
# New Repository Template
My professional portfolio website.
This template contains all of our basic files for a new GitHub repository. There is also a handy workflow that will create an issue on a new repository made from this template, with a checklist for the steps we usually take in setting up a new repository.
If you're starting a Node.JS project with TypeScript, we have a [specific template](https://github.com/naomi-lgbt/nodejs-typescript-template) for that purpose.
## Readme
Delete all of the above text (including this line), and uncomment the below text to use our standard readme template.
<!-- # Project Name
Project Description
## Live Version
This page is currently deployed. [View the live website.](https://nhcarrigan.com)
This page is currently deployed. [View the live website.]
## Feedback and Bugs
@ -26,4 +36,4 @@ Copyright held by Naomi Carrigan.
## Contact
We may be contacted through our [Chat Server](http://chat.nhcarrigan.com) or via email at `contact@nhcarrigan.com`.
We may be contacted through our [Chat Server](http://chat.nhcarrigan.com) or via email at `contact@nhcarrigan.com`. -->

3
SECURITY.md Normal file
View File

@ -0,0 +1,3 @@
# Security Policy
Our security policy can be found here: https://docs.nhcarrigan.com/#/security

3
TERMS.md Normal file
View File

@ -0,0 +1,3 @@
# Terms of Service
Our Terms of Service can be found here: https://docs.nhcarrigan.com/#/terms

2
do.env
View File

@ -1,2 +0,0 @@
DO_ACCESS_KEY="op://Environment Variables - Development/DO Spaces/username"
DO_SECRET_KEY="op://Environment Variables - Development/DO Spaces/credential"

View File

@ -1,34 +0,0 @@
import NaomisConfig from "@nhcarrigan/eslint-config";
export default [
...NaomisConfig,
{
rules: {
"@typescript-eslint/naming-convention": "off",
"unicorn/filename-case": "off",
"max-lines": "off",
"max-lines-per-function": "off",
"complexity": "off",
"import/no-default-export": "off",
"import/extensions": ["warn", "never"]
}
},
{
files: ["src/config/*.ts"],
rules: {
"stylistic/max-len": "off"
}
},
{
files: ["src/icons/*.ts"],
rules: {
"@typescript-eslint/consistent-type-assertions": "off"
}
},
{
files: ["test/**/*.spec.ts"],
rules: {
"max-nested-callbacks": "off"
}
}
]

View File

@ -1,30 +0,0 @@
import { ListObjectsV2Command, S3Client } from "@aws-sdk/client-s3";
import { writeFile } from "fs/promises";
import { join } from "path";
(async () => {
const s3 = new S3Client({
endpoint: "https://sfo3.digitaloceanspaces.com",
region: "sfo3",
credentials: {
accessKeyId: process.env.DO_ACCESS_KEY as string,
secretAccessKey: process.env.DO_SECRET_KEY as string
}
})
const command = new ListObjectsV2Command({
Bucket: "nhcarrigan-cdn",
Prefix: "koikatsu"
})
const { Contents } = await s3.send(command);
const names = Contents?.map((content) => content.Key?.replace("koikatsu/", "")).filter((name) => name) || [];
await writeFile(join(process.cwd(), "src", "config", "Koikatsu.ts"), `/**
* @copyright nhcarrigan
* @license Naomi's Public License
* @author Naomi Carrigan
*/
export const Koikatsu = ${JSON.stringify(names, null, 2)};`, "utf-8");
})()

View File

@ -1,15 +0,0 @@
/** @type {import('next').NextConfig} */
const nextConfig = {
eslint: {
ignoreDuringBuilds: true
},
images: {
remotePatterns: [
{
hostname: "cdn.nhcarrigan.com"
}
]
}
};
export default nextConfig;

View File

@ -1,53 +0,0 @@
{
"name": "portfolio",
"version": "0.1.0",
"private": true,
"scripts": {
"prebuild": "pnpm lint && pnpm test",
"dev": "next dev",
"build": "next build",
"start": "next start",
"lint": "eslint src test --max-warnings 0",
"test": "op run --env-file=do.env --no-masking -- vitest run --coverage",
"koikatsu": "op run --env-file=do.env --no-masking -- tsx koikatsu.ts",
"scan": "SONAR_TOKEN='op://Environment Variables - Development/SonarCloud/portfolio' op run -- sonar-scanner -Dsonar.organization=nhcarrigan -Dsonar.projectKey=nhcarrigan_portfolio -Dsonar.sources=. -Dsonar.host.url=https://sonarcloud.io"
},
"dependencies": {
"@fortawesome/fontawesome-svg-core": "6.6.0",
"@fortawesome/free-brands-svg-icons": "6.6.0",
"@fortawesome/free-solid-svg-icons": "6.6.0",
"@fortawesome/react-fontawesome": "0.2.2",
"@pixiv/three-vrm": "3.1.6",
"@react-three/drei": "9.117.2",
"@react-three/fiber": "9.0.0-beta.1",
"crisp-sdk-web": "1.0.25",
"next": "15.0.2",
"next-hubspot": "1.4.0-beta.1",
"next-plausible": "3.12.2",
"react": "18.3.1",
"react-dom": "18.3.1",
"three": "0.170.0"
},
"devDependencies": {
"@aws-sdk/client-s3": "3.693.0",
"@nhcarrigan/eslint-config": "5.0.0-rc2",
"@nhcarrigan/typescript-config": "4.0.0",
"@types/node": "22.8.4",
"@types/react": "18.3.12",
"@types/react-dom": "18.3.1",
"@types/three": "0.170.0",
"@vitest/coverage-istanbul": "2.1.4",
"eslint": "9.13.0",
"jsdom": "25.0.1",
"postcss": "8.4.47",
"tailwindcss": "3.4.14",
"tsx": "4.19.2",
"typescript": "5.6.3",
"vitest": "2.1.4"
},
"resolutions": {
"react": "18.3.1",
"react-dom": "18.3.1",
"next": "15.0.2"
}
}

7772
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

View File

@ -1,8 +0,0 @@
/** @type {import('postcss-load-config').Config} */
const config = {
plugins: {
tailwindcss: {},
},
};
export default config;

View File

@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 394 80"><path fill="#000" d="M262 0h68.5v12.7h-27.2v66.6h-13.6V12.7H262V0ZM149 0v12.7H94v20.4h44.3v12.6H94v21h55v12.6H80.5V0h68.7zm34.3 0h-17.8l63.8 79.4h17.9l-32-39.7 32-39.6h-17.9l-23 28.6-23-28.6zm18.3 56.7-9-11-27.1 33.7h17.8l18.3-22.7z"/><path fill="#000" d="M81 79.3 17 0H0v79.3h13.6V17l50.2 62.3H81Zm252.6-.4c-1 0-1.8-.4-2.5-1s-1.1-1.6-1.1-2.6.3-1.8 1-2.5 1.6-1 2.6-1 1.8.3 2.5 1a3.4 3.4 0 0 1 .6 4.3 3.7 3.7 0 0 1-3 1.8zm23.2-33.5h6v23.3c0 2.1-.4 4-1.3 5.5a9.1 9.1 0 0 1-3.8 3.5c-1.6.8-3.5 1.3-5.7 1.3-2 0-3.7-.4-5.3-1s-2.8-1.8-3.7-3.2c-.9-1.3-1.4-3-1.4-5h6c.1.8.3 1.6.7 2.2s1 1.2 1.6 1.5c.7.4 1.5.5 2.4.5 1 0 1.8-.2 2.4-.6a4 4 0 0 0 1.6-1.8c.3-.8.5-1.8.5-3V45.5zm30.9 9.1a4.4 4.4 0 0 0-2-3.3 7.5 7.5 0 0 0-4.3-1.1c-1.3 0-2.4.2-3.3.5-.9.4-1.6 1-2 1.6a3.5 3.5 0 0 0-.3 4c.3.5.7.9 1.3 1.2l1.8 1 2 .5 3.2.8c1.3.3 2.5.7 3.7 1.2a13 13 0 0 1 3.2 1.8 8.1 8.1 0 0 1 3 6.5c0 2-.5 3.7-1.5 5.1a10 10 0 0 1-4.4 3.5c-1.8.8-4.1 1.2-6.8 1.2-2.6 0-4.9-.4-6.8-1.2-2-.8-3.4-2-4.5-3.5a10 10 0 0 1-1.7-5.6h6a5 5 0 0 0 3.5 4.6c1 .4 2.2.6 3.4.6 1.3 0 2.5-.2 3.5-.6 1-.4 1.8-1 2.4-1.7a4 4 0 0 0 .8-2.4c0-.9-.2-1.6-.7-2.2a11 11 0 0 0-2.1-1.4l-3.2-1-3.8-1c-2.8-.7-5-1.7-6.6-3.2a7.2 7.2 0 0 1-2.4-5.7 8 8 0 0 1 1.7-5 10 10 0 0 1 4.3-3.5c2-.8 4-1.2 6.4-1.2 2.3 0 4.4.4 6.2 1.2 1.8.8 3.2 2 4.3 3.4 1 1.4 1.5 3 1.5 5h-5.8z"/></svg>

Before

Width:  |  Height:  |  Size: 1.3 KiB

View File

@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 283 64"><path fill="black" d="M141 16c-11 0-19 7-19 18s9 18 20 18c7 0 13-3 16-7l-7-5c-2 3-6 4-9 4-5 0-9-3-10-7h28v-3c0-11-8-18-19-18zm-9 15c1-4 4-7 9-7s8 3 9 7h-18zm117-15c-11 0-19 7-19 18s9 18 20 18c6 0 12-3 16-7l-8-5c-2 3-5 4-8 4-5 0-9-3-11-7h28l1-3c0-11-8-18-19-18zm-10 15c2-4 5-7 10-7s8 3 9 7h-19zm-39 3c0 6 4 10 10 10 4 0 7-2 9-5l8 5c-3 5-9 8-17 8-11 0-19-7-19-18s8-18 19-18c8 0 14 3 17 8l-8 5c-2-3-5-5-9-5-6 0-10 4-10 10zm83-29v46h-9V5h9zM37 0l37 64H0L37 0zm92 5-27 48L74 5h10l18 30 17-30h10zm59 12v10l-3-1c-6 0-10 4-10 10v15h-9V17h9v9c0-5 6-9 13-9z"/></svg>

Before

Width:  |  Height:  |  Size: 629 B

View File

@ -1,119 +0,0 @@
/**
* @copyright nhcarrigan
* @license Naomi's Public License
* @author Naomi Carrigan
*/
import type { JSX } from "react";
/**
* Renders the /about page.
* @returns A React Component.
*/
const About = (): JSX.Element => {
return (
<main className="w-4/5 text-center max-w-4xl m-auto mt-16 mb-16 rounded-lg">
<h1 className="text-5xl">{`About Naomi`}</h1>
<section>
<p className="mb-2">
{`Passionate technologist dedicated to building inclusive tech
communities and empowering individuals to break into the field. With
a rich background in community management, software engineering, and
developer experience, I strive to create accessible pathways for
diverse talent.`}
</p>
<p className="mb-2">{`My expertise spans:`}</p>
<ul className="w-4/5 m-auto">
<li
className="mb-2 relative before:content-['🩵']
before:absolute before:left-[-1em]"
>
<strong>{`Inclusive Community Building:`}</strong>
{` Cultivated
welcoming communities of 20,000 to 300K+ members across Discord,
Slack, and GitHub, with a focus on supporting underrepresented
groups in tech.`}
</li>
<li
className="mb-2 relative before:content-['🩵']
before:absolute before:left-[-1em]"
>
<strong>{`Empowering Education:`}</strong>
{` Contributed to and
maintained open-source curricula used by millions of aspiring
developers globally, focusing on accessibility and engaging
learning experiences.`}
</li>
<li
className="mb-2 relative before:content-['🩵']
before:absolute before:left-[-1em]"
>
<strong>{`Software Engineering for Inclusivity:`}</strong>
{` Developed
sophisticated bots and tools that not only streamline moderation
and boost engagement but also promote safe, inclusive spaces for
all community members.`}
</li>
<li
className="mb-2 relative before:content-['🩵']
before:absolute before:left-[-1em]"
>
<strong>{`Developer Experience (DX):`}</strong>
{` Led initiatives to
improve documentation, SDK support, and overall developer
satisfaction, with an emphasis on making resources accessible to
newcomers in the field.`}
</li>
<li
className="mb-2 relative before:content-['🩵']
before:absolute before:left-[-1em]"
>
<strong>{`Mentorship and Advocacy:`}</strong>
{` Implemented programs to
support aspiring developers, particularly those from
under-represented backgrounds, in their journey into tech careers.`}
</li>
</ul>
<p className="mb-2">
{`Key achievements include redesigning freeCodeCamp's Responsive
Web Design curriculum for greater accessibility, developing
AI-powered community management tools that foster inclusive
interactions, and creating engagement systems that significantly
increased participation from diverse user groups.`}
</p>
<p className="mb-2">
{`I'm driven by the belief that technology should be a field open
to all. My approach combines technical expertise with a deep
commitment to diversity, equity, and inclusion, resulting in
solutions that not only drive engagement and innovation but also
break down barriers to entry in tech.`}
</p>
<p className="mb-2">
{`Seeking opportunities to lead transformative projects that expand
access to tech education, foster inclusive community growth, and
empower individuals from all backgrounds to thrive in the tech
industry. Let's connect to discuss how I can best support your
organisation!`}
</p>
<p className="mb-2">
{`Want to get to know Naomi better? Check out her `}
<a
className="underline"
href="https://loan.nhcarrigan.com"
rel="noopener noreferrer"
target="_blank"
>
{`Life of a Naomi game`}
</a>
{`!`}
</p>
</section>
</main>
);
};
export default About;

View File

@ -1,50 +0,0 @@
/**
* @copyright nhcarrigan
* @license Naomi's Public License
* @author Naomi Carrigan
*/
import { NextResponse } from "next/server";
import { getCodebergActivty } from "../../../lib/codeberg";
import { getGithubData } from "../../../lib/github";
/**
* GET route handler for the activity API.
* Loads recent activity from Codeberg and GitHub.
* @returns The formatted data.
*/
export async function GET(): Promise<NextResponse> {
const codeberg = await getCodebergActivty();
const github = await getGithubData();
const normalised: Array<{
type: string;
date: Date;
repo: string;
repoName: string;
}> = [
...codeberg.map((index) => {
return {
date: new Date(index.created),
repo: index.repo.html_url,
repoName: index.repo.full_name,
type: index.op_type,
};
}),
...github.map((index) => {
return {
date: new Date(index.created_at),
repo: index.repo.url.replace("api.github.com/repos", "github.com"),
repoName: index.repo.name,
type: index.type,
};
}),
];
return NextResponse.json(
normalised.
toSorted((a, b) => {
return new Date(b.date).getTime() - new Date(a.date).getTime();
}).
slice(0, 100),
);
}

View File

@ -1,28 +0,0 @@
/**
* @copyright nhcarrigan
* @license Naomi's Public License
* @author Naomi Carrigan
*/
import { NextResponse } from "next/server";
import { getCodebergIssues } from "../../../lib/codeberg";
/**
* GET route handler for the activity API.
* Loads recent activity from Codeberg and GitHub.
* @returns The formatted data.
*/
export async function GET(): Promise<NextResponse> {
const issues = await getCodebergIssues();
const normalised = issues.map((issue) => {
return {
body: issue.body,
labels: issue.labels.map((label) => {
return label.name;
}),
number: issue.number,
title: issue.title,
url: issue.html_url,
};
});
return NextResponse.json(normalised);
}

View File

@ -1,48 +0,0 @@
/**
* @copyright nhcarrigan
* @license Naomi's Public License
* @author Naomi Carrigan
*/
"use client";
import Script from "next/script";
import type { JSX } from "react";
/**
* Renders the /polycule page.
* @returns A React Component.
*/
const Sales = (): JSX.Element => {
return (
<>
<main className="w-4/5 text-center
max-w-4xl m-auto mt-16 mb-1 rounded-lg">
<h1 className="text-5xl">{`Appeal a Sanction`}</h1>
<p>{`This form allows you to appeal a moderation action taken against you on one of our platforms.`}</p>
</main>
<style>
{`.hbspt-form {
max-width: 750px;
margin: auto;
background-color: #04624f;
border-radius: 1rem;
padding: 1rem;
margin-bottom: 100px;
font-family: "Fira Code", monospace;
}`}
</style>
<Script
src="//js.hsforms.net/forms/embed/v2.js"
strategy="beforeInteractive"
type="text/javascript"
></Script>
<Script strategy="afterInteractive">
{`hbspt.forms.create({
portalId: "47086586",
formId: "2db4284c-86a1-47d2-a019-c460ef809402",
});`}
</Script>
</>
);
};
export default Sales;

View File

@ -1,48 +0,0 @@
/**
* @copyright nhcarrigan
* @license Naomi's Public License
* @author Naomi Carrigan
*/
"use client";
import Script from "next/script";
import type { JSX } from "react";
/**
* Renders the /apply page.
* @returns A React Component.
*/
const Apply = (): JSX.Element => {
return (
<>
<main className="w-4/5 text-center
max-w-4xl m-auto mt-16 mb-1 rounded-lg">
<h1 className="text-5xl">{`Staff Application`}</h1>
<p>{`This form allows you to apply to join NHCarrigan's volunteer staff team.`}</p>
</main>
<style>
{`.hbspt-form {
max-width: 750px;
margin: auto;
background-color: #04624f;
border-radius: 1rem;
padding: 1rem;
margin-bottom: 100px;
font-family: "Fira Code", monospace;
}`}
</style>
<Script
src="//js.hsforms.net/forms/embed/v2.js"
strategy="beforeInteractive"
type="text/javascript"
></Script>
<Script strategy="afterInteractive">
{`hbspt.forms.create({
portalId: "47086586",
formId: "833ff1c0-6c24-4c26-9af0-331c1f7ce6d4",
});`}
</Script>
</>
);
};
export default Apply;

View File

@ -1,46 +0,0 @@
/**
* @copyright nhcarrigan
* @license Naomi's Public License
* @author Naomi Carrigan
*/
import { ArtComponent } from "../../components/art";
import { Rule } from "../../components/rule";
import { Art } from "../../config/Art";
import type { JSX } from "react";
/**
* Renders the /art page.
* @returns A React Component.
*/
const Arts = (): JSX.Element => {
return (
<main
className="w-[95%] text-center
max-w-4xl m-auto mt-16 mb-16 rounded-lg"
>
<h1 className="text-5xl">{`Art`}</h1>
<section>
<p className="mb-2">{`See various art depicting Naomi.`}</p>
<Rule />
<div className="grid sm:grid-cols-2 lg:grid-cols-3 grid-cols-1 gap-y-5">
{Art.toSorted((a, b) => {
return a.name.localeCompare(b.name);
}).map((art) => {
return (
<ArtComponent
alt={art.alt}
artist={art.artist}
img={art.img}
key={art.name}
name={art.name}
url={art.url}
/>
);
})}
</div>
</section>
</main>
);
};
export default Arts;

View File

@ -1,214 +0,0 @@
/**
* @copyright nhcarrigan
* @license Naomi's Public License
* @author Naomi Carrigan
*/
"use client";
import { useEffect, useState, type ChangeEvent, type JSX } from "react";
import { Rule } from "../../components/rule";
type Category = "question" | "compliment" | "confess" | "never";
const ColourMap: Record<Category, { background: string; foreground: string }>
= {
compliment: {
background: "#a6f1c6",
foreground: "#0f9d58",
},
confess: {
background: "#f7c6d2",
foreground: "#b03060",
},
never: {
background: "#f7e6c6",
foreground: "#b8860b",
},
question: {
background: "#a6e6fc",
foreground: "#03779e",
},
};
const TitleMap: Record<Category, string> = {
compliment: "Pay Naomi a Compliment",
confess: "Confess Your Sins to Naomi",
never: "Never Have I Ever?",
question: "Ask Naomi a Question",
};
const DescriptionMap: Record<Category, string> = {
compliment:
// eslint-disable-next-line stylistic/max-len
"Have you wanted to tell Naomi she's cute, but you've been too shy? Here's your chance!",
confess:
// eslint-disable-next-line stylistic/max-len
"Is there something weighing on your mind that you can't tell anyone else? Confess it here!",
never:
// eslint-disable-next-line stylistic/max-len
"What do you think Naomi has done that you haven't? Let's play a game of Never Have I Ever!",
question: "Do you have a question for Naomi? Ask it here!",
};
interface DataRecord {
category: Category;
question: string;
answer: string;
}
/**
* Renders the /ask page.
* @returns A React Component.
*/
const Ask = (): JSX.Element => {
const [ category, setCategory ] = useState<Category>("question");
const [ question, setQuestion ] = useState<string>("");
const [ submitted, setSubmitted ] = useState<boolean>(false);
const [ errored, setErrored ] = useState<boolean>(false);
const [ history, setHistory ] = useState<Array<DataRecord>>([]);
useEffect(() => {
fetch("https://anon.nhcarrigan.com/recent").then(async(response) => {
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
const result = await response.json() as Array<DataRecord>;
setHistory(result);
}).
catch((error: unknown) => {
// eslint-disable-next-line no-console
console.error(error);
setHistory([]);
});
}, []);
const handleCategoryChange = (
event: ChangeEvent<HTMLSelectElement>,
): void => {
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
setCategory(event.target.value as Category);
};
const handleQuestionUpdate = (
event: ChangeEvent<HTMLTextAreaElement>,
): void => {
setQuestion(event.target.value);
};
const submitForm = (): void => {
fetch("https://anon.nhcarrigan.com/api", {
body: JSON.stringify({
category,
question,
}),
headers: {
"Content-Type": "application/json",
},
method: "POST",
}).
then((response) => {
if (response.ok) {
setSubmitted(true);
} else {
setErrored(true);
}
}).
catch(() => {
setErrored(true);
});
};
return (
<main className="w-4/5 text-center max-w-4xl m-auto mt-16 mb-16 rounded-lg">
<h1 className="text-5xl">{`Ask Me Anything!`}</h1>
<p>
{`This page allows you to anonymously ask any question you might wish! Once approved and answered, your question and our response will be visible in our `}
<a
className="underline"
href="https://chat.nhcarrigan.com"
>{`Discord`}</a>
{`!`}
</p>
<Rule />
{!submitted && !errored
&& <section>
<h2 className="text-3xl">{TitleMap[category]}</h2>
<p className="mb-2">{DescriptionMap[category]}</p>
<form>
<select
className="text-center border-2 rounded-lg p-0.5 mb-0.5"
// eslint-disable-next-line react/jsx-no-bind
onChange={handleCategoryChange}
style={{
backgroundColor: ColourMap[category].background,
borderColor: ColourMap[category].foreground,
color: ColourMap[category].foreground,
}}
>
<option value="question">{`Question`}</option>
<option value="compliment">{`Compliment`}</option>
<option value="confess">{`Confession`}</option>
<option value="never">{`Never Have I Ever?`}</option>
</select>
<textarea
className={`w-full h-48 p-2 border-2`}
// eslint-disable-next-line react/jsx-no-bind
onChange={handleQuestionUpdate}
placeholder="Type your question here..."
style={{
backgroundColor: ColourMap[category].background,
borderColor: ColourMap[category].foreground,
color: ColourMap[category].foreground,
}}
/>
<button
className="font-bold py-2 px-4 rounded mt-2"
// eslint-disable-next-line react/jsx-no-bind
onClick={submitForm}
style={{
backgroundColor: ColourMap[category].background,
borderColor: ColourMap[category].foreground,
color: ColourMap[category].foreground,
}}
type="button"
>
{`Submit`}
</button>
</form>
</section>
}
{submitted
? <section>
<h2 className="text-3xl">{`Question Submitted!`}</h2>
<p>{`Your question has been submitted! Please wait for approval and response.`}</p>
</section>
: null}
{errored
? <section>
<h2 className="text-3xl">{`Submission Error`}</h2>
<p>{`An error occurred while submitting your question. Please try again later.`}</p>
</section>
: null}
<Rule />
<h2 className="text-3xl">{`Prior Questions`}</h2>
<p>{`Here are the most recently answered questions - if you want to see the full history, join our Discord!`}</p>
{history.length > 0
? history.map((record) => {
return (
<section
className="border-2 rounded-lg p-2 mt-2"
key={record.question}
style={{
backgroundColor: ColourMap[record.category].background,
borderColor: ColourMap[record.category].foreground,
color: ColourMap[record.category].foreground,
}}
>
<h3 className="text-2xl">{record.question}</h3>
<p>{record.answer}</p>
</section>
);
})
: <p>{`No questions have been answered yet!`}</p>
}
</main>
);
};
export default Ask;

View File

@ -1,46 +0,0 @@
/**
* @copyright nhcarrigan
* @license Naomi's Public License
* @author Naomi Carrigan
*/
import { Certification } from "../../components/cert";
import { Rule } from "../../components/rule";
import { Certifications } from "../../config/Certifications";
import type { JSX } from "react";
/**
* Renders the /certs page.
* @returns A React Component.
*/
const Certs = (): JSX.Element => {
return (
<main className="w-[95%] text-center
max-w-4xl m-auto mt-16 mb-16 rounded-lg">
<h1 className="text-5xl">{`Certs`}</h1>
<section>
<p className="mb-2">
{`This page lists the professional certifications Naomi has obtained
throughout her time as a developer.`}
</p>
<Rule />
<div className="grid sm:grid-cols-2 lg:grid-cols-3 grid-cols-1 gap-y-5">
{Certifications.toSorted(
(a, b) => {
return b.date.getTime() - a.date.getTime();
},
).map((cert) => {
return <Certification
date={cert.date}
fileName={cert.fileName}
issuer={cert.issuer}
key={cert.name}
name={cert.name}
/>;
})}
</div>
</section>
</main>
);
};
export default Certs;

View File

@ -1,108 +0,0 @@
/**
* @copyright nhcarrigan
* @license Naomi's Public License
* @author Naomi Carrigan
*/
import Script from "next/script";
import { Rule } from "../../components/rule";
import { Social } from "../../components/social";
import { Donate, HireMe, Socials } from "../../config/Socials";
import type { JSX } from "react";
/**
* Renders the /contact page.
* @returns A React Component.
*/
const Contact = (): JSX.Element => {
return (
<main className="w-4/5 text-center max-w-4xl m-auto mt-16 mb-16 rounded-lg">
<style>
{`.hbspt-form {
max-width: 750px;
margin: auto;
background-color: #04624f;
border-radius: 1rem;
padding: 1rem;
margin-bottom: 100px;
font-family: "Fira Code", monospace;
}`}
</style>
<h1 className="text-5xl">{`Contact Us`}</h1>
<p>
{`We offer many different ways to get in touch with us. This page lists
all of our available social media accounts. Use the buttons below to
choose your preferred method.`}
</p>
<p>
{`Note that the items are sorted alphabetically, not by order of
response times. Monitoring levels and activity may vary by platform.`}
</p>
<p>
{`With ${Socials.length.toLocaleString("en-GB")} choices, you shouldn't have any complaints!
:3`}
</p>
<p>
{`But if none of these work for you at all, there's a direct contact form at the bottom of this list!`}
</p>
<Rule />
<section>
<p>A quick note that we have explicitly deactivated our accounts on the following platforms. If you see an account on these platforms using our branding (either as NaomiLGBT OR NHCarrigan), it is an impersonation and should be reported.</p>
<ul>
<li>Twitch</li>
<li>Twitter</li>
<li>Instagram</li>
<li>Threads</li>
<li>WhatsApp</li>
</ul>
</section>
<Rule />
<section>
<div>
{[ HireMe, Donate ].map(
({ link, label, alt, icon, color, background }) => {
return <Social
alt={alt}
background={background}
color={color}
icon={icon}
key={label}
label={label}
link={link}
/>;
}
,
)}
{Socials.toSorted((a, b) => {
return a.label.localeCompare(b.label);
}).map(
({ link, label, alt, icon, color, background }) => {
return <Social
alt={alt}
background={background}
color={color}
icon={icon}
key={label}
label={label}
link={link}
/>;
}
,
)}
</div>
</section>
<Script
src="//js.hsforms.net/forms/embed/v2.js"
strategy="beforeInteractive"
type="text/javascript"
></Script>
<Script strategy="afterInteractive">
{`hbspt.forms.create({
portalId: "47086586",
formId: "4db250c8-a1a7-4a62-94d7-82592fa83a58",
});`}
</Script>
</main>
);
};
export default Contact;

View File

@ -1,86 +0,0 @@
/**
* @copyright nhcarrigan
* @license Naomi's Public License
* @author Naomi Carrigan
*/
"use client";
import type { JSX } from "react";
/**
* Renders the /contribute page.
* @returns A React Component.
*/
const ContributeComponent = (): JSX.Element => {
return (
<main className="w-[95%] text-center
max-w-4xl m-auto mt-16 mb-16 rounded-lg">
<h1 className="text-5xl">{`Open for Contribution~!`}</h1>
<section>
<p className="mb-2">{`Our issue tracker is currently unavailable while we work with the Codeberg team to address rate limit issues.`}</p>
</section>
</main>
);
/*
*To be restored when rate-limit is lifted.
*const [ issues, setIssues ] = useState<
*Array<{
* labels: Array<string>;
* number: number;
* title: string;
* url: string;
* body: string;
*}>
*>([]);
*
*useEffect(() => {
*void fetch("/api/contribute").
* then(async(data) => {
* // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
* return (await data.json()) as Array<{
* labels: Array<string>;
* number: number;
* title: string;
* url: string;
* body: string;
* }>;
* }).
* then((data) => {
* setIssues(data);
* });
*}, []);
*
*if (issues.length === 0) {
*return (
* <main className="w-[95%] text-center
* max-w-4xl m-auto mt-16 mb-16 rounded-lg">
* <h1 className="text-5xl">{`Open for Contribution~!`}</h1>
* <section>
* <p className="text-3xl">{`Loading...`}</p>
* </section>
* </main>
*);
*}
*
*return (
* <main className="w-[95%] text-center
* max-w-4xl m-auto mt-16 mb-16 rounded-lg">
* <h1 className="text-5xl">{`Open for Contribution~!`}</h1>
* <section>
* <p className="mb-2">{`Heya! This page lists issues across all of our projects that are currently open for contribution.
* We'd love to have you work on one!`}</p>
* <Rule />
* <ol className="relative border-s border-[--primary] w-4/5 m-auto">
* {issues.map((act) => {
* return (
* <Issue key={act.url} {...act} />
* );
* })}
* </ol>
* </section>
* </main>
*);
*/
};
export default ContributeComponent;

View File

@ -1,45 +0,0 @@
/**
* @copyright nhcarrigan
* @license Naomi's Public License
* @author Naomi Carrigan
*/
import { Game } from "../../components/game";
import { Rule } from "../../components/rule";
import { Games } from "../../config/Games";
import type { JSX } from "react";
/**
* Renders the /games page.
* @returns A React Component.
*/
const Gamez = (): JSX.Element => {
return (
<main
className="w-[95%] text-center
max-w-4xl m-auto mt-16 mb-16 rounded-lg"
>
<h1 className="text-5xl">{`Games`}</h1>
<section>
<p className="mb-2">{`See how Naomi has appeared in various games.`}</p>
<Rule />
<div className="grid sm:grid-cols-2 lg:grid-cols-3 grid-cols-1 gap-y-5">
{Games.toSorted((a, b) => {
return a.name.localeCompare(b.name);
}).map((game) => {
return (
<Game
alt={game.alt}
img={game.img}
key={game.name}
name={game.name}
url={game.url}
/>
);
})}
</div>
</section>
</main>
);
};
export default Gamez;

View File

@ -1,24 +0,0 @@
@tailwind base;
@tailwind components;
@tailwind utilities;
:root {
--current: #995c00;
--former: #99004d;
}
* {
font-family: "OpenDyslexic";
}
nav {
color: var(--foreground);
background-color: var(--background);
font-family: "OpenDyslexic Mono", monospace;
}
@layer utilities {
.text-balance {
text-wrap: balance;
}
}

View File

@ -1,39 +0,0 @@
/**
* @copyright nhcarrigan
* @license Naomi's Public License
* @author Naomi Carrigan
*/
import { KoikatsuComponent } from "../../components/koikatsu";
import { Rule } from "../../components/rule";
import { Koikatsu } from "../../config/Koikatsu";
import type { JSX } from "react";
/**
* Renders the /games page.
* @returns A React Component.
*/
const KoikatsuPage = (): JSX.Element => {
return (
<main
className="w-[95%] text-center
max-w-4xl m-auto mt-16 mb-16 rounded-lg"
>
<h1 className="text-5xl">{`Koikatsu`}</h1>
<section>
<p className="mb-2">{`Images of Naomi generated in Koikatsu. Note that the list of images is dynamically generated, so we aren't able to provide alt text for these.`}</p>
<Rule />
<div className="grid sm:grid-cols-2 lg:grid-cols-3 grid-cols-1 gap-y-5">
{Koikatsu.toSorted((a, b) => {
return a.localeCompare(b);
}).map((img) => {
return (
<KoikatsuComponent img={img} key={img} />
);
})}
</div>
</section>
</main>
);
};
export default KoikatsuPage;

View File

@ -1,69 +0,0 @@
/**
* @copyright nhcarrigan
* @license Naomi's Public License
* @author Naomi Carrigan
*/
import { Inter } from "next/font/google";
import Script from "next/script";
import { Navigation } from "../components/navigation";
import type { Metadata } from "next";
import type { JSX, ReactNode } from "react";
// eslint-disable-next-line import/no-unassigned-import
import "./globals.css";
// eslint-disable-next-line new-cap
const inter = Inter({ subsets: [ "latin" ] });
const metadata: Metadata = {
description:
// eslint-disable-next-line stylistic/max-len
"This page tells you everything you could ever want to know about Naomi and her consulting firm nhcarrigan.",
openGraph: {
images: "https://cdn.nhcarrigan.com/background.png",
},
title: "Naomi's Portfolio",
twitter: {
card: "summary_large_image",
images: "https://cdn.nhcarrigan.com/background.png",
site: "@naomi_lgbt",
},
};
/**
* The top-level wrapper for the React application.
* Handles mounting the shadow DOM.
* @param opts - The rendering options.
* @param opts.children - The children elements to render.
* @returns A JSX element.
*/
const RootLayout = ({
children,
}: Readonly<{
children: ReactNode;
}>): JSX.Element => {
return (
<html lang="en">
<Script
async={true}
defer={true}
src="https://cdn.nhcarrigan.com/headers/index.js"
strategy={"afterInteractive"}
type="text/javascript"
></Script>
<link
href="https://cdn.nhcarrigan.com/logo.png"
rel="icon"
sizes="any"
/>
<body className={inter.className}>
<header>
<Navigation />
</header>
{children}
</body>
</html>
);
};
export { metadata };
export default RootLayout;

View File

@ -1,222 +0,0 @@
/**
* @copyright nhcarrigan
* @license Naomi's Public License
* @author Naomi Carrigan
*/
import type { JSX } from "react";
/**
* Renders the /manifesto page.
* @returns A React Component.
*/
const Manifesto = (): JSX.Element => {
return (
<main className="w-4/5 text-center max-w-4xl m-auto mt-16 mb-16 rounded-lg">
<h1 className="text-3xl">{`The Lion, The Witch, The Audacity of This Bitch`}</h1>
<p className="text-2xl italic">{`Naomi's Transfemme Manifesto`}</p>
<p>
{`In a world of binaries and boundaries, we emerge - glorious, glistening,
and unapologetically ourselves. We are the lionesses who refused to be
tamed, the witches who brew potions of self-love, and the audacious
beings who dared to rewrite the rules of gender. This is our manifesto,
our spell-book, our battle cry.`}
</p>
<h2 className="text-2xl">{`I. We Are the Lions`}</h2>
<ol>
<li>
{`Our manes are diverse: short, long, neon, natural - each strand a
testament to our journey.`}
</li>
<li>
{`We prowl through life with grace, strength, and an occasional stumble
(because even lionesses trip sometimes, darling).`}
</li>
<li>
{`Our roars echo through boardrooms, classrooms, and everywhere we have
been told to stay silent.`}
</li>
<li>
{`We fiercely protect our pride - our chosen family, our allies, our
community.`}
</li>
<li>
{`Like lions, we bask in the sun of our authenticity, soaking up the
warmth of self-acceptance.`}
</li>
</ol>
<h2 className="text-2xl">{`II. We Are the Witches`}</h2>
<ol>
<li>
{`Our spellbook is filled with incantations of self-affirmation and
hexes against transphobia.`}
</li>
<li>
{`We stir cauldrons of change, mixing potions of progress and elixirs of
equality.`}
</li>
<li>
{`Our wands (be they makeup brushes, pens, or literal wands) cast spells
of transformation.`}
</li>
<li>
{`We commune with the spirits of our trans ancestors, drawing strength
from their legacy.`}
</li>
<li>
{`In our coven, every body is sacred, every identity valid, every
expression magical.`}
</li>
</ol>
<h2 className="text-2xl">{`III. We Have the Audacity`}</h2>
<ol>
<li>
{`We have the audacity to exist loudly in a world that wishes us to be
quiet.`}
</li>
<li>
{`We dare to love our bodies, curves, edges, and all, defying those who
say we should not.`}
</li>
<li>
{`We boldly claim our place in women's spaces, sports, and
narratives.`}
</li>
<li>
{`We redefine beauty standards with every strut, sashay, and hair flip.`}
</li>
<li>
{`We have the gall to demand respect, rights, and recognition - and
honey, we look fabulous doing it.`}
</li>
</ol>
<h2 className="text-2xl">{`IV. Our Decrees`}</h2>
<ol>
<li>
{`We decree that gender is a playground, not a prison. Swing on the
monkey bars of masculinity, slide down the curves of femininity, or
build sandcastles of androgyny.`}
</li>
<li>
{`We proclaim that our bodies are our own, to modify or maintain as we
see fit. Your opinion on our transitions is like our facial hair -
unwanted and about to be removed.`}
</li>
<li>
{`We declare our right to safe spaces, medical care, and public
restrooms without fear or judgment.`}
</li>
<li>
{`We assert our humanity in the face of legislation that tries to erase
us. Our existence is not up for debate.`}
</li>
<li>
{`We affirm our right to joy, love, and celebration. Our lives are not
just about struggle - we're here to thrive, baby!`}
</li>
</ol>
<h2 className="text-2xl">{`V. Our Commitments`}</h2>
<ol>
<li>
{`We vow to lift as we climb, ensuring no trans sibling is left behind.`}
</li>
<li>
{`We pledge to celebrate the diversity within our community - every
shade, shape, and expression of transness.`}
</li>
<li>
{`We promise to continue educating, even when it's exhausting, because
knowledge is the enemy of ignorance.`}
</li>
<li>
{`We commit to loving ourselves fiercely, even on days when the world
makes it hard.`}
</li>
<li>
{`We dedicate ourselves to creating art, music, literature, and memes
that tell our stories and make our voices heard.`}
</li>
</ol>
<h2 className="text-2xl">{`VI. The Transfemme Toolbox`}</h2>
<ol>
<li>{`Eyeliner sharp enough to wing and to slay our enemies.`}</li>
<li>
{`A vocabulary expansive enough to articulate our identities and to
eloquently tell transphobes where to go.`}
</li>
<li>
{`Heels high enough to reach new heights (and flats comfortable enough
for when the revolution requires running).`}
</li>
<li>
{`A chosen name that feels like home and a dead name composted for
future growth.`}
</li>
<li>
{`A support network of fellow lions, witches, and audacious bitches to
remind us we're not alone.`}
</li>
</ol>
<h2 className="text-2xl">{`VII. Our Vision of the Future`}</h2>
<p>{`In our ideal world:`}</p>
<ol>
<li>
{`Gender reveal parties are replaced by "I'll reveal my gender when I'm
good and ready" parties.`}
</li>
<li>
{`The only time we're asked about our genitals is by our doctors or
consensual partners.`}
</li>
<li>{`Trans joy is as commonplace as cis assumptions once were.`}</li>
<li>
{`Our stories are told by us, not about us, in media, literature, and
history books.`}
</li>
<li>
{`The audacity of our existence is celebrated, not merely tolerated.`}
</li>
</ol>
<h2 className="text-2xl">{`The Tea is Served`}</h2>
<p>
{`So here we stand, in all our lionhearted, witchy, audacious glory. We've
stirred the pot, we've cast our spells, we've roared our truths. The
teacup of tradition lays shattered at our feet, and darling, the brew
we're serving now is a potent blend of authenticity, resistance, and
fierce, uncompromising love.`}
</p>
<p>
{`To those who support us: we see you, we appreciate you, we invite you to
roar alongside us. To those who don't understand us: we invite you to
listen, to learn, and to expand your world. To those who oppose us: your
time is up, your reign is over, the future is gloriously,
unapologetically trans.`}
</p>
<p>
{`Remember, we didn't come this far, break this many barriers, and perfect
our contouring skills just to be anything less than the majestic,
magical, audacious bitches we are.`}
</p>
<p className="text-2xl">
{`The lion has spoken. The witch has cast her spell. This bitch is here to
stay.`}
</p>
<p className="text-3xl">
{`Long live the transfemme revolution! 🦁✨👑💄🏳️‍⚧️`}
</p>
</main>
);
};
export default Manifesto;

View File

@ -1,173 +0,0 @@
/**
* @copyright nhcarrigan
* @license Naomi's Public License
* @author Naomi Carrigan
*/
import Image from "next/image";
import { Rule } from "../../components/rule";
import type { JSX } from "react";
/**
* Renders the /manual page.
* @returns A React Component.
*/
const Manual = (): JSX.Element => {
return (
<main className="w-4/5 text-center max-w-4xl m-auto mt-16 mb-16 rounded-lg">
<h1 className="text-5xl">{`Naomi's User Manual`}</h1>
<p className="text-3xl">{`Model T42-P9000`}</p>
<section>
<p className="mb-2">
{`Hiya! This page is meant to give you a run-down of what working with
me is like. It's like a li'l insight into the way I best
interact with people and perform on a team.`}
</p>
<Image
alt="If you knew I was so unstable, why'd you hire me?"
className="m-auto"
height={500}
src="https://cdn.nhcarrigan.com/hire.jpeg"
width={500}
/>
<Rule />
</section>
<section>
<h2 className="text-3xl">{`My Values`}</h2>
<p className="mb-2">
{`I tend to be very firm in my values, to the degree that I shy away
from organisations or projects which do not align with my ethics.`}
</p>
<ul className="w-4/5 m-auto">
<li
className="mb-2 relative before:content-['🩵']
before:absolute before:left-[-1em]"
>
{`First and foremost, do not pass judgement. I will not begrudge you
for your religious beliefs, political alignments, or any other
aspects of your life. And I expect the same courtesy in return.
You do not have to accept who I am, or support my choices, but we
need to maintain a respectful and cordial professional
relationship. Expressing hateful, mean-spirited, or vitriolic
comments does not foster such an environment, and my tolerance for
such is nil.`}
</li>
<li
className="mb-2 relative before:content-['🩵']
before:absolute before:left-[-1em]"
>
{`Second, we shall do no harm. I very strongly believe that
technology is meant to advance our society, not regress it.
Software should not be used to automate people's careers
away, or replace creative works with pale imitations, or
harass/target someone, or restrict access to information.`}
</li>
</ul>
<Rule />
</section>
<section>
<h2 className="text-3xl">{`Environment`}</h2>
<p className="mb-2">
{`I have found that I best thrive and produce the greatest works in
specific environments.`}
</p>
<ul className="w-4/5 m-auto">
<li
className="mb-2 relative before:content-['🩵']
before:absolute before:left-[-1em]"
>
{`Ideas should be freely discussed, challenged, and evaluated. I am
not a "yes girl" to blindly follow orders. If I hear a
plan that I think misses the mark, I will absolutely voice my
concerns. And I welcome the same scrutiny in return. Discussion
needs to be constructive and fruitful - if we're going around
in circles, it's time to table it and sleep on our thoughts.`}
</li>
<li
className="mb-2 relative before:content-['🩵']
before:absolute before:left-[-1em]"
>
{`We are not our ideas, however. "This is bad and you should
feel bad" helps no one. "I'm not sure that is the
best approach, can we consider doing this instead?" keeps the
conversation focused on the right things and moving forward.`}
</li>
<li
className="mb-2 relative before:content-['🩵']
before:absolute before:left-[-1em]"
>
{`ADHD means my productivity is highly fluctuating. There are days
where I can sit and bang out a week of work in 16 hours, and there
are days where I stare mindlessly at the screen and then realise
the sun has set already. Flexibility in both schedule and
deadlines is very important to me.`}
</li>
<li
className="mb-2 relative before:content-['🩵']
before:absolute before:left-[-1em]"
>
{`Likewise, insomnia can rear its ugly head and absolutely wreck my
sleep schedule without any warning. Asynchronous comms are always
preferred over meetings, but if a meeting must happen the
afternoon hours are the best. Too early and I'll likely fail
to wake up. Too late and I might be incoherent.`}
</li>
<li
className="mb-2 relative before:content-['🩵']
before:absolute before:left-[-1em]"
>
{`If given something like a Trello or a Monday board, I will 100%
make it pretty and load every single task ever on there. I'm
a sucker for organising workloads and the easiest way for me to be
transparent about the work I'm doing is to just let you look
at a task board. If you say "what did you do yesterday"
I will not remember this for I have slept since then.`}
</li>
</ul>
<Rule />
</section>
<section>
<h2 className="text-3xl">{`Communication`}</h2>
<p>
{`As with many people, there are certain approaches to communication
that are more effective for me.`}
</p>
<ul className="w-4/5 m-auto">
<li
className="mb-2 relative before:content-['🩵']
before:absolute before:left-[-1em]"
>
{`Don't just say "hello" in my DMs or ping me without
context. You'll pull me out of a workflow to wait for the
rest of the message. Send it all at once, or save the ping for the
last part.`}
</li>
<li
className="mb-2 relative before:content-['🩵']
before:absolute before:left-[-1em]"
>
{`I have generalised anxiety disorder. Please for the love of all
things, do NOT say "we need to talk" or "do you
have time to meet". I will 100% sit there right up until the
meeting starts stressing about getting fired and not actually
getting any work done. If you need to call me out, just rip the
bandage off and come out of the gate with it.`}
</li>
<li
className="mb-2 relative before:content-['🩵']
before:absolute before:left-[-1em]"
>
{`I dunno if you noticed the tone changed in this document about a
million times. That's pretty much Naomi in a nutshell.
I'll go from collected and eloquent to manic and sending
messages faster than Discord can process. I try my hardest to stay
professional, but ADHD makes that very hard. I'll swear
sometimes, I'll say totally off-the-wall things. But I really
do try!`}
</li>
</ul>
</section>
</main>
);
};
export default Manual;

View File

@ -1,48 +0,0 @@
/**
* @copyright nhcarrigan
* @license Naomi's Public License
* @author Naomi Carrigan
*/
"use client";
import Script from "next/script";
import type { JSX } from "react";
/**
* Renders the /polycule page.
* @returns A React Component.
*/
const Newsletter = (): JSX.Element => {
return (
<>
<main className="w-4/5 text-center
max-w-4xl m-auto mt-16 mb-1 rounded-lg">
<h1 className="text-5xl">{`Newsletter`}</h1>
<p>{`Don't want to join our chat server? Not a fan of our other platforms for announcing product updates? You can subscribe to our newsletter to receive the same information via a regular ol' email.`}</p>
</main>
<style>
{`.hbspt-form {
max-width: 750px;
margin: auto;
background-color: #04624f;
border-radius: 1rem;
padding: 1rem;
margin-bottom: 100px;
font-family: "Fira Code", monospace;
}`}
</style>
<Script
src="//js.hsforms.net/forms/embed/v2.js"
strategy="beforeInteractive"
type="text/javascript"
></Script>
<Script strategy="afterInteractive">
{`hbspt.forms.create({
portalId: "47086586",
formId: "1ed1ea33-a8f4-4956-8ccd-f72f44765ad9",
});`}
</Script>
</>
);
};
export default Newsletter;

View File

@ -1,102 +0,0 @@
/**
* @copyright nhcarrigan
* @license Naomi's Public License
* @author Naomi Carrigan
*/
import { faUpRightFromSquare } from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import Image from "next/image";
import React, { type JSX } from "react";
import { NavItems } from "../config/NavItems";
const generateRandomColor = (): string => {
return `#${Math.floor(Math.random() * 16_777_215).
toString(16).
padStart(6, "0")}`;
};
const getLuminance = (hexColor: string): number => {
const r = Number.parseInt(hexColor.slice(1, 3), 16);
const g = Number.parseInt(hexColor.slice(3, 5), 16);
const b = Number.parseInt(hexColor.slice(5, 7), 16);
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
const a: [number, number, number] = [ r, g, b ].map((v) => {
const w = v / 255;
return w <= 0.039_28
? w / 12.92
: Math.pow((w + 0.055) / 1.055, 2.4);
}) as [number, number, number];
const rl = a[0] * 0.2126;
const gl = a[1] * 0.7152;
const bl = a[2] * 0.0722;
return rl + gl + bl;
};
const generateColorPair = (): { background: string; color: string } => {
const backgroundColor = generateRandomColor();
const backgroundLuminance = getLuminance(backgroundColor);
const textColor
= backgroundLuminance > 0.5
? "#00000099"
: "#FFFFFF99";
return {
background: backgroundColor,
color: textColor,
};
};
/**
* Renders the main React component.
* @returns A JSX element.
*/
const Home = (): JSX.Element => {
return (
<main className="w-4/5 text-center max-w-4xl m-auto mt-16 mb-16 rounded-lg">
<h1 className="text-4xl mb-2">{`Naomi Carrigan`}</h1>
<Image
alt="Naomi Carrigan"
className="rounded-full m-auto"
height={200}
src="https://cdn.nhcarrigan.com/profile.png"
width={200}
/>
<p className="text-2xl">{`Software Engineer | Community Manager | VTuber`}</p>
{NavItems.map((item, index) => {
const { background, color } = generateColorPair();
return (
<a
className="flex max-w-[300px] w-[95%] m-auto justify-between
items-center border-solid border-2 rounded-3xl h-14 p-8 my-4"
href={item.href}
key={item.href}
rel={item.href.startsWith("http")
? "noreferrer"
: ""}
style={{
background: background,
borderColor: color,
color: color,
}}
target={item.href.startsWith("http")
? "_blank"
: "_self"}
>
{index % 2 === 1
? "🩷"
: "🩵"} {item.text}{" "}
{item.href.startsWith("http")
? <FontAwesomeIcon
aria-label="External link"
icon={faUpRightFromSquare} />
: null}
</a>
);
})}
</main>
);
};
export default Home;

View File

@ -1,42 +0,0 @@
/**
* @copyright nhcarrigan
* @license Naomi's Public License
* @author Naomi Carrigan
*/
import { Partner } from "../../components/partner";
import { Rule } from "../../components/rule";
import { Partners } from "../../config/Partners";
import type { JSX } from "react";
/**
* Renders the /polycule page.
* @returns A React Component.
*/
const Polycule = (): JSX.Element => {
return (
<main className="w-[95%] text-center
max-w-4xl m-auto mt-16 mb-16 rounded-lg">
<h1 className="text-5xl">{`Naomi's Polycule`}</h1>
<section>
<p className="mb-2">
{`Meet the people who love and support Naomi to the ends of the earth.`}
</p>
<Rule />
<div className="w-full">
{Partners.map((member) => {
return <Partner
anniversary={member.anniversary}
avatar={member.avatar}
key={member.name}
name={member.name}
relationship={member.relationship}
url={member.url}
/>;
})}
</div>
</section>
</main>
);
};
export default Polycule;

View File

@ -1,32 +0,0 @@
/**
* @copyright nhcarrigan
* @license Naomi's Public License
* @author Naomi Carrigan
*/
import { Project } from "../../components/project";
import { Projects } from "../../config/Projects";
import type { JSX } from "react";
/**
* Renders the /projects page.
* @returns A React Component.
*/
const ProjectPage = (): JSX.Element => {
return (
<main className="w-4/5 text-center max-w-4xl m-auto mt-16 mb-16 rounded-lg">
<h1 className="text-5xl">{`Our Projects`}</h1>
<p className="text-2xl">{`These are all of the projects we are currently maintaining.`}</p>
<section>
{Projects.toSorted((a, b) => {
return a.name.localeCompare(b.name);
}).map((project) => {
return (
<Project key={project.name} {...project} />
);
})}
</section>
</main>
);
};
export default ProjectPage;

View File

@ -1,137 +0,0 @@
/**
* @copyright nhcarrigan
* @license Naomi's Public License
* @author Naomi Carrigan
*/
/* eslint-disable react/no-unknown-property, react/no-multi-comp */
"use client";
import { VRMLoaderPlugin, type VRM } from "@pixiv/three-vrm";
import { OrbitControls } from "@react-three/drei";
// @ts-expect-error -- It seems like the beta version has type-def issues.
import { Canvas } from "@react-three/fiber";
import { useState, useRef, type ChangeEvent, type JSX, useEffect } from "react";
import { PerspectiveCamera } from "three";
// eslint-disable-next-line import/extensions -- We need this apparently.
import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader.js";
import { Rule } from "../../components/rule";
import { MainVRoid, VRoid } from "../../config/Vroid";
const concatenated = [
MainVRoid,
...VRoid.toSorted((a, b) => {
return a.name.localeCompare(b.name);
}),
];
/**
* Scene setup component for lighting and controls.
* @returns The Three.JS scene.
*/
const SceneSetup = (): JSX.Element => {
return (
<>
{/* Main directional light from front-top */}
{ /* @ts-expect-error -- why */}
<directionalLight
castShadow={true}
intensity={1}
position={[ 0, 5, 5 ]}
/>
{/* Fill light from back */}
{ /* @ts-expect-error -- why */}
<directionalLight
intensity={0.5}
position={[ 0, 3, -5 ]}
/>
{/* Ambient light for overall scene brightness */}
{ /* @ts-expect-error -- why */}
<ambientLight intensity={0.5} />
{/* Orbit controls for camera manipulation */}
<OrbitControls
enablePan={true}
enableRotate={true}
enableZoom={true}
maxDistance={20}
minDistance={1}
target={[ 0, 0.8, 0 ]}
/>
</>
);
};
/**
* Reference component for displaying and interacting with VRM models.
* @returns The reference page.
*/
const Reference = (): JSX.Element => {
const [ selected, setSelected ] = useState<string>(MainVRoid.file);
const aspect = 1920 / 1080;
const { current: camera }
= useRef(new PerspectiveCamera(30, aspect, 0.1, 1000));
const handleChange = (event: ChangeEvent): void => {
const { target } = event;
if (target instanceof HTMLSelectElement) {
setSelected(target.value);
}
};
const loader = new GLTFLoader();
loader.register((parser) => {
return new VRMLoaderPlugin(parser);
});
const [ model, setModel ] = useState<JSX.Element | null>(null);
useEffect(() => {
loader.load(`https://cdn.nhcarrigan.com/vrm/${selected}`, (gltf) => {
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
const { vrm } = gltf.userData as { vrm: VRM };
if (vrm.lookAt) {
vrm.lookAt.target = camera;
}
// Center the model
vrm.scene.position.set(0, 0, 0);
// Add rotation if needed
vrm.scene.rotation.y = Math.PI;
/* @ts-expect-error -- why */
setModel(<primitive object={vrm.scene} />);
});
}, [ selected ]);
useEffect(() => {
// Position camera to better frame the model
camera.position.set(0, 0, 3);
}, [ camera ]);
return (
<main className="w-4/5 text-center max-w-4xl m-auto mt-16 mb-16 rounded-lg">
<h1 className="text-5xl">{`Reference`}</h1>
<section>
<p className="mb-2">{`Want to draw art of Naomi? Here's a fully interactive reference page with all of her model's outfits!`}</p>
<select
className="px-2 bg-[--background] border-2
border-solid border-[--foreground]"
// eslint-disable-next-line react/jsx-no-bind
onChange={handleChange}
>
{concatenated.map((vroid) => {
return <option key={vroid.name} value={vroid.file}>
{vroid.name}
</option>;
})}
</select>
<Rule />
</section>
<div className="h-[600px]">
<Canvas camera={camera}>
<SceneSetup />
{model}
</Canvas>
</div>
</main>
);
};
export default Reference;

View File

@ -1,48 +0,0 @@
/**
* @copyright nhcarrigan
* @license Naomi's Public License
* @author Naomi Carrigan
*/
import { Review } from "../../components/review";
import { Rule } from "../../components/rule";
import { Testimonials } from "../../config/Testimonials";
import type { JSX } from "react";
/**
* Renders the /reviews page.
* @returns A React Component.
*/
const Reviews = (): JSX.Element => {
return (
<main className="w-[95%] text-center max-w-4xl
m-auto mt-16 mb-16 rounded-lg">
<h1 className="text-5xl">{`Client Reviews`}</h1>
<section>
<p className="mb-2">
{`We think we're pretty great to work with, but don't take
our word for it. Here's what our clients have to say.`}
</p>
<Rule />
<ol className="relative border-s border-[--primary] w-4/5 m-auto">
{Testimonials.toSorted(
(a, b) => {
return b.date.getTime() - a.date.getTime();
},
).map((review) => {
return <Review
content={review.content}
date={review.date}
key={review.date.toISOString()}
name={review.name}
sourceIcon={review.sourceIcon}
sourceName={review.sourceName}
sourceUrl={review.sourceUrl}
/>;
})}
</ol>
</section>
</main>
);
};
export default Reviews;

View File

@ -1,48 +0,0 @@
/**
* @copyright nhcarrigan
* @license Naomi's Public License
* @author Naomi Carrigan
*/
"use client";
import Script from "next/script";
import type { JSX } from "react";
/**
* Renders the /polycule page.
* @returns A React Component.
*/
const Sales = (): JSX.Element => {
return (
<>
<main className="w-4/5 text-center
max-w-4xl m-auto mt-16 mb-1 rounded-lg">
<h1 className="text-5xl">{`Sales Inquiry`}</h1>
<p>{`This form allows you to send a general sales inquiry to our team. Upon submission, you will be taken to our consultation booking page. Note that general inquiries are low priority - if you need an urgent response, you should use the booking page to schedule a paid consultation.`}</p>
</main>
<style>
{`.hbspt-form {
max-width: 750px;
margin: auto;
background-color: #04624f;
border-radius: 1rem;
padding: 1rem;
margin-bottom: 100px;
font-family: "Fira Code", monospace;
}`}
</style>
<Script
src="//js.hsforms.net/forms/embed/v2.js"
strategy="beforeInteractive"
type="text/javascript"
></Script>
<Script strategy="afterInteractive">
{`hbspt.forms.create({
portalId: "47086586",
formId: "fa90d8cb-40e2-4f36-b7a8-2bda6ac1d0cb",
});`}
</Script>
</>
);
};
export default Sales;

View File

@ -1,42 +0,0 @@
/**
* @copyright nhcarrigan
* @license Naomi's Public License
* @author Naomi Carrigan
*/
import { Member } from "../../components/member";
import { Rule } from "../../components/rule";
import { TeamMembers } from "../../config/TeamMembers";
import type { JSX } from "react";
/**
* Renders the /team page.
* @returns A React Component.
*/
const Team = (): JSX.Element => {
return (
<main className="w-[95%] text-center
max-w-4xl m-auto mt-16 mb-16 rounded-lg">
<h1 className="text-5xl">{`Our Team`}</h1>
<section>
<p className="mb-2">
{`Meet the people behind nhcarrigan's success!`}
</p>
<Rule />
<div className="w-full">
{TeamMembers.map((member) => {
return <Member
avatar={member.avatar}
joinDate={member.joinDate}
key={member.name}
name={member.name}
role={member.role}
url={member.url}
/>;
})}
</div>
</section>
</main>
);
};
export default Team;

View File

@ -1,126 +0,0 @@
/* eslint-disable stylistic/max-len */
/**
* @copyright nhcarrigan
* @license Naomi's Public License
* @author Naomi Carrigan
*/
import { Rule } from "../../components/rule";
import type { JSX } from "react";
/**
* Renders the /tech page.
* @returns A React Component.
*/
const PlayPage = (): JSX.Element => {
return (
<main
className="w-[95%] text-center
max-w-4xl m-auto mt-16 mb-16 rounded-lg"
>
<h1 className="text-5xl">{`Technologies`}</h1>
<p className="mb-2">
{`These are the technologies I use on a regular basis.`}
</p>
<section>
<Rule />
<h2 className="text-3xl">{`Environment`}</h2>
<div className="w-full flex flex-wrap justify-evenly">
<img
alt="Arch Linux"
className="w-[100px]"
src="https://cdn.jsdelivr.net/gh/devicons/devicon@latest/icons/archlinux/archlinux-original.svg"
/>
<img
alt="VSCode"
className="w-[100px]"
src="https://cdn.jsdelivr.net/gh/devicons/devicon@latest/icons/vscode/vscode-original.svg"
/>
<img
alt="Prisma"
className="w-[100px]"
src="https://cdn.jsdelivr.net/gh/devicons/devicon@latest/icons/prisma/prisma-original.svg"
/>
<img
alt="Node.js"
className="w-[100px]"
src="https://cdn.jsdelivr.net/gh/devicons/devicon@latest/icons/nodejs/nodejs-original.svg"
/>
</div>
</section>
<section>
<Rule />
<h2 className="text-3xl">{`Languages`}</h2>
<div className="w-full flex flex-wrap justify-evenly">
<img
alt="JavaScript"
className="w-[100px]"
src="https://cdn.jsdelivr.net/gh/devicons/devicon@latest/icons/javascript/javascript-original.svg"
/>
<img
alt="TypeScript"
className="w-[100px]"
src="https://cdn.jsdelivr.net/gh/devicons/devicon@latest/icons/typescript/typescript-original.svg"
/>
<img
alt="Python"
className="w-[100px]"
src="https://cdn.jsdelivr.net/gh/devicons/devicon@latest/icons/python/python-original.svg"
/>
<img
alt="Dotnet"
className="w-[100px]"
src="https://cdn.jsdelivr.net/gh/devicons/devicon@latest/icons/dotnetcore/dotnetcore-original.svg"
/>
<img
alt="Kotlin"
className="w-[100px]"
src="https://cdn.jsdelivr.net/gh/devicons/devicon@latest/icons/kotlin/kotlin-original.svg"
/>
<img
alt="Rust"
className="w-[100px]"
src="https://cdn.jsdelivr.net/gh/devicons/devicon@latest/icons/rust/rust-original.svg"
/>
<img
alt="Ruby"
className="w-[100px]"
src="https://cdn.jsdelivr.net/gh/devicons/devicon@latest/icons/ruby/ruby-original.svg"
/>
</div>
</section>
<section>
<Rule />
<h2 className="text-3xl">{`Coming Soon!`}</h2>
<div className="w-full flex flex-wrap justify-evenly">
<img
alt="Haskell"
className="w-[100px]"
src="https://cdn.jsdelivr.net/gh/devicons/devicon@latest/icons/haskell/haskell-original.svg"
/>
<img
alt="Zig"
className="w-[100px]"
src="https://cdn.jsdelivr.net/gh/devicons/devicon@latest/icons/zig/zig-original.svg"
/>
<img
alt="Go"
className="w-[100px]"
src="https://cdn.jsdelivr.net/gh/devicons/devicon@latest/icons/go/go-original.svg"
/>
<img
alt="Dart"
className="w-[100px]"
src="https://cdn.jsdelivr.net/gh/devicons/devicon@latest/icons/dart/dart-original.svg"
/>
<img
alt="Flutter"
className="w-[100px]"
src="https://cdn.jsdelivr.net/gh/devicons/devicon@latest/icons/flutter/flutter-original.svg"
/>
</div>
</section>
</main>
);
};
export default PlayPage;

View File

@ -1,104 +0,0 @@
/**
* @copyright nhcarrigan
* @license Naomi's Public License
* @author Naomi Carrigan
*/
import { faCalendar, faTasks } from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { Job } from "../../components/job";
import { Rule } from "../../components/rule";
import { Jobs } from "../../config/Jobs";
import { Volunteer } from "../../icons/Volunteer";
import type { JSX } from "react";
/**
* Renders the /work page.
* @returns A React Component.
*/
const Work = (): JSX.Element => {
return (
<main className="w-4/5 text-center max-w-4xl m-auto mt-16 mb-16 rounded-lg">
<h1 className="text-5xl">{`Our Work`}</h1>
<p>
{`We run a software engineering and community management firm known as
nhcarrigan.`}
</p>
<Rule />
<section>
<h2 className="text-3xl">{`Legend`}</h2>
<p>
{`Our work is listed here in reverse chronological order. The symbols
and colours have a specific meaning:`}
</p>
<table className="m-auto w-1/2">
<thead>
<tr>
<th>{`Symbol`}</th>
<th>{`Meaning`}</th>
</tr>
</thead>
<tbody>
<tr>
<td>
<FontAwesomeIcon className="h-14" icon={faCalendar} />
</td>
<td>{`Fixed-Rate Contract (hourly/salary)`}</td>
</tr>
<tr>
<td>
<FontAwesomeIcon className="h-14" icon={faTasks} />
</td>
<td>{`Project-based Contract`}</td>
</tr>
<tr>
<td>
<FontAwesomeIcon className="h-14" icon={Volunteer} />
</td>
<td>{`Pro-bono Contract`}</td>
</tr>
<tr>
<td>
<p className="h-14 w-14 border-[--current]
border-double border-4"></p>
</td>
<td className="text-[--current]">{`Current Contract`}</td>
</tr>
<tr>
<td>
<p className="h-14 w-14 border-[--former]
border-dashed border-2"></p>
</td>
<td className="text-[--former]">{`Former Contract`}</td>
</tr>
</tbody>
</table>
<Rule />
</section>
<section>
<h2 className="text-3xl">{`Timeline`}</h2>
<ol className="relative border-s border-[--primary] w-4/5 m-auto">
{Jobs.toSorted((a, b) => {
return b.start.getTime() - a.start.getTime();
}).map(
(job) => {
return <Job
company={job.company}
description={job.description}
end={job.end}
key={`${job.title} - ${job.company}`}
link={job.link}
logo={job.logo}
start={job.start}
title={job.title}
type={job.type}
/>;
}
,
)}
</ol>
</section>
</main>
);
};
export default Work;

View File

@ -1,80 +0,0 @@
/**
* @copyright nhcarrigan
* @license Naomi's Public License
* @author Naomi Carrigan
*/
import type { JSX } from "react";
interface ActivityProperties {
readonly type: string;
readonly date: Date;
readonly repo: string;
readonly repoName: string;
readonly heart: string;
}
const TypeToString: Record<string, string> = {
DeleteEvent: "deleted a branch on",
IssueCommentEvent: "commented on",
IssuesEvent: "created or updated an issue in",
PullRequestEvent: "created or merged a PR in",
PullRequestReviewCommentEvent: "commented on a PR in",
PullRequestReviewEvent: "reviewed a PR in",
PushEvent: "committed to",
close_issue: "closed an issue in",
commit_repo: "committed to",
create_branch: "created a branch in",
create_issue: "created an issue in",
create_pull_request: "created a PR in",
delete_branch: "deleted a branch on",
merge_pull_request: "merged a PR in",
};
const getType = (type: string): string => {
return TypeToString[type] ?? `performed a ${type}`;
};
/**
* Renders the view for a Github or Codeberg activity.
* @param properties - The activity to render.
* @returns A JSX element.
*/
export const Activity = (properties: ActivityProperties): JSX.Element => {
const { type, date, repo, repoName, heart } = properties;
return (
<li className="ms-6">
<span
className="absolute flex items-center
justify-center w-6 h-6 rounded-full -start-3"
>
{heart}
</span>
<div
className="items-center justify-between
p-4 bg-white border border-gray-200 rounded-lg
shadow-sm sm:flex dark:bg-gray-700 dark:border-gray-600"
>
<time
className="mb-1 text-xs font-normal
text-gray-400 sm:order-last sm:mb-0"
>
{date.toLocaleString("en-GB")}
</time>
<div
className="text-sm font-normal
text-gray-500 lex dark:text-gray-300"
>
{`Naomi has ${getType(type)} `}
<a
className="font-semibold text-[#abfcec] hover:underline"
href={repo}
rel="noopener noreferrer"
target="_blank"
>
{repoName}
</a>{" "}
</div>
</div>
</li>
);
};

View File

@ -1,49 +0,0 @@
/**
* @copyright nhcarrigan
* @license Naomi's Public License
* @author Naomi Carrigan
*/
import Image from "next/image";
import type { JSX } from "react";
interface ArtProperties {
readonly name: string;
readonly img: string;
readonly artist: string;
readonly url: string;
readonly alt: string;
}
/**
* Renders the view for an art piece.
* @param properties - The art to render.
* @returns A JSX element.
*/
export const ArtComponent = (properties: ArtProperties): JSX.Element => {
const { name, img, artist, url, alt } = properties;
return (
<div className="w-[300px] h-[300px] border-2
border-solid border-[--foreground] m-auto text-center items-center">
<p className="text-l">
{`${name} by `}
<a className="underline" href={url} rel="noreferrer" target="_blank">
{artist}
</a>
</p>
<a
href={`https://cdn.nhcarrigan.com/art/${img}`}
rel="noreferrer"
target="_blank"
>
<Image
alt={alt}
className="m-auto object-contain max-h-[250px] max-w-[250px]"
height={250}
src={`https://cdn.nhcarrigan.com/art/${img}`}
width={250}
/>
</a>
</div>
);
};

View File

@ -1,50 +0,0 @@
/**
* @copyright nhcarrigan
* @license Naomi's Public License
* @author Naomi Carrigan
*/
import Image from "next/image";
import type { JSX } from "react";
interface CertProperties {
readonly name: string;
readonly fileName: string;
readonly issuer: string;
readonly date: Date;
}
/**
* Renders the view for a certification.
* @param properties - The certification to render.
* @returns A JSX element.
*/
export const Certification = (properties: CertProperties): JSX.Element => {
const { name, fileName, issuer, date } = properties;
return (
<div className="w-[300px] h-[300px] border-2
border-solid border-[--foreground] m-auto text-center items-center">
<p className="text-xl">{name}</p>
<a
href={`https://cdn.nhcarrigan.com/certifications/${fileName}`}
rel="noreferrer"
target="_blank"
>
<Image
alt={name}
className="m-auto"
height={250}
src={`https://cdn.nhcarrigan.com/certifications/${fileName}`}
width={250}
/>
</a>
<p>{issuer}</p>
<p>
{date.toLocaleDateString("en-GB", {
month: "long",
year: "numeric",
})}
</p>
</div>
);
};

View File

@ -1,50 +0,0 @@
/**
* @copyright nhcarrigan
* @license Naomi's Public License
* @author Naomi Carrigan
*/
import Image from "next/image";
import type { JSX } from "react";
interface GameProperties {
readonly name: string;
readonly img: string;
readonly url: string;
readonly alt: string;
}
/**
* Renders the view for a game.
* @param properties - The game to render.
* @returns A JSX element.
*/
export const Game = (properties: GameProperties): JSX.Element => {
const { name, img, url, alt } = properties;
return (
<div className="w-[300px] h-[300px] border-2
border-solid border-[--foreground] m-auto text-center items-center">
<a
className="text-xl underline"
href={url}
rel="noopener noreferrer"
target="_blank"
>
<p>{name}</p>
</a>
<a
href={`https://cdn.nhcarrigan.com/games/${img}`}
rel="noreferrer"
target="_blank"
>
<Image
alt={alt}
className="m-auto object-contain max-h-[250px] max-w-[250px]"
height={250}
src={`https://cdn.nhcarrigan.com/games/${img}`}
width={250}
/>
</a>
</div>
);
};

View File

@ -1,70 +0,0 @@
/**
* @copyright nhcarrigan
* @license Naomi's Public License
* @author Naomi Carrigan
*/
import type { JSX } from "react";
interface IssueProperties {
labels: Array<string>;
number: number;
title: string;
url: string;
body: string;
}
/**
* Renders the view for a Codeberg issue.
* @param properties - The issue to render.
* @returns A JSX element.
*/
export const Issue = (properties: IssueProperties): JSX.Element => {
const { labels, number, title, url, body } = properties;
return (
<div className="p-6 mb-2 bg-[--foreground] text-[--background]
border border-gray-200 rounded-lg shadow">
<h2 className="mb-2 text-2xl font-bold tracking-tight">{`#${number.toString()} ${title}`}</h2>
{labels.map((label) => {
return (
<span
className="inline-flex items-center bg-pink-100
text-pink-800 text-xsfont-medium px-2.5 py-0.5
rounded-full dark:bg-pink-900 dark:text-pink-300"
key={label}
>
{label}
</span>
);
})}
<p className="mb-3 font-normal text-gray-700 dark:text-gray-400">
{body}
</p>
<a
className="inline-flex items-center px-3 py-2 text-sm
font-medium text-center text-[--foreground] bg-[--background]
rounded-lg focus:ring-4 focus:outline-none focus:ring-blue-300
dark:focus:ring-blue-800"
href={url}
rel="noopener noreferrer"
target="_blank"
>
{`View Issue`}
<svg
aria-hidden="true"
className="rtl:rotate-180 w-3.5 h-3.5 ms-2"
fill="none"
viewBox="0 0 14 10"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M1 5h12m0 0L9 1m4 4L9 9"
stroke="currentColor"
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth="2"
/>
</svg>
</a>
</div>
);
};

View File

@ -1,112 +0,0 @@
/**
* @copyright nhcarrigan
* @license Naomi's Public License
* @author Naomi Carrigan
*/
"use client";
import {
faCalendar,
faQuestionCircle,
faTasks,
} from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { type JSX, useCallback, useState } from "react";
import { Volunteer } from "../icons/Volunteer";
interface JobProperties {
readonly title: string;
readonly company: string;
readonly start: Date;
readonly end: Date | null;
readonly link: string;
readonly type: "volunteer" | "fixed" | "project" | "hypothetical";
readonly description: string;
readonly logo: string;
}
const IconMap = {
fixed: faCalendar,
hypothetical: faQuestionCircle,
project: faTasks,
volunteer: Volunteer,
};
const getColor
= (type: JobProperties["type"], end: JobProperties["end"]): string => {
if (type === "hypothetical") {
return "text-[--primary]";
}
if (end) {
return "text-[--former]";
}
return "text-[--current]";
};
const getBorder
= (type: JobProperties["type"], end: JobProperties["end"]): string => {
if (type === "hypothetical") {
return "border-[--primary]";
}
if (end) {
return "border-[--former]";
}
return "border-[--current]";
};
/**
* Renders the view for a job.
* @param properties - The job to render.
* @returns A JSX element.
*/
export const Job = (properties: JobProperties): JSX.Element => {
const { title, company, start, end, type, description } = properties;
const [ showDescription, setShowDescription ] = useState(false);
const toggleDescription = useCallback((): void => {
setShowDescription(!showDescription);
}, [ showDescription ]);
const color = getColor(type, end);
const border = getBorder(type, end);
const borderStyle = end
? "border-dashed border-2"
: "border-double border-4";
return (
<li className={`mb-10 ms-6 ${color}`}>
<span
className={`absolute flex items-center justify-center w-6 h-6 bg-[--background] rounded-full -start-3 ${color}`}
>
<FontAwesomeIcon className="text-3xl" icon={IconMap[type]} />
</span>
<h3 className={`flex items-center mb-1 text-lg font-semibold`}>
{`${title} for ${company}`}
</h3>
<time className="block mb-2 text-sm font-normal leading-none">
{start.toLocaleDateString("en-US", {
month: "long",
year: "numeric",
})}{" - "}
{end
? end.toLocaleDateString("en-US", {
month: "long",
year: "numeric",
})
: "Present"}
</time>
{showDescription
? <div
className="mb-4 text-base font-normal"
// eslint-disable-next-line react/no-danger
dangerouslySetInnerHTML={{ __html: description }}
></div>
: null}
<button
className={`inline-flex items-center px-4 py-2 text-sm font-medium ${borderStyle} ${border}`}
onClick={toggleDescription}
type="button"
>
{showDescription
? "Hide Details"
: "Show Details"}
</button>
</li>
);
};

View File

@ -1,36 +0,0 @@
/**
* @copyright nhcarrigan
* @license Naomi's Public License
* @author Naomi Carrigan
*/
import Image from "next/image";
import type { JSX } from "react";
/**
* Renders the view for a koikatsu shot.
* @param props - An object containing the image file name.
* @param props.img - The file name of the image to render.
* @returns A JSX element.
*/
export const KoikatsuComponent = ({ img }: { readonly img: string }):
JSX.Element => {
return (
<div className="w-[300px] border-2
border-solid border-[--foreground] m-auto text-center items-center">
<a
href={`https://cdn.nhcarrigan.com/koikatsu/${img}`}
rel="noreferrer"
target="_blank"
>
<Image
alt="This work is solely decorative. If you'd like alt text,
please reach out in our Discord and we'll be happy to provide it."
className="m-auto object-cover"
height={300}
src={`https://cdn.nhcarrigan.com/koikatsu/${img}`}
width={300}
/>
</a>
</div>
);
};

View File

@ -1,60 +0,0 @@
/**
* @copyright nhcarrigan
* @license Naomi's Public License
* @author Naomi Carrigan
*/
import Image from "next/image";
import type { JSX } from "react";
interface MemberProperties {
readonly name: string;
readonly avatar: string;
readonly role: string;
readonly url: string;
readonly joinDate: Date;
}
/**
* Renders the view for a team member.
* @param properties - The member to render.
* @returns A JSX element.
*/
export const Member = (properties: MemberProperties): JSX.Element => {
const { name, avatar, role, url, joinDate } = properties;
return (
<div className="flex items-start gap-2.5 pb-10 w-full">
<Image
alt={`${name}'s avatar.`}
className="rounded-full"
height={75}
src={`https://cdn.nhcarrigan.com/avatars/${avatar}`}
width={75}
/>
<div
className="flex flex-col w-full leading-1.5
p-4 border-gray-200 bg-gray-100 rounded-e-xl
rounded-es-xl dark:bg-gray-700"
>
<div>
<a
className="text-sm font-semibold text-[#abfcec]"
href={url}
target="noopener noreferrer"
>
{name}
</a>
<p className="text-sm font-normal text-gray-500 dark:text-gray-400">
{joinDate.toLocaleDateString("en-GB", {
month: "long",
year: "numeric",
})}
</p>
</div>
<p className="text-sm font-normal py-2.5 text-gray-900 dark:text-white">
{role}
</p>
</div>
</div>
);
};

View File

@ -1,87 +0,0 @@
/**
* @copyright nhcarrigan
* @license Naomi's Public License
* @author Naomi Carrigan
*/
"use client";
import {
faBars,
faTimes,
faUpRightFromSquare,
} from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import Image from "next/image";
import React, { type JSX, useState, useCallback } from "react";
import { NavItems } from "../config/NavItems";
import { Rule } from "./rule";
/**
* Conditionally renders the navigation component when
* not on the home page.
* @returns A JSX element.
*/
export const Navigation = (): JSX.Element | null => {
const [ isOpen, setIsOpen ] = useState(false);
const toggleMenu = useCallback((): void => {
setIsOpen(!isOpen);
}, [ isOpen ]);
return (
<div className="fixed w-full top-0 z-50"
style={{ fontFamily: "OpenDyslexic Mono" }}>
<nav
className="w-full flex justify-between
items-center h-14 px-4 bg-[--background] text-[--foreground]"
>
<a href="/">
<Image
alt="nhcarrigan's logo"
height={50}
src="https://cdn.nhcarrigan.com/logo.png"
width={50}
/>
</a>
<div className="flex items-center">
<button onClick={toggleMenu} type="button">
<FontAwesomeIcon icon={isOpen
? faTimes
: faBars} size="2x" />
</button>
</div>
</nav>
{isOpen
? <div className="bg-[--background] text-[--foreground]
h-[50vh] overflow-y-auto">
{NavItems.map((item, index) => {
return (
<a
className="block py-2 px-4 text-2xl hover:bg-[--foreground]
hover:text-[--background]"
href={item.href}
key={item.href}
onClick={toggleMenu}
rel={item.href.startsWith("http")
? "noreferrer"
: ""}
target={item.href.startsWith("http")
? "_blank"
: "_self"}
>
{index % 2 === 1
? "🩷"
: "🩵"} {item.text}
{item.href.startsWith("http")
? <FontAwesomeIcon
aria-label="External link"
icon={faUpRightFromSquare} />
: null}
</a>
);
})}
</div>
: null}
<Rule />
</div>
);
};

View File

@ -1,59 +0,0 @@
/**
* @copyright nhcarrigan
* @license Naomi's Public License
* @author Naomi Carrigan
*/
import Image from "next/image";
import type { JSX } from "react";
interface PartnerProperties {
readonly name: string;
readonly avatar: string;
readonly relationship: string;
readonly url: string;
readonly anniversary: Date;
}
/**
* Renders the view for a polycule member.
* @param properties - The member to render.
* @returns A JSX element.
*/
export const Partner = (properties: PartnerProperties): JSX.Element => {
const { name, avatar, relationship, url, anniversary } = properties;
return (
<div className="flex items-start gap-2.5 pb-10 w-full">
<Image
alt={`${name}'s avatar.`}
className="rounded-full"
height={75}
src={`https://cdn.nhcarrigan.com/avatars/${avatar}`}
width={75}
/>
<div className="flex flex-col w-full leading-1.5 p-4
border-gray-200 bg-gray-100 rounded-e-xl
rounded-es-xl dark:bg-gray-700">
<div>
<a
className="text-sm font-semibold text-[#abfcec]"
href={url}
target="noopener noreferrer"
>
{name}
</a>
<p className="text-sm font-normal text-gray-500 dark:text-gray-400">
{anniversary.toLocaleDateString("en-GB", {
day: "numeric",
month: "long",
year: "numeric",
})}
</p>
</div>
<p className="text-sm font-normal py-2.5 text-gray-900 dark:text-white">
{relationship}
</p>
</div>
</div>
);
};

View File

@ -1,101 +0,0 @@
/**
* @copyright nhcarrigan
* @license Naomi's Public License
* @author Naomi Carrigan
*/
import type { JSX } from "react";
interface ProjectProperties {
name: string;
url: string;
source?: string;
description: string;
type: "Website" | "Bot" | "API" | "Game";
}
const Colours: { [key in ProjectProperties["type"]]: string } = {
API: "bg-sky-100 text-sky-900 dark:bg-sky-900 dark:text-sky-100",
Bot:
"bg-purple-100 text-purple-900 dark:bg-purple-900 dark:text-purple-100",
Game: "bg-green-100 text-green-900 dark:bg-green-900 dark:text-green-100",
Website: "bg-amber-100 text-amber-900 dark:bg-amber-900 dark:text-amber-100",
};
/**
* Renders the view for a project.
* @param properties - The project to render.
* @returns A JSX element.
*/
export const Project = (properties: ProjectProperties): JSX.Element => {
const { name, url, source, description, type } = properties;
return (
<div className="p-6 mb-2 bg-[--foreground] text-[--background]
border border-gray-200 rounded-lg shadow w-[50%] m-auto">
<h2 className="mb-2 text-2xl font-bold tracking-tight">{name}</h2>
<span
className={`inline-flex items-center text-xsfont-medium px-2.5 py-0.5
rounded-full ${Colours[type]}`}
>
{type}
</span>
<p className="mb-3 font-normal">
{description}
</p>
<a
className="inline-flex items-center px-3 py-2 text-sm
font-medium text-center text-[--foreground] bg-[--background]
rounded-lg focus:ring-4 focus:outline-none focus:ring-blue-300
dark:focus:ring-blue-800"
href={url}
rel="noopener noreferrer"
target="_blank"
>
{`See Project`}
<svg
aria-hidden="true"
className="rtl:rotate-180 w-3.5 h-3.5 ms-2"
fill="none"
viewBox="0 0 14 10"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M1 5h12m0 0L9 1m4 4L9 9"
stroke="currentColor"
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth="2"
/>
</svg>
</a>
{source === undefined
? null
: <a
className="ml-1 inline-flex items-center px-3 py-2 text-sm
font-medium text-center text-[--foreground] bg-[--background]
rounded-lg focus:ring-4 focus:outline-none focus:ring-blue-300
dark:focus:ring-blue-800"
href={source}
rel="noopener noreferrer"
target="_blank"
>
{`View Source`}
<svg
aria-hidden="true"
className="rtl:rotate-180 w-3.5 h-3.5 ms-2"
fill="none"
viewBox="0 0 14 10"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M1 5h12m0 0L9 1m4 4L9 9"
stroke="currentColor"
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth="2"
/>
</svg>
</a>
}
</div>
);
};

View File

@ -1,60 +0,0 @@
/**
* @copyright nhcarrigan
* @license Naomi's Public License
* @author Naomi Carrigan
*/
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { Rule } from "./rule";
import type { IconDefinition } from "@fortawesome/fontawesome-svg-core";
import type { JSX } from "react";
interface ReviewProperties {
readonly name: string;
readonly date: Date;
readonly content: string;
readonly sourceIcon: IconDefinition;
readonly sourceUrl: string;
readonly sourceName: string;
}
/**
* Renders the view for a review.
* @param properties - The review to render.
* @returns A JSX element.
*/
export const Review = (properties: ReviewProperties): JSX.Element => {
const { name, date, content, sourceIcon, sourceUrl, sourceName } = properties;
return (
<li className="mb-10 ms-6">
<span className="absolute flex items-center justify-center
w-6 h-6 bg-[--background] text-[--foreground] rounded-full -start-3">
<FontAwesomeIcon icon={sourceIcon} />
</span>
<div className="items-center justify-between p-4 bg-white
border border-gray-200 rounded-lg shadow-sm sm:flex
dark:bg-gray-700 dark:border-gray-600">
<time className="mb-1 text-xs font-normal
text-gray-400 sm:order-last sm:mb-0">
{date.toLocaleDateString("en-GB")}
</time>
<div className="text-md font-normal text-gray-500 dark:text-gray-300">
{`Review from `}
<a
className="font-semibold text-[#abfcec] hover:underline"
href={sourceUrl}
rel="noopener noreferrer"
target="_blank"
>
{name}
</a>{` via `}
<span className="bg-gray-100 text-gray-800 text-xs font-normal
me-2 px-2.5 py-0.5 rounded dark:bg-gray-600 dark:text-gray-300">
{sourceName}
</span>
<Rule />
<p className="text-sm">{content}</p>
</div>
</div>
</li>
);
};

View File

@ -1,14 +0,0 @@
/**
* @copyright nhcarrigan
* @license Naomi's Public License
* @author Naomi Carrigan
*/
import type { JSX } from "react";
/**
* Renders a customised horizontal rule.
* @returns A JSX element.
*/
export const Rule = (): JSX.Element => {
return <hr className="border-dashed border-2 border-[--primary-color]"></hr>;
};

View File

@ -1,45 +0,0 @@
/**
* @copyright nhcarrigan
* @license Naomi's Public License
* @author Naomi Carrigan
*/
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import type { IconDefinition } from "@fortawesome/fontawesome-svg-core";
import type { JSX } from "react";
interface SocialProperties {
readonly icon: IconDefinition;
readonly link: string;
readonly label: string;
readonly alt: string;
readonly color: string;
readonly background: string;
}
/**
* Renders the view for a social media link.
* @param properties - The link to render.
* @returns A JSX element.
*/
export const Social = (properties: SocialProperties): JSX.Element => {
const { icon, link, label, alt, background, color } = properties;
return (
<a
aria-label={label}
className="flex max-w-[300px] w-[95%] m-auto justify-between
items-center border-solid border-2 rounded-3xl h-14 p-8 my-4"
href={link}
rel="noreferrer"
style={{
background: background,
borderColor: color,
color: color,
}}
target="_blank"
>
<FontAwesomeIcon aria-label={alt} icon={icon} size="3x" />
<strong>{label}</strong>
</a>
);
};

View File

@ -1,122 +0,0 @@
/**
* @copyright nhcarrigan
* @license Naomi's Public License
* @author Naomi Carrigan
*/
/**
* List of art to render.
*/
export const Art: Array<{
name: string;
img: string;
artist: string;
url: string;
alt: string;
}> = [
{
alt: "Pixel art portrait of a person with medium-length brown hair, purple glasses, and a blue top against a pink and blue striped background. A blue star-shaped hair clip adorns their hair.",
artist: "Jazzybee",
img: "profile.png",
name: "Avatar",
url: "https://jazzybee.itch.io/sdvcharactercreator",
},
{
alt: "Anime-style illustration of a character wearing a large brown witch hat decorated with roses and hanging charms against a cloudy background.",
artist: "Picrew",
img: "ai-bot.png",
name: "AI Bot",
url: "https://picrew.me/en/image_maker/1382748",
},
{
alt: "Anime-style portrait of a character with short burgundy hair and glasses, wearing a black blazer over a light blue shirt with a choker, against a pale blue patterned background.",
artist: "Picrew",
img: "mod-bot.png",
name: "Mod Bot",
url: "https://picrew.me/en/image_maker/27700",
},
{
alt: "Anime-style portrait of a character with wavy brown hair, glasses, and a black lacy top, winking and smiling",
artist: "Picrew",
img: "translation-bot.png",
name: "Translation Bot",
url: "https://picrew.me/en/image_maker/3595",
},
{
alt: "Anime-style character with brown hair and glasses wearing a teal hat and shirt with a heart design, smiling excitedly",
artist: "Picrew",
img: "task-bot.png",
name: "Task Bot",
url: "https://picrew.me/en/image_maker/700620",
},
{
alt: "Anime-style portrait of a character with glasses and wavy hair, wearing an off-shoulder pink top with a heart pendant necklace, against a bright pink circular background.",
artist: "Picrew",
img: "boost-bot.png",
name: "Boost Monitor Bot",
url: "https://picrew.me/en/image_maker/1310292",
},
{
alt: "Anime-style portrait of a character with blonde and black hair, blushing cheeks, and teary blue eyes, smiling against a turquoise background.",
artist: "Picrew",
img: "bridge.png",
name: "Social Media Bridge",
url: "https://picrew.me/en/image_maker/21208",
},
{
alt: "Gothic anime-style portrait of a character with purple eyeshadow, spider hair clip, and choker necklace in a forest setting",
artist: "Picrew",
img: "trick-or-treat.png",
name: "Trick or Treat",
url: "https://picrew.me/en/image_maker/1712061",
},
{
alt: "Cartoon character in a blue winter outfit with a pointed hat, holding a bloody sack, against a pink snowflake background",
artist: "Picrew",
img: "padoru.png",
name: "Padoru",
url: "https://picrew.me/en/image_maker/1843743",
},
{
alt: "Cartoon portrait of a character with brown hair and glasses, smiling against a transgender flag heart background",
artist: "Picrew",
img: "trans.png",
name: "Trans Pride",
url: "https://picrew.me/en/image_maker/100365/",
},
{
alt: "Anime-style portrait of a character with headphones and glasses, wearing a choker and holding a drink, against a pink pixelated background. Text 'xoxo 4Dear' visible.",
artist: "Picrew",
img: "alt-text.png",
name: "Alt-text Generator",
url: "https://picrew.me/en/image_maker/2003689/",
},
{
alt: "Anime-style illustration of a character with brown hair and large blue eyes, sipping a drink through a straw with a shush expression, wearing a blue sweater against a pink background.",
artist: "Picrew",
img: "anon.png",
name: "Anon Bot",
url: "https://picrew.me/en/image_maker/2307052/",
},
{
alt: "Anime-style illustration of a character with brown hair and glasses, making cat claw shapes with her hands. She wears a black outfit with white bows, surrounded by heart symbols on a turquoise background.",
artist: "Picrew",
img: "eval.png",
name: "Code Evaluator",
url: "https://picrew.me/en/image_maker/1787745/",
},
{
alt: "Anime-style portrait of a character with wavy brown hair and glasses, looking thoughtful against a background of pink cherry blossoms. She wears an off-shoulder dark top, and has a lit cigarette in her hand.",
artist: "Picrew",
img: "librarian.png",
name: "Librarian Bot",
url: "https://picrew.me/en/image_maker/2435029",
},
{
alt: "An anime-style illustration of a character with shoulder-length wavy brown hair, blue eyes behind black-rimmed glasses, wearing a beige cardigan over a white top with a black choker. They are holding a blue book and pen, with a question mark speech bubble above their head. The background is pastel purple with decorative white sparkles and chain patterns.",
artist: "Picrew",
img: "tickets.png",
name: "Ticket System",
url: "https://picrew.me/en/image_maker/625876",
},
];

View File

@ -1,112 +0,0 @@
/**
* @copyright nhcarrigan
* @license Naomi's Public License
* @author Naomi Carrigan
*/
/**
* List of certifications to render.
*/
export const Certifications: Array<{
name: string;
fileName: string;
issuer: string;
date: Date;
}> = [
{
date: new Date("April 17 2020"),
fileName: "responsive-web-design.png",
issuer: "freeCodeCamp",
name: "Responsive Web Design",
},
{
date: new Date("April 24, 2020"),
fileName: "javascript.png",
issuer: "freeCodeCamp",
name: "JavaScript Algorithms and Data Structures",
},
{
date: new Date("April 28, 2020"),
fileName: "front-end-libs.png",
issuer: "freeCodeCamp",
name: "Front End Libraries",
},
{
date: new Date("May 19, 2020"),
fileName: "infosec.png",
issuer: "freeCodeCamp",
name: "Information Security and Quality Assurance",
},
{
date: new Date("May 25, 2020"),
fileName: "legacy-full-stack.png",
issuer: "freeCodeCamp",
name: "Full Stack Developer",
},
{
date: new Date("May 25, 2020"),
fileName: "data-visualisation.png",
issuer: "freeCodeCamp",
name: "Data Visualisation",
},
{
date: new Date("May 8 2020"),
fileName: "back-end-dev.png",
issuer: "freeCodeCamp",
name: "Back End Development and APIs",
},
{
date: new Date("July 3 2020"),
fileName: "quality-assurance.png",
issuer: "freeCodeCamp",
name: "Quality Assurance",
},
{
date: new Date("August 14 2020"),
fileName: "legacy-front-end.png",
issuer: "freeCodeCamp",
name: "Legacy Front End",
},
{
date: new Date("July 3, 2020"),
fileName: "scientific-computing.png",
issuer: "freeCodeCamp",
name: "Scientific Computing with Python",
},
{
date: new Date("May 9 2024"),
fileName: "mongo-nodejs.jpg",
issuer: "MongoDB",
name: "Node.js Developer",
},
{
date: new Date("May 9 2024"),
fileName: "mongo-self-admin.jpg",
issuer: "MongoDB",
name: "Self-Managed Database Admin",
},
{
date: new Date("May 9 2024"),
fileName: "mongo-data-model.jpg",
issuer: "MongoDB",
name: "Data Modelling",
},
{
date: new Date("May 9 2024"),
fileName: "mongo-atlas-admin.jpg",
issuer: "MongoDB",
name: "Atlas Database Admin",
},
{
date: new Date("May 9 2024"),
fileName: "ecommerce-retail.jpg",
issuer: "MongoDB",
name: "E-Commerce Modernisation and Personalisation",
},
{
date: new Date("November 12, 2024"),
fileName: "c-sharp.png",
issuer: "freeCodeCamp",
name: "Foundational C# with Microsoft",
},
];

View File

@ -1,220 +0,0 @@
/**
* @copyright nhcarrigan
* @license Naomi's Public License
* @author Naomi Carrigan
*/
/**
* List of screenshots from games to render.
*/
export const Games: Array<{
name: string;
img: string;
url: string;
alt: string;
}> = [
{
alt: "A fantasy character in a pink outfit and tiara stands barefoot on rocky ground in a rainy, dark setting. She holds a weapon and is surrounded by puddles and a shadowy landscape with hints of ancient architecture.",
img: "bloody-spell.jpg",
name: "Bloody Spell",
url: "https://store.steampowered.com/app/992300/_Bloody_Spell/",
},
{
alt: "Animated character in a purple traditional Chinese robe wielding a large sword in a wooden temple-like structure with ornate pillars and lanterns.",
img: "dw-9.jpg",
name: "Dynasty Warriors 9: Empires",
url: "https://store.steampowered.com/app/1341200/DYNASTY_WARRIORS_9_Empires/",
},
{
alt: "A stylized female character in a video game or 3D rendering, wearing a white top and long red skirt, holding a sword and striking a dramatic pose with one arm raised. She stands on a stone platform with mountains in the background.",
img: "soul-calibur.jpg",
name: "Soul Calibur VI",
url: "https://store.steampowered.com/app/544750/SOULCALIBUR_VI/",
},
{
alt: "A virtual character in a red dress sits on a throne in a futuristic corridor. The character has short hair and is barefoot. Above the character is the text 'Avalon'. The scene appears to be from a video game or digital simulation, with a dark, metallic environment surrounding the central figure.",
img: "swtor.jpg",
name: "Star Wars: The Old Republic",
url: "https://store.steampowered.com/app/1286830/STAR_WARS_The_Old_Republic/",
},
{
alt: "Anime-style illustration of a young woman in a dark floral kimono standing in a lush green field. Behind her, a vibrant galaxy-like spiral shimmers in the sky. Yellow flowers bloom in the foreground, and glowing particles float around her. The scene has a magical, ethereal quality.",
img: "idling-god.png",
name: "Idling to Rule the Gods",
url: "https://store.steampowered.com/app/466170/Idling_to_Rule_the_Gods/",
},
{
alt: "A female video game character stands on a wooden bridge in a Japanese-style garden. She wears samurai-like armor and holds a long bow. The character has long dark hair and glasses. The scene is rendered in a soft, slightly blurred style with pink cherry blossom trees in the background.",
img: "nioh-2.jpg",
name: "Nioh 2",
url: "https://store.steampowered.com/app/1325200/Nioh_2__The_Complete_Edition/",
},
{
alt: "3D rendering of a figure wearing a Japanese-style school uniform with a white top, pink sailor collar, and purple pleated skirt, standing against a dark background. The figure has short brown hair and is shown in a full-body pose.",
img: "deathly-stillness.jpg",
name: "Deathly Stillness",
url: "https://store.steampowered.com/app/1727650/Deathly_Stillness/",
},
{
alt: "A 3D rendered character in a futuristic or sci-fi style outfit. The figure is wearing a light-colored bodysuit with straps and mechanical details, holding a large gun. The character has blonde hair and stands against a dark background in a ready pose.",
img: "once-human.jpg",
name: "Once Human",
url: "https://store.steampowered.com/app/2139460/Once_Human/",
},
{
alt: "A woman in post-apocalyptic armor stands in a desolate urban landscape. She wears sunglasses, leather armor pieces, and holds a weapon. The background shows damaged buildings and debris in a hazy, dusty environment.",
img: "fallout-4.jpg",
name: "Fallout 4",
url: "https://store.steampowered.com/app/377160/Fallout_4/",
},
{
alt: "Fantasy video game character in a revealing purple and gold outfit with a crown, standing in a lush mountainous landscape with floating islands and waterfalls. Character selection interface visible at the bottom of the image.",
img: "gw2.png",
name: "Guild Wars 2",
url: "https://store.steampowered.com/app/1284210/Guild_Wars_2/",
},
{
alt: "A 3D rendered scene of a medieval-style courtyard at night. A woman in a long teal dress stands in the center of a cobblestone path. Wooden archways and stone walls with lit lanterns frame the path, creating a moody atmosphere.",
img: "nwn.jpg",
name: "Neverwinter Nights",
url: "https://store.steampowered.com/app/704450/Neverwinter_Nights_Enhanced_Edition/",
},
{
alt: "A female video game character in medieval-style clothing stands in a rugged stone environment. She wears a tattered brown tunic, leather armor, and leg wraps. Her pose is fierce and ready for action, with dark hair framing her face. The background shows rocky terrain and ancient stone walls.",
img: "lords-of-the-fallen.jpg",
name: "Lords of the Fallen",
url: "https://store.steampowered.com/app/1501750/Lords_of_the_Fallen/",
},
{
alt: "Anime-style character in a futuristic black outfit with glowing blue accents standing in a forest setting. The character has short brown hair and large eyes, wearing a long coat with high slits revealing thigh-high boots.",
img: "vroid.png",
name: "VRoid",
url: "https://store.steampowered.com/app/1486350/VRoid_Studio_v1294/",
},
{
alt: "Anime-style illustration of a girl lying on her back, holding a smartphone above her face. She's surrounded by various objects including a pink rabbit toy, headphones, candies, a game controller, and a potted plant. The scene depicts a cluttered, colorful bedroom or living space.",
img: "koikatsu.png",
name: "Koikatsu",
url: "https://store.steampowered.com/app/1073440/__Koikatsu_Party/",
},
{
alt: "A female video game character stands in a dark, wooden structure. She has short hair and wears rustic clothing. The scene includes a health and magic bar in the top left corner and a minimap in the top right. The environment is dimly lit with some grass on the ground.",
img: "amalur.jpg",
name: "Kingdoms of Amalur",
url: "https://store.steampowered.com/app/1041720/Kingdoms_of_Amalur_ReReckoning/",
},
{
alt: "A 3D-rendered character in a futuristic setting, wearing a form-fitting white and black bodysuit with a red insignia on the chest. The character has short brown hair and glasses, standing confidently in an urban environment with other figures visible in the background.",
img: "encased.jpg",
name: "Encased",
url: "https://store.steampowered.com/app/921800/Encased_A_SciFi_PostApocalyptic_RPG/",
},
{
alt: "A blonde woman in a black Gothic-style outfit stands in a dimly lit room with large windows. She wears glasses, a corset-like top, fishnet stockings, and lace gloves. The room has a patterned carpet and appears to be in an old building.",
img: "demonologist.jpg",
name: "Demonologist",
url: "https://store.steampowered.com/app/1929610/Demonologist/",
},
{
alt: "A 3D rendered female video game character model wearing a shiny green outfit consisting of a sleeveless top and short skirt with thigh straps. The character has long brown hair and is standing in a neutral pose with a dark cape draped behind her.",
img: "mka.png",
name: "Mortal Kombat: Armageddon",
url: "https://en.wikipedia.org/wiki/Mortal_Kombat:_Armageddon",
},
{
alt: "A 3D video game character model of a woman with short dark hair wearing a teal green dress with purple accents. The dress has a laced front, thigh-high slit, and is paired with purple arm bands. The character stands in a combat-ready pose within an ornate frame against a dark background. The name 'NAOMI' is displayed beneath the character.",
img: "sc3.png",
name: "Soul Calibur III",
url: "https://en.wikipedia.org/wiki/Soulcalibur_III",
},
{
alt: "A 3D rendered character with elven features, glowing cyan eyes, and brown hair. The figure wears a blue and gray outfit consisting of a long coat, fitted pants, and a metallic necklace. The character is depicted in a dark, moody setting.",
img: "v-rising.jpg",
name: "V Rising",
url: "https://store.steampowered.com/app/1604030/V_Rising/",
},
{
alt: "Digital illustration of a female character in a flowing teal dress standing on a hillside overlooking a fantasy landscape with distant buildings and fields.",
img: "aow-3.jpg",
name: "Age of Wonders 3",
url: "https://store.steampowered.com/app/226840/Age_of_Wonders_III/",
},
{
alt: "Digital illustration of a character in a white and pink dress with bell sleeves and a crown, walking on a dirt path through a forested area with tall grass and flowers.",
img: "bannerlord.jpg",
name: "Mount & Blade II: Bannerlord",
url: "https://store.steampowered.com/app/261550/Mount__Blade_II_Bannerlord/",
},
{
alt: "3D render of an anime-style character with pale skin and light hair, wearing a short purple dress with a textured pattern, standing against a plain gray background.",
img: "codevein.jpg",
name: "Code Vein",
url: "https://store.steampowered.com/app/678960/CODE_VEIN/",
},
{
alt: "Digital artwork of a fantasy character with white hair in a long white dress holding a staff, standing against a backdrop of cloudy skies and distant ruins.",
img: "fallen-enchantress.jpg",
name: "Fallen Enchantress: Legendary Heroes",
url: "https://store.steampowered.com/app/228260/Fallen_Enchantress_Legendary_Heroes/",
},
{
alt: "Pixelated video game character in a green dress standing in a dark hallway. She has brown hair and wears glasses.",
img: "zomboid.jpg",
name: "Project Zomboid",
url: "https://store.steampowered.com/app/108600/Project_Zomboid/",
},
{
alt: "3D render of an anime-style character in a cozy room. The character wears a pink dress, glasses, and has short brown hair. The room features a round window, bookshelves, plants, and a purple cushion with a cat-shaped teapot. The scene has a warm, soft lighting.",
img: "spirit-city.png",
name: "Spirit City: Lofi Sessions",
url: "https://store.steampowered.com/app/2113850/Spirit_City_Lofi_Sessions/",
},
{
alt: "a female character in a fantasy or adventure game setting. She is wearing a dark outfit with ornate details, including a hooded cape and armor-like elements. The character is standing in a lush, jungle-like environment, with tall trees and foliage in the background. She is holding a large weapon, likely a sword or staff, in her hand, suggesting she is a warrior or adventurer. The character has a serious expression on her face, indicating she is focused and ready for action. Overall, the image conveys a sense of mystery, power, and exploration in a fantastical and immersive world.",
img: "mh-world.jpg",
name: "Monster Hunter: World",
url: "https://store.steampowered.com/app/582010/Monster_Hunter_World/",
},
{
alt: "A 3D character model showing a female figure wearing a bright neon green futuristic bodysuit with black armored accents and panels. The suit features geometric patterns and protective plating across the torso, limbs, and joints. The character has brown hair styled with side-swept bangs and stands in a neutral pose against a dark background. Text at the top of the image reads \"Origin: Human\" and \"Naomi\".",
img: "empyrion.jpg",
name: "Empyrion: Galactic Survival",
url: "https://store.steampowered.com/app/383120/Empyrion__Galactic_Survival/",
},
{
alt: "A 3D rendered anime-style female character model shown in a confident pose against a dark gray background. She has a short black bob haircut and is wearing a burgundy bikini-style outfit with gold accents, including a central pendant. Her accessories include gold bracelets and a red decorative garter or belt around one thigh. She wears elaborate burgundy strappy sandals that lace up her calves. The character is standing with hands on hips in a pose that casts a distinct shadow. The rendering features smooth shading and a slight bluish rim lighting effect that highlights the character's silhouette.",
img: "angel-legion.png",
name: "Angel Legion",
url: "https://store.steampowered.com/app/1333350/Angel_Legion/",
},
{
alt: "A detailed anime-style illustration of an angelic warrior character against a sunset cityscape background. The character has long blonde hair and wears elaborate white and gold armor with flowing white robes accented by blue and orange fabrics. She has multiple large white wings spread dramatically behind her and wears a golden crown-like headpiece. Golden chains float decoratively around her dress and armor. She's depicted in a dynamic pose with futuristic city towers and a reddish-orange sky visible in the background. The artwork combines elements of fantasy and sci-fi, with ornate details in the character's costume and architectural elements of the setting.",
img: "idle-angels.jpg",
name: "Idle Angels",
url: "https://play.google.com/store/apps/details?id=com.mujoysg.hxbb&hl=en-US&pli=1",
},
{
alt: "A 3D rendered video game character wearing an ornate turquoise and white dress with bell sleeves and a matching cape. The outfit features intricate trim details, a bow at the waist, and layered fabric elements. The character wears round glasses and has brown hair styled in a neat bob cut. The character is shown barefoot against a dark blue background.",
img: "dw-8.jpg",
name: "Dynasty Warriors 8 Empires",
url: "https://store.steampowered.com/app/322520/DYNASTY_WARRIORS_8_Empires/",
},
{
alt: "A video game character stands on a dock wearing a traditional Japanese kimono in royal blue with delicate flower patterns and a red hem. The kimono is accessorized with a decorative obi belt and a sword at the waist. The character has round glasses and shoulder-length blonde hair. In the background, wooden ships are moored at the harbor against a mountainous coastline.",
img: "samurai-4.jpg",
name: "Way of the Samurai 4",
url: "https://store.steampowered.com/app/312780/Way_of_the_Samurai_4/",
},
{
alt: "A 3D fantasy character dressed in a light blue and white flowing robe with exposed midriff stands wielding a magical staff with purple crystals. In the background looms a dark, gothic castle silhouetted against a misty green sky with a large moon. The scene is atmospheric with purple and blue lighting effects, and mysterious armored figures can be seen in the shadows on either side.",
img: "aow-4.jpg",
name: "Age of Wonders 4",
url: "https://store.steampowered.com/app/1669000/Age_of_Wonders_4/",
},
{
alt: "A 3D rendered character standing in a nighttime wilderness setting, illuminated by a large full moon and orange ambient lighting. The figure wears tattered, primitive clothing consisting of a rough-textured tunic and shorts with wrapped cloth around the lower legs. The clothing appears weathered and torn. The character is positioned on rocky terrain with foliage visible in the background. The lighting creates a dramatic contrast between cool moonlight and warm ground reflections.",
img: "enshrouded.jpg",
name: "Enshrouded",
url: "https://store.steampowered.com/app/1203620/Enshrouded/",
},
];

View File

@ -1,777 +0,0 @@
/**
* @copyright nhcarrigan
* @license Naomi's Public License
* @author Naomi Carrigan
*/
/**
* List of professional work to render.
*/
export const Jobs: Array<{
title: string;
company: string;
/**
* Set ALL dates to the 5th. These are not exact days, but intended to avoid month discrepancies
* when dealing with timezones.
*/
start: Date;
/**
* Set ALL dates to the 5th. These are not exact days, but intended to avoid month discrepancies
* when dealing with timezones.
*/
end: Date | null;
link: string;
type: "volunteer" | "fixed" | "project" | "hypothetical";
description: string;
/**
* File name of logo.
*/
logo: string;
}> = [
{
company: "Your Company!",
description: `You could be our next client! Hit the "Contact" link and use the "Hire Us" button to get in touch!`,
end: null,
link: "https://topmate.io/nhcarrigan/913920",
logo: "future.jpeg",
start: new Date(Date.now()),
title: "Consultant",
type: "hypothetical",
},
{
company: "nhcarrigan",
description:
"Began my journey learning to code, starting from the top of the freeCodeCamp curriculum.",
end: null,
link: "https://naomi.lgbt",
logo: "nhcarrigan.jpeg",
start: new Date("April 5 2020"),
title: "Started Journey",
type: "hypothetical",
},
{
company: "Artists For Palestine",
description: `As a Development Lead at Art 4 Palestine, I developed a bot that efficiently manages integrations between Airtable forms, Trello boards, and Discord, streamlining workflow and improving productivity. The bot also pulls news articles from reputable sources and cross-posts them into the server, keeping the community informed with reliable updates.
Additionally, I guided and mentored other developers in the design and coding of the website, ensuring high-quality output and consistent alignment with project goals. My contributions have been instrumental in supporting the organization's initiatives and fostering collaboration within the development team.`,
end: null,
link: "https://art4palestine.org",
logo: "a4p.jpeg",
start: new Date("November 5 2023"),
title: "Development Lead",
type: "volunteer",
},
{
company: "AngelRose",
description: `As a Discord Moderator at AngelRose, I played a key role in maintaining a safe, respectful, and engaging environment for community members. I monitored conversations, enforcing community guidelines to prevent disruptive behavior and protect users. Additionally, I addressed and resolved conflicts, providing support and guidance to members to promote a positive experience. My contributions helped uphold the integrity of the community and foster an inclusive and welcoming space for all participants.`,
end: null,
link: "https://discord.gg/kYpjgEB",
logo: "angel.png",
start: new Date("September 5 2023"),
title: "Community Moderator",
type: "volunteer",
},
{
company: "Deepgram",
description: `<div class="pl-4">
<p>As a Discord Bot Developer, I spearheaded the creation and implementation of an advanced bot designed to revolutionize community management and user interactions. My primary focus involved developing a comprehensive suite of features to streamline communication, enhance user engagement, and provide valuable insights into community health.</p>
<p>Leveraging AI capabilities, I integrated intelligent automation to address user queries efficiently and maintain an organized community structure. Additionally, I implemented cross-platform integration features to ensure seamless information flow between Discord, GitHub, and ProductBoard, fostering a cohesive ecosystem for community management.</p>
<p>Through this multifaceted approach, I significantly improved community interactions, user satisfaction, and the overall efficiency of community management processes.</p>
<p>Key responsibilities and achievements include:</p>
<ul class="list-none">
<li class="mb-2 relative before:content-['🩵']">Message Management and Organization:
<ul class="pl-4 mt-2">
<li class="mb-2 relative before:content-['🩷']">Developed functionality to relocate messages from standard channels to forum channels</li>
<li class="mb-2 relative before:content-['🩷']">Implemented a scheduled messaging system to guide users towards appropriate channels</li>
</ul>
</li>
<li class="mb-2 relative before:content-['🩵']">AI-Powered Assistance:
<ul class="pl-4 mt-2">
<li class="mb-2 relative before:content-['🩷']">Integrated AI capabilities for automatic question answering in forum channels</li>
<li class="mb-2 relative before:content-['🩷']">Designed feature for marking responses as correct answers</li>
</ul>
</li>
<li class="mb-2 relative before:content-['🩵']">Community Engagement Tools:
<ul class="pl-4 mt-2">
<li class="mb-2 relative before:content-['🩷']">Developed daily and weekly aggregations of unanswered questions</li>
<li class="mb-2 relative before:content-['🩷']">Implemented a reminder system for inactive questions after seven days</li>
<li class="mb-2 relative before:content-['🩷']">Created cross-posting functionality to GitHub discussion board for answered questions</li>
</ul>
</li>
<li class="mb-2 relative before:content-['🩵']">Metrics and Analytics:
<ul class="pl-4 mt-2">
<li class="mb-2 relative before:content-['🩷']">Developed tracking system for community health indicators including unanswered, answered, and closed questions</li>
<li class="mb-2 relative before:content-['🩷']">Created a dashboard for easy monitoring of community engagement</li>
</ul>
</li>
<li class="mb-2 relative before:content-['🩵']">Cross-Platform Integration:
<ul class="pl-4 mt-2">
<li class="mb-2 relative before:content-['🩷']">Implemented feature to post feedback messages to ProductBoard</li>
<li class="mb-2 relative before:content-['🩷']">Designed system for cross-posting between Discord and GitHub</li>
</ul>
</li>
</ul>
</div>`,
end: new Date("June 5 2024"),
link: "https://deepgram.com",
logo: "deepgram.jpeg",
start: new Date("July 5 2023"),
title: "Community Bot Engineer",
type: "project",
},
{
company: "BigBadBeaver Productions",
description: `<div class="pl-4">
<p>As a Twitch Bot Developer, I spearheaded the creation and deployment of "PrivateTwigs," a custom chat bot designed to revolutionize stream management and viewer engagement. My role involved engineering sophisticated features, implementing data analysis tools, and creating user-friendly interfaces to empower streamers with valuable insights and enhanced interaction capabilities.</p>
<p>By developing a comprehensive logging system and custom redemption rewards, I significantly improved the streaming experience for both content creators and viewers. My work directly contributed to increased viewer engagement and provided streamers with powerful tools to manage and grow their channels effectively.</p>
<p>Through close collaboration with streamers and careful attention to Twitch's guidelines, I ensured that PrivateTwigs not only met but exceeded user expectations while maintaining full compliance with platform regulations.</p>
<p>Key responsibilities and achievements include:</p>
<ul class="list-none">
<li class="mb-2 relative before:content-['🩵'] ml-[-1rem]">PrivateTwigs Bot Development:
<ul class="pl-4 mt-2">
<li class="mb-2 relative before:content-['🩷']">Engineered and deployed a custom Twitch chat bot, enhancing stream management and viewer engagement</li>
<li class="mb-2 relative before:content-['🩷']">Developed comprehensive logging functionality for all chat messages and stream events</li>
<li class="mb-2 relative before:content-['🩷']">Implemented data analysis tools to derive strategic insights from stream data</li>
<li class="mb-2 relative before:content-['🩷']">Created a user-friendly interface for streamers to access and utilize collected data</li>
</ul>
</li>
<li class="mb-2 relative before:content-['🩵']">Custom Redemption Rewards System:
<ul class="pl-4 mt-2">
<li class="mb-2 relative before:content-['🩷']">Designed and implemented a custom redemption rewards system within the bot</li>
<li class="mb-2 relative before:content-['🩷']">Enabled unique viewer interactions, increasing overall stream engagement</li>
<li class="mb-2 relative before:content-['🩷']">Developed a flexible framework allowing streamers to easily create and modify rewards</li>
<li class="mb-2 relative before:content-['🩷']">Integrated reward system with Twitch's API to ensure seamless operation</li>
</ul>
</li>
<li class="mb-2 relative before:content-['🩵']">Performance Optimization and Compliance:
<ul class="pl-4 mt-2">
<li class="mb-2 relative before:content-['🩷']">Optimized bot performance to handle high-traffic streams without latency</li>
<li class="mb-2 relative before:content-['🩷']">Ensured compliance with Twitch's terms of service and API guidelines</li>
</ul>
</li>
<li class="mb-2 relative before:content-['🩵']">Continuous Improvement and Collaboration:
<ul class="pl-4 mt-2">
<li class="mb-2 relative before:content-['🩷']">Collaborated with streamers to gather feedback and iteratively improve bot features</li>
<li class="mb-2 relative before:content-['🩷']">Regularly updated and refined bot functionality based on user needs and platform changes</li>
</ul>
</li>
</ul>
</div>`,
end: new Date("January 5 2024"),
link: "https://linktr.ee/bigbadbeaver",
logo: "beaver.png",
start: new Date("May 5 2023"),
title: "Twitch Integration Engineer",
type: "project",
},
{
company: "Sema Software",
description: `<div class="pl-4">
<p>As an Open Source Community Manager, I successfully spearheaded the growth of our Discord community from 300 to 1,000 members, achieving a remarkable 233% increase. My role involved implementing strategic engagement initiatives, creating an inclusive environment, and leading multiple open source projects that significantly enhanced developer productivity and community engagement.</p>
<p>By developing standardized tools and resources, such as project templates and skills assessment bots, I streamlined processes and improved consistency across the organization. My work on the Developer Skills Matrix ecosystem, including the creation of dedicated bots and websites, facilitated self-assessment and skill development among community members.</p>
<p>Through the engineering of specialized Discord bots and the cultivation of a vibrant community atmosphere, I increased the visibility of open source opportunities and drove higher levels of member participation and retention. My efforts in cross-functional collaboration ensured that community initiatives aligned with broader business objectives, contributing to both user growth and product adoption.</p>
<p>Key responsibilities and achievements include:</p>
<ul class="list-none">
<li class="mb-2 relative before:content-['🩵'] ml-[-1rem]">Community Growth and Engagement:
<ul class="pl-4 mt-2">
<li class="mb-2 relative before:content-['🩷']">Spearheaded growth of Discord community from 300 to 1,000 members, representing a 233% increase</li>
<li class="mb-2 relative before:content-['🩷']">Implemented strategic engagement initiatives and created an inclusive environment</li>
<li class="mb-2 relative before:content-['🩷']">Cultivated a vibrant, engaging community atmosphere, resulting in increased member participation and retention</li>
</ul>
</li>
<li class="mb-2 relative before:content-['🩵'] ml-[-1rem]">Open Source Initiatives Leadership:
<ul class="pl-4 mt-2">
<li class="mb-2 relative before:content-['🩷']">Led multiple open source initiatives, enhancing developer productivity and community engagement</li>
<li class="mb-2 relative before:content-['🩷']">Developed and implemented a standardized base template for new projects, streamlining project initiation and improving consistency</li>
<li class="mb-2 relative before:content-['🩷']">Engineered a Discord bot to query and showcase projects from the Open Source Welcoming Committee, increasing visibility of opportunities</li>
</ul>
</li>
<li class="mb-2 relative before:content-['🩵'] ml-[-1rem]">Developer Skills Matrix Ecosystem Management:
<ul class="pl-4 mt-2">
<li class="mb-2 relative before:content-['🩷']">Created and maintained a Discord bot for self-assessments</li>
<li class="mb-2 relative before:content-['🩷']">Developed a dedicated website for the Skills Matrix</li>
<li class="mb-2 relative before:content-['🩷']">Implemented a Slack bot to extend accessibility across platforms</li>
</ul>
</li>
<li class="mb-2 relative before:content-['🩵'] ml-[-1rem]">Strategic Alignment and Collaboration:
<ul class="pl-4 mt-2">
<li class="mb-2 relative before:content-['🩷']">Collaborated cross-functionally to align community initiatives with overall business objectives</li>
<li class="mb-2 relative before:content-['🩷']">Drove both user growth and product adoption through strategic community management</li>
</ul>
</li>
</ul>
</div>`,
end: new Date("September 5 2022"),
link: "https://www.semasoftware.com",
logo: "sema.jpeg",
start: new Date("May 5 2022"),
title: "Community Manager and Open-Source Engineer",
type: "fixed",
},
{
company: "4C",
description: `<div class="pl-4">
<p>As a Discord Community Growth Manager, I successfully orchestrated the exponential growth of our Discord community, expanding it from 1,100 to 3,350 members a remarkable 205% increase. My role encompassed implementing strategic engagement initiatives, developing community events, and creating a safe, inclusive environment that fostered active participation and meaningful interactions among members.</p>
<p>By implementing a comprehensive onboarding process and establishing clear community guidelines, I ensured new members were effectively integrated and all participants felt welcome and secure. My data-driven approach, involving the analysis of community metrics and user feedback, allowed for continuous improvement of engagement strategies and overall member satisfaction.</p>
<p>Through close collaboration with cross-functional teams, I aligned community initiatives with broader business objectives, ensuring that our thriving Discord community contributed significantly to our organization's goals. My proactive conflict resolution and attentive addressing of member concerns maintained a positive community atmosphere, crucial for sustained growth and engagement.</p>
<p>Key responsibilities and achievements include:</p>
<ul class="list-none">
<li class="mb-2 relative before:content-['🩵'] ml-[-1rem]">Community Growth and Engagement:
<ul class="pl-4 mt-2">
<li class="mb-2 relative before:content-['🩷']">Orchestrated exponential growth of Discord community from 1,100 to 3,350 members, representing a 205% increase</li>
<li class="mb-2 relative before:content-['🩷']">Implemented strategic engagement initiatives to foster an active and thriving community space</li>
<li class="mb-2 relative before:content-['🩷']">Developed and executed community events, driving participation and member retention</li>
<li class="mb-2 relative before:content-['🩷']">Created and moderated discussion channels to encourage meaningful interactions</li>
</ul>
</li>
<li class="mb-2 relative before:content-['🩵'] ml-[-1rem]">Community Management and Moderation:
<ul class="pl-4 mt-2">
<li class="mb-2 relative before:content-['🩷']">Implemented a comprehensive onboarding process for new members, enhancing their integration into the community</li>
<li class="mb-2 relative before:content-['🩷']">Established and enforced community guidelines, ensuring a safe and inclusive environment for all members</li>
<li class="mb-2 relative before:content-['🩷']">Managed conflict resolution and addressed member concerns, maintaining a positive community atmosphere</li>
</ul>
</li>
<li class="mb-2 relative before:content-['🩵'] ml-[-1rem]">Data-Driven Strategy and Collaboration:
<ul class="pl-4 mt-2">
<li class="mb-2 relative before:content-['🩷']">Analysed community metrics and user feedback to continually improve engagement strategies and member satisfaction</li>
<li class="mb-2 relative before:content-['🩷']">Collaborated with cross-functional teams to align community initiatives with broader business objectives</li>
</ul>
</li>
</ul>
</div>`,
end: new Date("November 5 2022"),
link: "https://discord.com/invite/ns5x8bTz25",
logo: "4c.png",
start: new Date("May 5 2022"),
title: "Community Manager",
type: "fixed",
},
{
company: "TweetShift",
description: `<div class="pl-4">
<p>As the Community Manager, I successfully managed and supported a vast user community spanning over 230,000 Discord servers, demonstrating my ability to operate effectively at scale. My role encompassed providing comprehensive support, implementing and enforcing community guidelines, and fostering high levels of engagement across this extensive user base.</p>
<p>By delivering high-quality support and creating robust self-service resources, I ensured optimal bot functionality and maintained high levels of user satisfaction. My proactive approach to community management, including the development and execution of strategies to prevent and mitigate issues, contributed to maintaining a safe and inclusive environment for all members.</p>
<p>Through organizing community events, creating informative content, and recognizing active contributors, I fostered a vibrant and engaged community. My work directly contributed to the growth, stability, and positive culture of this large-scale Discord ecosystem.</p>
<p>Key responsibilities and achievements include:</p>
<ul class="list-none">
<li class="mb-2 relative before:content-['🩵'] ml-[-1rem]">Large-Scale Community Management:
<ul class="pl-4 mt-2">
<li class="mb-2 relative before:content-['🩷']">Managed and supported a vast user community spanning over 230,000 Discord servers</li>
<li class="mb-2 relative before:content-['🩷']">Demonstrated ability to operate effectively at scale, maintaining high standards across a large user base</li>
</ul>
</li>
<li class="mb-2 relative before:content-['🩵']">Comprehensive User Support:
<ul class="pl-4 mt-2">
<li class="mb-2 relative before:content-['🩷']">Provided high-quality support to users, ensuring optimal bot functionality and user satisfaction</li>
<li class="mb-2 relative before:content-['🩷']">Responded to user inquiries and troubleshooting requests in a timely and effective manner</li>
<li class="mb-2 relative before:content-['🩷']">Created and maintained user guides and FAQs to empower self-service problem-solving</li>
<li class="mb-2 relative before:content-['🩷']">Collaborated with the development team to relay user feedback and suggest improvements</li>
</ul>
</li>
<li class="mb-2 relative before:content-['🩵']">Community Guidelines and Moderation:
<ul class="pl-4 mt-2">
<li class="mb-2 relative before:content-['🩷']">Implemented and enforced community guidelines to maintain a safe and inclusive environment</li>
<li class="mb-2 relative before:content-['🩷']">Moderated discussions and user-generated content across multiple channels</li>
<li class="mb-2 relative before:content-['🩷']">Resolved conflicts and addressed user concerns promptly and professionally</li>
<li class="mb-2 relative before:content-['🩷']">Developed and executed strategies to prevent and mitigate potential community issues</li>
</ul>
</li>
<li class="mb-2 relative before:content-['🩵']">Community Engagement Initiatives:
<ul class="pl-4 mt-2">
<li class="mb-2 relative before:content-['🩷']">Organized and facilitated community events and discussions</li>
<li class="mb-2 relative before:content-['🩷']">Created and curated content to keep users informed about updates and best practices</li>
<li class="mb-2 relative before:content-['🩷']">Recognized and rewarded active and helpful community members</li>
</ul>
</li>
</ul>
</div>`,
end: new Date("May 5 2023"),
link: "https://tweetshift.com",
logo: "tweetshift.png",
start: new Date("January 5 2022"),
title: "Community Manager",
type: "fixed",
},
{
company: "Rythm",
description: `<div class="pl-4">
<p>As a Discord Community Manager specializing in bot development, I spearheaded the creation and implementation of advanced management tools for a thriving community of over 300,000 members. My primary focus involved developing a comprehensive suite of bots and systems to streamline moderation, enhance user engagement, and provide valuable insights into community health and staff performance.</p>
<p>Leveraging my expertise in Discord bot development, I implemented robust automoderation systems, designed engaging economy features, and created powerful analytics tools. My work significantly improved community interactions, user satisfaction, and the overall efficiency of community management processes.</p>
<p>Through this multifaceted approach, I fostered a more engaging, secure, and well-managed community environment, contributing to its substantial growth and user retention.</p>
<p>Key responsibilities and achievements include:</p>
<ul class="list-none">
<li class="mb-2 relative before:content-['🩵'] ml-[-1rem]">Comprehensive Moderation Bot:
<ul class="pl-4 mt-2">
<li class="mb-2 relative before:content-['🩷']">Implemented robust automoderation system with customizable rules</li>
<li class="mb-2 relative before:content-['🩷']">Developed extensive moderation history tracking and individual case management</li>
<li class="mb-2 relative before:content-['🩷']">Created evidence logging system and staff-only note functionality</li>
<li class="mb-2 relative before:content-['🩷']">Integrated FAQ response system for efficient community support</li>
</ul>
</li>
<li class="mb-2 relative before:content-['🩵']">Economy and Engagement Bot:
<ul class="pl-4 mt-2">
<li class="mb-2 relative before:content-['🩷']">Designed leveling system to reward long-term activity</li>
<li class="mb-2 relative before:content-['🩷']">Implemented role-based rewards and currency system</li>
<li class="mb-2 relative before:content-['🩷']">Created customisable user profiles and badge earning mechanism</li>
<li class="mb-2 relative before:content-['🩷']">Developed specialised reward purchasing system</li>
</ul>
</li>
<li class="mb-2 relative before:content-['🩵']">Staff Management and Analytics Tools:
<ul class="pl-4 mt-2">
<li class="mb-2 relative before:content-['🩷']">Built staff incentive bot for recognising exceptional contributions</li>
<li class="mb-2 relative before:content-['🩷']">Developed staff analytics bot tracking performance metrics (commands used, messages sent, modmail threads closed)</li>
<li class="mb-2 relative before:content-['🩷']">Implemented leadership tools for volunteer moderator management</li>
</ul>
</li>
<li class="mb-2 relative before:content-['🩵']">Community Engagement Tools:
<ul class="pl-4 mt-2">
<li class="mb-2 relative before:content-['🩷']">Created analytics bot for monitoring user engagement</li>
<li class="mb-2 relative before:content-['🩷']">Developed music-themed trivia bot for community entertainment</li>
<li class="mb-2 relative before:content-['🩷']">Built cross-platform social media bot for Twitter-Discord-Slack integration</li>
</ul>
</li>
</ul>
</div>`,
end: new Date("November 5, 2024"),
link: "https://rythm.fm",
logo: "rythm.jpeg",
start: new Date("April 5 2022"),
title: "Senior Integrations Engineer",
type: "fixed",
},
{
company: "Streamcord",
description: `<div class="pl-4">
<p>As a Community Manager, I played a pivotal role in nurturing and expanding a vibrant community of over 50,000 members. My responsibilities encompassed a wide range of areas, including community engagement, technical support, human resources management, and bot operations. I was instrumental in fostering a thriving ecosystem around the Streamcord bot, which is utilized by over 1 million communities.</p>
<p>My multifaceted approach involved implementing innovative engagement strategies, contributing to technical infrastructure, spearheading human resources initiatives, and ensuring seamless bot operations. Through these efforts, I significantly enhanced member retention, activity levels, and overall user satisfaction.</p>
<p>By bridging the gap between the user community and the development team, I facilitated continuous improvement of the Streamcord bot and associated services, directly contributing to its widespread adoption and success.</p>
<p>Key responsibilities and achievements include:</p>
<ul class="list-none">
<li class="mb-2 relative before:content-['🩵'] ml-[-1rem]">Community Management and Growth:
<ul class="pl-4 mt-2">
<li class="mb-2 relative before:content-['🩷']">Managed and nurtured a thriving community of 50,000+ members</li>
<li class="mb-2 relative before:content-['🩷']">Provided comprehensive support for the Streamcord bot, utilized by over 1 million communities</li>
<li class="mb-2 relative before:content-['🩷']">Implemented engagement strategies, including staff streams and game nights, to foster community interaction</li>
<li class="mb-2 relative before:content-['🩷']">Led a complete community overhaul, significantly boosting member retention and activity</li>
</ul>
</li>
<li class="mb-2 relative before:content-['🩵']">Technical Infrastructure and Development:
<ul class="pl-4 mt-2">
<li class="mb-2 relative before:content-['🩷']">Supported the development process for the Streamcord bot</li>
<li class="mb-2 relative before:content-['🩷']">Maintained and updated documentation to ensure clarity and accessibility</li>
<li class="mb-2 relative before:content-['🩷']">Collaborated on the development and maintenance of the dashboard site</li>
</ul>
</li>
<li class="mb-2 relative before:content-['🩵']">Human Resources Initiatives:
<ul class="pl-4 mt-2">
<li class="mb-2 relative before:content-['🩷']">Conducted interviews and managed the onboarding process for new staff members</li>
<li class="mb-2 relative before:content-['🩷']">Developed and delivered comprehensive training programs for team members</li>
<li class="mb-2 relative before:content-['🩷']">Implemented and conducted quarterly staff evaluations to ensure team performance and growth</li>
</ul>
</li>
<li class="mb-2 relative before:content-['🩵']">Bot Operations and User Support:
<ul class="pl-4 mt-2">
<li class="mb-2 relative before:content-['🩷']">Addressed user queries and troubleshooting requests promptly</li>
<li class="mb-2 relative before:content-['🩷']">Collaborated with the development team to implement user feedback and feature requests</li>
<li class="mb-2 relative before:content-['🩷']">Monitored bot performance across millions of communities to maintain high uptime and user satisfaction</li>
</ul>
</li>
</ul>
</div>`,
end: new Date("December 5 2024"),
link: "https://streamcord.io",
logo: "streamcord.jpeg",
start: new Date("August 5 2021"),
title: "Community Manager and Infrastructure Engineer",
type: "fixed",
},
{
company: "Battlesnake",
description: `As a Community Moderator at Battlesnake, I played a vital role in ensuring a safe and welcoming environment for players. My focus was on promoting a positive experience for all members, allowing them to enjoy the game and interact with one another respectfully.
Additionally, I contributed to driving engagement for the Summer League 2021 and the Caster House system, fostering enthusiasm and participation in these events. My efforts helped create an inclusive and vibrant community for Battlesnake enthusiasts.`,
end: new Date("November 5 2022"),
link: "https://play.battlesnake.com",
logo: "battlesnake.jpeg",
start: new Date("June 5 2021"),
title: "Community Moderator",
type: "volunteer",
},
{
company: "Caylus Crew",
description: `As the Discord Administrator and Platform Engineering Manager at Caylus Crew, I developed custom bots that enhanced the community experience and streamlined operations. One such bot posted daily messages wishing happy birthday to members, fostering a sense of connection and camaraderie. I also created a bot to manage sponsor perks, ensuring efficient and accurate distribution of benefits to eligible members.
In addition to technical contributions, I coached and trained moderators, providing quarterly staff reviews to support their professional growth and improve performance. My work played a pivotal role in maintaining a vibrant, well-managed community and ensuring an exceptional experience for all participants.`,
end: null,
link: "https://discord.gg/infinite",
logo: "caylus.png",
start: new Date("June 5 2021"),
title: "Discord Administrator and Platform Engineering Manager",
type: "volunteer",
},
{
company: "Xcentric Collective",
description: `As an Integrations Engineer at Xcentric Collective, I developed a custom Discord bot that incorporated a unique Matchmaking Rating (MMR) system to calculate Rocket League proficiency. This system enabled users to track and monitor their skill levels accurately.
The bot also featured the ability to define teams and find matches with opponents of similar skill levels, facilitating balanced and fair gameplay. Additionally, the bot allowed users to schedule matches seamlessly, providing a streamlined and efficient experience for the community. My work enhanced the overall gaming experience and engagement within the Xcentric Collective community. As an Integrations Engineer at Xcentric Collective, I developed a custom Discord bot that incorporated a unique Matchmaking Rating (MMR) system to calculate Rocket League proficiency. This system enabled users to track and monitor their skill levels accurately. The bot also featured the ability to define teams and find matches with opponents of similar skill levels, facilitating balanced and fair gameplay. Additionally, the bot allowed users to schedule matches seamlessly, providing a streamlined and efficient experience for the community. My work enhanced the overall gaming experience and engagement within the Xcentric Collective community.`,
end: new Date("July 5 2023"),
link: "http://discord.gg/U3jQVYNbJt",
logo: "xcentric.jpg",
start: new Date("April 5 2021"),
title: "Integrations Engineer",
type: "volunteer",
},
{
company: "DigitalOcean",
description: `As a Hacktoberfest Community Moderator at DigitalOcean, I supported the community by building a custom bot to ensure repository links were correctly included in promotional channel messages, streamlining interactions, and providing automated responses for frequently asked questions. This contributed to a smoother experience for participants and enhanced community engagement.
In addition to managing the bot, I answered queries and guided developers in their open-source contributions, helping them navigate the Hacktoberfest event and maximize their impact. By maintaining a safe and welcoming community space, I fostered an inclusive environment for developers of all skill levels to collaborate and grow. My efforts played a crucial role in the success of the event and the satisfaction of its participants.`,
end: new Date("November 5 2024"),
link: "https://hacktoberfest.com",
logo: "digitalocean.jpeg",
start: new Date("April 5 2021"),
title: "Hacktoberfest Community Moderator",
type: "volunteer",
},
{
company: "EddieHub",
description: `As a Discord Administrator for EddieHub, I played a key role in moderating the community and fostering an open and inclusive environment. My focus was on upholding community guidelines and ensuring a positive experience for all members.
I provided support and encouragement to members on their development path, offering guidance and resources to help them grow and succeed. Additionally, I planned and managed community events and initiatives, creating opportunities for members to engage, learn, and collaborate.
My efforts contributed to the vibrancy and success of the EddieHub community, helping to create a welcoming space for developers to thrive.`,
end: new Date("May 5 2023"),
link: "https://www.eddiehub.org",
logo: "eddiehub.jpeg",
start: new Date("January 5 2021"),
title: "Discord Administrator",
type: "volunteer",
},
{
company: "Commit Your Code",
description: `As the Discord Administrator and Lead Integrations Engineer at Commit Your Code, I played a key role in fostering a supportive and friendly community environment by moderating interactions and ensuring a positive space for members. I provided guidance to individuals on their development path, offering support as they prepared for their first job or encountered coding challenges.
To enhance community security, I built a robust verification system that significantly reduced the number of compromised accounts, safeguarding members' data and promoting a safe space for collaboration. My contributions have been instrumental in supporting members' growth and maintaining a secure, welcoming atmosphere within the community.`,
end: null,
link: "https://discord.gg/StwJYeq",
logo: "cyc.jpeg",
start: new Date("December 5 2020"),
title: "Discord Administrator and Lead Integrations Engineer",
type: "volunteer",
},
{
company: "freeCodeCamp",
description: `<div class="pl-4">
<p>As a Community Manager at freeCodeCamp, I played a crucial role in maintaining and enhancing an open-source curriculum used by millions of developers worldwide. My responsibilities encompassed curriculum development, technical solution implementation, community management across multiple platforms, and contributing to the overall growth of the freeCodeCamp ecosystem.</p>
<p>By leading curriculum redesigns, developing technical solutions, and fostering vibrant online communities, I significantly improved user engagement, accessibility, and the overall learning experience for developers at all levels. My work directly contributed to the expansion and success of freeCodeCamp's mission to provide free coding education to anyone, anywhere.</p>
<p>Through collaborative efforts with a global team of contributors and strategic alignment with organizational goals, I helped shape freeCodeCamp's direction and impact in the world of coding education.</p>
<p>Key responsibilities and achievements include:</p>
<ul class="list-none">
<li class="mb-2 relative before:content-['🩵'] ml-[-1rem]">Curriculum Development and Enhancement:
<ul class="pl-4 mt-2 list-none">
<li class="mb-2 relative before:content-['🩷']">Led complete redesign of Responsive Web Design curriculum, improving accessibility and user engagement</li>
<li class="mb-2 relative before:content-['🩷']">Collaborated with global team of contributors to ensure curriculum relevance and quality</li>
<li class="mb-2 relative before:content-['🩷']">Implemented user feedback to continuously improve learning materials</li>
</ul>
</li>
<li class="mb-2 relative before:content-['🩵']">Technical Solutions Development:
<ul class="pl-4 mt-2">
<li class="mb-2 relative before:content-['🩷']">Built and deployed a moderation bot for Discord, significantly improving community safety and functionality</li>
<li class="mb-2 relative before:content-['🩷']">Created an efficient tool for distributing weekly email newsletter to millions of subscribers</li>
<li class="mb-2 relative before:content-['🩷']">Optimized community management processes across Discord, Forum, and Reddit platforms</li>
</ul>
</li>
<li class="mb-2 relative before:content-['🩵']">Community Management and Engagement:
<ul class="pl-4 mt-2">
<li class="mb-2 relative before:content-['🩷']">Provided guidance and support to users on their web development journey</li>
<li class="mb-2 relative before:content-['🩷']">Implemented engagement strategies resulting in increased user participation and retention</li>
<li class="mb-2 relative before:content-['🩷']">Fostered a welcoming and inclusive environment for learners of all levels</li>
</ul>
</li>
<li class="mb-2 relative before:content-['🩵']">Strategic Growth and Representation:
<ul class="pl-4 mt-2">
<li class="mb-2 relative before:content-['🩷']">Collaborated with leadership to align community initiatives with organizational goals</li>
<li class="mb-2 relative before:content-['🩷']">Analyzed user data and feedback to inform strategic decisions</li>
<li class="mb-2 relative before:content-['🩷']">Represented freeCodeCamp in external events and collaborations</li>
</ul>
</li>
</ul>
</div>`,
end: null,
link: "https://freecodecamp.org",
logo: "fcc.jpeg",
start: new Date("December 5, 2020"),
title: "Educational Developer and Community Manager",
type: "fixed",
},
{
company: "Virtual Insanity",
description: `As a Discord Moderator for Virtual Insanity, an adult-only community, I was instrumental in cultivating a secure, respectful, and interactive atmosphere for our diverse members. My responsibilities encompassed vigilant monitoring of discussions, ensuring compliance with established guidelines to deter any disruptive conduct, and safeguarding our users. Alongside conflict resolution, I provided empathetic support and guidance, fostering a harmonious environment conducive to positive interactions. Moreover, I actively assisted in verifying identification documents, reinforcing our commitment to maintaining a safe and authentic community experience. Through these efforts, I contributed to upholding the community's integrity and nurturing an inclusive space for all participants to thrive.`,
end: null,
link: "https://discord.com/invite/GDYNGnrGUs",
logo: "troopy.png",
start: new Date("May 5 2024"),
title: "Discord Moderator",
type: "volunteer",
},
{
company: "Azuliah (VTuber)",
description: `As a Discord Administrator and Integrations Engineer at Azuliah, I established custom integrations to streamline moderation efforts and enhance community management. These integrations supported the moderation team in maintaining a safe and welcoming space for all members.
In addition to technical contributions, I trained the owner and moderation team on best practices for running a successful community. My guidance included techniques for efficient moderation, conflict resolution, and fostering positive interactions among members. Through my efforts, I played a key role in ensuring the community's smooth operation and promoting a vibrant, supportive environment.`,
end: new Date("April 5 2024"),
link: "https://discord.com/invite/XNSy8PMvyy",
logo: "azuliah.jpg",
start: new Date("December 5 2023"),
title: "Discord Administrator and Integrations Engineer",
type: "volunteer",
},
{
company: "Rion Kuroko (VTuber)",
description: `As a Discord Moderator for Rion Kuroko, I constructed the server almost entirely from scratch to tailor it to the specific needs of the community. This involved designing and implementing structures, channels, and rules that supported a smooth and organized environment.
I also provided guidance to the owner on the technical aspects of Discord moderation, sharing best practices and offering solutions to effectively manage the server. My efforts played a key role in establishing a functional, user-friendly community space and empowering the owner with the knowledge needed to maintain and grow the server.`,
end: new Date("Jan 5 2024"),
link: "https://discord.com",
logo: "rion.jpg",
start: new Date("Nov 5 2023"),
title: "Discord Moderator",
type: "volunteer",
},
{
company: "Rythm",
description: `As a Senior Discord Moderator for Rythm, I played a dual role in overseeing community moderation and mentoring the moderation team. My responsibilities included tracking weekly staff activity to monitor performance and identify areas for improvement, ensuring the team remained effective and engaged.
Additionally, I guided and supported moderators, helping them develop their skills and excel in their roles. By identifying opportunities to enhance staff activity, I contributed to the overall health and vibrancy of the community. My efforts were instrumental in maintaining a positive, safe, and well-managed space for all members.`,
end: new Date("July 5 2022"),
link: "https://discord.com/invite/rythm",
logo: "rythm.jpeg",
start: new Date("Feb 5 2022"),
title: "Senior Discord Moderator",
type: "volunteer",
},
{
company: "TweetShift",
description: `As Technical Support Staff for TweetShift, I responded promptly to user queries, addressing issues and bugs within the bot to ensure a smooth user experience. I provided clear guidance on how to use the bot's features effectively, helping users maximize its capabilities.
My role involved troubleshooting technical challenges and offering solutions to enhance user satisfaction. By delivering efficient support and sharing helpful tips, I contributed to the overall success and reliability of the bot for the TweetShift community.`,
end: new Date("Jan 5 2022"),
link: "https://discord.com/invite/zdfQhjc",
logo: "tweetshift.png",
start: new Date("Oct 5 2021"),
title: "Technical Support Staff",
type: "volunteer",
},
{
company: "Rythm",
description: `As a Discord Moderator for Rythm, I played a central role in maintaining a safe, respectful, and welcoming environment for community members. I monitored conversations to ensure compliance with community guidelines and addressed any disruptive behavior promptly.
My efforts helped foster a positive and inclusive space for all members, contributing to the overall health and vibrancy of the Rythm community.`,
end: new Date("Feb 5 2022"),
link: "https://discord.com/invite/rythm",
logo: "rythm.jpeg",
start: new Date("Sept 5 2021"),
title: "Discord Moderator",
type: "volunteer",
},
{
company: "Streamcord",
description: `As Technical Support Staff for Streamcord, I provided essential support to users by triaging and debugging issues related to the Streamcord Discord bot. My role involved investigating and resolving technical challenges to ensure a seamless user experience.
Acting as a liaison between users and developers, I facilitated clear communication and reported user feedback to the development team for continuous improvement. Additionally, I moderated and engaged with the community, fostering a positive and inclusive environment for all participants. My efforts contributed to the overall success and satisfaction of the Streamcord community.`,
end: new Date("Aug 5 2021"),
link: "https://discord.com/invite/streamcord",
logo: "streamcord.jpeg",
start: new Date("Mar 5 2021"),
title: "Technical Support Staff",
type: "volunteer",
},
{
company: "freeCodeCamp",
description: `As a Community Moderator for freeCodeCamp, I provided vital support to users (campers) as they navigated the freeCodeCamp curriculum. My role included assisting users in debugging their code and answering questions, ensuring they received the guidance they needed to progress in their learning journey.
I engaged with and moderated the community on the forum and Discord server, fostering a positive, supportive, and inclusive environment for all members. Additionally, I assisted with issue triage and pull request review on GitHub, contributing to the ongoing improvement and development of freeCodeCamp's open-source projects. My efforts played a key role in maintaining the quality of the community and empowering users to achieve their learning goals.`,
end: new Date("Dec 5 2020"),
link: "https://discord.com/invite/freecodecamp-org-official-fi-fo-692816967895220344",
logo: "fcc.jpeg",
start: new Date("Jun 5 2020"),
title: "Community Moderator",
type: "volunteer",
},
{
company: "FruitPursuits",
description: `As a Discord Moderator for FruitPursuits, I provide crucial support to members, ensuring they have a seamless experience within our community. I troubleshoot technical issues, enforce community guidelines, and foster engagement among members. Collaborating with fellow moderators, I contribute to the ongoing improvement of our Discord server, empowering users to fully enjoy their fruit-loving journey.`,
end: null,
link: "https://discord.gg/xcy2fRsC5K",
logo: "fruit.png",
start: new Date("March 5 2024"),
title: "Community Moderator",
type: "volunteer",
},
{
company: "Deepgram",
description: `
<div class="pl-4">
<p>As a DX Consultant at Deepgram, I spearhead efforts to enhance community engagement and streamline developer experiences. Leveraging my expertise, I optimize community management workflows on platforms like Slack, GitHub Discussions, and Discord. My primary focus involves acting as a Community Manager, where I strive to answer approximately 60% of community inquiries, foster engagement, and ensure valuable feedback reaches the Product Board for consideration.</p>
<p>In parallel, I lead DX initiatives, delivering minor documentation improvements, documenting new product features, and integrating new solutions. My proficiency extends to SDK support (JS, Python), where I deliver enhancements and develop new applications as needed. Additionally, I provide high-priority support for demo applications.</p>
<p>Through my multifaceted approach, I drive tangible improvements in community interactions and developer experiences, contributing to Deepgram's growth and user satisfaction.</p>
<p>Key responsibilities and achievements include:</p>
<ul class="list-none">
<li class="mb-2 relative before:content-['🩵'] ml-[-1rem]">Community Management:
<ul class="pl-4 mt-2">
<li class="mb-2 relative before:content-['🩷']">Provide community support across Slack, GitHub Discussions, and Discord</li>
<li class="mb-2 relative before:content-['🩷']">Address approximately 60% of community inquiries, ensuring prompt and accurate responses</li>
<li class="mb-2 relative before:content-['🩷']">Foster community engagement through proactive interactions and targeted initiatives</li>
<li class="mb-2 relative before:content-['🩷']">Facilitate feedback flow to Product Board, driving user-centric product improvements</li>
</ul>
</li>
<li class="mb-2 relative before:content-['🩵']">Developer Experience (DX) Initiatives:
<ul class=" pl-4 mt-2">
<li class="mb-2 relative before:content-['🩷']">Spearhead documentation improvements, enhancing clarity and accessibility</li>
<li class="mb-2 relative before:content-['🩷']">Integrate innovative solutions to streamline developer workflows</li>
<li class="mb-2 relative before:content-['🩷']">Deliver high-priority support for demo applications, showcasing product capabilities</li>
</ul>
</li>
<li class="mb-2 relative before:content-['🩵']">SDK Support and Development:
<ul class="pl-4 mt-2">
<li class="mb-2 relative before:content-['🩷']">Provide expert support for JavaScript and Python SDKs</li>
<li class="mb-2 relative before:content-['🩷']">Implement enhancements to existing SDKs based on developer feedback and emerging needs</li>
<li class="mb-2 relative before:content-['🩷']">Develop new applications leveraging Deepgram's SDKs to demonstrate best practices</li>
</ul>
</li>
<li class="mb-2 relative before:content-['🩵']">Workflow Optimization:
<ul class="pl-4 mt-2">
<li class="mb-2 relative before:content-['🩷']">Streamline community management processes across multiple platforms</li>
<li class="mb-2 relative before:content-['🩷']">Implement efficient systems for tracking and addressing developer inquiries</li>
<li class="mb-2 relative before:content-['🩷']">Optimize feedback collection and integration into product development cycle</li>
</ul>
</li>
</ul>
</div>`,
end: null,
link: "https://deepgram.com",
logo: "deepgram.jpeg",
start: new Date("June 5 2024"),
title: "Developer Experience Consultant",
type: "fixed",
},
{
company: "Safeway",
description: `<div class="pl-4">
<p>As the Service Operations Manager at Safeway, I played a pivotal role in overseeing the store's day-to-day operations and maintaining exceptional service standards. My responsibilities encompassed a wide range of critical functions, from personnel management and training to ensuring compliance with safety regulations and company policies.</p>
<p>By focusing on hiring, onboarding, and mentoring both new associates and management personnel, I fostered a skilled and motivated workforce capable of delivering high-quality service. My implementation of comprehensive safety programs and strict adherence to OSHA regulations created a secure environment for both employees and customers.</p>
<p>Through diligent auditing of financial records and assistance with payroll processing, I contributed to the store's financial accuracy and operational efficiency. My collaborative approach to problem-solving and commitment to enforcing company standards helped maintain a positive work environment and uphold Safeway's reputation for excellence in service.</p>
<p>Key responsibilities and achievements include:</p>
<ul class="list-none">
<li class="mb-2 relative before:content-['🩵'] ml-[-1rem]">Personnel Management and Development:
<ul class="pl-4 mt-2">
<li class="mb-2 relative before:content-['🩷']">Hired, onboarded, and trained new associates to maintain a skilled workforce</li>
<li class="mb-2 relative before:content-['🩷']">Guided and mentored new PICs and department managers, ensuring their preparedness for leadership roles</li>
<li class="mb-2 relative before:content-['🩷']">Addressed associate concerns and collaboratively developed solutions to maintain a positive work environment</li>
</ul>
</li>
<li class="mb-2 relative before:content-['🩵'] ml-[-1rem]">Safety and Compliance:
<ul class="pl-4 mt-2">
<li class="mb-2 relative before:content-['🩷']">Maintained compliance with OSHA safety regulations across all store operations</li>
<li class="mb-2 relative before:content-['🩷']">Implemented a comprehensive safety program within the store to ensure employee and customer well-being</li>
<li class="mb-2 relative before:content-['🩷']">Enforced company policies and procedures, addressing violations appropriately</li>
</ul>
</li>
<li class="mb-2 relative before:content-['🩵'] ml-[-1rem]">Financial Management and Auditing:
<ul class="pl-4 mt-2">
<li class="mb-2 relative before:content-['🩷']">Audited weekly bookkeeping records for cash shortages and discrepancies, ensuring financial accuracy</li>
<li class="mb-2 relative before:content-['🩷']">Assisted with processing weekly payroll and timekeeping as needed</li>
</ul>
</li>
<li class="mb-2 relative before:content-['🩵'] ml-[-1rem]">Operational Excellence:
<ul class="pl-4 mt-2">
<li class="mb-2 relative before:content-['🩷']">Oversaw day-to-day store operations to maintain exceptional service standards</li>
<li class="mb-2 relative before:content-['🩷']">Upheld high service expectations and promoted a positive work environment</li>
<li class="mb-2 relative before:content-['🩷']">Contributed to the efficient management of store operations through various initiatives</li>
</ul>
</li>
</ul>
</div>`,
end: new Date("5 April 2020"),
link: "https://www.safeway.com",
logo: "safeway.png",
start: new Date("5 August 2009"),
title: "Service Operations Manager",
type: "fixed",
},
{
company: "Vancouver School of Arts and Academics",
description: `<div class="pl-4">
<p>As a student at the Vancouver School of Arts and Academics, I immersed myself in a diverse and enriching artistic environment, with a primary focus on music and a secondary emphasis on theatre. This multidisciplinary approach allowed me to develop a broad range of skills across various art forms, fostering my creativity and artistic expression.</p>
<p>My dedication to music, particularly in band, saw me master multiple instruments including the clarinet, piano, bassoon, and saxophone. This comprehensive musical education enhanced my understanding of different musical styles and techniques, as well as my ability to collaborate within an ensemble setting.</p>
<p>In theatre, I honed my skills both as an actor and as a theatre technician, gaining a well-rounded understanding of stage production. Additionally, I explored other artistic disciplines such as dance, visual arts, filmography, and literature, further broadening my creative horizons and interdisciplinary approach to the arts.</p>
<p>Key areas of focus and achievements include:</p>
<ul class="list-none">
<li class="mb-2 relative before:content-['🩵'] ml-[-1rem]">Music:
<ul class="pl-4 mt-2">
<li class="mb-2 relative before:content-['🩷']">Participated actively in the school band program</li>
<li class="mb-2 relative before:content-['🩷']">Developed proficiency in multiple instruments: clarinet, piano, bassoon, and saxophone</li>
<li class="mb-2 relative before:content-['🩷']">Gained experience in ensemble playing and musical collaboration</li>
</ul>
</li>
<li class="mb-2 relative before:content-['🩵'] ml-[-1rem]">Theatre:
<ul class="pl-4 mt-2">
<li class="mb-2 relative before:content-['🩷']">Performed as an actor in various school productions</li>
<li class="mb-2 relative before:content-['🩷']">Gained technical theatre experience, working behind the scenes on productions</li>
<li class="mb-2 relative before:content-['🩷']">Developed a comprehensive understanding of stage production processes</li>
</ul>
</li>
<li class="mb-2 relative before:content-['🩵'] ml-[-1rem]">Interdisciplinary Arts Exploration:
<ul class="pl-4 mt-2">
<li class="mb-2 relative before:content-['🩷']">Explored dance, enhancing physical expression and movement skills</li>
<li class="mb-2 relative before:content-['🩷']">Engaged in visual arts projects, developing artistic techniques and creative vision</li>
<li class="mb-2 relative before:content-['🩷']">Participated in filmography studies, gaining insight into visual storytelling</li>
<li class="mb-2 relative before:content-['🩷']">Studied literature, enhancing writing and analytical skills</li>
</ul>
</li>
</ul>
</div>`,
end: new Date("5 June 2009"),
link: "https://arts.vansd.org/",
logo: "vsaa.png",
start: new Date("5 September 2001"),
title: "Student",
type: "volunteer",
},
];

View File

@ -1,40 +0,0 @@
/**
* @copyright nhcarrigan
* @license Naomi's Public License
* @author Naomi Carrigan
*/
export const Koikatsu = [
"CharaStudio-2024-10-15-19-14-34-Render.png",
"CharaStudio-2024-10-15-19-15-43-Render.png",
"CharaStudio-2024-10-16-09-30-57-Render.png",
"CharaStudio-2024-10-18-11-54-39-Render.png",
"CharaStudio-2024-10-26-09-13-34-Render.png",
"CharaStudio-2024-10-27-09-44-24-Render.png",
"CharaStudio-2024-10-27-09-45-11-Render.png",
"CharaStudio-2024-10-31-13-20-16-Render.png",
"CharaStudio-2024-10-31-13-27-20-Render.png",
"CharaStudio-2024-11-01-22-20-26-Render.png",
"CharaStudio-2024-11-01-22-21-00-Render.png",
"CharaStudio-2024-11-01-22-22-04-Render.png",
"CharaStudio-2024-11-01-22-22-40-Render.png",
"CharaStudio-2024-11-01-22-23-32-Render.png",
"CharaStudio-2024-11-02-13-41-30-Render.png",
"CharaStudio-2024-11-02-13-45-05-Render.png",
"CharaStudio-2024-11-02-13-46-02-Render.png",
"CharaStudio-2024-11-14-18-12-22-Render.png",
"CharaStudio-2024-11-14-18-13-23-Render.png",
"CharaStudio-2024-11-18-10-22-40-Render.png",
"CharaStudio-2024-11-18-10-23-28-Render.png",
"CharaStudio-2024-11-18-10-24-39-Render.png",
"CharaStudio-2024-11-18-10-25-50-Render.png",
"CharaStudio-2024-11-18-10-27-48-Render.png",
"CharaStudio-2024-11-18-10-29-25-Render.png",
"CharaStudio-2024-11-18-10-30-05-Render.png",
"CharaStudio-2024-11-22-19-12-18-Render.png",
"CharaStudio-2024-11-22-19-13-00-Render.png",
"CharaStudio-2024-11-22-19-13-44-Render.png",
"CharaStudio-2024-11-22-19-15-24-Render.png",
"CharaStudio-2024-11-22-19-16-16-Render.png",
"CharaStudio-2024-11-22-19-16-51-Render.png",
"CharaStudio-2024-11-28-11-11-56-Render.png",
];

View File

@ -1,39 +0,0 @@
/**
* @copyright nhcarrigan
* @license Naomi's Public License
* @author Naomi Carrigan
*/
/**
* Navigation items to render on home page and
* on main navbar.
*/
export const NavItems = [
{ href: "/about", text: "About Naomi" },
{ href: "/manual", text: "User Manual" },
{ href: "/work", text: "Employment History" },
{ href: "/contact", text: "Contact Us" },
{ href: "/certs", text: "Certifications" },
{ href: "/reviews", text: "Reviews" },
{ href: "/games", text: "Game Screenshots" },
{ href: "/team", text: "The NHCarrigan Team" },
{ href: "/polycule", text: "Polycule" },
{ href: "/art", text: "Art of Naomi" },
{ href: "/manifesto", text: "Transfemme Manifesto" },
{ href: "/ask", text: "Ask Me Anything!" },
{ href: "/tech", text: "Technologies" },
{ href: "/contribute", text: "Contribute to our Projects" },
{ href: "/koikatsu", text: "Koikatsu Scenes" },
{ href: "/ref", text: "Reference Sheet" },
{ href: "/projects", text: "Our Projects" },
{ href: "/sales", text: "Sales Inquiries" },
{ href: "/newsletter", text: "Newsletter" },
{ href: "/appeal", text: "Sanction Appeals" },
{ href: "https://games.nhcarrigan.com", text: "Game Dev" },
{ href: "https://merch.nhcarrigan.link", text: "Merchandise" },
{ href: "https://docs.nhcarrigan.com", text: "Documentation" },
{ href: "https://chat.nhcarrigan.com", text: "Support" },
{ href: "/apply", text: "Staff Application" },
].sort((a, b) => {
return a.text.localeCompare(b.text);
});

View File

@ -1,40 +0,0 @@
/**
* @copyright nhcarrigan
* @license Naomi's Public License
* @author Naomi Carrigan
*/
/**
* List of polycule members to render.
*/
export const Partners: Array<{
name: string;
avatar: string;
relationship: string;
url: string;
anniversary: Date;
}> = [
{
anniversary: new Date("January 1, 2023"),
avatar: "dashi.png",
name: "Sadashi",
relationship: "Romantic Partner",
url: "https://chat.nhcarrigan.com",
},
{
anniversary: new Date("November 17, 2023"),
avatar: "estel.png",
name: "Rain",
relationship: "Fiancée",
url: "https://chat.nhcarrigan.com",
},
{
anniversary: new Date("October 1, 2023"),
avatar: "fruit.png",
name: "Kaitlyn",
relationship: "Queer-Platonic Partner",
url: "https://kaitlyn.nhcarrigan.com",
},
].sort((a, b) => {
return a.anniversary.getTime() - b.anniversary.getTime();
});

View File

@ -1,232 +0,0 @@
/**
* @copyright nhcarrigan
* @license Naomi's Public License
* @author Naomi Carrigan
*/
/**
* List of projects to render.
*/
export const Projects: Array<{
name: string;
url: string;
source?: string;
description: string;
type: "Website" | "Bot" | "API" | "Game";
}> = [
{
description: "A tool to monitor the email complaints of the freeCodeCamp newsletter.",
name: "Email Monitor",
source: "https://github.com/freecodecamp/email-complaint-monitoring",
type: "API",
url: "https://complaint.freecodecamp.org/",
},
{
description: "Our self-hosted LibreTranslate instance.",
name: "Translation API",
source: "https://github.com/LibreTranslate/LibreTranslate",
type: "API",
url: "https://trans.nhcarrigan.com/",
},
{
description: "API to authenticate our Slack translation bot.",
name: "Translation Slack Auth",
type: "API",
url: "https://trans-slack.nhcarrigan.com/slack/install",
},
{
description: "AI bot in our Discord which generates alt text.",
name: "AltGenerator",
source: "https://codeberg.org/nhcarrigan/alt-generator",
type: "Bot",
url: "https://alt.nhcarrigan.com/",
},
{
description: "A bot and API to allow submitting anonymous questions for Naomi to answer.",
name: "Anon Bot",
source: "https://codeberg.org/nhcarrigan/anon-bot",
type: "Bot",
url: "https://anon.nhcarrigan.com/",
},
{
description: "A bot to track art requests and latest news updates for the Art 4 Palestine charity.",
name: "Art4Palestine Bot",
source: "https://codeberg.org/nhcarrigan/a4p-bot",
type: "Bot",
url: "https://afp.nhcarrigan.com/",
},
{
description: "A bot to remove special booster colour roles when someone stops boosting.",
name: "Boost Monitor",
source: "https://codeberg.org/nhcarrigan/boost-monitor",
type: "Bot",
url: "https://oogie.nhcarrigan.com/",
},
{
description: "Custom moderation utility for freeCodeCamp.",
name: "CamperChan",
source: "github.com/freeCodeCamp/camperchan/",
type: "Bot",
url: "https://camperchan.nhcarrigan.com/",
},
{
description: "AI-powered bot in our Discord community which can evaluate code snippets.",
name: "Code Evaluator",
source: "https://codeberg.org/nhcarrigan/code-evaluator",
type: "Bot",
url: "https://eval.nhcarrigan.com/",
},
{
description: "Community syndication and automation tool that bridges Github discussions and Discord threads into an internal Slack channel.",
name: "Deepgram Bot",
type: "Bot",
url: "https://deepgram-discord-bot.fly.dev/",
},
{
description: "AI bot designed to answer queries by providing actual sources.",
name: "Librarian",
source: "https://codeberg.org/nhcarrigan/librarian",
type: "Bot",
url: "https://lib.nhcarrigan.com/",
},
{
description: "Python bot to detect links in the promote-your-stream channel for Streamcord.",
name: "Link Detector",
source: "https://codeberg.org/nhcarrigan/link-detector",
type: "Bot",
url: "https://linkdetector.nhcarrigan.com/health",
},
{
description: "Our paid general-purpose moderation bot for Discord.",
name: "Moderation Bot",
source: "https://codeberg.org/nhcarrigan/mod-bot",
type: "Bot",
url: "https://hooks.nhcarrigan.com/",
},
{
description: "A general-purpose AI bot for our Discord community.",
name: "NaomiAI",
source: "https://codeberg.org/nhcarrigan/anthropic-bot",
type: "Bot",
url: "https://naomiai.nhcarrigan.com/",
},
{
description: "A bot that bridges discussions between Discord, Slack, Matrix, and IRC.",
name: "Social Media Bridge",
source: "https://codeberg.org/nhcarrigan/social-media-bridge",
type: "Bot",
url: "https://bridge.nhcarrigan.com/",
},
{
description: "A kanban-style task management bot for Discord, installed directly to your user account.",
name: "Task Bot",
source: "https://codeberg.org/nhcarrigan/user-task-bot",
type: "Bot",
url: "https://tasks.nhcarrigan.com/",
},
{
description: "A Zelda RP bot for my friend Ruu.",
name: "Tingle Bot",
source: "https://codeberg.org/nhcarrigan/tingle-bot",
type: "Bot",
url: "https://ruubot.nhcarrigan.com/",
},
{
description: "A bot for Slack and Discord to translate user messages.",
name: "Translation Bot",
source: "https://codeberg.org/nhcarrigan/translation-bot",
type: "Bot",
url: "https://trans-bot.nhcarrigan.com/",
},
{
description: "Our first game, an introduction to our original characters Becca and Rosalia",
name: "Beccalia: Prologue",
type: "Game",
url: "https://beccalia.nhcarrigan.com/prologue",
},
{
description: "A cancelled game that explores Becca and Rosalia's origin stories.",
name: "Beccalia: Origins",
type: "Game",
url: "https://beccalia.nhcarrigan.com/origins",
},
{
description: "A short game built for a weekend game jam our friend hosted.",
name: "Ruu's Goblin Quest",
type: "Game",
url: "https://goblin.nhcarrigan.com/",
},
{
description: "Our self-hosted Plausible analytics.",
name: "Analytics",
source: "https://github.com/plausible/analytics/",
type: "Website",
url: "https://analytics.nhcarrigan.com/",
},
{
description: "A quick landing page for our Beccalia games.",
name: "Beccalia Landing",
type: "Website",
url: "https://beccalia.nhcarrigan.com/",
},
{
description: "A manual username service to provide free custom handles to Bluesky users.",
name: "BlueSky Username Service",
type: "Website",
url: "https://naomi.party/",
},
{
description: "Community marketing site for Deepgram.",
name: "Deepgram Community",
type: "Website",
url: "https://community.deepgram.com/",
},
{
description: "Personal site for my sister.",
name: "Denna",
source: "https://codeberg.org/nhcarrigan/denna",
type: "Website",
url: "https://denna.nhcarrigan.com/",
},
{
description: "Our primary documentation platform.",
name: "Documentation",
source: "https://codeberg.org/nhcarrigan/docs",
type: "Website",
url: "https://docs.nhcarrigan.com/",
},
{
description: "The core freeCodeCamp curriculum.",
name: "freeCodeCamp",
source: "https://github.com/freecodecamp/freecodecamp",
type: "Website",
url: "https://www.freecodecamp.org/",
},
{
description: "A small server to handle link redirections.",
name: "Link Redirection Service",
type: "Website",
url: "https://nhcarrigan.link/",
},
{
description: "Personal website for my partner Kaitlyn.",
name: "Kaitlyn",
source: "https://codeberg.org/nhcarrigan/kaitlyn",
type: "Website",
url: "https://kaitlyn.nhcarrigan.com/",
},
{
description: "This website you're looking at right now!",
name: "Portfolio",
source: "https://codeberg.org/nhcarrigan/portfolio",
type: "Website",
url: "https://nhcarrigan.com/",
},
{
description: "Portfolio site for my friend Starfazers.",
name: "Starfazers",
source: "https://codeberg.org/nhcarrigan/starfazers",
type: "Website",
url: "https://starfazers.nhcarrigan.com/",
},
];

View File

@ -1,536 +0,0 @@
/**
* @copyright nhcarrigan
* @license Naomi's Public License
* @author Naomi Carrigan
*/
import {
faAngellist,
faBluesky,
faDiscord,
faFreeCodeCamp,
faGithub,
faGooglePlus,
faHashnode,
faItchIo,
faLinkedinIn,
faMastodon,
faMeetup,
faNpm,
faPatreon,
faPaypal,
faProductHunt,
faReddit,
faSignalMessenger,
faSlack,
faSteam,
faStripe,
faTelegramPlane,
faTiktok,
faTumblr,
faWordpress,
faYoutube,
faSnapchat,
} from "@fortawesome/free-brands-svg-icons";
import {
faAtom,
faBriefcase,
faChessKnight,
faComputer,
faEnvelope,
faGamepad,
faHashtag,
faMoneyBill,
} from "@fortawesome/free-solid-svg-icons";
import { Codeberg } from "../icons/Codeberg";
import { Coursera } from "../icons/Coursera";
import { Fiverr } from "../icons/Fiverr";
import { Gather } from "../icons/Gather";
import { Gog } from "../icons/Gog";
import { Gumroad } from "../icons/Gumroad";
import { Kofi } from "../icons/KoFi";
import { Matrix } from "../icons/Matrix";
import { Peerlist } from "../icons/Peerlist";
import { Pixiv } from "../icons/Pixiv";
import { Polywork } from "../icons/Polywork";
import { RetroAchievements } from "../icons/RetroAchievements";
import { Saylor } from "../icons/Saylor";
import { TeeSpring } from "../icons/TeeSpring";
import { Throne } from "../icons/Throne";
import { Topmate } from "../icons/Topmate";
import { TreeNation } from "../icons/TreeNation";
import { Udemy } from "../icons/Udemy";
import { VRoid } from "../icons/VRoid";
import type { IconDefinition } from "@fortawesome/fontawesome-svg-core";
/**
* Custom button with gradient for hire CTA.
*/
const HireMe: {
icon: IconDefinition;
link: string;
label: string;
alt: string;
color: string;
background: string;
} = {
alt: "Briefcase Icon",
background: `linear-gradient(
90deg,
#5bcefa,
#f5a9b8,
#ffffff,
#f5a9b8,
#5bcefa
)`,
color: "#003600",
icon: faBriefcase,
label: "Hire Us!",
link: "https://docs.nhcarrigan.com/about/hire/",
};
/**
* Custom button with gradient for Donate CTA.
*/
const Donate: {
icon: IconDefinition;
link: string;
label: string;
alt: string;
color: string;
background: string;
} = {
alt: "Money Icon",
background: `linear-gradient(
90deg,
rgba(255, 0, 0, 1) 0%,
rgba(251, 7, 217, 1) 10%,
rgba(186, 12, 248, 1) 20%,
rgba(95, 21, 242, 1) 30%,
rgba(28, 127, 238, 1) 40%,
rgba(47, 201, 226, 1) 50%,
rgba(63, 218, 216, 1) 60%,
rgba(79, 220, 74, 1) 70%,
rgba(208, 222, 33, 1) 80%,
rgba(255, 154, 0, 1) 90%,
rgba(255, 0, 0, 1) 100%
)`,
color: "#003600",
icon: faMoneyBill,
label: "Donate 💜",
link: "https://docs.nhcarrigan.com/about/donate/",
};
/**
* List of social media buttons to render.
*/
const Socials: Array<{
icon: IconDefinition;
link: string;
label: string;
alt: string;
color: string;
background: string;
}> = [
{
alt: "Codeberg Logo",
background: "#0B3049",
color: "#B5DDFF",
icon: Codeberg,
label: "Codeberg",
link: "https://codeberg.org/naomi-lgbt",
},
{
alt: "GitHub Logo",
background: "#333333",
color: "#FFFFFF",
icon: faGithub,
label: "GitHub",
link: "https://github.com/nhcarrigan",
},
{
alt: "Discord Logo",
background: "#7289DA",
color: "#FFFFFF",
icon: faDiscord,
label: "Discord",
link: "https://chat.naomi.lgbt",
},
{
alt: "Element Logo",
background: "#29B6F6",
color: "#FFFFFF",
icon: Matrix,
label: "Matrix",
link: "https://matrix.to/#/#naomi:matrix.org",
},
{
alt: "Octothorpe",
background: "#000000",
color: "#FFFFFF",
icon: faHashtag,
label: "IRC",
link: "https://docs.nhcarrigan.com/about/contact/#33-irc-channels",
},
{
alt: "Slack Logo",
background: "#4A154B",
color: "#FFFFFF",
icon: faSlack,
label: "Slack",
link: "https://join.slack.com/t/naomi-lgbt/signup",
},
{
alt: "Reddit Logo",
background: "#FF4500",
color: "#FFFFFF",
icon: faReddit,
label: "Reddit",
link: "https://reddit.com/r/nhcarrigan",
},
{
alt: "Hashnode Logo",
background: "#2962FF",
color: "#FFFFFF",
icon: faHashnode,
label: "Blog",
link: "https://blog.nhcarrigan.com",
},
{
alt: "LinkedIn Logo",
background: "#0077B5",
color: "#FFFFFF",
icon: faLinkedinIn,
label: "LinkedIn",
link: "https://linkedin.com/in/naomi-lgbt",
},
{
alt: "Peerlist Logo",
background: "#219653",
color: "#FFFFFF",
icon: Peerlist,
label: "Peerlist",
link: "https://resume.nhcarrigan.com",
},
{
alt: "Polywork Logo",
background: "#7C3AED",
color: "#FFFFFF",
icon: Polywork,
label: "Polywork",
link: "https://polywork.nhcarrigan.com/",
},
{
alt: "Fiverr Logo",
background: "#1DBF73",
color: "#FFFFFF",
icon: Fiverr,
label: "Fiverr",
link: "https://www.fiverr.com/nhcarrigan",
},
{
alt: "Mastodon Logo",
background: "#2B90D9",
color: "#FFFFFF",
icon: faMastodon,
label: "Mastodon",
link: "https://mastodon.social/@naomi_lgbt",
},
{
alt: "Steam Logo",
background: "#1b2838",
color: "#c7d5e0",
icon: faSteam,
label: "Steam",
link: "https://steamcommunity.com/id/naomi-lgbt/",
},
{
alt: "How Long to Beat Logo",
background: "#333333",
color: "#FFFFFF",
icon: faGamepad,
label: "HLTB",
link: "https://howlongtobeat.com/user/naomi_lgbt",
},
{
alt: "Snapchat Logo",
background: "#FFFC00",
color: "#000000",
icon: faSnapchat,
label: "Snapchat",
link: "https://www.snapchat.com/add/naomi-lgbt",
},
{
alt: "GOG Logo",
background: "#863A3A",
color: "#FFFFFF",
icon: Gog,
label: "GOG",
link: "https://www.gog.com/u/naomi-lgbt",
},
{
alt: "Itch.io Logo",
background: "#FA5C5C",
color: "#FFFFFF",
icon: faItchIo,
label: "Itch.io",
link: "https://nhcarrigan.itch.io/",
},
{
alt: "Lichess Logo",
background: "#000000",
color: "#FFFFFF",
icon: faChessKnight,
label: "Lichess",
link: "https://lichess.org/../naomi-lgbt",
},
{
alt: "Saylor Academy Logo",
background: "#469dcc",
color: "#183140",
icon: Saylor,
label: "Saylor Academy",
link: "https://learn.saylor.org/user/profile.php?id=2074619",
},
{
alt: "Paypal Logo",
background: "#003087",
color: "#FFFFFF",
icon: faPaypal,
label: "Paypal",
link: "https://paypal.me/nhcarrigan",
},
{
alt: "Ko-Fi Logo",
background: "#FF5E5B",
color: "#FFFFFF",
icon: Kofi,
label: "Ko-Fi",
link: "https://ko-fi.com/nhcarrigan",
},
{
alt: "Patreon Logo",
background: "#F96854",
color: "#FFFFFF",
icon: faPatreon,
label: "Patreon",
link: "https://patreon.com/nhcarrigan",
},
{
alt: "freeCodeCamp Logo",
background: "#0a0a23",
color: "#FFFFFF",
icon: faFreeCodeCamp,
label: "freeCodeCamp",
link: "https://forum.freecodecamp.org/u/nhcarrigan/summary",
},
{
alt: "NPM Logo",
background: "#CB3837",
color: "#FFFFFF",
icon: faNpm,
label: "NPM",
link: "https://www.npmjs.com/~nhcarrigan",
},
{
alt: "GatherTown Logo",
background: "#7B68EE",
color: "#FFFFFF",
icon: Gather,
label: "GatherTown",
link: "https://app.gather.town/invite?token=CiIvbSnrQiW-akXFSPL_",
},
{
alt: "VRoid Logo",
background: "#ffe100",
color: "#000000",
icon: VRoid,
label: "VRoid",
link: "https://hub.vroid.com/en/characters/6033404747153826650/models/3483506204509065121",
},
{
alt: "Pixiv Logo",
background: "#0096FA",
color: "#FFFFFF",
icon: Pixiv,
label: "Pixiv",
link: "https://www.pixiv.net/en/users/77818154",
},
{
alt: "Email Icon",
background: "#000000",
color: "#FFFFFF",
icon: faEnvelope,
label: "Email",
link: "https://docs.nhcarrigan.com/about/contact/#7-email-communication",
},
{
alt: "Coursera Logo",
background: "#0056D2",
color: "#FFFFFF",
icon: Coursera,
label: "Coursera",
link: "https://www.coursera.org/learner/naomi-lgbt",
},
{
alt: "Udemy Logo",
background: "#EC5252",
color: "#FFFFFF",
icon: Udemy,
label: "Udemy",
link: "https://www.udemy.com/user/naomi-carrigan/",
},
{
alt: "Wordpress Logo",
background: "#1E8EDE",
color: "#FFFFFF",
icon: faWordpress,
label: "Gravatar",
link: "https://gravatar.com/nhcarrigan",
},
{
alt: "Computer Icon",
background: "#000000",
color: "#FFFFFF",
icon: faComputer,
label: "PC Part Picker",
link: "https://pcpartpicker.com/user/nhcarrigan/",
},
{
alt: "Throne.me Logo",
background: "#000000",
color: "#FFFFFF",
icon: Throne,
label: "Throne",
link: "https://throne.com/naomilgbt",
},
{
alt: "Stripe Logo",
background: "#6772E5",
color: "#FFFFFF",
icon: faStripe,
label: "Stripe",
link: "https://buy.stripe.com/cN24iTfqu1j6b3afZ2",
},
{
alt: "Signal Logo",
background: "#FFFFFF",
color: "#3A76F0",
icon: faSignalMessenger,
label: "Signal",
link: "https://signal.me/#eu/YGo6ag7kAwkdfkw863-J4qLK3VyKn8uWLhvyX60Jx5J0qrDZnz1B_aLrjM9yAMe6",
},
{
alt: "Angellist Logo",
background: "#000000",
color: "#FFFFFF",
icon: faAngellist,
label: "WellFound",
link: "https://wellfound.com/u/naomi-h-carrigan",
},
{
alt: "ProtonDB Logo",
background: "#000000",
color: "#FFFFFF",
icon: faAtom,
label: "ProtonDB",
link: "https://www.protondb.com/users/1717755560",
},
{
alt: "TeeSpring Logo",
background: "#000000",
color: "#FFFFFF",
icon: TeeSpring,
label: "Merch",
link: "https://nhcarrigan.creator-spring.com/",
},
{
alt: "BlueSky Logo",
background: "#1DA1F2",
color: "#FFFFFF",
icon: faBluesky,
label: "BlueSky",
link: "https://bsky.app/profile/naomi.lgbt",
},
{
alt: "Telegram Logo",
background: "#0088cc",
color: "#FFFFFF",
icon: faTelegramPlane,
label: "Telegram",
link: "https://t.me/naomi_lgbt",
},
{
alt: "Google Chat Logo",
background: "#DB4437",
color: "#FFFFFF",
icon: faGooglePlus,
label: "Google Chat",
link: "https://chat.google.com/room/AAAAK270m3M",
},
{
alt: "Tree Nation Logo",
background: "#FFFFFF",
color: "#55C1A8",
icon: TreeNation,
label: "Tree Nation",
link: "https://tree-nation.com/profile/naomi-carrigan",
},
{
alt: "Meetup Logo",
background: "#FF6D00",
color: "#FFFFFF",
icon: faMeetup,
label: "Meetup",
link: "https://www.meetup.com/members/437962584/",
},
{
alt: "Tumblr Logo",
background: "#36465D",
color: "#FFFFFF",
icon: faTumblr,
label: "Tumblr",
link: "https://www.tumblr.com/naomi-lgbt",
},
{
alt: "YouTube Logo",
background: "#FF0000",
color: "#FFFFFF",
icon: faYoutube,
label: "YouTube",
link: "https://www.youtube.com/@naomilgbt",
},
{
alt: "RetroAchievements Logo",
background: "#1066dd",
color: "#cc9a00",
icon: RetroAchievements,
label: "RetroAchievements",
link: "https://retroachievements.org/user/naomilgbt",
},
{
alt: "ProductHunt Logo",
background: "#da552f",
color: "#FFFFFF",
icon: faProductHunt,
label: "ProductHunt",
link: "https://www.producthunt.com/@naomi_lgbt",
},
{
alt: "Topmate Logo",
background: "#e44332",
color: "#FFFFFF",
icon: Topmate,
label: "Topmate",
link: "https://topmate.io/nhcarrigan",
},
{
alt: "Gumroad Logo",
background: "#fe90e7",
color: "#000000",
icon: Gumroad,
label: "Gumroad",
link: "https://nhcarrigan.gumroad.com",
},
];
export { HireMe, Donate, Socials };

View File

@ -1,45 +0,0 @@
/**
* @copyright nhcarrigan
* @license Naomi's Public License
* @author Naomi Carrigan
*/
/**
* List of nhcarrigan team members to render.
*/
export const TeamMembers: Array<{
name: string;
avatar: string;
role: string;
url: string;
joinDate: Date;
}> = [
{
avatar: "naomi.png",
joinDate: new Date("April 1, 2020"),
name: "Naomi Carrigan",
role: "Founder / CEO",
url: "https://chat.nhcarrigan.com",
},
{
avatar: "denna.png",
joinDate: new Date("April 2, 2020"),
name: "Denna",
role: "Chief Financial Officer",
url: "https://denna.nhcarrigan.com",
},
{
avatar: "tim.png",
joinDate: new Date("April 2, 2020"),
name: "Tim",
role: "Chief Technical Officer",
url: "https://chat.nhcarrigan.com",
},
{
avatar: "anna.png",
joinDate: new Date("August 29, 2023"),
name: "Anna",
role: "Software Engineering Intern",
url: "https://chat.nhcarrigan.com",
},
];

View File

@ -1,90 +0,0 @@
/**
* @copyright nhcarrigan
* @license Naomi's Public License
* @author Naomi Carrigan
*/
import { faLinkedin } from "@fortawesome/free-brands-svg-icons";
import type { IconDefinition } from "@fortawesome/fontawesome-svg-core";
/**
* List of reviews to render.
*/
export const Testimonials: Array<{
name: string;
date: Date;
content: string;
sourceIcon: IconDefinition;
sourceUrl: string;
sourceName: string;
}> = [
{
content:
"Naomi has done a fantastic job in creating Becca Bot, which is an integral part in managing the EddieHub Discord Community. As founder of EddieHub, Naomi is super helpful to all Community members and an excellent moderator, from our text channels to audio calls and live streams. Naomi demonstrates an excellent technical knowledge and is always keen to share this with the community.",
date: new Date("June 30, 2023"),
name: "Eddie Jaoude",
sourceIcon: faLinkedin,
sourceName: "LinkedIn",
sourceUrl: "https://www.linkedin.com/in/naomi-lgbt/details/recommendations/",
},
{
content:
"If you need a problem solver, look at Naomi. Naomi is a fantastic part of the online tech community by teaching and offering help to beginners on their journeys into tech. She has created some great solutions and is a consistent learner. Naomi has led initiatives using Javascript and front-end technologies to produce finished products within a volunteer position. Highly recommend Naomi to any team.",
date: new Date("July 6 2023"),
name: "Danny Thompson",
sourceIcon: faLinkedin,
sourceName: "LinkedIn",
sourceUrl: "https://www.linkedin.com/in/naomi-lgbt/details/recommendations/",
},
{
content:
"Naomi is an absolute trailblazer, and is an amazing person to work with! Naomi is humorous and also has an amazing attitude to work with. Her ability to solve complex problems efficiently astounds me. Not only does she demonstrate outstanding technical knowledge, but also does an amazing job at elucidating her needs as an engineer. She is a very warm person and quite easy to work with. Naomi is immensely perceptive and very calculated with what she does. Naomi would make an excellent addition to any company that is lucky enough to hire her!",
date: new Date("May 2 2024"),
name: "Francez Urmatan",
sourceIcon: faLinkedin,
sourceName: "LinkedIn",
sourceUrl: "https://www.linkedin.com/in/naomi-lgbt/details/recommendations/",
},
{
content:
"I've worked alongside Naomi on a number of projects, and it is always a blessing to have her on the team. She is knowledgable, reliable, and always willing to jump in with creative and efficient engineering solutions to complex workflow problems. Naomi is also such a patient teacher, effectively explaining how things work and enabling others to become more independent. I always look forward to working with Naomi, and recommend you work with her if you have the opportunity!",
date: new Date("May 14 2024"),
name: "Katey Berry",
sourceIcon: faLinkedin,
sourceName: "LinkedIn",
sourceUrl: "https://www.linkedin.com/in/naomi-lgbt/details/recommendations/",
},
{
content:
"She is a dedicated programmer and spends most of her time either making bots, or coding. She has an excellent work ethic and goes until she is satisfied with the end product.",
date: new Date("May 30, 2024"),
name: "Kaitlyn Nichols",
sourceIcon: faLinkedin,
sourceName: "LinkedIn",
sourceUrl: "https://www.linkedin.com/in/naomi-lgbt/details/recommendations/",
},
{
content:
"Naomi is an incredibly dynamic and resourceful professional, always ready with a multitude of solutions for any challenge. Her problem-solving skills are like watching a masterful sequence unfold, earning her the well-deserved nickname 'the technomancer.' Naomi's strong educational background is evident in her clear and concise explanations, making complex concepts easily understandable. She excels in communication, ensuring that everyone feels valued and integral to the team. Naomi is truly the glue that holds any team together. Adding her to your team will be a decision you won't regret.",
date: new Date("July 15, 2024"),
name: "Alix Takada Sharp",
sourceIcon: faLinkedin,
sourceName: "LinkedIn",
sourceUrl: "https://www.linkedin.com/in/naomi-lgbt/details/recommendations/",
},
{
content: "Naomi's erudition on just about every development topic under the sun, expediency at completing massive technical undertakings solo, and undeniable passion for the work she does is an ever-present joy and boon for any organization lucky enough to work with her. As an example, Naomi composed an extensive and accessible DB comprising all available traits and behaviors of our Users, whipped up an extremely user-friendly API that our team of end-users could utilize seamlessly, and regularly developed additional clever dataflows for very particular asks. Every aspect of this work was done impeccably and frictionlessly, and that's just one of the dozens of projects she developed with our team during the time I worked alongside her. As brilliant as Naomi is, she's also humble, hilarious, and an all-around aspirational figure to all people looking to find true passion for themselves alongside professional success. I strive to be more like her, and I know I'm not alone in that.",
date: new Date("September 27, 2024"),
name: "Chris Ohman",
sourceIcon: faLinkedin,
sourceName: "LinkedIn",
sourceUrl: "https://www.linkedin.com/in/naomi-lgbt/details/recommendations/",
},
{
content: "Naomi always had the knowledge and information for nearly every question I ever had. It was such an honor to work with her, and anyone would be lucky to have the chance for her to work with you or your team.",
date: new Date("October 28 2024"),
name: "Alexis Madsen",
sourceIcon: faLinkedin,
sourceName: "LinkedIn",
sourceUrl: "https://www.linkedin.com/in/naomi-lgbt/details/recommendations/",
},
];

View File

@ -1,70 +0,0 @@
/**
* @copyright nhcarrigan
* @license Naomi's Public License
* @author Naomi Carrigan
*/
/**
* List of vroid models to render.
*/
const VRoid = [
{
file: "business.vrm",
name: "Business Suit",
},
{
file: "casual.vrm",
name: "Casual Outfit",
},
{
file: "formal.vrm",
name: "Formal Outfit",
},
{
file: "sleep.vrm",
name: "Sleepwear",
},
{
file: "swim.vrm",
name: "Swimsuit",
},
{
file: "goth.vrm",
name: "Goth Outfit",
},
{
file: "kimono.vrm",
name: "Kimono",
},
{
file: "knight.vrm",
name: "Valiant Knight",
},
{
file: "miko.vrm",
name: "Divine Miko",
},
{
file: "onmyoji.vrm",
name: "Onmyōji",
},
{
file: "sailor.vrm",
name: "Sailor Fuku",
},
{
file: "sweater.vrm",
name: "Sweater Dress",
},
{
file: "witch",
name: "Arcane Witch",
},
];
const MainVRoid = {
file: "main.vrm",
name: "Main Outfit",
};
export { VRoid, MainVRoid };

View File

@ -1,73 +0,0 @@
/**
* @copyright nhcarrigan
* @license Naomi's Public License
* @author Naomi Carrigan
*/
import type { IconDefinition } from "@fortawesome/fontawesome-svg-core";
/**
* Custom FontAwesome icon definition for the
* Codeberg logo.
*/
export const Codeberg: IconDefinition = {
icon: [
474,
474,
[],
"U+E002",
`M 36.00,373.00
C 19.99,344.87 11.56,324.72 5.00,293.00
5.00,293.00 2.08,280.00 2.08,280.00
2.08,280.00 2.08,271.04 2.08,271.04
1.21,265.55 0.02,268.68 0.00,259.00
0.00,259.00 0.00,232.00 0.00,232.00
0.10,225.30 1.32,226.49 2.08,221.96
2.08,221.96 2.08,214.00 2.08,214.00
2.08,214.00 4.55,203.00 4.55,203.00
8.89,181.33 13.79,163.93 23.75,144.00
23.75,144.00 31.87,128.00 31.87,128.00
40.56,112.80 56.86,91.48 69.17,79.17
69.17,79.17 80.00,69.72 80.00,69.72
90.99,60.09 102.48,51.08 115.00,43.46
115.00,43.46 132.00,34.75 132.00,34.75
194.09,3.71 265.92,2.29 330.00,28.45
346.58,35.22 368.94,48.49 383.00,59.51
383.00,59.51 397.00,71.72 397.00,71.72
418.24,90.34 435.64,113.79 448.25,139.00
460.07,162.66 464.56,176.20 469.80,202.00
471.25,209.15 473.99,218.02 474.00,225.00
474.00,225.00 474.00,270.00 474.00,270.00
474.00,270.00 469.42,294.00 469.42,294.00
469.42,294.00 465.25,313.00 465.25,313.00
465.25,313.00 454.33,343.00 454.33,343.00
454.33,343.00 439.00,373.00 439.00,373.00
439.00,373.00 437.00,373.00 437.00,373.00
437.00,373.00 386.42,307.00 386.42,307.00
386.42,307.00 285.87,177.00 285.87,177.00
285.87,177.00 250.35,131.00 250.35,131.00
247.89,127.81 240.50,116.27 236.17,117.49
234.17,118.05 231.85,121.40 230.58,123.00
230.58,123.00 221.13,135.00 221.13,135.00
221.13,135.00 183.35,184.00 183.35,184.00
183.35,184.00 88.88,306.00 88.88,306.00
88.88,306.00 55.65,349.00 55.65,349.00
50.94,355.09 41.27,368.61 36.00,373.00 Z
M 244.00,138.00
C 244.00,138.00 272.65,174.00 272.65,174.00
272.65,174.00 327.65,245.00 327.65,245.00
327.65,245.00 401.88,341.00 401.88,341.00
401.88,341.00 433.00,382.00 433.00,382.00
433.00,382.00 409.96,410.00 409.96,410.00
409.96,410.00 400.00,419.17 400.00,419.17
400.00,419.17 389.00,429.68 389.00,429.68
389.00,429.68 361.00,449.54 361.00,449.54
361.00,449.54 346.00,457.31 346.00,457.31
346.00,457.31 331.00,465.00 331.00,465.00
331.00,465.00 315.85,409.00 315.85,409.00
315.85,409.00 283.85,289.00 283.85,289.00
283.85,289.00 257.12,189.00 257.12,189.00
257.12,189.00 244.00,138.00 244.00,138.00 Z`,
],
iconName: "yyy",
prefix: "xxx",
} as never;

View File

@ -1,126 +0,0 @@
/**
* @copyright nhcarrigan
* @license Naomi's Public License
* @author Naomi Carrigan
*/
import type { IconDefinition } from "@fortawesome/fontawesome-svg-core";
/**
* Custom FontAwesome icon definition for the
* Coursera logo.
*/
export const Coursera: IconDefinition = {
icon: [
825,
825,
[],
"U+E002",
`M 397.00,0.23
C 397.00,0.23 421.00,0.23 421.00,0.23
421.00,0.23 436.00,1.92 436.00,1.92
436.00,1.92 445.00,1.92 445.00,1.92
464.83,2.24 500.36,9.70 520.00,14.91
564.71,26.78 604.32,45.18 642.72,70.91
642.72,70.91 666.54,87.59 666.54,87.59
679.69,97.87 691.91,109.49 703.71,121.29
750.05,167.63 785.48,224.18 804.76,287.00
804.76,287.00 816.55,331.00 816.55,331.00
816.55,331.00 818.37,344.00 818.37,344.00
820.23,353.40 822.89,368.59 823.09,378.00
823.09,378.00 823.09,390.00 823.09,390.00
823.81,395.27 824.91,394.72 825.00,402.00
825.00,402.00 825.00,419.00 825.00,419.00
824.99,427.76 823.88,428.69 823.08,436.00
823.08,436.00 823.08,446.00 823.08,446.00
822.88,455.97 820.17,471.99 818.31,482.00
818.31,482.00 816.76,493.00 816.76,493.00
813.29,511.46 806.77,533.13 800.72,551.00
800.72,551.00 789.17,579.17 789.17,579.17
743.04,685.52 649.01,770.68 538.00,804.76
514.40,812.01 493.53,817.23 469.00,820.29
469.00,820.29 445.00,823.09 445.00,823.09
445.00,823.09 435.00,823.09 435.00,823.09
427.99,823.92 429.93,824.98 420.00,825.00
420.00,825.00 405.00,825.00 405.00,825.00
405.00,825.00 389.00,823.08 389.00,823.08
389.00,823.08 379.00,823.08 379.00,823.08
368.84,822.88 353.18,820.20 343.00,818.31
343.00,818.31 332.00,816.76 332.00,816.76
308.66,812.37 277.98,802.81 256.00,793.71
211.64,775.33 173.47,751.31 137.46,719.58
137.46,719.58 121.29,703.71 121.29,703.71
74.93,657.35 39.53,600.84 20.24,538.00
20.24,538.00 8.24,493.00 8.24,493.00
8.24,493.00 6.81,482.00 6.81,482.00
6.81,482.00 5.21,475.00 5.21,475.00
3.59,463.77 2.02,452.36 2.00,441.00
2.00,441.00 0.00,421.00 0.00,421.00
0.00,421.00 0.00,405.00 0.00,405.00
0.00,405.00 1.92,389.00 1.92,389.00
1.92,389.00 1.92,380.00 1.92,380.00
2.15,367.31 4.82,354.46 6.86,342.00
12.62,306.62 23.37,271.55 38.55,239.00
85.92,137.42 175.10,56.39 282.00,21.68
301.73,15.28 321.55,10.19 342.00,6.86
342.00,6.86 350.00,5.18 350.00,5.18
350.00,5.18 378.00,2.00 378.00,2.00
387.62,1.89 387.16,2.56 397.00,0.23 Z
M 654.00,274.00
C 652.59,267.31 647.58,262.01 643.51,256.72
635.54,246.34 626.80,236.89 617.43,227.75
582.03,193.25 534.25,169.22 486.00,159.22
486.00,159.22 475.00,157.75 475.00,157.75
475.00,157.75 469.00,156.26 469.00,156.26
469.00,156.26 443.00,154.00 443.00,154.00
443.00,154.00 419.00,154.00 419.00,154.00
419.00,154.00 393.00,156.26 393.00,156.26
393.00,156.26 387.00,157.75 387.00,157.75
387.00,157.75 376.00,159.22 376.00,159.22
359.46,162.64 337.52,169.42 322.09,176.22
310.29,181.41 299.65,187.64 288.72,194.38
230.27,230.42 189.21,287.07 173.67,354.00
173.67,354.00 169.00,376.00 169.00,376.00
169.00,376.00 169.00,384.00 169.00,384.00
168.19,389.27 167.09,388.72 167.00,396.00
167.00,396.00 167.00,427.00 167.00,427.00
167.02,437.40 168.03,434.44 169.06,441.00
169.06,441.00 169.06,450.00 169.06,450.00
171.22,463.47 175.55,480.94 179.94,493.83
208.58,578.07 278.08,641.10 364.00,663.24
375.88,666.30 405.06,670.98 417.00,671.00
417.00,671.00 445.00,671.00 445.00,671.00
445.00,671.00 469.00,668.63 469.00,668.63
469.00,668.63 475.00,667.19 475.00,667.19
475.00,667.19 486.00,665.76 486.00,665.76
486.00,665.76 503.00,661.27 503.00,661.27
547.18,648.72 587.85,626.54 620.12,593.45
631.39,581.89 638.18,574.40 647.68,561.15
651.38,556.00 655.09,552.51 656.00,546.00
656.00,546.00 622.00,526.15 622.00,526.15
622.00,526.15 574.08,498.06 574.08,498.06
574.08,498.06 546.00,482.00 546.00,482.00
534.75,499.99 523.33,511.09 506.00,523.14
494.21,531.34 480.79,536.77 467.09,540.79
458.67,543.26 443.67,545.99 435.00,546.00
424.27,546.02 411.46,544.96 401.00,542.55
357.16,532.46 320.34,499.15 303.73,457.72
300.20,448.91 295.05,428.27 295.00,419.00
295.00,419.00 295.00,405.00 295.00,405.00
295.08,398.63 295.76,399.32 296.68,394.00
298.79,381.82 299.55,375.89 304.46,364.00
311.29,347.50 322.76,330.34 335.46,317.80
352.35,301.13 374.31,288.72 397.17,282.45
397.17,282.45 406.00,280.91 406.00,280.91
413.70,279.46 411.09,279.01 420.00,279.00
420.00,279.00 442.00,279.00 442.00,279.00
461.77,279.03 484.13,288.32 501.09,297.97
508.30,302.07 525.10,315.12 530.25,321.17
532.57,323.88 541.23,335.82 544.15,336.27
546.02,336.55 550.51,333.55 552.25,332.55
552.25,332.55 574.00,319.99 574.00,319.99
574.00,319.99 631.99,286.46 631.99,286.46
631.99,286.46 654.00,274.00 654.00,274.00 Z`,
],
iconName: "yyy",
prefix: "xxx",
} as never;

View File

@ -1,63 +0,0 @@
/**
* @copyright nhcarrigan
* @license Naomi's Public License
* @author Naomi Carrigan
*/
import type { IconDefinition } from "@fortawesome/fontawesome-svg-core";
/**
* Custom FontAwesome icon definition for the
* Fiverr logo.
*/
export const Fiverr: IconDefinition = {
icon: [
300,
300,
[],
"U+E002",
`M 131.00,0.21
C 131.00,0.21 161.00,0.21 161.00,0.21
175.05,0.02 192.91,4.74 206.00,9.81
219.21,14.93 234.03,23.67 245.00,32.61
271.56,54.26 290.61,84.25 297.40,118.00
298.88,125.38 299.99,130.37 300.00,138.00
300.00,138.00 300.00,164.00 300.00,164.00
299.71,188.69 285.28,221.51 270.63,241.00
257.74,258.14 242.56,270.96 224.00,281.57
207.02,291.29 180.65,299.97 161.00,300.00
161.00,300.00 137.00,300.00 137.00,300.00
126.65,299.88 110.91,295.97 101.00,292.67
56.73,277.91 22.19,243.07 7.08,199.00
-1.16,174.97 -0.04,162.44 0.00,138.00
0.02,124.75 3.92,109.38 8.58,97.00
29.12,42.42 74.15,9.01 131.00,0.21 Z
M 176.00,58.00
C 152.33,58.00 122.24,54.22 107.10,77.00
104.97,80.22 103.13,84.29 102.04,88.00
100.10,94.62 100.00,104.07 100.00,111.00
100.00,111.00 78.00,111.00 78.00,111.00
78.00,111.00 78.00,141.00 78.00,141.00
95.43,141.00 99.81,138.98 100.00,149.00
100.00,149.00 100.00,200.00 100.00,200.00
100.00,200.00 100.00,220.00 100.00,220.00
100.00,221.94 99.75,225.72 100.99,227.26
102.70,229.38 107.50,229.00 110.00,229.00
110.00,229.00 138.00,229.00 138.00,229.00
138.00,229.00 138.00,163.00 138.00,163.00
138.00,158.95 136.99,145.29 139.60,142.74
141.71,140.68 146.23,141.00 149.00,141.00
149.00,141.00 169.00,141.00 169.00,141.00
171.37,141.04 174.58,140.96 176.40,142.74
178.34,144.64 177.99,148.47 178.00,151.00
178.00,151.00 178.00,229.00 178.00,229.00
178.00,229.00 215.00,229.00 215.00,229.00
215.00,229.00 215.00,111.00 215.00,111.00
215.00,111.00 138.00,111.00 138.00,111.00
138.00,106.78 137.73,101.98 139.34,98.01
143.35,88.13 153.31,89.00 162.00,89.00
162.00,89.00 176.00,89.00 176.00,89.00
176.00,89.00 176.00,58.00 176.00,58.00 Z`,
],
iconName: "yyy",
prefix: "xxx",
} as never;

View File

@ -1,83 +0,0 @@
/**
* @copyright nhcarrigan
* @license Naomi's Public License
* @author Naomi Carrigan
*/
import type { IconDefinition } from "@fortawesome/fontawesome-svg-core";
/**
* Custom FontAwesome icon definition for the
* GatherTown logo.
*/
export const Gather: IconDefinition = {
icon: [
38,
42,
[],
"U+E002",
`M 5.00,0.00
C 5.00,0.00 7.00,0.00 7.00,0.00
7.00,0.00 17.00,10.00 17.00,10.00
17.00,10.00 10.00,9.00 10.00,9.00
10.00,9.00 9.00,15.00 9.00,15.00
9.00,15.00 5.00,14.00 5.00,14.00
6.50,6.48 5.94,8.12 4.00,1.00
4.00,1.00 5.00,0.00 5.00,0.00 Z
M 20.00,14.00
C 20.11,12.71 20.06,11.37 20.60,10.15
24.66,0.89 36.99,13.91 26.89,16.61
25.97,16.80 24.94,16.81 24.00,16.61
22.18,16.37 21.52,15.79 20.00,15.00
19.74,22.50 17.00,24.66 10.00,21.00
9.92,23.16 10.07,25.75 8.40,27.40
6.21,29.57 1.33,29.29 0.33,24.95
-0.95,19.37 3.30,16.65 10.00,21.00
10.26,13.53 12.65,11.13 20.00,14.00 Z
M 25.00,10.00
C 25.00,10.00 26.00,14.00 26.00,14.00
26.00,14.00 25.00,10.00 25.00,10.00 Z
M 16.00,16.00
C 16.00,16.00 14.00,16.00 14.00,16.00
14.00,16.00 13.00,17.00 13.00,17.00
13.00,17.00 13.00,19.00 13.00,19.00
13.00,19.00 14.00,20.00 14.00,20.00
14.00,20.00 16.00,20.00 16.00,20.00
16.00,20.00 17.00,19.00 17.00,19.00
17.00,19.00 17.00,17.00 17.00,17.00
17.00,17.00 16.00,16.00 16.00,16.00 Z
M 21.00,27.00
C 21.08,24.86 20.92,22.37 22.60,20.74
25.35,18.08 30.07,19.45 31.16,23.05
32.37,27.10 27.72,32.83 20.89,27.00
20.89,27.00 20.89,30.96 20.89,30.96
20.59,31.90 20.38,32.76 19.83,33.57
18.92,34.88 17.56,35.55 15.98,35.55
9.23,35.55 9.53,24.34 17.00,25.35
18.77,25.59 19.54,26.23 21.00,27.00 Z
M 7.00,23.00
C 7.00,23.00 4.00,22.00 4.00,22.00
4.00,22.00 3.00,25.00 3.00,25.00
3.00,25.00 7.00,23.00 7.00,23.00 Z
M 28.00,23.00
C 28.00,23.00 24.00,25.00 24.00,25.00
24.00,25.00 28.00,26.00 28.00,26.00
28.00,26.00 28.00,23.00 28.00,23.00 Z
M 18.00,30.00
C 18.00,30.00 14.00,29.00 14.00,29.00
15.59,31.26 15.58,31.39 18.00,30.00 Z
M 23.31,33.02
C 32.01,29.83 33.13,38.37 28.77,40.97
24.19,43.71 18.07,38.68 23.31,33.02 Z
M 27.00,35.00
C 27.00,35.00 25.00,35.00 25.00,35.00
25.00,35.00 24.00,36.00 24.00,36.00
24.00,36.00 24.00,38.00 24.00,38.00
24.00,38.00 25.00,39.00 25.00,39.00
25.00,39.00 27.00,39.00 27.00,39.00
27.00,39.00 28.00,38.00 28.00,38.00
28.00,38.00 28.00,36.00 28.00,36.00
28.00,36.00 27.00,35.00 27.00,35.00 Z`,
],
iconName: "yyy",
prefix: "xxx",
} as never;

View File

@ -1,22 +0,0 @@
/**
* @copyright nhcarrigan
* @license Naomi's Public License
* @author Naomi Carrigan
*/
import type { IconDefinition } from "@fortawesome/fontawesome-svg-core";
/**
* Custom FontAwesome icon definition for the
* Good Ol' Games logo.
*/
export const Gog: IconDefinition = {
icon: [
34,
31,
[],
"U+E002",
`M31,31H3a3,3,0,0,1-3-3V3A3,3,0,0,1,3,0H31a3,3,0,0,1,3,3V28A3,3,0,0,1,31,31ZM4,24.5A1.5,1.5,0,0,0,5.5,26H11V24H6.5a.5.5,0,0,1-.5-.5v-3a.5.5,0,0,1,.5-.5H11V18H5.5A1.5,1.5,0,0,0,4,19.5Zm8-18A1.5,1.5,0,0,0,10.5,5h-5A1.5,1.5,0,0,0,4,6.5v5A1.5,1.5,0,0,0,5.5,13H9V11H6.5a.5.5,0,0,1-.5-.5v-3A.5.5,0,0,1,6.5,7h3a.5.5,0,0,1,.5.5v6a.5.5,0,0,1-.5.5H4v2h6.5A1.5,1.5,0,0,0,12,14.5Zm0,13v5A1.5,1.5,0,0,0,13.5,26h5A1.5,1.5,0,0,0,20,24.5v-5A1.5,1.5,0,0,0,18.5,18h-5A1.5,1.5,0,0,0,12,19.5Zm9-13A1.5,1.5,0,0,0,19.5,5h-5A1.5,1.5,0,0,0,13,6.5v5A1.5,1.5,0,0,0,14.5,13h5A1.5,1.5,0,0,0,21,11.5Zm9,0A1.5,1.5,0,0,0,28.5,5h-5A1.5,1.5,0,0,0,22,6.5v5A1.5,1.5,0,0,0,23.5,13H27V11H24.5a.5.5,0,0,1-.5-.5v-3a.5.5,0,0,1,.5-.5h3a.5.5,0,0,1,.5.5v6a.5.5,0,0,1-.5.5H22v2h6.5A1.5,1.5,0,0,0,30,14.5ZM30,18H22.5A1.5,1.5,0,0,0,21,19.5V26h2V20.5a.5.5,0,0,1,.5-.5h1v6h2V20H28v6h2ZM18.5,11h-3a.5.5,0,0,1-.5-.5v-3a.5.5,0,0,1,.5-.5h3a.5.5,0,0,1,.5.5v3A.5.5,0,0,1,18.5,11Zm-4,9h3a.5.5,0,0,1,.5.5v3a.5.5,0,0,1-.5.5h-3a.5.5,0,0,1-.5-.5v-3A.5.5,0,0,1,14.5,20Z`,
],
iconName: "yyy",
prefix: "xxx",
} as never;

View File

@ -1,212 +0,0 @@
/**
* @copyright nhcarrigan
* @license Naomi's Public License
* @author Naomi Carrigan
*/
import type { IconDefinition } from "@fortawesome/fontawesome-svg-core";
/**
* Custom FontAwesome icon definition for the
* Gumroad logo.
*/
export const Gumroad: IconDefinition = {
icon: [
806,
807,
[],
"U+E002",
`M 364.00,13.21
C 364.00,13.21 407.00,13.21 407.00,13.21
407.00,13.21 430.00,14.84 430.00,14.84
470.27,19.14 502.77,27.65 540.00,43.72
576.05,59.28 613.12,82.48 642.00,109.08
675.08,139.56 703.05,173.90 723.74,214.00
738.19,241.99 750.78,274.21 757.58,305.00
784.23,425.71 753.19,550.83 669.83,643.00
639.15,676.93 601.80,705.56 561.00,726.24
516.61,748.75 475.34,760.23 426.00,765.17
426.00,765.17 402.00,767.00 402.00,767.00
402.00,767.00 376.00,767.00 376.00,767.00
376.00,767.00 366.00,766.09 366.00,766.09
330.81,763.68 296.20,757.84 263.00,745.42
204.49,723.54 155.94,692.99 113.09,647.00
65.89,596.34 30.94,528.28 18.61,460.00
15.57,443.12 13.03,422.08 13.00,405.00
13.00,405.00 12.02,391.00 12.02,391.00
12.02,391.00 13.00,367.00 13.00,367.00
13.00,367.00 14.84,347.00 14.84,347.00
18.92,308.86 29.28,269.90 45.31,235.00
88.37,141.20 166.12,67.87 264.00,33.86
287.93,25.55 309.94,20.14 335.00,16.43
335.00,16.43 364.00,13.21 364.00,13.21 Z
M 487.00,15.00
C 487.00,15.00 488.00,15.00 488.00,15.00
488.00,15.00 487.00,16.00 487.00,16.00
487.00,16.00 487.00,15.00 487.00,15.00 Z
M 279.00,16.00
C 279.00,16.00 280.00,16.00 280.00,16.00
280.00,16.00 279.00,17.00 279.00,17.00
279.00,17.00 279.00,16.00 279.00,16.00 Z
M 515.00,21.00
C 515.00,21.00 516.00,21.00 516.00,21.00
516.00,21.00 515.00,22.00 515.00,22.00
515.00,22.00 515.00,21.00 515.00,21.00 Z
M 259.00,25.00
C 259.00,25.00 260.00,25.00 260.00,25.00
260.00,25.00 259.00,26.00 259.00,26.00
259.00,26.00 259.00,25.00 259.00,25.00 Z
M 193.00,53.00
C 193.00,53.00 194.00,53.00 194.00,53.00
194.00,53.00 193.00,54.00 193.00,54.00
193.00,54.00 193.00,53.00 193.00,53.00 Z
M 642.00,93.00
C 642.00,93.00 643.00,93.00 643.00,93.00
643.00,93.00 642.00,94.00 642.00,94.00
642.00,94.00 642.00,93.00 642.00,93.00 Z
M 682.00,133.00
C 682.00,133.00 683.00,133.00 683.00,133.00
683.00,133.00 682.00,134.00 682.00,134.00
682.00,134.00 682.00,133.00 682.00,133.00 Z
M 591.00,314.00
C 591.00,314.00 589.71,302.00 589.71,302.00
588.99,296.11 587.42,289.73 585.85,284.00
578.82,258.31 565.04,234.46 546.91,215.00
519.65,185.73 479.11,167.16 440.00,160.59
430.57,159.00 419.52,157.05 410.00,157.00
410.00,157.00 389.00,156.00 389.00,156.00
389.00,156.00 374.00,157.00 374.00,157.00
328.27,157.53 280.79,174.27 245.00,202.67
204.83,234.54 180.07,285.67 173.29,336.00
170.87,353.96 170.79,371.90 171.00,390.00
171.10,397.99 173.12,413.92 174.58,422.00
182.77,467.44 200.62,508.93 235.00,540.91
259.89,564.06 294.39,579.29 328.00,583.71
341.20,585.45 354.70,585.15 368.00,585.00
395.65,584.67 429.52,572.90 451.00,555.54
475.68,535.59 490.57,509.76 500.49,480.00
500.49,480.00 505.79,460.00 505.79,460.00
505.79,460.00 508.00,449.00 508.00,449.00
508.00,449.00 508.00,576.00 508.00,576.00
508.00,576.00 603.00,576.00 603.00,576.00
603.00,576.00 603.00,366.00 603.00,366.00
603.00,366.00 387.00,366.00 387.00,366.00
387.00,374.75 386.09,401.28 388.00,408.00
388.00,408.00 423.00,407.00 423.00,407.00
423.00,407.00 490.00,407.00 490.00,407.00
481.72,435.57 476.08,457.30 454.58,479.83
425.65,510.14 379.12,514.70 342.00,497.69
325.65,490.20 311.69,478.08 300.67,464.00
282.46,440.74 273.94,411.05 271.91,382.00
271.91,382.00 271.00,370.00 271.00,370.00
271.00,370.00 274.46,338.00 274.46,338.00
282.81,293.71 310.68,253.08 355.00,239.03
401.17,224.39 455.83,241.98 476.27,288.00
479.83,296.01 482.60,305.22 483.00,314.00
483.00,314.00 591.00,314.00 591.00,314.00 Z
M 51.00,201.00
C 51.00,201.00 52.00,201.00 52.00,201.00
52.00,201.00 51.00,202.00 51.00,202.00
51.00,202.00 51.00,201.00 51.00,201.00 Z
M 42.00,213.00
C 42.00,213.00 43.00,213.00 43.00,213.00
43.00,213.00 42.00,214.00 42.00,214.00
42.00,214.00 42.00,213.00 42.00,213.00 Z
M 39.00,219.00
C 39.00,219.00 40.00,219.00 40.00,219.00
40.00,219.00 39.00,220.00 39.00,220.00
39.00,220.00 39.00,219.00 39.00,219.00 Z
M 36.00,225.00
C 36.00,225.00 37.00,225.00 37.00,225.00
37.00,225.00 36.00,226.00 36.00,226.00
36.00,226.00 36.00,225.00 36.00,225.00 Z
M 756.00,229.00
C 756.00,229.00 757.00,229.00 757.00,229.00
757.00,229.00 756.00,230.00 756.00,230.00
756.00,230.00 756.00,229.00 756.00,229.00 Z
M 771.00,259.00
C 771.00,259.00 772.00,259.00 772.00,259.00
772.00,259.00 771.00,260.00 771.00,260.00
771.00,260.00 771.00,259.00 771.00,259.00 Z
M 17.00,283.00
C 17.00,283.00 18.00,283.00 18.00,283.00
18.00,283.00 17.00,284.00 17.00,284.00
17.00,284.00 17.00,283.00 17.00,283.00 Z
M 783.00,289.00
C 783.00,289.00 784.00,289.00 784.00,289.00
784.00,289.00 783.00,290.00 783.00,290.00
783.00,290.00 783.00,289.00 783.00,289.00 Z
M 2.00,346.00
C 2.00,346.00 3.00,346.00 3.00,346.00
3.00,346.00 2.00,347.00 2.00,347.00
2.00,347.00 2.00,346.00 2.00,346.00 Z
M 5.00,454.00
C 5.00,454.00 6.00,454.00 6.00,454.00
6.00,454.00 5.00,455.00 5.00,455.00
5.00,455.00 5.00,454.00 5.00,454.00 Z
M 24.00,517.00
C 24.00,517.00 25.00,517.00 25.00,517.00
25.00,517.00 24.00,518.00 24.00,518.00
24.00,518.00 24.00,517.00 24.00,517.00 Z
M 689.00,539.00
C 689.97,545.46 701.63,554.40 707.00,558.00
704.77,551.47 694.61,543.33 689.00,539.00 Z
M 33.00,547.00
C 33.00,547.00 34.00,547.00 34.00,547.00
34.00,547.00 33.00,548.00 33.00,548.00
33.00,548.00 33.00,547.00 33.00,547.00 Z
M 48.00,577.00
C 48.00,577.00 49.00,577.00 49.00,577.00
49.00,577.00 48.00,578.00 48.00,578.00
48.00,578.00 48.00,577.00 48.00,577.00 Z
M 749.00,618.00
C 749.00,618.00 750.00,618.00 750.00,618.00
750.00,618.00 749.00,619.00 749.00,619.00
749.00,619.00 749.00,618.00 749.00,618.00 Z
M 79.00,625.00
C 79.00,625.00 80.00,625.00 80.00,625.00
80.00,625.00 79.00,626.00 79.00,626.00
79.00,626.00 79.00,625.00 79.00,625.00 Z
M 107.00,658.00
C 107.00,658.00 108.00,658.00 108.00,658.00
108.00,658.00 107.00,659.00 107.00,659.00
107.00,659.00 107.00,658.00 107.00,658.00 Z
M 721.00,658.00
C 721.00,658.00 722.00,658.00 722.00,658.00
722.00,658.00 721.00,659.00 721.00,659.00
721.00,659.00 721.00,658.00 721.00,658.00 Z
M 113.00,664.00
C 113.00,664.00 114.00,664.00 114.00,664.00
114.00,664.00 113.00,665.00 113.00,665.00
113.00,665.00 113.00,664.00 113.00,664.00 Z
M 588.00,766.00
C 588.00,766.00 589.00,766.00 589.00,766.00
589.00,766.00 588.00,767.00 588.00,767.00
588.00,767.00 588.00,766.00 588.00,766.00 Z
M 562.00,778.00
C 562.00,778.00 563.00,778.00 563.00,778.00
563.00,778.00 562.00,779.00 562.00,779.00
562.00,779.00 562.00,778.00 562.00,778.00 Z
M 559.00,779.00
C 559.00,779.00 560.00,779.00 560.00,779.00
560.00,779.00 559.00,780.00 559.00,780.00
559.00,780.00 559.00,779.00 559.00,779.00 Z
M 276.00,781.00
C 276.00,781.00 277.00,781.00 277.00,781.00
277.00,781.00 276.00,782.00 276.00,782.00
276.00,782.00 276.00,781.00 276.00,781.00 Z
M 543.00,785.00
C 543.00,785.00 544.00,785.00 544.00,785.00
544.00,785.00 543.00,786.00 543.00,786.00
543.00,786.00 543.00,785.00 543.00,785.00 Z
M 344.00,800.00
C 344.00,800.00 345.00,800.00 345.00,800.00
345.00,800.00 344.00,801.00 344.00,801.00
344.00,801.00 344.00,800.00 344.00,800.00 Z
M 467.00,803.00
C 467.00,803.00 468.00,803.00 468.00,803.00
468.00,803.00 467.00,804.00 467.00,804.00
467.00,804.00 467.00,803.00 467.00,803.00 Z`,
],
iconName: "yyy",
prefix: "xxx",
} as never;

View File

@ -1,77 +0,0 @@
/**
* @copyright nhcarrigan
* @license Naomi's Public License
* @author Naomi Carrigan
*/
import type { IconDefinition } from "@fortawesome/fontawesome-svg-core";
/**
* Custom FontAwesome icon definition for the
* Ko-Fi logo.
*/
export const Kofi: IconDefinition = {
icon: [
245,
162,
[],
"U+E002",
`M 180.00,126.00
C 177.32,145.89 167.90,160.97 146.00,161.00
146.00,161.00 123.00,162.00 123.00,162.00
123.00,162.00 36.00,162.00 36.00,162.00
11.68,161.96 1.04,147.01 1.00,124.00
1.00,124.00 1.00,19.00 1.00,19.00
1.07,5.88 7.47,1.02 20.00,1.00
20.00,1.00 184.00,1.00 184.00,1.00
208.36,1.04 232.17,16.98 240.56,40.00
244.19,49.95 244.12,58.64 244.00,69.00
243.60,102.66 211.64,125.71 180.00,126.00 Z
M 18.31,15.60
C 15.32,18.12 16.01,20.28 16.00,24.00
16.00,24.00 15.00,42.00 15.00,42.00
15.00,42.00 15.00,75.00 15.00,75.00
15.00,75.00 16.00,92.00 16.00,92.00
16.00,92.00 16.00,125.00 16.00,125.00
16.02,140.23 21.27,146.98 37.00,147.00
37.00,147.00 132.00,147.00 132.00,147.00
132.00,147.00 143.00,146.17 143.00,146.17
153.16,145.20 158.48,145.34 163.07,134.00
167.02,124.25 162.50,117.54 169.13,113.01
173.46,110.04 179.93,111.34 185.00,110.83
185.00,110.83 194.00,109.10 194.00,109.10
215.15,103.72 228.06,87.48 229.68,66.00
229.90,63.01 229.34,60.94 229.07,58.00
226.37,28.64 203.62,15.04 176.00,15.00
176.00,15.00 70.00,15.00 70.00,15.00
70.00,15.00 36.00,15.00 36.00,15.00
30.94,15.00 22.97,14.47 18.31,15.60 Z
M 171.04,29.65
C 182.06,27.33 197.48,28.99 205.83,37.18
223.51,54.55 219.29,88.40 194.00,95.96
187.88,97.79 172.05,100.22 167.56,94.77
164.83,91.47 165.01,86.06 165.00,82.00
165.00,82.00 165.00,60.00 165.00,60.00
165.00,53.97 164.02,36.80 167.14,32.39
168.39,30.61 169.24,30.50 171.04,29.65 Z
M 111.00,41.44
C 125.13,39.94 137.62,49.59 138.81,64.00
140.27,81.55 119.30,98.75 108.00,110.00
105.33,112.66 95.11,122.59 92.00,123.26
89.18,123.85 87.00,121.74 85.00,120.11
79.95,115.98 76.58,112.53 72.00,108.00
72.00,108.00 58.00,94.00 58.00,94.00
48.82,84.73 43.00,78.85 43.01,65.00
43.01,60.36 43.76,56.05 46.22,52.01
52.64,41.47 69.42,39.75 80.00,44.09
85.80,46.47 88.14,49.98 91.00,49.98
93.15,49.99 97.00,46.83 99.00,45.63
103.65,42.84 105.80,42.41 111.00,41.44 Z
M 180.00,83.00
C 186.51,82.86 192.10,81.90 196.79,76.90
204.64,68.51 202.92,52.32 192.96,46.23
188.79,43.68 184.66,44.00 180.00,44.00
180.00,44.00 180.00,83.00 180.00,83.00 Z`,
],
iconName: "yyy",
prefix: "xxx",
} as never;

View File

@ -1,70 +0,0 @@
/**
* @copyright nhcarrigan
* @license Naomi's Public License
* @author Naomi Carrigan
*/
import type { IconDefinition } from "@fortawesome/fontawesome-svg-core";
/**
* Custom FontAwesome icon definition for the
* Matrix.org logo.
*/
export const Matrix: IconDefinition = {
icon: [
342,
342,
[],
"U+E002",
`M 138.00,0.53
C 150.87,-1.59 166.46,0.98 179.00,4.13
230.88,17.15 270.41,61.51 279.08,114.00
279.08,114.00 281.00,131.00 281.00,131.00
281.08,137.92 281.47,143.03 277.20,148.99
268.97,160.46 252.22,161.04 243.39,149.98
237.90,143.12 239.56,138.59 238.83,131.00
238.25,124.97 237.10,118.87 235.63,113.00
230.45,92.32 217.03,73.13 200.00,60.48
188.68,52.07 173.95,45.62 160.00,43.28
149.18,41.47 136.43,43.78 128.21,34.91
117.46,23.31 123.25,5.13 138.00,0.53 Z
M 126.00,61.42
C 132.79,60.60 140.80,60.41 147.00,63.67
157.30,69.10 161.07,83.05 155.00,93.00
148.91,102.97 142.67,102.25 133.00,103.17
133.00,103.17 121.00,104.75 121.00,104.75
106.64,107.11 91.56,113.68 80.00,122.50
61.64,136.52 50.33,153.71 44.63,176.00
43.46,180.57 42.62,185.30 42.17,190.00
41.42,197.85 43.18,203.96 37.61,210.99
28.88,221.99 10.70,222.28 2.99,210.00
-0.87,203.84 -0.08,195.99 0.00,189.00
0.10,181.05 1.94,171.72 3.87,164.00
14.25,122.51 43.23,89.80 82.00,72.31
97.65,65.25 109.47,63.78 126.00,61.42 Z
M 315.00,123.64
C 330.97,120.43 341.97,128.41 342.00,145.00
342.03,164.57 338.91,182.06 330.69,200.00
308.91,247.57 260.01,281.64 207.00,281.00
183.02,280.71 177.62,255.16 192.04,243.39
198.72,237.94 203.50,239.55 211.00,238.83
217.03,238.25 223.12,237.09 229.00,235.63
249.81,230.42 269.96,216.52 282.28,199.00
290.55,187.24 296.09,175.19 298.74,161.00
301.56,145.87 296.54,130.60 315.00,123.64 Z
M 78.00,184.53
C 87.56,183.00 96.80,186.96 101.08,196.00
101.08,196.00 105.45,225.00 105.45,225.00
108.31,239.01 115.29,252.68 123.90,264.00
136.86,281.04 157.21,293.39 178.00,298.11
188.70,300.54 202.89,298.40 210.98,304.56
222.59,313.38 221.84,332.30 209.00,339.64
203.20,342.95 194.60,342.07 188.00,342.00
180.39,341.91 168.41,339.51 161.00,337.42
119.62,325.74 86.75,295.86 70.60,256.00
70.60,256.00 66.29,243.00 66.29,243.00
63.87,234.58 62.76,227.67 61.84,219.00
60.14,203.20 59.71,189.94 78.00,184.53 Z`,
],
iconName: "yyy",
prefix: "xxx",
} as never;

View File

@ -1,136 +0,0 @@
/**
* @copyright nhcarrigan
* @license Naomi's Public License
* @author Naomi Carrigan
*/
import type { IconDefinition } from "@fortawesome/fontawesome-svg-core";
/**
* Custom FontAwesome icon definition for the
* Peerlist logo.
*/
export const Peerlist: IconDefinition = {
icon: [
512,
512,
[],
"U+E002",
`M 214.00,0.14
C 214.00,0.14 243.00,0.14 243.00,0.14
243.00,0.14 291.00,0.14 291.00,0.14
291.00,0.14 301.00,1.00 301.00,1.00
301.00,1.00 311.00,1.00 311.00,1.00
311.00,1.00 328.00,2.83 328.00,2.83
375.51,7.58 421.85,17.89 457.91,51.42
483.50,75.23 497.13,112.43 503.80,146.00
507.93,166.77 510.12,187.89 511.04,209.00
511.04,209.00 512.00,220.00 512.00,220.00
512.59,270.71 513.41,322.24 502.42,372.00
495.29,404.31 483.17,434.75 459.72,458.83
437.47,481.67 407.37,493.82 377.00,501.37
326.73,513.88 274.38,512.08 223.00,512.00
223.00,512.00 208.00,511.00 208.00,511.00
208.00,511.00 204.00,511.00 204.00,511.00
204.00,511.00 166.00,507.13 166.00,507.13
125.75,501.54 81.42,488.74 52.28,458.83
18.32,423.96 7.84,375.75 2.84,329.00
2.84,329.00 0.91,302.00 0.91,302.00
0.91,302.00 0.00,290.00 0.00,290.00
0.00,290.00 0.00,253.00 0.00,253.00
0.00,253.00 0.00,223.00 0.00,223.00
0.00,223.00 1.00,205.00 1.00,205.00
1.00,205.00 6.59,155.00 6.59,155.00
11.95,123.04 22.32,89.63 42.81,64.00
74.31,24.60 121.91,10.61 170.00,4.28
170.00,4.28 201.00,1.09 201.00,1.09
201.00,1.09 214.00,0.14 214.00,0.14 Z
M 234.00,18.14
C 227.52,19.22 223.42,18.99 217.00,19.00
217.00,19.00 205.00,20.04 205.00,20.04
205.00,20.04 197.00,20.04 197.00,20.04
149.57,24.69 92.98,33.42 60.44,72.00
34.70,102.51 25.98,143.28 21.84,182.00
21.84,182.00 19.00,224.00 19.00,224.00
19.00,224.00 18.00,241.00 18.00,241.00
18.00,241.00 18.00,273.00 18.00,273.00
18.00,273.00 18.96,283.00 18.96,283.00
18.96,283.00 18.96,297.00 18.96,297.00
18.96,297.00 19.91,307.00 19.91,307.00
19.91,307.00 24.92,353.00 24.92,353.00
30.18,384.75 40.74,418.98 63.09,443.00
93.04,475.19 139.93,485.66 182.00,490.16
182.00,490.16 205.00,492.09 205.00,492.09
205.00,492.09 215.00,493.04 215.00,493.04
215.00,493.04 229.00,493.04 229.00,493.04
229.00,493.04 241.00,494.00 241.00,494.00
241.00,494.00 271.00,494.00 271.00,494.00
271.00,494.00 283.00,493.04 283.00,493.04
283.00,493.04 295.00,493.04 295.00,493.04
295.00,493.04 307.00,492.09 307.00,492.09
327.86,490.66 348.55,488.59 369.00,483.88
398.65,477.06 426.42,466.49 447.96,444.00
469.93,421.06 480.00,389.49 486.00,359.00
490.02,338.59 492.97,308.77 493.00,288.00
493.00,288.00 494.00,271.00 494.00,271.00
494.00,271.00 494.00,241.00 494.00,241.00
494.00,241.00 493.04,229.00 493.04,229.00
493.04,229.00 493.04,217.00 493.04,217.00
493.04,217.00 492.09,205.00 492.09,205.00
490.82,186.52 489.06,168.22 485.40,150.00
478.89,117.63 467.20,84.85 442.00,62.17
412.18,35.33 368.80,25.99 330.00,21.84
330.00,21.84 307.00,19.91 307.00,19.91
307.00,19.91 295.00,18.96 295.00,18.96
295.00,18.96 283.00,18.96 283.00,18.96
283.00,18.96 271.00,18.14 271.00,18.14
271.00,18.14 234.00,18.14 234.00,18.14 Z
M 156.00,101.00
C 156.00,101.00 231.00,101.00 231.00,101.00
231.00,101.00 270.00,101.00 270.00,101.00
304.65,101.05 338.60,117.93 361.91,143.00
370.38,152.10 378.11,164.62 383.14,176.00
398.86,211.57 395.05,254.17 374.58,287.00
365.39,301.73 358.75,306.40 347.28,318.17
331.52,334.35 322.21,343.76 301.00,353.14
279.20,362.77 264.27,364.00 241.00,364.00
241.00,364.00 241.00,411.00 241.00,411.00
241.00,411.00 223.00,411.00 223.00,411.00
223.00,411.00 223.00,429.00 223.00,429.00
223.00,429.00 138.00,429.00 138.00,429.00
138.00,429.00 138.00,119.00 138.00,119.00
138.00,119.00 156.00,119.00 156.00,119.00
156.00,119.00 156.00,101.00 156.00,101.00 Z
M 223.00,329.00
C 263.91,329.00 301.86,332.36 336.00,304.54
349.16,293.81 359.70,280.51 366.69,265.00
374.05,248.67 375.20,234.53 375.00,217.00
374.56,179.46 346.33,143.35 313.00,128.31
291.09,118.42 270.44,118.00 247.00,118.00
247.00,118.00 207.00,118.00 207.00,118.00
207.00,118.00 182.00,118.00 182.00,118.00
180.01,118.00 176.19,117.77 174.60,119.02
172.62,120.59 173.00,124.70 173.00,127.00
173.00,127.00 173.00,332.00 173.00,332.00
173.00,332.00 173.00,385.00 173.00,385.00
173.02,393.64 173.36,393.98 182.00,394.00
182.00,394.00 223.00,394.00 223.00,394.00
223.00,394.00 223.00,329.00 223.00,329.00 Z
M 223.00,166.00
C 223.00,166.00 266.00,166.00 266.00,166.00
306.49,166.06 336.49,205.40 321.39,244.00
319.11,249.82 315.95,255.30 311.82,260.00
300.28,273.13 284.59,280.92 267.00,281.00
267.00,281.00 253.00,281.00 253.00,281.00
253.00,281.00 223.00,281.00 223.00,281.00
223.00,281.00 223.00,166.00 223.00,166.00 Z
M 241.00,202.00
C 241.00,202.00 241.00,255.00 241.00,255.00
241.02,263.64 241.36,263.98 250.00,264.00
258.53,264.02 277.96,264.47 284.58,259.01
289.25,255.16 289.06,244.57 289.00,239.00
288.79,221.67 275.23,207.53 259.00,203.16
253.08,201.56 247.07,202.00 241.00,202.00 Z`,
],
iconName: "yyy",
prefix: "xxx",
} as never;

View File

@ -1,104 +0,0 @@
/**
* @copyright nhcarrigan
* @license Naomi's Public License
* @author Naomi Carrigan
*/
import type { IconDefinition } from "@fortawesome/fontawesome-svg-core";
/**
* Custom FontAwesome icon definition for the
* Pixiv logo.
*/
export const Pixiv: IconDefinition = {
icon: [
900,
900,
[],
"U+E002",
`M 163.00,0.11
C 163.00,0.11 227.00,0.11 227.00,0.11
227.00,0.11 352.00,0.11 352.00,0.11
352.00,0.11 729.00,0.11 729.00,0.11
746.13,0.03 770.08,6.03 786.00,12.40
841.04,34.42 882.48,82.12 895.65,140.00
897.84,149.64 899.98,161.14 900.00,171.00
900.00,171.00 900.00,729.00 900.00,729.00
899.98,740.77 897.22,753.60 894.37,765.00
878.79,827.30 827.30,878.79 765.00,894.37
753.60,897.22 740.77,899.98 729.00,900.00
729.00,900.00 171.00,900.00 171.00,900.00
153.87,899.97 129.92,893.97 114.00,887.60
59.04,865.61 17.50,817.79 4.35,760.00
2.16,750.36 0.02,738.86 0.00,729.00
0.00,729.00 0.00,171.00 0.00,171.00
0.02,161.14 2.16,149.64 4.35,140.00
17.02,84.31 55.24,39.01 107.00,15.31
126.46,6.40 142.16,3.45 163.00,0.11 Z
M 311.00,616.00
C 373.56,636.85 424.71,647.77 491.00,647.00
491.00,647.00 501.00,646.09 501.00,646.09
561.64,641.94 619.68,625.46 669.00,588.63
686.93,575.24 698.59,564.39 712.74,547.00
728.39,527.76 738.75,508.08 747.42,485.00
752.85,470.57 758.82,444.32 759.00,429.00
759.00,429.00 759.82,414.00 759.82,414.00
759.82,414.00 759.00,404.00 759.00,404.00
758.67,375.23 751.71,346.17 739.77,320.00
730.28,299.20 719.08,281.37 704.13,264.00
659.77,212.46 592.74,182.82 526.00,174.85
526.00,174.85 504.00,172.91 504.00,172.91
504.00,172.91 494.00,172.00 494.00,172.00
494.00,172.00 462.00,172.00 462.00,172.00
462.00,172.00 450.00,172.91 450.00,172.91
412.36,175.49 375.85,182.56 340.00,194.51
317.45,202.03 295.26,211.12 274.00,221.75
231.59,242.96 192.08,269.69 156.00,300.43
156.00,300.43 130.00,324.01 130.00,324.01
127.74,326.25 122.03,331.98 121.40,335.00
120.64,338.62 127.54,347.74 129.66,351.00
129.66,351.00 151.19,385.00 151.19,385.00
153.01,387.93 158.61,397.57 161.21,398.94
166.85,401.91 176.80,394.78 175.82,381.00
175.82,381.00 173.22,363.58 173.22,363.58
174.13,359.05 184.45,345.15 187.65,341.00
200.18,324.75 224.03,301.37 241.00,290.00
241.00,290.00 241.00,639.00 241.00,639.00
241.00,639.00 241.00,707.00 241.00,707.00
240.99,709.72 241.32,713.33 239.40,715.49
237.70,717.41 233.44,718.49 231.00,719.34
223.81,721.87 210.84,727.47 212.43,737.00
213.73,744.73 218.25,745.99 225.00,746.00
225.00,746.00 327.00,746.00 327.00,746.00
329.00,746.00 332.13,746.11 333.96,745.40
339.03,743.42 340.93,736.79 338.99,732.00
336.42,725.65 327.11,721.40 321.00,719.06
318.33,718.04 313.62,716.99 312.02,714.58
310.78,712.71 311.00,709.21 311.00,707.00
311.00,707.00 311.00,616.00 311.00,616.00 Z
M 450.00,209.21
C 450.00,209.21 484.00,209.21 484.00,209.21
484.00,209.21 510.00,211.92 510.00,211.92
552.94,219.03 591.07,237.96 620.91,270.00
649.77,300.99 665.37,339.51 671.13,381.00
672.06,387.70 672.99,395.27 673.00,402.00
673.00,402.00 673.00,424.00 673.00,424.00
672.82,438.76 668.47,460.87 663.97,475.00
656.91,497.22 644.57,519.21 629.56,537.00
600.09,571.93 557.72,594.50 513.00,602.58
491.49,606.46 470.75,606.25 449.00,606.00
449.00,606.00 439.00,605.09 439.00,605.09
405.01,602.76 374.70,598.15 342.00,587.98
342.00,587.98 321.00,580.00 321.00,580.00
318.39,578.88 313.56,577.02 312.02,574.61
310.78,572.66 311.00,569.27 311.00,567.00
311.00,567.00 311.00,263.00 311.00,263.00
311.00,260.56 310.79,257.34 312.02,255.18
313.46,252.66 317.52,250.33 320.00,248.81
320.00,248.81 342.00,237.22 342.00,237.22
367.65,225.16 397.00,216.77 425.00,212.42
425.00,212.42 450.00,209.21 450.00,209.21 Z
`,
],
iconName: "yyy",
prefix: "xxx",
} as never;

View File

@ -1,85 +0,0 @@
/**
* @copyright nhcarrigan
* @license Naomi's Public License
* @author Naomi Carrigan
*/
import type { IconDefinition } from "@fortawesome/fontawesome-svg-core";
/**
* Custom FontAwesome icon definition for the
* Polywork logo.
*/
export const Polywork: IconDefinition = {
icon: [
225,
225,
[],
"U+E002",
`M 153.00,155.00
C 153.00,177.49 155.16,201.18 134.00,215.78
117.90,226.88 101.50,224.00 83.00,224.00
83.00,224.00 57.00,224.00 57.00,224.00
36.75,224.00 21.13,223.75 8.22,205.00
5.78,201.46 3.67,197.12 2.44,193.00
0.64,186.98 0.01,182.25 0.00,176.00
0.00,176.00 0.00,49.00 0.00,49.00
0.05,19.44 19.43,0.05 49.00,0.00
49.00,0.00 176.00,0.00 176.00,0.00
203.99,0.04 223.96,18.67 224.00,47.00
224.00,47.00 224.00,89.00 224.00,89.00
224.00,112.86 226.74,132.44 204.00,147.95
200.27,150.49 196.33,152.29 192.00,153.56
182.70,156.30 170.69,156.05 161.00,156.00
157.55,155.98 156.36,155.95 153.00,155.00 Z
M 70.00,11.00
C 52.54,11.00 34.21,8.10 21.09,22.01
17.77,25.54 15.22,29.35 13.77,34.00
11.01,42.87 12.00,61.03 12.00,71.00
12.00,71.00 70.00,71.00 70.00,71.00
70.00,71.00 70.00,11.00 70.00,11.00 Z
M 141.00,71.00
C 141.00,71.00 141.00,19.00 141.00,19.00
140.94,10.87 139.73,11.02 132.00,11.00
132.00,11.00 82.94,11.00 82.94,11.00
82.94,11.00 82.94,65.00 82.94,65.00
82.65,71.56 84.51,70.99 91.00,71.00
91.00,71.00 141.00,71.00 141.00,71.00 Z
M 212.00,71.00
C 212.00,71.00 212.00,46.00 212.00,46.00
211.99,40.91 212.06,38.94 210.30,34.00
200.99,7.84 175.95,12.00 154.00,12.00
154.00,12.00 154.00,71.00 154.00,71.00
154.00,71.00 212.00,71.00 212.00,71.00 Z
M 70.00,84.00
C 70.00,84.00 11.00,84.00 11.00,84.00
11.00,84.00 11.00,136.00 11.00,136.00
11.02,144.64 11.36,144.98 20.00,145.00
20.00,145.00 70.00,145.00 70.00,145.00
70.00,145.00 70.00,84.00 70.00,84.00 Z
M 141.00,84.00
C 141.00,84.00 83.00,84.00 83.00,84.00
83.00,84.00 83.00,144.00 83.00,144.00
83.00,144.00 141.00,144.00 141.00,144.00
141.00,144.00 141.00,84.00 141.00,84.00 Z
M 212.00,84.00
C 212.00,84.00 154.00,84.00 154.00,84.00
154.00,84.00 154.00,145.00 154.00,145.00
176.30,145.00 201.22,148.17 210.45,122.00
212.02,117.55 211.99,114.59 212.00,110.00
212.00,110.00 212.00,84.00 212.00,84.00 Z
M 70.00,157.00
C 70.00,157.00 11.00,157.00 11.00,157.00
11.00,177.94 8.44,201.56 33.00,210.30
37.94,212.06 39.91,211.99 45.00,212.00
45.00,212.00 70.00,212.00 70.00,212.00
70.00,212.00 70.00,157.00 70.00,157.00 Z
M 141.00,158.00
C 141.00,158.00 83.00,158.00 83.00,158.00
83.00,158.00 83.00,213.00 83.00,213.00
83.00,213.00 106.00,213.00 106.00,213.00
110.59,212.99 113.55,213.02 118.00,211.45
143.85,202.34 141.00,180.01 141.00,158.00 Z`,
],
iconName: "yyy",
prefix: "xxx",
} as never;

View File

@ -1,116 +0,0 @@
/**
* @copyright nhcarrigan
* @license Naomi's Public License
* @author Naomi Carrigan
*/
import type { IconDefinition } from "@fortawesome/fontawesome-svg-core";
/**
* Custom FontAwesome icon definition for the
* RetroAchievements logo.
*/
export const RetroAchievements: IconDefinition = {
icon: [
500,
275,
[],
"U+E002",
`M 0.00,0.00
C 0.00,0.00 73.00,0.00 73.00,0.00
73.00,0.00 116.00,0.00 116.00,0.00
150.90,0.05 184.08,28.35 194.12,61.00
197.20,71.03 199.09,81.49 199.00,92.00
198.86,108.25 194.88,127.04 186.39,141.00
183.49,145.75 178.82,151.91 174.92,155.83
172.79,157.98 170.04,159.58 170.72,163.01
170.72,163.01 175.25,172.00 175.25,172.00
175.25,172.00 187.58,194.00 187.58,194.00
187.58,194.00 215.86,245.00 215.86,245.00
215.86,245.00 232.00,275.00 232.00,275.00
232.00,275.00 200.00,275.00 200.00,275.00
200.00,275.00 192.61,274.01 192.61,274.01
192.61,274.01 186.43,265.00 186.43,265.00
186.43,265.00 175.00,245.00 175.00,245.00
175.00,245.00 139.40,183.00 139.40,183.00
139.40,183.00 117.00,143.00 117.00,143.00
160.97,139.31 175.67,72.18 138.00,47.10
122.50,36.79 106.57,39.00 89.00,39.00
89.00,39.00 0.00,39.00 0.00,39.00
0.00,39.00 0.00,0.00 0.00,0.00 Z
M 238.00,275.00
C 238.00,275.00 253.58,229.00 253.58,229.00
253.58,229.00 278.31,159.00 278.31,159.00
278.31,159.00 308.66,73.00 308.66,73.00
308.66,73.00 326.32,24.00 326.32,24.00
332.59,12.07 343.55,2.89 357.00,0.23
357.00,0.23 375.00,0.23 375.00,0.23
381.82,0.08 386.99,1.57 393.00,4.79
412.88,15.46 416.50,37.70 423.81,57.00
423.81,57.00 446.69,122.00 446.69,122.00
446.69,122.00 474.69,201.00 474.69,201.00
474.69,201.00 492.34,251.00 492.34,251.00
494.69,257.75 499.30,268.27 500.00,275.00
500.00,275.00 336.00,275.00 336.00,275.00
336.00,275.00 336.00,241.00 336.00,241.00
336.00,241.00 452.00,241.00 452.00,241.00
452.00,241.00 435.95,197.00 435.95,197.00
435.95,197.00 397.42,90.00 397.42,90.00
397.42,90.00 384.42,54.00 384.42,54.00
381.75,46.85 381.24,41.88 373.00,39.11
367.19,37.16 360.56,39.79 357.53,45.09
357.53,45.09 351.95,60.00 351.95,60.00
351.95,60.00 341.33,90.00 341.33,90.00
341.33,90.00 299.31,210.00 299.31,210.00
299.31,210.00 285.95,248.00 285.95,248.00
285.95,248.00 277.00,275.00 277.00,275.00
277.00,275.00 238.00,275.00 238.00,275.00 Z
M 0.00,47.00
C 0.00,47.00 110.00,47.00 110.00,47.00
123.38,47.16 136.40,52.85 144.20,64.00
155.04,79.48 152.55,106.67 140.67,121.00
129.04,135.04 117.41,135.00 101.00,135.00
101.00,135.00 130.42,186.00 130.42,186.00
130.42,186.00 181.00,275.00 181.00,275.00
181.00,275.00 147.00,275.00 147.00,275.00
147.00,275.00 139.33,273.98 139.33,273.98
139.33,273.98 126.15,253.00 126.15,253.00
126.15,253.00 85.00,182.00 85.00,182.00
85.00,182.00 85.00,275.00 85.00,275.00
85.00,275.00 47.00,275.00 47.00,275.00
47.00,275.00 47.00,95.00 47.00,95.00
47.00,95.00 102.00,95.00 102.00,95.00
105.16,94.98 112.73,94.56 110.60,89.22
109.14,85.55 103.19,86.01 100.00,86.00
100.00,86.00 38.00,86.00 38.00,86.00
38.00,86.00 38.00,275.00 38.00,275.00
38.00,275.00 0.00,275.00 0.00,275.00
0.00,275.00 0.00,47.00 0.00,47.00 Z
M 285.00,275.00
C 285.00,275.00 302.00,224.00 302.00,224.00
302.00,224.00 344.00,102.00 344.00,102.00
344.00,102.00 358.14,61.00 358.14,61.00
359.89,56.05 361.21,48.97 367.02,47.43
373.36,45.76 376.14,49.86 378.19,55.00
378.19,55.00 390.00,88.00 390.00,88.00
390.00,88.00 423.05,182.00 423.05,182.00
423.05,182.00 434.34,214.00 434.34,214.00
436.60,220.49 439.37,226.04 440.00,233.00
440.00,233.00 336.00,233.00 336.00,233.00
336.00,233.00 335.00,229.00 335.00,229.00
335.00,229.00 325.00,261.00 325.00,261.00
325.00,261.00 320.16,273.40 320.16,273.40
320.16,273.40 313.00,275.00 313.00,275.00
313.00,275.00 285.00,275.00 285.00,275.00 Z
M 370.00,131.00
C 370.00,131.00 361.28,155.00 361.28,155.00
361.28,155.00 348.00,198.00 348.00,198.00
348.00,198.00 391.00,198.00 391.00,198.00
391.00,198.00 370.00,131.00 370.00,131.00 Z
M 337.00,227.00
C 337.00,227.00 336.00,227.00 336.00,227.00
336.00,227.00 337.00,228.00 337.00,228.00
337.00,228.00 337.00,227.00 337.00,227.00 Z`,
],
iconName: "yyy",
prefix: "xxx",
} as never;

View File

@ -1,70 +0,0 @@
/**
* @copyright nhcarrigan
* @license Naomi's Public License
* @author Naomi Carrigan
*/
import type { IconDefinition } from "@fortawesome/fontawesome-svg-core";
/**
* Custom FontAwesome icon definition for the
* Saylor Academy logo.
*/
export const Saylor: IconDefinition = {
icon: [
171,
134,
[],
"U+E002",
`M 0.00,0.00
C 0.00,0.00 24.00,0.00 24.00,0.00
42.06,0.03 57.59,5.04 74.00,12.00
72.31,15.58 65.88,24.25 61.99,25.22
59.37,25.87 51.31,22.48 48.00,21.63
37.00,18.80 31.31,18.00 20.00,18.00
20.00,18.00 26.08,55.00 26.08,55.00
26.08,55.00 33.00,100.00 33.00,100.00
45.96,100.01 59.12,102.79 71.00,108.00
69.19,112.61 63.94,119.86 59.00,121.31
56.37,122.09 46.55,119.33 43.00,118.75
35.41,117.51 25.85,118.00 18.00,118.00
18.00,118.00 13.08,88.00 13.08,88.00
13.08,88.00 4.58,34.00 4.58,34.00
4.58,34.00 0.00,0.00 0.00,0.00 Z
M 67.00,126.00
C 70.80,117.82 83.00,108.14 81.81,94.00
80.97,83.99 74.07,77.87 69.09,70.00
65.00,63.53 62.41,53.66 63.17,46.00
64.82,29.19 75.60,19.06 90.00,11.76
114.41,-0.63 136.60,0.00 163.00,0.00
163.00,0.00 153.87,61.00 153.87,61.00
153.87,61.00 152.00,75.00 152.00,75.00
148.70,74.04 137.56,71.72 135.77,69.44
133.80,66.95 136.08,58.21 136.58,55.00
136.58,55.00 142.00,18.00 142.00,18.00
126.51,18.01 107.23,22.25 94.00,30.47
86.94,34.85 80.49,41.13 81.10,50.00
81.78,60.00 90.38,66.51 94.63,75.00
99.92,85.58 99.00,93.72 99.00,105.00
99.00,105.00 119.00,101.00 119.00,101.00
119.00,101.00 121.89,117.41 121.89,117.41
121.89,117.41 106.00,122.33 106.00,122.33
106.00,122.33 91.00,129.01 91.00,129.01
91.00,129.01 81.00,133.39 81.00,133.39
81.00,133.39 67.00,126.00 67.00,126.00 Z
M 118.00,72.00
C 118.00,72.00 150.00,80.86 150.00,80.86
150.00,80.86 168.00,87.00 168.00,87.00
168.00,87.00 154.00,95.00 154.00,95.00
156.53,98.54 166.08,107.66 166.66,110.00
167.68,114.07 159.11,122.25 155.00,120.83
152.31,119.90 143.54,110.54 141.00,108.00
138.65,112.89 135.79,119.24 131.00,122.00
131.00,122.00 118.00,72.00 118.00,72.00 Z
M 99.00,105.00
C 99.00,105.00 98.00,105.00 98.00,105.00
98.00,105.00 99.00,106.00 99.00,106.00
99.00,106.00 99.00,105.00 99.00,105.00 Z`,
],
iconName: "yyy",
prefix: "xxx",
} as never;

View File

@ -1,74 +0,0 @@
/**
* @copyright nhcarrigan
* @license Naomi's Public License
* @author Naomi Carrigan
*/
import type { IconDefinition } from "@fortawesome/fontawesome-svg-core";
/**
* Custom FontAwesome icon definition for the
* TeeSpring logo.
*/
export const TeeSpring: IconDefinition = {
icon: [
475,
545,
[],
"U+E002",
`M 240.00,0.00
C 240.00,0.00 244.00,0.00 244.00,0.00
244.00,0.00 254.00,1.04 254.00,1.04
254.00,1.04 263.00,1.04 263.00,1.04
304.10,5.09 342.37,17.33 377.00,40.08
435.19,78.31 469.28,140.18 474.09,209.00
474.09,209.00 475.00,219.00 475.00,219.00
475.82,289.26 446.65,351.38 393.00,396.73
382.45,405.65 369.17,414.11 357.00,420.69
357.00,420.69 337.27,430.64 337.27,430.64
334.29,433.27 332.39,439.31 330.69,443.00
327.83,449.23 324.42,455.20 320.77,461.00
310.40,477.47 293.49,496.40 278.00,508.10
249.81,529.41 203.43,544.94 168.00,545.00
168.00,545.00 150.00,545.00 150.00,545.00
125.42,544.96 90.40,535.79 68.00,525.69
49.96,517.55 32.70,506.76 17.00,494.77
17.00,494.77 0.00,481.00 0.00,481.00
2.57,475.47 6.82,471.50 10.84,467.00
10.84,467.00 33.28,442.00 33.28,442.00
35.47,439.49 42.88,430.22 46.04,430.18
48.97,430.14 57.23,437.77 60.00,439.87
70.46,447.78 83.12,455.65 95.00,461.22
136.97,480.90 194.02,482.07 233.00,454.56
238.56,450.64 241.26,447.73 246.00,443.00
224.21,442.93 191.85,432.40 172.00,423.31
117.49,398.35 72.00,360.79 45.75,306.00
36.23,286.14 31.44,267.91 29.91,246.00
29.67,242.56 28.93,240.60 29.18,237.00
30.23,222.27 32.09,207.57 38.31,194.00
42.82,184.15 47.86,176.08 55.17,168.00
89.09,130.48 146.65,132.44 190.00,149.92
205.26,156.07 219.68,164.39 233.00,174.01
256.93,191.30 280.05,215.68 296.83,240.00
313.68,264.43 328.11,289.43 336.72,318.00
339.48,327.18 342.55,336.33 343.00,346.00
349.38,343.12 354.12,337.88 359.00,333.00
368.02,323.98 373.77,317.88 380.68,307.00
411.97,257.71 413.89,196.46 383.99,146.00
359.25,104.26 314.53,77.92 267.00,71.72
267.00,71.72 249.00,70.00 249.00,70.00
249.00,70.00 240.00,70.00 240.00,70.00
240.00,70.00 240.00,0.00 240.00,0.00 Z
M 277.00,375.00
C 276.73,345.54 264.44,317.53 249.05,293.00
232.19,266.12 210.91,241.80 184.00,224.69
172.49,217.38 153.57,209.06 140.00,207.15
140.00,207.15 126.00,207.15 126.00,207.15
115.14,207.13 104.29,213.21 100.92,224.00
98.90,230.49 98.93,234.35 99.00,241.00
99.27,263.45 112.66,287.80 126.21,305.00
151.90,337.62 201.72,367.04 243.00,373.56
254.27,375.34 265.63,375.00 277.00,375.00 Z`,
],
iconName: "yyy",
prefix: "xxx",
} as never;

View File

@ -1,93 +0,0 @@
/**
* @copyright nhcarrigan
* @license Naomi's Public License
* @author Naomi Carrigan
*/
import type { IconDefinition } from "@fortawesome/fontawesome-svg-core";
/**
* Custom FontAwesome icon definition for the
* Throne.me logo.
*/
export const Throne: IconDefinition = {
icon: [
738,
621,
[],
"U+E002",
`M 364.00,0.65
C 380.58,-2.77 384.82,13.12 390.75,25.00
390.75,25.00 436.25,114.00 436.25,114.00
436.25,114.00 501.25,242.00 501.25,242.00
509.55,258.59 526.58,284.93 526.99,303.00
527.58,329.12 511.89,341.11 495.00,358.00
495.00,358.00 471.96,382.00 471.96,382.00
471.96,382.00 440.00,414.00 440.00,414.00
440.00,414.00 418.96,436.00 418.96,436.00
418.96,436.00 390.00,465.00 390.00,465.00
383.82,471.18 376.58,481.87 367.00,480.80
359.95,480.01 351.03,469.03 346.00,464.00
346.00,464.00 300.00,417.00 300.00,417.00
300.00,417.00 239.00,355.00 239.00,355.00
224.23,340.23 209.04,325.70 210.51,303.00
210.78,298.85 211.58,292.96 212.77,289.00
212.77,289.00 235.75,242.00 235.75,242.00
235.75,242.00 298.75,119.00 298.75,119.00
298.75,119.00 320.74,76.00 320.74,76.00
320.74,76.00 343.69,31.00 343.69,31.00
346.88,25.11 354.43,7.97 358.21,4.21
360.24,2.20 361.48,1.71 364.00,0.65 Z
M 11.00,204.59
C 13.62,204.13 15.36,203.84 18.00,204.59
23.76,206.43 34.33,218.33 39.00,223.00
39.00,223.00 102.00,287.00 102.00,287.00
102.00,287.00 131.96,317.00 131.96,317.00
131.96,317.00 141.01,327.00 141.01,327.00
141.01,327.00 176.96,363.00 176.96,363.00
176.96,363.00 186.01,373.00 186.01,373.00
186.01,373.00 235.96,423.00 235.96,423.00
235.96,423.00 316.00,505.00 316.00,505.00
316.00,505.00 361.00,551.00 361.00,551.00
366.28,556.28 376.33,564.19 376.52,572.00
376.65,577.57 372.41,583.22 367.00,584.58
367.00,584.58 360.00,585.17 360.00,585.17
360.00,585.17 345.00,586.00 345.00,586.00
345.00,586.00 334.00,586.96 334.00,586.96
299.43,588.47 264.60,593.98 231.00,602.37
212.72,606.95 183.56,617.64 167.00,618.82
163.80,619.04 161.15,618.37 158.00,618.07
135.75,616.01 118.33,604.57 107.44,585.00
102.99,577.01 98.68,561.24 96.15,552.00
96.15,552.00 64.42,443.00 64.42,443.00
64.42,443.00 26.02,311.00 26.02,311.00
26.02,311.00 3.42,233.00 3.42,233.00
0.08,221.29 -4.79,209.26 11.00,204.59 Z
M 720.00,204.61
C 730.62,202.68 739.38,209.98 737.53,221.00
737.53,221.00 729.71,249.00 729.71,249.00
729.71,249.00 714.58,301.00 714.58,301.00
714.58,301.00 678.42,425.00 678.42,425.00
678.42,425.00 646.72,534.00 646.72,534.00
638.26,562.21 633.90,594.97 606.00,611.13
601.21,613.90 595.29,616.69 590.00,618.28
569.52,624.42 556.97,616.60 538.00,611.14
538.00,611.14 500.00,600.87 500.00,600.87
491.51,598.75 482.71,597.52 475.00,593.12
465.90,587.93 450.35,570.35 442.00,562.00
442.00,562.00 416.72,536.00 416.72,536.00
412.08,530.66 408.35,526.63 410.43,519.00
411.45,515.25 414.38,512.76 416.92,510.00
416.92,510.00 432.00,494.00 432.00,494.00
432.00,494.00 465.96,460.01 465.96,460.01
465.96,460.01 483.00,442.00 483.00,442.00
483.00,442.00 509.96,415.00 509.96,415.00
509.96,415.00 519.01,405.00 519.01,405.00
519.01,405.00 552.96,371.01 552.96,371.01
552.96,371.01 651.00,271.00 651.00,271.00
651.00,271.00 665.04,256.00 665.04,256.00
665.04,256.00 696.00,225.00 696.00,225.00
702.65,218.35 711.22,207.67 720.00,204.61 Z`,
],
iconName: "yyy",
prefix: "xxx",
} as never;

View File

@ -1,52 +0,0 @@
/**
* @copyright nhcarrigan
* @license Naomi's Public License
* @author Naomi Carrigan
*/
import type { IconDefinition } from "@fortawesome/fontawesome-svg-core";
/**
* Custom FontAwesome icon definition for the
* Topmate.io logo.
*/
export const Topmate: IconDefinition = {
icon: [
502,
503,
[],
"U+E002",
`M 240.00,0.42
C 256.32,-1.56 286.52,2.28 303.00,5.60
400.40,25.19 477.58,103.88 497.00,201.00
497.00,201.00 501.17,232.00 501.17,232.00
501.17,232.00 502.00,241.00 502.00,241.00
502.35,270.85 499.89,297.30 490.98,326.00
467.36,401.97 409.93,461.62 335.00,488.31
310.99,496.86 285.45,501.71 260.00,502.00
260.00,502.00 251.00,502.66 251.00,502.66
251.00,502.66 242.00,502.00 242.00,502.00
242.00,502.00 234.00,502.00 234.00,502.00
211.79,501.74 178.65,493.13 158.00,484.80
126.34,472.03 97.19,453.16 73.01,428.99
-2.96,353.01 -20.43,237.27 25.32,141.00
55.16,78.19 112.06,31.52 178.00,11.02
194.55,5.88 209.86,3.32 227.00,1.28
227.00,1.28 240.00,0.42 240.00,0.42 Z
M 376.00,177.00
C 368.26,163.21 357.11,149.88 345.00,139.75
284.88,89.46 195.07,94.22 142.17,153.00
130.81,165.62 121.94,180.30 115.60,196.00
110.16,209.48 105.17,229.47 105.00,244.00
105.00,244.00 105.00,255.00 105.00,255.00
105.01,263.83 107.03,276.36 109.13,285.00
119.96,329.56 149.30,364.60 191.00,383.69
237.19,404.84 292.51,398.62 334.00,369.98
344.45,362.76 364.10,345.47 369.00,334.00
369.00,334.00 295.00,281.71 295.00,281.71
295.00,281.71 251.00,250.00 251.00,250.00
251.00,250.00 297.00,223.60 297.00,223.60
297.00,223.60 376.00,177.00 376.00,177.00 Z`,
],
iconName: "yyy",
prefix: "xxx",
} as never;

View File

@ -1,148 +0,0 @@
/**
* @copyright nhcarrigan
* @license Naomi's Public License
* @author Naomi Carrigan
*/
import type { IconDefinition } from "@fortawesome/fontawesome-svg-core";
/**
* Custom FontAwesome icon definition for the
* Tree Nation logo.
*/
export const TreeNation: IconDefinition = {
icon: [
52,
52,
[],
"U+E002",
`M 25.00,52.00
C 15.12,50.14 7.59,47.52 2.41,38.00
-0.15,33.27 -0.06,29.18 0.00,24.00
0.16,10.76 10.76,0.16 24.00,0.00
31.74,-0.09 36.64,0.42 42.96,5.53
54.40,14.78 54.92,33.47 44.82,43.90
39.64,49.24 33.11,51.04 26.00,52.00
26.00,46.30 24.65,37.69 28.00,33.00
24.79,30.12 25.93,24.77 27.00,21.00
27.00,21.00 23.00,36.00 23.00,36.00
26.19,40.33 25.00,46.83 25.00,52.00 Z
M 31.00,48.00
C 50.79,42.34 56.10,15.81 37.00,5.41
32.73,3.09 28.74,2.88 24.00,3.02
9.50,3.42 -0.31,18.27 3.64,32.00
6.11,40.60 11.93,45.13 20.00,48.00
20.00,45.66 20.29,41.35 18.98,39.43
17.24,36.88 13.97,37.30 11.11,35.27
4.88,30.84 6.93,25.10 12.00,21.00
10.87,15.81 11.98,10.65 18.00,9.33
20.79,8.72 23.27,9.99 26.00,9.85
28.83,9.92 31.54,8.42 34.98,9.85
38.83,11.21 42.64,19.18 44.00,23.04
47.45,32.86 35.14,33.49 32.60,36.43
30.43,38.94 31.00,44.75 31.00,48.00 Z
M 22.00,14.00
C 22.00,14.00 17.00,15.00 17.00,15.00
17.00,15.00 22.00,14.00 22.00,14.00 Z
M 23.00,15.00
C 23.00,15.00 21.00,20.00 21.00,20.00
21.00,20.00 24.00,20.00 24.00,20.00
24.00,20.00 23.00,15.00 23.00,15.00 Z
M 30.00,15.00
C 30.00,15.00 29.00,15.00 29.00,15.00
29.00,15.00 30.00,16.00 30.00,16.00
30.00,16.00 30.00,15.00 30.00,15.00 Z
M 35.00,15.00
C 35.00,15.00 34.00,15.00 34.00,15.00
34.00,15.00 35.00,16.00 35.00,16.00
35.00,16.00 35.00,15.00 35.00,15.00 Z
M 35.00,18.00
C 35.00,18.00 34.00,18.00 34.00,18.00
34.00,18.00 35.00,19.00 35.00,19.00
35.00,19.00 35.00,18.00 35.00,18.00 Z
M 18.00,19.00
C 18.00,19.00 17.00,19.00 17.00,19.00
17.00,19.00 18.00,20.00 18.00,20.00
18.00,20.00 18.00,19.00 18.00,19.00 Z
M 34.00,19.00
C 34.00,19.00 33.00,19.00 33.00,19.00
33.00,19.00 34.00,20.00 34.00,20.00
34.00,20.00 34.00,19.00 34.00,19.00 Z
M 20.00,20.00
C 20.00,20.00 19.00,20.00 19.00,20.00
19.00,20.00 20.00,21.00 20.00,21.00
20.00,21.00 20.00,20.00 20.00,20.00 Z
M 25.00,20.00
C 25.00,20.00 24.00,20.00 24.00,20.00
24.00,20.00 25.00,21.00 25.00,21.00
25.00,21.00 25.00,20.00 25.00,20.00 Z
M 28.00,20.00
C 28.00,20.00 27.00,20.00 27.00,20.00
27.00,20.00 28.00,21.00 28.00,21.00
28.00,21.00 28.00,20.00 28.00,20.00 Z
M 35.00,23.00
C 35.00,23.00 34.00,23.00 34.00,23.00
34.00,23.00 35.00,24.00 35.00,24.00
35.00,24.00 35.00,23.00 35.00,23.00 Z
M 39.00,23.00
C 39.00,23.00 38.00,23.00 38.00,23.00
38.00,23.00 39.00,24.00 39.00,24.00
39.00,24.00 39.00,23.00 39.00,23.00 Z
M 14.00,26.00
C 14.00,26.00 13.00,26.00 13.00,26.00
13.00,26.00 14.00,27.00 14.00,27.00
14.00,27.00 14.00,26.00 14.00,26.00 Z
M 18.00,26.00
C 18.00,26.00 17.00,26.00 17.00,26.00
17.00,26.00 18.00,27.00 18.00,27.00
18.00,27.00 18.00,26.00 18.00,26.00 Z
M 19.00,27.00
C 19.00,27.00 17.00,31.00 17.00,31.00
17.00,31.00 19.00,27.00 19.00,27.00 Z
M 39.00,27.00
C 39.00,27.00 38.00,27.00 38.00,27.00
38.00,27.00 39.00,28.00 39.00,28.00
39.00,28.00 39.00,27.00 39.00,27.00 Z
M 33.00,28.00
C 33.00,28.00 32.00,28.00 32.00,28.00
32.00,28.00 33.00,29.00 33.00,29.00
33.00,29.00 33.00,28.00 33.00,28.00 Z
M 32.00,29.00
C 32.00,29.00 31.00,29.00 31.00,29.00
31.00,29.00 32.00,30.00 32.00,30.00
32.00,30.00 32.00,29.00 32.00,29.00 Z
M 14.00,30.00
C 14.00,30.00 13.00,30.00 13.00,30.00
13.00,30.00 14.00,31.00 14.00,31.00
14.00,31.00 14.00,30.00 14.00,30.00 Z
M 31.00,30.00
C 31.00,30.00 30.00,30.00 30.00,30.00
30.00,30.00 31.00,31.00 31.00,31.00
31.00,31.00 31.00,30.00 31.00,30.00 Z
M 20.00,31.00
C 20.00,31.00 19.00,31.00 19.00,31.00
19.00,31.00 20.00,32.00 20.00,32.00
20.00,32.00 20.00,31.00 20.00,31.00 Z
M 30.00,31.00
C 30.00,31.00 29.00,31.00 29.00,31.00
29.00,31.00 30.00,32.00 30.00,32.00
30.00,32.00 30.00,31.00 30.00,31.00 Z
M 21.00,32.00
C 21.00,32.00 20.00,32.00 20.00,32.00
20.00,32.00 21.00,33.00 21.00,33.00
21.00,33.00 21.00,32.00 21.00,32.00 Z
M 29.00,32.00
C 29.00,32.00 28.00,32.00 28.00,32.00
28.00,32.00 29.00,33.00 29.00,33.00
29.00,33.00 29.00,32.00 29.00,32.00 Z
M 22.00,33.00
C 22.00,33.00 21.00,33.00 21.00,33.00
21.00,33.00 22.00,34.00 22.00,34.00
22.00,34.00 22.00,33.00 22.00,33.00 Z
M 23.00,34.00
C 23.00,34.00 22.00,34.00 22.00,34.00
22.00,34.00 23.00,35.00 23.00,35.00
23.00,35.00 23.00,34.00 23.00,34.00 Z`,
],
iconName: "yyy",
prefix: "xxx",
} as never;

View File

@ -1,155 +0,0 @@
/**
* @copyright nhcarrigan
* @license Naomi's Public License
* @author Naomi Carrigan
*/
import type { IconDefinition } from "@fortawesome/fontawesome-svg-core";
/**
* Custom FontAwesome icon definition for the
* Udemy logo.
*/
export const Udemy: IconDefinition = {
icon: [
2118,
2118,
[],
"U+E002",
`M 1027.00,0.21
C 1027.00,0.21 1083.00,0.21 1083.00,0.21
1083.00,0.21 1098.00,1.00 1098.00,1.00
1098.00,1.00 1148.00,3.83 1148.00,3.83
1148.00,3.83 1185.00,7.28 1185.00,7.28
1242.11,14.33 1297.67,25.39 1353.00,41.29
1516.40,88.26 1668.12,175.50 1791.00,293.04
1933.98,429.80 2037.87,606.97 2085.87,799.00
2098.98,851.43 2107.96,904.25 2113.17,958.00
2113.17,958.00 2116.00,989.00 2116.00,989.00
2116.00,989.00 2116.00,998.00 2116.00,998.00
2116.00,998.00 2117.04,1008.00 2117.04,1008.00
2117.04,1008.00 2117.04,1023.00 2117.04,1023.00
2117.04,1023.00 2118.00,1035.00 2118.00,1035.00
2118.00,1035.00 2118.00,1083.00 2118.00,1083.00
2118.00,1083.00 2117.00,1100.00 2117.00,1100.00
2117.00,1100.00 2114.17,1148.00 2114.17,1148.00
2114.17,1148.00 2110.72,1185.00 2110.72,1185.00
2102.72,1249.75 2089.35,1313.67 2069.98,1376.00
2017.27,1545.58 1919.24,1702.31 1791.00,1824.96
1682.55,1928.69 1552.28,2008.03 1411.00,2058.31
1330.08,2087.10 1245.37,2104.90 1160.00,2113.17
1160.00,2113.17 1100.00,2117.00 1100.00,2117.00
1100.00,2117.00 1083.00,2118.00 1083.00,2118.00
1083.00,2118.00 1035.00,2118.00 1035.00,2118.00
1035.00,2118.00 1023.00,2117.04 1023.00,2117.04
1023.00,2117.04 1008.00,2117.04 1008.00,2117.04
1008.00,2117.04 982.00,2115.09 982.00,2115.09
982.00,2115.09 915.00,2108.28 915.00,2108.28
844.59,2099.01 767.69,2080.44 701.00,2056.05
586.65,2014.23 483.34,1956.90 389.00,1879.58
306.50,1811.96 237.26,1735.42 177.67,1647.00
84.91,1509.36 27.58,1349.41 7.28,1185.00
4.48,1162.30 1.03,1122.44 1.00,1100.00
1.00,1100.00 0.00,1083.00 0.00,1083.00
0.00,1083.00 0.00,1035.00 0.00,1035.00
0.00,1035.00 0.96,1023.00 0.96,1023.00
0.96,1023.00 0.96,1008.00 0.96,1008.00
0.96,1008.00 2.91,982.00 2.91,982.00
4.78,954.82 7.75,927.99 11.73,901.00
26.84,798.40 56.07,704.16 99.31,610.00
99.31,610.00 112.75,583.00 112.75,583.00
133.71,541.08 157.37,500.60 183.98,462.00
216.84,414.31 252.99,368.87 293.04,327.00
415.66,198.79 572.46,100.72 742.00,48.02
801.74,29.46 871.80,13.82 934.00,7.16
934.00,7.16 989.00,2.00 989.00,2.00
989.00,2.00 998.00,2.00 998.00,2.00
998.00,2.00 1009.00,1.00 1009.00,1.00
1015.02,0.97 1021.03,1.27 1027.00,0.21 Z
M 1518.00,690.00
C 1518.00,690.00 1518.00,426.00 1518.00,426.00
1518.00,423.77 1518.24,420.43 1517.01,418.53
1515.72,416.54 1512.07,414.78 1510.00,413.58
1510.00,413.58 1494.00,404.15 1494.00,404.15
1494.00,404.15 1419.00,359.80 1419.00,359.80
1419.00,359.80 1152.00,202.20 1152.00,202.20
1152.00,202.20 1083.00,161.58 1083.00,161.58
1083.00,161.58 1066.00,151.58 1066.00,151.58
1063.11,149.94 1060.49,148.08 1057.00,148.74
1054.06,149.29 1047.80,153.32 1045.00,155.00
1045.00,155.00 1024.00,167.40 1024.00,167.40
1024.00,167.40 952.00,209.99 952.00,209.99
952.00,209.99 789.00,306.01 789.00,306.01
789.00,306.01 704.00,356.28 704.00,356.28
704.00,356.28 624.00,403.42 624.00,403.42
624.00,403.42 608.00,412.99 608.00,412.99
605.78,414.29 601.33,416.46 599.99,418.53
598.76,420.43 599.00,423.77 599.00,426.00
599.00,426.00 599.00,689.00 599.00,689.00
599.00,689.00 638.00,667.20 638.00,667.20
638.00,667.20 710.00,624.60 710.00,624.60
710.00,624.60 940.00,488.99 940.00,488.99
940.00,488.99 1024.00,439.40 1024.00,439.40
1024.00,439.40 1048.00,425.15 1048.00,425.15
1048.00,425.15 1058.00,420.19 1058.00,420.19
1058.00,420.19 1068.00,424.72 1068.00,424.72
1068.00,424.72 1092.00,438.99 1092.00,438.99
1092.00,438.99 1183.00,492.60 1183.00,492.60
1183.00,492.60 1399.00,620.01 1399.00,620.01
1399.00,620.01 1481.00,668.42 1481.00,668.42
1481.00,668.42 1518.00,690.00 1518.00,690.00 Z
M 839.73,918.00
C 839.73,918.00 599.00,918.00 599.00,918.00
599.00,918.00 599.00,1443.00 599.00,1443.00
599.00,1443.00 599.00,1516.00 599.00,1516.00
599.00,1516.00 599.00,1560.00 599.00,1560.00
599.00,1560.00 603.45,1613.28 603.45,1613.28
614.91,1704.32 653.23,1790.62 722.00,1852.83
783.61,1908.57 850.45,1939.88 931.00,1957.58
951.57,1962.09 982.42,1966.56 1003.32,1967.81
1003.32,1967.81 1027.00,1969.00 1027.00,1969.00
1030.87,1969.05 1037.63,1969.15 1041.00,1971.00
1041.00,1971.00 1042.00,1969.00 1042.00,1969.00
1042.00,1969.00 1043.00,1971.00 1043.00,1971.00
1043.00,1971.00 1045.00,1969.00 1045.00,1969.00
1048.05,1971.81 1060.56,1971.10 1064.00,1969.00
1066.02,1970.69 1067.61,1969.70 1070.00,1969.00
1070.00,1969.00 1070.00,1971.00 1070.00,1971.00
1070.00,1971.00 1071.00,1971.00 1071.00,1971.00
1071.00,1971.00 1072.00,1969.00 1072.00,1969.00
1072.00,1969.00 1072.00,1971.00 1072.00,1971.00
1072.00,1971.00 1073.00,1971.00 1073.00,1971.00
1075.36,1968.47 1082.62,1969.01 1086.00,1969.00
1086.00,1969.00 1108.49,1967.78 1108.49,1967.78
1140.13,1965.79 1171.15,1959.99 1202.00,1952.99
1202.00,1952.99 1237.00,1942.67 1237.00,1942.67
1300.26,1921.58 1359.29,1886.83 1406.87,1839.86
1468.86,1778.64 1503.51,1693.23 1513.68,1607.58
1520.04,1554.02 1518.00,1499.86 1518.00,1446.00
1518.00,1446.00 1518.00,918.00 1518.00,918.00
1518.00,918.00 1277.21,918.00 1277.21,918.00
1277.21,918.00 1277.21,965.89 1277.21,965.89
1277.21,965.89 1277.21,1030.98 1277.21,1030.98
1277.21,1030.98 1277.21,1173.03 1277.21,1173.03
1277.21,1173.03 1277.21,1493.03 1277.21,1493.03
1277.21,1493.03 1277.21,1523.00 1277.21,1523.00
1276.78,1553.58 1270.07,1585.69 1258.55,1614.00
1225.82,1694.41 1146.00,1745.09 1060.00,1746.00
994.18,1746.69 928.60,1716.51 887.45,1665.00
876.49,1651.28 867.61,1635.94 860.31,1620.00
845.13,1586.86 839.80,1549.82 839.73,1513.67
839.73,1513.67 839.73,1116.33 839.73,1116.33
839.73,1116.33 839.73,984.33 839.73,984.33
839.73,984.33 839.73,941.67 839.73,941.67
839.73,941.67 839.73,918.00 839.73,918.00 Z
M 1048.00,1970.00
C 1048.00,1970.00 1047.00,1970.00 1047.00,1970.00
1047.00,1970.00 1048.00,1971.00 1048.00,1971.00
1048.00,1971.00 1048.00,1970.00 1048.00,1970.00 Z
M 1068.00,1970.00
C 1068.00,1970.00 1067.00,1970.00 1067.00,1970.00
1067.00,1970.00 1068.00,1971.00 1068.00,1971.00
1068.00,1971.00 1068.00,1970.00 1068.00,1970.00 Z`,
],
iconName: "yyy",
prefix: "xxx",
} as never;

View File

@ -1,355 +0,0 @@
/**
* @copyright nhcarrigan
* @license Naomi's Public License
* @author Naomi Carrigan
*/
import type { IconDefinition } from "@fortawesome/fontawesome-svg-core";
/**
* Custom FontAwesome icon definition for the
* VRoid Hub logo.
*/
export const VRoid: IconDefinition = {
icon: [
280,
280,
[],
"U+E002",
`M 61.00,31.00
C 60.65,24.68 66.72,14.29 74.00,16.00
74.00,16.00 72.00,17.00 72.00,17.00
72.00,17.00 164.00,17.00 164.00,17.00
164.00,17.00 191.00,17.00 191.00,17.00
191.00,17.00 208.00,16.00 208.00,16.00
208.00,16.00 206.00,16.00 206.00,16.00
206.00,16.00 206.00,15.00 206.00,15.00
212.92,16.47 218.39,21.62 218.00,29.00
221.98,29.92 222.79,32.63 224.72,36.00
224.72,36.00 234.00,53.00 234.00,53.00
234.00,53.00 232.00,52.00 232.00,52.00
232.00,52.00 233.00,55.00 233.00,55.00
233.00,55.00 235.00,54.00 235.00,54.00
235.00,54.00 249.00,79.00 249.00,79.00
249.00,79.00 247.00,78.00 247.00,78.00
247.00,78.00 248.00,81.00 248.00,81.00
248.00,81.00 250.00,80.00 250.00,80.00
250.00,80.00 256.00,91.00 256.00,91.00
256.00,91.00 254.00,90.00 254.00,90.00
254.00,90.00 255.00,93.00 255.00,93.00
255.00,93.00 257.00,92.00 257.00,92.00
257.00,92.00 275.00,124.00 275.00,124.00
275.00,124.00 273.00,123.00 273.00,123.00
273.00,123.00 274.00,126.00 274.00,126.00
274.00,126.00 276.00,125.00 276.00,125.00
286.57,142.99 275.21,156.66 266.00,172.00
266.00,172.00 263.00,174.00 263.00,174.00
263.00,174.00 265.00,173.00 265.00,173.00
265.00,173.00 255.72,190.00 255.72,190.00
253.79,193.37 252.98,196.08 249.00,197.00
249.20,200.89 249.15,203.03 245.00,204.00
245.35,210.64 239.39,218.34 236.00,224.00
236.00,224.00 233.00,226.00 233.00,226.00
233.00,226.00 235.00,225.00 235.00,225.00
235.00,225.00 232.00,231.00 232.00,231.00
232.00,231.00 229.00,233.00 229.00,233.00
229.00,233.00 231.00,232.00 231.00,232.00
231.00,232.00 221.00,250.00 221.00,250.00
221.00,250.00 218.00,252.00 218.00,252.00
218.00,252.00 220.00,251.00 220.00,251.00
217.90,255.69 215.54,260.21 210.99,262.99
205.64,266.26 187.96,265.00 181.00,265.00
181.00,265.00 78.00,265.00 78.00,265.00
75.50,264.96 73.37,264.96 71.00,263.99
64.87,261.50 59.65,253.55 60.00,247.00
54.76,245.79 50.15,234.82 48.00,230.00
48.00,230.00 50.00,231.00 50.00,231.00
50.00,231.00 49.00,228.00 49.00,228.00
49.00,228.00 47.00,229.00 47.00,229.00
47.00,229.00 45.00,221.00 45.00,221.00
39.76,219.79 35.15,208.82 33.00,204.00
33.00,204.00 35.00,205.00 35.00,205.00
35.00,205.00 34.00,202.00 34.00,202.00
34.00,202.00 32.00,203.00 32.00,203.00
32.00,203.00 30.00,195.00 30.00,195.00
26.02,194.08 25.21,191.37 23.28,188.00
23.28,188.00 14.58,173.00 14.58,173.00
14.58,173.00 0.73,148.00 0.73,148.00
0.22,146.13 0.10,142.99 0.05,141.00
-0.22,128.88 4.95,123.08 11.00,113.00
11.00,113.00 29.00,82.00 29.00,82.00
29.00,82.00 32.00,80.00 32.00,80.00
32.00,80.00 30.00,81.00 30.00,81.00
30.00,81.00 51.40,43.00 51.40,43.00
53.84,38.87 55.99,32.15 61.00,31.00 Z
M 71.00,17.00
C 71.00,17.00 70.00,17.00 70.00,17.00
70.00,17.00 71.00,18.00 71.00,18.00
71.00,18.00 71.00,17.00 71.00,17.00 Z
M 210.00,17.00
C 210.00,17.00 209.00,17.00 209.00,17.00
209.00,17.00 210.00,18.00 210.00,18.00
210.00,18.00 210.00,17.00 210.00,17.00 Z
M 69.00,18.00
C 69.00,18.00 68.00,18.00 68.00,18.00
68.00,18.00 69.00,19.00 69.00,19.00
69.00,19.00 69.00,18.00 69.00,18.00 Z
M 212.00,18.00
C 212.00,18.00 211.00,18.00 211.00,18.00
211.00,18.00 212.00,19.00 212.00,19.00
212.00,19.00 212.00,18.00 212.00,18.00 Z
M 68.00,19.00
C 68.00,19.00 67.00,19.00 67.00,19.00
67.00,19.00 68.00,20.00 68.00,20.00
68.00,20.00 68.00,19.00 68.00,19.00 Z
M 213.00,19.00
C 213.00,19.00 212.00,19.00 212.00,19.00
212.00,19.00 213.00,20.00 213.00,20.00
213.00,20.00 213.00,19.00 213.00,19.00 Z
M 67.00,20.00
C 67.00,20.00 66.00,20.00 66.00,20.00
66.00,20.00 67.00,21.00 67.00,21.00
67.00,21.00 67.00,20.00 67.00,20.00 Z
M 214.00,20.00
C 214.00,20.00 213.00,20.00 213.00,20.00
213.00,20.00 214.00,21.00 214.00,21.00
214.00,21.00 214.00,20.00 214.00,20.00 Z
M 215.00,21.00
C 215.00,21.00 214.00,21.00 214.00,21.00
214.00,21.00 215.00,22.00 215.00,22.00
215.00,22.00 215.00,21.00 215.00,21.00 Z
M 218.00,26.00
C 218.00,26.00 217.00,26.00 217.00,26.00
217.00,26.00 218.00,27.00 218.00,27.00
218.00,27.00 218.00,26.00 218.00,26.00 Z
M 62.00,28.00
C 62.00,28.00 61.00,28.00 61.00,28.00
61.00,28.00 62.00,29.00 62.00,29.00
62.00,29.00 62.00,28.00 62.00,28.00 Z
M 222.00,33.00
C 222.00,33.00 221.00,33.00 221.00,33.00
221.00,33.00 222.00,34.00 222.00,34.00
222.00,34.00 222.00,33.00 222.00,33.00 Z
M 58.00,35.00
C 58.00,35.00 57.00,35.00 57.00,35.00
57.00,35.00 58.00,36.00 58.00,36.00
58.00,36.00 58.00,35.00 58.00,35.00 Z
M 226.00,40.00
C 226.00,40.00 225.00,40.00 225.00,40.00
225.00,40.00 226.00,41.00 226.00,41.00
226.00,41.00 226.00,40.00 226.00,40.00 Z
M 54.00,42.00
C 54.00,42.00 53.00,42.00 53.00,42.00
53.00,42.00 54.00,43.00 54.00,43.00
54.00,43.00 54.00,42.00 54.00,42.00 Z
M 237.00,59.00
C 237.00,59.00 236.00,59.00 236.00,59.00
236.00,59.00 237.00,60.00 237.00,60.00
237.00,60.00 237.00,59.00 237.00,59.00 Z
M 43.00,61.00
C 43.00,61.00 42.00,61.00 42.00,61.00
42.00,61.00 43.00,62.00 43.00,62.00
43.00,62.00 43.00,61.00 43.00,61.00 Z
M 241.00,66.00
C 241.00,66.00 240.00,66.00 240.00,66.00
240.00,66.00 241.00,67.00 241.00,67.00
241.00,67.00 241.00,66.00 241.00,66.00 Z
M 39.00,68.00
C 39.00,68.00 38.00,68.00 38.00,68.00
38.00,68.00 39.00,69.00 39.00,69.00
39.00,69.00 39.00,68.00 39.00,68.00 Z
M 230.00,107.00
C 227.93,100.49 221.87,92.94 218.05,87.00
215.87,83.61 213.79,79.70 209.91,78.01
205.93,76.27 186.57,76.99 181.00,77.00
178.57,77.00 175.25,76.87 173.00,77.74
167.52,79.86 162.48,89.99 159.32,95.00
159.32,95.00 134.05,135.00 134.05,135.00
130.60,140.50 123.07,151.60 121.00,157.00
121.00,157.00 119.00,157.00 119.00,157.00
116.73,149.81 105.10,132.46 100.60,125.00
98.47,121.46 93.21,111.99 90.48,109.70
87.49,107.18 83.71,107.05 80.00,107.00
80.00,107.00 50.00,107.00 50.00,107.00
50.91,115.07 63.16,132.35 67.95,140.00
67.95,140.00 102.95,197.00 102.95,197.00
107.53,204.32 113.56,216.86 120.00,222.00
120.00,222.00 174.32,134.00 174.32,134.00
174.32,134.00 184.81,117.00 184.81,117.00
184.81,117.00 192.09,108.17 192.09,108.17
192.09,108.17 201.00,107.00 201.00,107.00
201.00,107.00 230.00,107.00 230.00,107.00 Z
M 252.00,85.00
C 252.00,85.00 251.00,85.00 251.00,85.00
251.00,85.00 252.00,86.00 252.00,86.00
252.00,86.00 252.00,85.00 252.00,85.00 Z
M 28.00,87.00
C 28.00,87.00 27.00,87.00 27.00,87.00
27.00,87.00 28.00,88.00 28.00,88.00
28.00,88.00 28.00,87.00 28.00,87.00 Z
M 24.00,94.00
C 24.00,94.00 23.00,94.00 23.00,94.00
23.00,94.00 24.00,95.00 24.00,95.00
24.00,95.00 24.00,94.00 24.00,94.00 Z
M 263.00,104.00
C 263.00,104.00 262.00,104.00 262.00,104.00
262.00,104.00 263.00,105.00 263.00,105.00
263.00,105.00 263.00,104.00 263.00,104.00 Z
M 16.00,108.00
C 16.00,108.00 15.00,108.00 15.00,108.00
15.00,108.00 16.00,109.00 16.00,109.00
16.00,109.00 16.00,108.00 16.00,108.00 Z
M 267.00,111.00
C 267.00,111.00 266.00,111.00 266.00,111.00
266.00,111.00 267.00,112.00 267.00,112.00
267.00,112.00 267.00,111.00 267.00,111.00 Z
M 13.00,113.00
C 13.00,113.00 12.00,113.00 12.00,113.00
12.00,113.00 13.00,114.00 13.00,114.00
13.00,114.00 13.00,113.00 13.00,113.00 Z
M 270.00,116.00
C 270.00,116.00 269.00,116.00 269.00,116.00
269.00,116.00 270.00,117.00 270.00,117.00
270.00,117.00 270.00,116.00 270.00,116.00 Z
M 271.00,118.00
C 271.00,118.00 270.00,118.00 270.00,118.00
270.00,118.00 271.00,119.00 271.00,119.00
271.00,119.00 271.00,118.00 271.00,118.00 Z
M 278.00,130.00
C 278.00,130.00 277.00,130.00 277.00,130.00
277.00,130.00 278.00,131.00 278.00,131.00
278.00,131.00 278.00,130.00 278.00,130.00 Z
M 2.00,132.00
C 2.00,132.00 1.00,132.00 1.00,132.00
1.00,132.00 2.00,133.00 2.00,133.00
2.00,133.00 2.00,132.00 2.00,132.00 Z
M 279.00,147.00
C 279.00,147.00 278.00,147.00 278.00,147.00
278.00,147.00 279.00,148.00 279.00,148.00
279.00,148.00 279.00,147.00 279.00,147.00 Z
M 8.00,157.00
C 8.00,157.00 7.00,157.00 7.00,157.00
7.00,157.00 8.00,158.00 8.00,158.00
8.00,158.00 8.00,157.00 8.00,157.00 Z
M 272.00,159.00
C 272.00,159.00 271.00,159.00 271.00,159.00
271.00,159.00 272.00,160.00 272.00,160.00
272.00,160.00 272.00,159.00 272.00,159.00 Z
M 12.00,164.00
C 12.00,164.00 11.00,164.00 11.00,164.00
11.00,164.00 12.00,165.00 12.00,165.00
12.00,165.00 12.00,164.00 12.00,164.00 Z
M 268.00,166.00
C 268.00,166.00 267.00,166.00 267.00,166.00
267.00,166.00 268.00,167.00 268.00,167.00
268.00,167.00 268.00,166.00 268.00,166.00 Z
M 23.00,183.00
C 23.00,183.00 22.00,183.00 22.00,183.00
22.00,183.00 23.00,184.00 23.00,184.00
23.00,184.00 23.00,183.00 23.00,183.00 Z
M 257.00,185.00
C 257.00,185.00 256.00,185.00 256.00,185.00
256.00,185.00 257.00,186.00 257.00,186.00
257.00,186.00 257.00,185.00 257.00,185.00 Z
M 27.00,190.00
C 27.00,190.00 26.00,190.00 26.00,190.00
26.00,190.00 27.00,191.00 27.00,191.00
27.00,191.00 27.00,190.00 27.00,190.00 Z
M 253.00,192.00
C 253.00,192.00 252.00,192.00 252.00,192.00
252.00,192.00 253.00,193.00 253.00,193.00
253.00,193.00 253.00,192.00 253.00,192.00 Z
M 31.00,197.00
C 31.00,197.00 30.00,197.00 30.00,197.00
30.00,197.00 31.00,198.00 31.00,198.00
31.00,198.00 31.00,197.00 31.00,197.00 Z
M 249.00,199.00
C 249.00,199.00 248.00,199.00 248.00,199.00
248.00,199.00 249.00,200.00 249.00,200.00
249.00,200.00 249.00,199.00 249.00,199.00 Z
M 245.00,206.00
C 245.00,206.00 244.00,206.00 244.00,206.00
244.00,206.00 245.00,207.00 245.00,207.00
245.00,207.00 245.00,206.00 245.00,206.00 Z
M 38.00,209.00
C 38.00,209.00 37.00,209.00 37.00,209.00
37.00,209.00 38.00,210.00 38.00,210.00
38.00,210.00 38.00,209.00 38.00,209.00 Z
M 242.00,211.00
C 242.00,211.00 241.00,211.00 241.00,211.00
241.00,211.00 242.00,212.00 242.00,212.00
242.00,212.00 242.00,211.00 242.00,211.00 Z
M 42.00,216.00
C 42.00,216.00 41.00,216.00 41.00,216.00
41.00,216.00 42.00,217.00 42.00,217.00
42.00,217.00 42.00,216.00 42.00,216.00 Z
M 238.00,218.00
C 238.00,218.00 237.00,218.00 237.00,218.00
237.00,218.00 238.00,219.00 238.00,219.00
238.00,219.00 238.00,218.00 238.00,218.00 Z
M 46.00,223.00
C 46.00,223.00 45.00,223.00 45.00,223.00
45.00,223.00 46.00,224.00 46.00,224.00
46.00,224.00 46.00,223.00 46.00,223.00 Z
M 53.00,235.00
C 53.00,235.00 52.00,235.00 52.00,235.00
52.00,235.00 53.00,236.00 53.00,236.00
53.00,236.00 53.00,235.00 53.00,235.00 Z
M 227.00,237.00
C 227.00,237.00 226.00,237.00 226.00,237.00
226.00,237.00 227.00,238.00 227.00,238.00
227.00,238.00 227.00,237.00 227.00,237.00 Z
M 57.00,242.00
C 57.00,242.00 56.00,242.00 56.00,242.00
56.00,242.00 57.00,243.00 57.00,243.00
57.00,243.00 57.00,242.00 57.00,242.00 Z
M 224.00,242.00
C 224.00,242.00 223.00,242.00 223.00,242.00
223.00,242.00 224.00,243.00 224.00,243.00
224.00,243.00 224.00,242.00 224.00,242.00 Z
M 223.00,244.00
C 223.00,244.00 222.00,244.00 222.00,244.00
222.00,244.00 223.00,245.00 223.00,245.00
223.00,245.00 223.00,244.00 223.00,244.00 Z
M 61.00,249.00
C 61.00,249.00 60.00,249.00 60.00,249.00
60.00,249.00 61.00,250.00 61.00,250.00
61.00,250.00 61.00,249.00 61.00,249.00 Z
M 64.00,254.00
C 64.00,254.00 63.00,254.00 63.00,254.00
63.00,254.00 64.00,255.00 64.00,255.00
64.00,255.00 64.00,254.00 64.00,254.00 Z
M 216.00,256.00
C 216.00,256.00 215.00,256.00 215.00,256.00
215.00,256.00 216.00,257.00 216.00,257.00
216.00,257.00 216.00,256.00 216.00,256.00 Z
M 67.00,259.00
C 67.00,259.00 66.00,259.00 66.00,259.00
66.00,259.00 67.00,260.00 67.00,260.00
67.00,260.00 67.00,259.00 67.00,259.00 Z
M 214.00,259.00
C 214.00,259.00 213.00,259.00 213.00,259.00
213.00,259.00 214.00,260.00 214.00,260.00
214.00,260.00 214.00,259.00 214.00,259.00 Z
M 213.00,260.00
C 213.00,260.00 212.00,260.00 212.00,260.00
212.00,260.00 213.00,261.00 213.00,261.00
213.00,261.00 213.00,260.00 213.00,260.00 Z
M 70.00,261.00
C 70.00,261.00 69.00,261.00 69.00,261.00
69.00,261.00 70.00,262.00 70.00,262.00
70.00,262.00 70.00,261.00 70.00,261.00 Z
M 211.00,261.00
C 211.00,261.00 210.00,261.00 210.00,261.00
210.00,261.00 211.00,262.00 211.00,262.00
211.00,262.00 211.00,261.00 211.00,261.00 Z
M 208.00,263.00
C 208.00,263.00 113.00,263.00 113.00,263.00
113.00,263.00 86.00,263.00 86.00,263.00
86.00,263.00 72.00,264.00 72.00,264.00
72.00,264.00 167.00,264.00 167.00,264.00
167.00,264.00 194.00,264.00 194.00,264.00
194.00,264.00 208.00,263.00 208.00,263.00 Z`,
],
iconName: "yyy",
prefix: "xxx",
} as never;

View File

@ -1,192 +0,0 @@
/**
* @copyright nhcarrigan
* @license Naomi's Public License
* @author Naomi Carrigan
*/
import type { IconDefinition } from "@fortawesome/fontawesome-svg-core";
/**
* Custom FontAwesome icon definition for
* volunteer positions on the timeline.
*/
export const Volunteer: IconDefinition = {
icon: [
800,
798,
[],
"U+E002",
`M 369.00,0.21
C 369.00,0.21 423.00,0.21 423.00,0.21
423.00,0.21 435.00,0.91 435.00,0.91
480.07,4.06 524.94,15.89 566.00,34.69
608.59,54.20 648.70,80.88 681.91,114.09
681.91,114.09 689.04,122.00 689.04,122.00
744.21,179.68 780.10,250.35 793.75,329.00
795.84,341.01 799.98,377.55 799.96,389.00
799.96,389.00 799.96,401.00 799.96,401.00
799.96,401.00 799.00,411.00 799.00,411.00
799.00,411.00 799.00,424.00 799.00,424.00
799.00,424.00 798.09,434.00 798.09,434.00
796.18,461.36 791.12,488.69 783.28,515.00
767.34,568.47 741.19,613.80 706.20,657.00
687.38,680.22 656.65,708.80 632.00,725.79
625.02,730.60 622.97,730.16 620.28,731.93
620.28,731.93 613.00,738.21 613.00,738.21
613.00,738.21 599.00,746.57 599.00,746.57
556.64,770.81 501.54,789.82 453.00,795.72
427.94,798.76 402.25,798.29 377.00,798.00
377.00,798.00 367.00,797.09 367.00,797.09
344.92,795.54 318.29,791.85 297.00,785.85
297.00,785.85 286.00,781.78 286.00,781.78
286.00,781.78 278.00,780.10 278.00,780.10
278.00,780.10 264.00,775.66 264.00,775.66
226.39,762.60 184.34,739.01 153.00,714.58
88.50,664.30 40.30,593.29 16.72,515.00
7.01,482.76 1.05,448.68 1.00,415.00
1.00,415.00 0.00,399.00 0.00,399.00
0.00,399.00 0.00,386.00 0.00,386.00
0.00,386.00 1.91,364.00 1.91,364.00
4.61,325.33 13.92,286.04 28.20,250.00
69.21,146.50 153.89,63.69 258.00,24.42
282.20,15.30 309.43,8.22 335.00,4.27
335.00,4.27 359.00,1.17 359.00,1.17
359.00,1.17 369.00,0.21 369.00,0.21 Z
M 401.00,91.28
C 394.52,92.22 391.36,91.97 385.00,92.00
385.00,92.00 353.00,95.27 353.00,95.27
313.54,101.08 274.97,114.38 241.00,135.42
241.00,135.42 212.00,155.35 212.00,155.35
209.44,157.33 202.07,162.65 200.71,165.09
198.21,169.54 204.20,174.18 207.00,177.00
207.00,177.00 235.00,205.00 235.00,205.00
235.00,205.00 306.00,276.00 306.00,276.00
306.00,276.00 324.00,294.00 324.00,294.00
326.43,296.43 330.64,301.14 334.00,301.90
338.06,302.82 342.52,298.70 346.00,296.91
350.15,294.78 352.51,295.01 357.00,295.00
357.00,295.00 441.00,295.00 441.00,295.00
443.61,295.00 446.49,294.89 449.00,295.65
459.82,298.91 479.22,317.96 488.00,325.72
494.82,331.74 493.43,330.92 499.09,337.00
524.87,364.72 545.33,396.98 557.33,433.00
561.89,446.67 566.83,467.67 567.00,482.00
567.12,492.76 567.23,503.33 565.72,514.00
565.04,518.78 562.18,527.73 563.74,532.00
565.85,537.79 574.50,544.90 579.00,549.09
579.00,549.09 605.00,575.00 605.00,575.00
605.00,575.00 625.00,594.91 625.00,594.91
627.41,597.11 630.45,600.14 633.91,598.27
636.09,597.09 641.72,589.38 643.58,587.00
651.47,576.86 658.60,566.02 665.20,555.00
686.91,518.74 700.15,476.84 705.15,435.00
705.15,435.00 707.09,413.00 707.09,413.00
707.09,413.00 707.09,397.00 707.09,397.00
707.09,397.00 707.09,388.00 707.09,388.00
702.39,255.14 612.04,137.79 483.00,102.85
463.36,97.53 444.19,94.76 424.00,92.83
417.04,92.17 407.75,90.66 401.00,91.28 Z
M 333.00,173.00
C 340.67,173.43 344.75,176.62 351.00,180.66
353.99,182.59 359.37,186.09 363.00,185.90
368.27,185.63 373.85,178.62 377.17,175.00
383.79,167.80 391.65,160.51 402.00,161.04
412.91,161.61 419.27,171.98 429.00,175.15
436.12,177.47 448.46,172.80 456.00,171.21
459.79,170.41 466.47,168.69 467.64,174.11
468.77,179.32 459.61,192.07 456.86,197.00
448.92,211.22 435.53,237.53 432.00,253.00
432.00,253.00 376.00,253.00 376.00,253.00
364.56,252.98 366.17,249.64 360.14,236.00
360.14,236.00 342.75,199.00 342.75,199.00
338.30,190.08 333.23,183.21 333.00,173.00 Z
M 167.04,199.65
C 161.94,202.39 158.17,208.43 154.65,213.00
146.44,223.65 136.99,238.09 130.75,250.00
112.14,285.48 99.61,322.10 94.85,362.00
94.85,362.00 93.00,383.00 93.00,383.00
93.00,383.00 93.00,417.00 93.00,417.00
93.24,437.49 99.91,469.27 105.98,489.00
112.01,508.63 119.50,527.91 129.31,546.00
129.31,546.00 143.67,569.00 143.67,569.00
185.29,631.41 245.79,675.35 318.00,695.42
336.37,700.53 355.00,703.70 374.00,705.09
374.00,705.09 384.00,706.04 384.00,706.04
384.00,706.04 398.00,706.04 398.00,706.04
398.00,706.04 407.00,706.90 407.00,706.90
407.00,706.90 424.00,705.17 424.00,705.17
451.49,702.51 459.30,700.93 486.00,694.37
486.00,694.37 496.00,692.37 496.00,692.37
496.00,692.37 512.00,685.42 512.00,685.42
531.68,676.89 536.15,675.06 555.00,663.99
571.20,654.47 572.79,653.64 588.00,642.13
590.62,640.15 598.82,634.69 599.70,631.91
601.27,626.99 591.16,618.99 588.00,615.96
588.00,615.96 556.00,584.00 556.00,584.00
553.97,581.97 544.57,571.87 542.83,571.25
538.60,569.74 527.54,580.43 524.00,583.10
510.97,592.95 489.94,601.58 474.00,605.35
458.43,609.02 442.90,611.00 427.00,612.09
427.00,612.09 415.00,613.00 415.00,613.00
415.00,613.00 385.00,613.00 385.00,613.00
385.00,613.00 355.00,610.28 355.00,610.28
315.40,605.41 272.06,591.54 249.44,556.00
244.25,547.85 241.28,541.17 238.34,532.00
235.37,522.72 233.02,508.74 233.00,499.00
233.00,499.00 233.00,480.00 233.00,480.00
233.04,451.21 250.10,408.55 264.80,384.00
274.06,368.54 279.87,359.91 291.59,346.00
294.18,342.93 302.39,334.91 301.98,331.00
301.71,328.47 298.71,325.74 297.00,324.00
297.00,324.00 282.00,310.00 282.00,310.00
282.00,310.00 225.00,253.00 225.00,253.00
225.00,253.00 185.04,213.00 185.04,213.00
180.16,207.90 174.98,199.05 167.04,199.65 Z
M 357.00,261.74
C 362.72,260.35 377.34,261.00 384.00,261.00
384.00,261.00 435.00,261.00 435.00,261.00
439.06,261.01 443.34,260.74 446.61,263.65
451.40,267.92 451.17,280.20 446.61,284.57
442.51,288.50 434.33,288.06 429.00,288.00
429.00,288.00 413.00,287.00 413.00,287.00
413.00,287.00 403.00,287.95 403.00,287.95
403.00,287.95 386.00,287.95 386.00,287.95
386.00,287.95 376.00,287.04 376.00,287.04
376.00,287.04 364.00,287.04 364.00,287.04
360.74,286.99 356.98,287.29 354.21,285.26
347.76,280.53 346.80,267.20 357.00,261.74 Z
M 454.00,407.00
C 453.95,391.01 445.11,376.53 431.00,368.90
431.00,368.90 415.05,362.86 415.05,362.86
409.17,359.38 411.17,354.32 408.41,351.98
405.46,349.50 394.97,350.00 391.16,350.00
391.00,351.94 390.89,356.32 391.16,358.00
392.38,362.29 400.62,370.40 403.84,374.00
403.84,374.00 424.00,395.00 424.00,395.00
427.16,398.16 435.29,407.11 439.00,408.39
442.08,409.45 450.38,407.48 454.00,407.00 Z
M 410.00,545.00
C 433.68,543.90 458.71,522.64 459.00,498.00
459.03,495.25 459.21,490.47 458.26,488.00
456.58,483.60 444.91,472.91 441.00,469.00
441.00,469.00 392.00,420.00 392.00,420.00
392.00,420.00 365.00,393.00 365.00,393.00
362.74,390.74 357.57,384.58 354.10,385.45
351.39,386.14 349.42,390.63 348.45,393.00
345.07,401.28 345.96,409.21 346.00,418.00
346.07,433.59 353.45,446.21 366.00,455.25
370.26,458.32 374.19,460.50 379.00,462.57
382.60,464.12 386.99,465.36 388.98,469.05
390.19,471.30 390.00,474.49 390.00,477.00
390.00,477.00 390.00,513.00 390.00,513.00
381.30,507.46 375.61,499.25 374.00,489.00
374.00,489.00 351.00,490.97 351.00,490.97
348.18,491.12 343.87,490.90 342.02,493.51
339.48,497.11 343.57,508.12 345.06,512.00
352.06,530.24 370.17,544.94 390.00,545.00
390.00,545.00 390.00,559.00 390.00,559.00
390.00,559.00 410.00,559.00 410.00,559.00
410.00,559.00 410.00,545.00 410.00,545.00 Z`,
],
iconName: "yyy",
prefix: "xxx",
} as never;

View File

@ -1,300 +0,0 @@
/**
* @copyright nhcarrigan
* @license Naomi's Public License
* @author Naomi Carrigan
*/
interface ActivityData {
id: number;
user_id: number;
op_type: string;
act_user_id: number;
act_user: ActUser;
repo_id: number;
repo: Repo;
comment_id: number;
comment?: Comment;
ref_name: string;
is_private: boolean;
content: string;
created: string;
}
interface ActUser {
id: number;
login: string;
login_name: string;
source_id: number;
full_name: string;
email: string;
avatar_url: string;
html_url: string;
language: string;
is_admin: boolean;
last_login: string;
created: string;
restricted: boolean;
active: boolean;
prohibit_login: boolean;
location: string;
pronouns: string;
website: string;
description: string;
visibility: string;
followers_count: number;
following_count: number;
starred_repos_count: number;
username: string;
}
interface Repo {
id: number;
owner: Owner;
name: string;
full_name: string;
description: string;
empty: boolean;
private: boolean;
fork: boolean;
template: boolean;
parent: unknown;
mirror: boolean;
size: number;
language: string;
languages_url: string;
html_url: string;
url: string;
link: string;
ssh_url: string;
clone_url: string;
original_url: string;
website: string;
stars_count: number;
forks_count: number;
watchers_count: number;
open_issues_count: number;
open_pr_counter: number;
release_counter: number;
default_branch: string;
archived: boolean;
created_at: string;
updated_at: string;
archived_at: string;
permissions: Permissions;
has_issues: boolean;
external_tracker: ExternalTracker;
has_wiki: boolean;
wiki_branch: string;
globally_editable_wiki: boolean;
has_pull_requests: boolean;
has_projects: boolean;
has_releases: boolean;
has_packages: boolean;
has_actions: boolean;
ignore_whitespace_conflicts: boolean;
allow_merge_commits: boolean;
allow_rebase: boolean;
allow_rebase_explicit: boolean;
allow_squash_merge: boolean;
allow_fast_forward_only_merge: boolean;
allow_rebase_update: boolean;
default_delete_branch_after_merge: boolean;
default_merge_style: string;
default_allow_maintainer_edit: boolean;
avatar_url: string;
internal: boolean;
mirror_interval: string;
object_format_name: string;
mirror_updated: string;
repo_transfer: unknown;
topics: unknown;
}
interface Owner {
id: number;
login: string;
login_name: string;
source_id: number;
full_name: string;
email: string;
avatar_url: string;
html_url: string;
language: string;
is_admin: boolean;
last_login: string;
created: string;
restricted: boolean;
active: boolean;
prohibit_login: boolean;
location: string;
pronouns: string;
website: string;
description: string;
visibility: string;
followers_count: number;
following_count: number;
starred_repos_count: number;
username: string;
}
interface Permissions {
admin: boolean;
push: boolean;
pull: boolean;
}
interface ExternalTracker {
external_tracker_url: string;
external_tracker_format: string;
external_tracker_style: string;
external_tracker_regexp_pattern: string;
}
interface Comment {
id: number;
html_url: string;
pull_request_url: string;
issue_url: string;
user: unknown;
original_author: string;
original_author_id: number;
body: string;
assets: Array<unknown>;
created_at: string;
updated_at: string;
}
interface Issue {
id: number;
url: string;
html_url: string;
number: number;
user: Owner;
original_author: string;
original_author_id: number;
title: string;
body: string;
ref: string;
assets: Array<unknown>;
labels: Array<Label>;
milestone: unknown;
assignee: unknown;
assignees: unknown;
state: string;
is_locked: boolean;
comments: number;
created_at: string;
updated_at: string;
closed_at: unknown;
due_date: unknown;
pull_request?: PullRequest;
repository: Repo;
pin_order: number;
}
interface Label {
id: number;
name: string;
exclusive: boolean;
is_archived: boolean;
color: string;
description: string;
url: string;
}
interface PullRequest {
merged: boolean;
merged_at: unknown;
draft: boolean;
html_url: string;
}
class Codeberg {
private activityCache: Array<ActivityData>;
private readonly issueCache: Array<Issue>;
private lastUpdate: Date | null = null;
public constructor() {
this.activityCache = [];
this.issueCache = [];
}
public async getActivitiesWithCache(): Promise<Array<ActivityData>> {
// Stale after 6 hours
if (this.lastUpdate && Date.now()
- this.lastUpdate.getTime() < 6 * 60 * 60 * 1000) {
return this.activityCache;
}
return await this.getActivities().then(() => {
return this.activityCache;
});
}
/* istanbul ignore next -- @preserve */
public async getIssuesWithCache(): Promise<Array<Issue>> {
// Stale after 6 hours
if (this.lastUpdate && Date.now()
- this.lastUpdate.getTime() < 6 * 60 * 60 * 1000) {
return this.issueCache;
}
return await this.getIssues().then(() => {
return this.issueCache;
});
}
/* istanbul ignore next -- @preserve */
private async getIssues(): Promise<void> {
const repositoryRequest
= await fetch("https://codeberg.org/api/v1/orgs/nhcarrigan/repos");
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
const repositoryData = await repositoryRequest.json() as Array<Repo>;
for (const repo of repositoryData) {
const issueRequest
// eslint-disable-next-line no-await-in-loop
= await fetch(`https://codeberg.org/api/v1/repos/nhcarrigan/${repo.name}/issues`);
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions, no-await-in-loop
const issueData = await issueRequest.json() as Array<Issue>;
for (const issue of issueData) {
const isHelpWanted = issue.labels.some((label) => {
return label.name === "help wanted";
});
const isFirsstTimer = issue.labels.some((label) => {
return label.name === "good first issue";
});
if (isHelpWanted || isFirsstTimer) {
this.issueCache.push(issue);
}
}
}
this.lastUpdate = new Date();
}
private async getActivities(): Promise<void> {
const activityRequest = await
// eslint-disable-next-line stylistic/max-len
fetch("https://codeberg.org/api/v1/users/naomi-lgbt/activities/feeds?only-performed-by=true");
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
const activityData = await activityRequest.json() as Array<ActivityData>;
this.activityCache = activityData;
this.lastUpdate = new Date();
}
}
const instantiated = new Codeberg();
/**
* Fetches and caches the Codeberg activity.
* @returns An array of activity objects.
*/
const getCodebergActivty = async(): Promise<Array<ActivityData>> => {
return await instantiated.getActivitiesWithCache();
};
/**
* Fetches and caches the Codeberg issues.
* @returns An array of issue objects, filtered for help wanted and good first issues.
*/
const getCodebergIssues = async(): Promise<Array<Issue>> => {
/* istanbul ignore next -- @preserve */
return await instantiated.getIssuesWithCache();
};
export { getCodebergActivty, getCodebergIssues };

View File

@ -1,733 +0,0 @@
/**
* @copyright nhcarrigan
* @license Naomi's Public License
* @author Naomi Carrigan
*/
interface ActivityData {
id: string;
type: string;
actor: Actor;
repo: Repo;
payload: Payload;
public: boolean;
created_at: string;
}
interface Actor {
id: number;
login: string;
display_login: string;
gravatar_id: string;
url: string;
avatar_url: string;
}
interface Repo {
id: number;
name: string;
url: string;
}
interface Payload {
repository_id?: number;
push_id?: number;
size?: number;
distinct_size?: number;
ref?: string;
head?: string;
before?: string;
commits?: Array<Commit>;
ref_type?: string;
pusher_type?: string;
action?: string;
number?: number;
pull_request?: PullRequest;
review?: Review;
issue?: Issue2;
comment?: Comment;
}
interface Commit {
sha: string;
author: Author;
message: string;
distinct: boolean;
url: string;
}
interface Author {
email: string;
name: string;
}
interface PullRequest {
url: string;
id: number;
node_id: string;
html_url: string;
diff_url: string;
patch_url: string;
issue_url: string;
number: number;
state: string;
locked: boolean;
title: string;
user: User;
body?: string;
created_at: string;
updated_at: string;
closed_at?: string;
merged_at?: string;
merge_commit_sha: string;
assignee: unknown;
assignees: Array<unknown>;
requested_reviewers: Array<unknown>;
requested_teams: Array<unknown>;
labels: Array<Label>;
milestone: unknown;
draft: boolean;
commits_url: string;
review_comments_url: string;
review_comment_url: string;
comments_url: string;
statuses_url: string;
head: Head;
base: Base;
_links: Links;
author_association: string;
auto_merge: unknown;
active_lock_reason: unknown;
merged?: boolean;
mergeable: unknown;
rebaseable: unknown;
mergeable_state?: string;
merged_by?: MergedBy;
comments?: number;
review_comments?: number;
maintainer_can_modify?: boolean;
commits?: number;
additions?: number;
deletions?: number;
changed_files?: number;
}
interface User {
login: string;
id: number;
node_id: string;
avatar_url: string;
gravatar_id: string;
url: string;
html_url: string;
followers_url: string;
following_url: string;
gists_url: string;
starred_url: string;
subscriptions_url: string;
organizations_url: string;
repos_url: string;
events_url: string;
received_events_url: string;
type: string;
site_admin: boolean;
}
interface Label {
id: number;
node_id: string;
url: string;
name: string;
color: string;
default: boolean;
description: string;
}
interface Head {
label: string;
ref: string;
sha: string;
user: User2;
repo: Repo2;
}
interface User2 {
login: string;
id: number;
node_id: string;
avatar_url: string;
gravatar_id: string;
url: string;
html_url: string;
followers_url: string;
following_url: string;
gists_url: string;
starred_url: string;
subscriptions_url: string;
organizations_url: string;
repos_url: string;
events_url: string;
received_events_url: string;
type: string;
site_admin: boolean;
}
interface Repo2 {
id: number;
node_id: string;
name: string;
full_name: string;
private: boolean;
owner: Owner;
html_url: string;
description: string;
fork: boolean;
url: string;
forks_url: string;
keys_url: string;
collaborators_url: string;
teams_url: string;
hooks_url: string;
issue_events_url: string;
events_url: string;
assignees_url: string;
branches_url: string;
tags_url: string;
blobs_url: string;
git_tags_url: string;
git_refs_url: string;
trees_url: string;
statuses_url: string;
languages_url: string;
stargazers_url: string;
contributors_url: string;
subscribers_url: string;
subscription_url: string;
commits_url: string;
git_commits_url: string;
comments_url: string;
issue_comment_url: string;
contents_url: string;
compare_url: string;
merges_url: string;
archive_url: string;
downloads_url: string;
issues_url: string;
pulls_url: string;
milestones_url: string;
notifications_url: string;
labels_url: string;
releases_url: string;
deployments_url: string;
created_at: string;
updated_at: string;
pushed_at: string;
git_url: string;
ssh_url: string;
clone_url: string;
svn_url: string;
homepage: string;
size: number;
stargazers_count: number;
watchers_count: number;
language: string;
has_issues: boolean;
has_projects: boolean;
has_downloads: boolean;
has_wiki: boolean;
has_pages: boolean;
has_discussions: boolean;
forks_count: number;
mirror_url: unknown;
archived: boolean;
disabled: boolean;
open_issues_count: number;
license: License;
allow_forking: boolean;
is_template: boolean;
web_commit_signoff_required: boolean;
topics: Array<string>;
visibility: string;
forks: number;
open_issues: number;
watchers: number;
default_branch: string;
}
interface Owner {
login: string;
id: number;
node_id: string;
avatar_url: string;
gravatar_id: string;
url: string;
html_url: string;
followers_url: string;
following_url: string;
gists_url: string;
starred_url: string;
subscriptions_url: string;
organizations_url: string;
repos_url: string;
events_url: string;
received_events_url: string;
type: string;
site_admin: boolean;
}
interface License {
key: string;
name: string;
spdx_id: string;
url: string;
node_id: string;
}
interface Base {
label: string;
ref: string;
sha: string;
user: User3;
repo: Repo3;
}
interface User3 {
login: string;
id: number;
node_id: string;
avatar_url: string;
gravatar_id: string;
url: string;
html_url: string;
followers_url: string;
following_url: string;
gists_url: string;
starred_url: string;
subscriptions_url: string;
organizations_url: string;
repos_url: string;
events_url: string;
received_events_url: string;
type: string;
site_admin: boolean;
}
interface Repo3 {
id: number;
node_id: string;
name: string;
full_name: string;
private: boolean;
owner: Owner2;
html_url: string;
description: string;
fork: boolean;
url: string;
forks_url: string;
keys_url: string;
collaborators_url: string;
teams_url: string;
hooks_url: string;
issue_events_url: string;
events_url: string;
assignees_url: string;
branches_url: string;
tags_url: string;
blobs_url: string;
git_tags_url: string;
git_refs_url: string;
trees_url: string;
statuses_url: string;
languages_url: string;
stargazers_url: string;
contributors_url: string;
subscribers_url: string;
subscription_url: string;
commits_url: string;
git_commits_url: string;
comments_url: string;
issue_comment_url: string;
contents_url: string;
compare_url: string;
merges_url: string;
archive_url: string;
downloads_url: string;
issues_url: string;
pulls_url: string;
milestones_url: string;
notifications_url: string;
labels_url: string;
releases_url: string;
deployments_url: string;
created_at: string;
updated_at: string;
pushed_at: string;
git_url: string;
ssh_url: string;
clone_url: string;
svn_url: string;
homepage: string;
size: number;
stargazers_count: number;
watchers_count: number;
language: string;
has_issues: boolean;
has_projects: boolean;
has_downloads: boolean;
has_wiki: boolean;
has_pages: boolean;
has_discussions: boolean;
forks_count: number;
mirror_url: unknown;
archived: boolean;
disabled: boolean;
open_issues_count: number;
license: License2;
allow_forking: boolean;
is_template: boolean;
web_commit_signoff_required: boolean;
topics: Array<string>;
visibility: string;
forks: number;
open_issues: number;
watchers: number;
default_branch: string;
}
interface Owner2 {
login: string;
id: number;
node_id: string;
avatar_url: string;
gravatar_id: string;
url: string;
html_url: string;
followers_url: string;
following_url: string;
gists_url: string;
starred_url: string;
subscriptions_url: string;
organizations_url: string;
repos_url: string;
events_url: string;
received_events_url: string;
type: string;
site_admin: boolean;
}
interface License2 {
key: string;
name: string;
spdx_id: string;
url: string;
node_id: string;
}
interface Links {
self: Self;
html: Html;
issue: Issue;
comments: Comments;
review_comments: ReviewComments;
review_comment: ReviewComment;
commits: Commits;
statuses: Statuses;
}
interface Self {
href: string;
}
interface Html {
href: string;
}
interface Issue {
href: string;
}
interface Comments {
href: string;
}
interface ReviewComments {
href: string;
}
interface ReviewComment {
href: string;
}
interface Commits {
href: string;
}
interface Statuses {
href: string;
}
interface MergedBy {
login: string;
id: number;
node_id: string;
avatar_url: string;
gravatar_id: string;
url: string;
html_url: string;
followers_url: string;
following_url: string;
gists_url: string;
starred_url: string;
subscriptions_url: string;
organizations_url: string;
repos_url: string;
events_url: string;
received_events_url: string;
type: string;
site_admin: boolean;
}
interface Review {
id: number;
node_id: string;
user: User4;
body: unknown;
commit_id: string;
submitted_at: string;
state: string;
html_url: string;
pull_request_url: string;
author_association: string;
_links: Links2;
}
interface User4 {
login: string;
id: number;
node_id: string;
avatar_url: string;
gravatar_id: string;
url: string;
html_url: string;
followers_url: string;
following_url: string;
gists_url: string;
starred_url: string;
subscriptions_url: string;
organizations_url: string;
repos_url: string;
events_url: string;
received_events_url: string;
type: string;
site_admin: boolean;
}
interface Links2 {
html: Html2;
pull_request: PullRequest2;
}
interface Html2 {
href: string;
}
interface PullRequest2 {
href: string;
}
interface Issue2 {
url: string;
repository_url: string;
labels_url: string;
comments_url: string;
events_url: string;
html_url: string;
id: number;
node_id: string;
number: number;
title: string;
user: User5;
labels: Array<Label2>;
state: string;
locked: boolean;
assignee: unknown;
assignees: Array<unknown>;
milestone: unknown;
comments: number;
created_at: string;
updated_at: string;
closed_at?: string;
author_association: string;
active_lock_reason: unknown;
body: string;
reactions: Reactions;
timeline_url: string;
performed_via_github_app: unknown;
state_reason?: string;
}
interface User5 {
login: string;
id: number;
node_id: string;
avatar_url: string;
gravatar_id: string;
url: string;
html_url: string;
followers_url: string;
following_url: string;
gists_url: string;
starred_url: string;
subscriptions_url: string;
organizations_url: string;
repos_url: string;
events_url: string;
received_events_url: string;
type: string;
site_admin: boolean;
}
interface Label2 {
id: number;
node_id: string;
url: string;
name: string;
color: string;
default: boolean;
description: string;
}
interface Reactions {
"url": string;
"total_count": number;
"+1": number;
"-1": number;
"laugh": number;
"hooray": number;
"confused": number;
"heart": number;
"rocket": number;
"eyes": number;
}
interface Comment {
url: string;
html_url: string;
issue_url?: string;
id: number;
node_id: string;
user: User6;
created_at: string;
updated_at: string;
author_association: string;
body: string;
reactions: Reactions2;
performed_via_github_app: unknown;
pull_request_review_id?: number;
diff_hunk?: string;
path?: string;
commit_id?: string;
original_commit_id?: string;
pull_request_url?: string;
_links?: Links3;
start_line?: number;
original_start_line?: number;
start_side?: string;
line?: number;
original_line?: number;
side?: string;
in_reply_to_id?: number;
original_position?: number;
position?: number;
subject_type?: string;
}
interface User6 {
login: string;
id: number;
node_id: string;
avatar_url: string;
gravatar_id: string;
url: string;
html_url: string;
followers_url: string;
following_url: string;
gists_url: string;
starred_url: string;
subscriptions_url: string;
organizations_url: string;
repos_url: string;
events_url: string;
received_events_url: string;
type: string;
site_admin: boolean;
}
interface Reactions2 {
"url": string;
"total_count": number;
"+1": number;
"-1": number;
"laugh": number;
"hooray": number;
"confused": number;
"heart": number;
"rocket": number;
"eyes": number;
}
interface Links3 {
self: Self2;
html: Html3;
pull_request: PullRequest3;
}
interface Self2 {
href: string;
}
interface Html3 {
href: string;
}
interface PullRequest3 {
href: string;
}
class Github {
private cache: Array<ActivityData>;
private lastUpdate: Date | null = null;
public constructor() {
this.cache = [];
}
public async getActivities(): Promise<Array<ActivityData>> {
// Stale after 1 hour
if (this.lastUpdate && Date.now()
- this.lastUpdate.getTime() < 60 * 60 * 1000) {
return this.cache;
}
return await this.refreshData().then(() => {
return this.cache;
});
}
private async refreshData(): Promise<Github> {
const response
= await fetch("https://api.github.com/users/naomi-lgbt/events");
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
const data = await response.json() as Array<ActivityData>;
this.cache = data;
this.lastUpdate = new Date();
return this;
}
}
const instantiated = new Github();
/**
* Fetches and caches the Github activity.
* @returns An array of activity objects.
*/
export const getGithubData = async(): Promise<Array<ActivityData>> => {
return await instantiated.getActivities();
};

View File

@ -1,11 +0,0 @@
import type { Config } from "tailwindcss";
const config: Config = {
content: [
"./src/pages/**/*.{js,ts,jsx,tsx,mdx}",
"./src/components/**/*.{js,ts,jsx,tsx,mdx}",
"./src/app/**/*.{js,ts,jsx,tsx,mdx}",
],
plugins: [],
};
export default config;

View File

@ -1,100 +0,0 @@
/**
* @copyright nhcarrigan
* @license Naomi's Public License
* @author Naomi Carrigan
*/
/* eslint-disable new-cap */
import { NextResponse } from "next/server";
import { describe, it, expect, vi } from "vitest";
import { GET } from "../../../../src/app/api/activity/route";
import { getCodebergActivty } from "../../../../src/lib/codeberg";
import { getGithubData } from "../../../../src/lib/github";
vi.mock("../../../../src/lib/codeberg");
vi.mock("../../../../src/lib/github");
describe("gET /api/activity", () => {
it("should return a sorted and limited list of activities", async() => {
expect.assertions(2);
const mockCodebergData = [
{
created: "2023-01-01T00:00:00Z",
op_type: "push",
repo: { full_name: "repo1", html_url: "https://codeberg.org/repo1" },
},
];
const mockGithubData = [
{
created_at: "2023-01-02T00:00:00Z",
repo: {
name: "repo2",
url: "https://api.github.com/repos/repo2",
},
type: "pull_request",
},
];
vi.mocked(getCodebergActivty).mockResolvedValue(mockCodebergData);
vi.mocked(getGithubData).mockResolvedValue(mockGithubData);
const response = await GET();
const json = await response.json();
expect(response, "did not respond with Next").toBeInstanceOf(NextResponse);
expect(json, "incorrect payload").toStrictEqual([
{
date: "2023-01-02T00:00:00.000Z",
repo: "https://github.com/repo2",
repoName: "repo2",
type: "pull_request",
},
{
date: "2023-01-01T00:00:00.000Z",
repo: "https://codeberg.org/repo1",
repoName: "repo1",
type: "push",
},
]);
});
it("should handle empty data from both sources", async() => {
expect.assertions(2);
vi.mocked(getCodebergActivty).mockResolvedValue([]);
vi.mocked(getGithubData).mockResolvedValue([]);
const response = await GET();
const json = await response.json();
expect(response, "did not use Next to respond").
toBeInstanceOf(NextResponse);
expect(json, "was not empty array").toStrictEqual([]);
});
it("should limit the results to 100 entries", async() => {
expect.assertions(2);
const mockCodebergData = Array.from({ length: 60 }, (_, index) => {
return {
created: `2023-01-${index + 1}T00:00:00Z`,
op_type: "push",
repo: { full_name: `repo${index + 1}`, html_url: `https://codeberg.org/repo${index + 1}` },
};
});
const mockGithubData = Array.from({ length: 60 }, (_, index) => {
return {
created_at: `2023-02-${index + 1}T00:00:00Z`,
repo: { name: `repo${index + 61}`, url: `https://api.github.com/repos/repo${index + 61}` },
type: "pull_request",
};
});
vi.mocked(getCodebergActivty).mockResolvedValue(mockCodebergData);
vi.mocked(getGithubData).mockResolvedValue(mockGithubData);
const response = await GET();
const json = await response.json();
expect(response, "did not use Next to respond").
toBeInstanceOf(NextResponse);
expect(json, "did not limit to 100 entries").toHaveLength(100);
});
});

View File

@ -1,55 +0,0 @@
/**
* @copyright nhcarrigan
* @license Naomi's Public License
* @author Naomi Carrigan
*/
/* eslint-disable new-cap */
import { NextResponse } from "next/server";
import { describe, it, expect, vi } from "vitest";
import { GET } from "../../../../src/app/api/contribute/route";
import { getCodebergIssues } from "../../../../src/lib/codeberg";
vi.mock("../../../../src/lib/codeberg");
describe("gET /api/contribute", () => {
it("should return a sorted and limited list of activities", async() => {
expect.assertions(2);
const mockCodebergData = [
{
body: "body1",
html_url: "https://codeberg.org/repo1/issue1",
labels: [ { name: "label1" } ],
number: 1,
title: "issue1",
},
];
vi.mocked(getCodebergIssues).mockResolvedValue(mockCodebergData);
const response = await GET();
const json = await response.json();
expect(response, "did not respond with Next").toBeInstanceOf(NextResponse);
expect(json, "incorrect payload").toStrictEqual([
{
body: "body1",
labels: [ "label1" ],
number: 1,
title: "issue1",
url: "https://codeberg.org/repo1/issue1",
},
]);
});
it("should handle empty data from both sources", async() => {
expect.assertions(2);
vi.mocked(getCodebergIssues).mockResolvedValue([]);
const response = await GET();
const json = await response.json();
expect(response, "did not use Next to respond").
toBeInstanceOf(NextResponse);
expect(json, "was not empty array").toStrictEqual([]);
});
});

View File

@ -1,107 +0,0 @@
/**
* @copyright nhcarrigan
* @license Naomi's Public License
* @author Naomi Carrigan
*/
import { ListObjectsV2Command, S3Client } from "@aws-sdk/client-s3";
import { describe, it, expect } from "vitest";
import { Art } from "../src/config/Art";
import { Certifications } from "../src/config/Certifications";
import { Games } from "../src/config/Games";
import { Koikatsu } from "../src/config/Koikatsu";
const s3 = new S3Client({
credentials: {
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
accessKeyId: process.env.DO_ACCESS_KEY as string,
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
secretAccessKey: process.env.DO_SECRET_KEY as string,
},
endpoint: "https://sfo3.digitaloceanspaces.com",
region: "sfo3",
});
describe("cdn files", () => {
describe("for games", async() => {
const command = new ListObjectsV2Command({
Bucket: "nhcarrigan-cdn",
Prefix: "games",
});
const { Contents } = await s3.send(command);
const names = Contents?.map((content) => {
return content.Key?.replace("games/", "");
}).filter(Boolean) || [];
it.each(names)("should have %s in the Games config", (name) => {
expect.assertions(1);
const isGameInConfig = Games.some((game) => {
return game.img === name;
});
expect(isGameInConfig, "is not in config").toBeTruthy();
});
});
describe("for koikatsu", async() => {
const command = new ListObjectsV2Command({
Bucket: "nhcarrigan-cdn",
Prefix: "koikatsu",
});
const { Contents } = await s3.send(command);
const names = Contents?.map((content) => {
return content.Key?.replace("koikatsu/", "");
}).filter(Boolean) || [];
it.each(names)("should have %s in the Koikatsu config", (name) => {
expect.assertions(1);
const isKoikatsuInConfig = Koikatsu.includes(name);
expect(isKoikatsuInConfig, "is not in config").toBeTruthy();
});
});
describe("for art", async() => {
const command = new ListObjectsV2Command({
Bucket: "nhcarrigan-cdn",
Prefix: "art",
});
const { Contents } = await s3.send(command);
const names = Contents?.map((content) => {
return content.Key?.replace("art/", "");
}).filter(Boolean) || [];
it.each(names)("should have %s in the Art config", (name) => {
expect.assertions(1);
const isArtInConfig = Art.some((art) => {
return art.img === name;
});
expect(isArtInConfig, "is not in config").toBeTruthy();
});
});
describe("for certifications", async() => {
const command = new ListObjectsV2Command({
Bucket: "nhcarrigan-cdn",
Prefix: "certifications",
});
const { Contents } = await s3.send(command);
const names = Contents?.map((content) => {
return content.Key?.replace("certifications/", "");
}).filter(Boolean) || [];
it.each(names)("should have %s in the Certifications config", (name) => {
expect.assertions(1);
const isCertInConfig = Certifications.some((cert) => {
return cert.fileName === name;
});
expect(isCertInConfig, "is not in config").toBeTruthy();
});
});
});

View File

@ -1,37 +0,0 @@
/**
* @copyright nhcarrigan
* @license Naomi's Public License
* @author Naomi Carrigan
*/
import { describe, it, expect } from "vitest";
import { Art } from "../../src/config/Art";
describe("art objects", () => {
it("should have unique names", () => {
expect.assertions(1);
const set = new Set(
Art.map((a) => {
return a.name;
}),
);
expect(set, "are not unique").toHaveLength(Art.length);
});
it("should have unique img properties", () => {
expect.assertions(1);
const set = new Set(
Art.map((a) => {
return a.img;
}),
);
expect(set, "are not unique").toHaveLength(Art.length);
});
it("should have alt text", () => {
expect.assertions(1);
const noText = Art.filter((a) => {
return a.alt.length === 0;
});
expect(noText, "found missing alt").toHaveLength(0);
});
});

View File

@ -1,29 +0,0 @@
/**
* @copyright nhcarrigan
* @license Naomi's Public License
* @author Naomi Carrigan
*/
import { describe, it, expect } from "vitest";
import { Certifications } from "../../src/config/Certifications";
describe("certification objects", () => {
it("should have unique names", () => {
expect.assertions(1);
const set = new Set(
Certifications.map((c) => {
return c.name;
}),
);
expect(set, "are not unique").toHaveLength(Certifications.length);
});
it("should have unique file names", () => {
expect.assertions(1);
const set = new Set(
Certifications.map((c) => {
return c.fileName;
}),
);
expect(set, "are not unique").toHaveLength(Certifications.length);
});
});

View File

@ -1,47 +0,0 @@
/**
* @copyright nhcarrigan
* @license Naomi's Public License
* @author Naomi Carrigan
*/
import { describe, it, expect } from "vitest";
import { Games } from "../../src/config/Games";
describe("games objects", () => {
it("should have unique names", () => {
expect.assertions(1);
const set = new Set(
Games.map((g) => {
return g.name;
}),
);
expect(set, "are not unique").toHaveLength(Games.length);
});
it("should have unique img properties", () => {
expect.assertions(1);
const set = new Set(
Games.map((g) => {
return g.img;
}),
);
expect(set, "are not unique").toHaveLength(Games.length);
});
it("should have unique urls", () => {
expect.assertions(1);
const set = new Set(
Games.map((g) => {
return g.url;
}),
);
expect(set, "are not unique").toHaveLength(Games.length);
});
it("should have alt text", () => {
expect.assertions(1);
const noText = Games.filter((g) => {
return g.alt.length === 0;
});
expect(noText, "found missing alt").toHaveLength(0);
});
});

Some files were not shown because too many files have changed in this diff Show More