generated from nhcarrigan/template
chore: use our configs, update dependencies (#34)
### Explanation This gets us in line with our other project standards, and allows us to start testing! ### Issue Closes #18 ### Attestations - [x] I have read and agree to the [Code of Conduct](https://docs.nhcarrigan.com/community/coc/) - [x] I have read and agree to the [Community Guidelines](https://docs.nhcarrigan.com/community/guide/). - [x] My contribution complies with the [Contributor Covenant](https://docs.nhcarrigan.com/dev/covenant/). ### Dependencies - [x] I have pinned the dependencies to a specific patch version. ### Style - [x] I have run the linter and resolved any errors. - [x] My pull request uses an appropriate title, matching the conventional commit standards. - [x] My scope of feat/fix/chore/etc. correctly matches the nature of changes in my pull request. ### Tests - [ ] My contribution adds new code, and I have added tests to cover it. - [ ] My contribution modifies existing code, and I have updated the tests to reflect these changes. - [ ] All new and existing tests pass locally with my changes. - [ ] Code coverage remains at or above the configured threshold. ### Documentation _No response_ ### Versioning Major - My pull request introduces a breaking change. Reviewed-on: https://codeberg.org/nhcarrigan/portfolio/pulls/34 Co-authored-by: Naomi Carrigan <commits@nhcarrigan.com> Co-committed-by: Naomi Carrigan <commits@nhcarrigan.com>
This commit is contained in:
parent
b24f0e83c2
commit
fe370dabb5
@ -1,3 +0,0 @@
|
|||||||
{
|
|
||||||
"extends": "next/core-web-vitals"
|
|
||||||
}
|
|
28
eslint.config.mjs
Normal file
28
eslint.config.mjs
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
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"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
@ -1,5 +1,8 @@
|
|||||||
/** @type {import('next').NextConfig} */
|
/** @type {import('next').NextConfig} */
|
||||||
const nextConfig = {
|
const nextConfig = {
|
||||||
|
eslint: {
|
||||||
|
ignoreDuringBuilds: true
|
||||||
|
},
|
||||||
images: {
|
images: {
|
||||||
remotePatterns: [
|
remotePatterns: [
|
||||||
{
|
{
|
||||||
|
20
package.json
20
package.json
@ -3,29 +3,31 @@
|
|||||||
"version": "0.1.0",
|
"version": "0.1.0",
|
||||||
"private": true,
|
"private": true,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
"prebuild": "pnpm lint",
|
||||||
"dev": "next dev",
|
"dev": "next dev",
|
||||||
"build": "next build",
|
"build": "next build",
|
||||||
"start": "next start",
|
"start": "next start",
|
||||||
"lint": "next lint"
|
"lint": "eslint src --max-warnings 0"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@fortawesome/fontawesome-svg-core": "6.6.0",
|
"@fortawesome/fontawesome-svg-core": "6.6.0",
|
||||||
"@fortawesome/free-brands-svg-icons": "6.6.0",
|
"@fortawesome/free-brands-svg-icons": "6.6.0",
|
||||||
"@fortawesome/free-solid-svg-icons": "6.6.0",
|
"@fortawesome/free-solid-svg-icons": "6.6.0",
|
||||||
"@fortawesome/react-fontawesome": "0.2.2",
|
"@fortawesome/react-fontawesome": "0.2.2",
|
||||||
"next": "14.2.6",
|
"next": "15.0.2",
|
||||||
"next-plausible": "3.12.2",
|
"next-plausible": "3.12.2",
|
||||||
"react": "18.3.1",
|
"react": "18.3.1",
|
||||||
"react-dom": "18.3.1"
|
"react-dom": "18.3.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/node": "20.14.8",
|
"@nhcarrigan/eslint-config": "5.0.0-rc2",
|
||||||
"@types/react": "18.3.9",
|
"@nhcarrigan/typescript-config": "4.0.0",
|
||||||
"@types/react-dom": "18.3.0",
|
"@types/node": "22.8.4",
|
||||||
"eslint": "8.57.1",
|
"@types/react": "18.3.12",
|
||||||
"eslint-config-next": "14.2.6",
|
"@types/react-dom": "18.3.1",
|
||||||
|
"eslint": "9.13.0",
|
||||||
"postcss": "8.4.47",
|
"postcss": "8.4.47",
|
||||||
"tailwindcss": "3.4.13",
|
"tailwindcss": "3.4.14",
|
||||||
"typescript": "5.6.2"
|
"typescript": "5.6.3"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
2765
pnpm-lock.yaml
generated
2765
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
@ -1,75 +1,94 @@
|
|||||||
|
/**
|
||||||
|
* @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 => {
|
const About = (): JSX.Element => {
|
||||||
return (
|
return (
|
||||||
<>
|
<main className="w-4/5 text-center max-w-4xl m-auto mt-16 mb-16 rounded-lg">
|
||||||
<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>
|
||||||
<h1 className="text-5xl">About Naomi</h1>
|
<section>
|
||||||
<section>
|
<p className="mb-2">
|
||||||
<p className="mb-2">
|
{`Passionate technologist dedicated to building inclusive tech
|
||||||
Passionate technologist dedicated to building inclusive tech
|
communities and empowering individuals to break into the field. With
|
||||||
communities and empowering individuals to break into the field. With
|
a rich background in community management, software engineering, and
|
||||||
a rich background in community management, software engineering, and
|
developer experience, I strive to create accessible pathways for
|
||||||
developer experience, I strive to create accessible pathways for
|
diverse talent.`}
|
||||||
diverse talent.
|
</p>
|
||||||
</p>
|
|
||||||
|
|
||||||
<p className="mb-2">My expertise spans:</p>
|
<p className="mb-2">{`My expertise spans:`}</p>
|
||||||
<ul className="w-4/5 m-auto">
|
<ul className="w-4/5 m-auto">
|
||||||
<li className="mb-2 relative before:content-['🩵'] before:absolute before:left-[-1em]">
|
<li className="mb-2 relative before:content-['🩵']
|
||||||
<strong>Inclusive Community Building:</strong> Cultivated
|
before:absolute before:left-[-1em]">
|
||||||
welcoming communities of 20,000 to 300K+ members across Discord,
|
<strong>{`Inclusive Community Building:`}</strong>
|
||||||
Slack, and GitHub, with a focus on supporting underrepresented
|
{` Cultivated
|
||||||
groups in tech.
|
welcoming communities of 20,000 to 300K+ members across Discord,
|
||||||
</li>
|
Slack, and GitHub, with a focus on supporting underrepresented
|
||||||
<li className="mb-2 relative before:content-['🩵'] before:absolute before:left-[-1em]">
|
groups in tech.`}
|
||||||
<strong>Empowering Education:</strong> Contributed to and
|
</li>
|
||||||
maintained open-source curricula used by millions of aspiring
|
<li className="mb-2 relative before:content-['🩵']
|
||||||
developers globally, focusing on accessibility and engaging
|
before:absolute before:left-[-1em]">
|
||||||
learning experiences.
|
<strong>{`Empowering Education:`}</strong>
|
||||||
</li>
|
{` Contributed to and
|
||||||
<li className="mb-2 relative before:content-['🩵'] before:absolute before:left-[-1em]">
|
maintained open-source curricula used by millions of aspiring
|
||||||
<strong>Software Engineering for Inclusivity:</strong> Developed
|
developers globally, focusing on accessibility and engaging
|
||||||
sophisticated bots and tools that not only streamline moderation
|
learning experiences.`}
|
||||||
and boost engagement but also promote safe, inclusive spaces for
|
</li>
|
||||||
all community members.
|
<li className="mb-2 relative before:content-['🩵']
|
||||||
</li>
|
before:absolute before:left-[-1em]">
|
||||||
<li className="mb-2 relative before:content-['🩵'] before:absolute before:left-[-1em]">
|
<strong>{`Software Engineering for Inclusivity:`}</strong>
|
||||||
<strong>Developer Experience (DX):</strong> Led initiatives to
|
{` Developed
|
||||||
improve documentation, SDK support, and overall developer
|
sophisticated bots and tools that not only streamline moderation
|
||||||
satisfaction, with an emphasis on making resources accessible to
|
and boost engagement but also promote safe, inclusive spaces for
|
||||||
newcomers in the field.
|
all community members.`}
|
||||||
</li>
|
</li>
|
||||||
<li className="mb-2">
|
<li className="mb-2 relative before:content-['🩵']
|
||||||
<strong>Mentorship and Advocacy:</strong> Implemented programs to
|
before:absolute before:left-[-1em]">
|
||||||
support aspiring developers, particularly those from
|
<strong>{`Developer Experience (DX):`}</strong>
|
||||||
underrepresented backgrounds, in their journey into tech careers.
|
{` Led initiatives to
|
||||||
</li>
|
improve documentation, SDK support, and overall developer
|
||||||
</ul>
|
satisfaction, with an emphasis on making resources accessible to
|
||||||
<p className="mb-2">
|
newcomers in the field.`}
|
||||||
Key achievements include redesigning freeCodeCamp's Responsive
|
</li>
|
||||||
Web Design curriculum for greater accessibility, developing
|
<li className="mb-2">
|
||||||
AI-powered community management tools that foster inclusive
|
<strong>{`Mentorship and Advocacy:`}</strong>
|
||||||
interactions, and creating engagement systems that significantly
|
{` Implemented programs to
|
||||||
increased participation from diverse user groups.
|
support aspiring developers, particularly those from
|
||||||
</p>
|
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">
|
<p className="mb-2">
|
||||||
I'm driven by the belief that technology should be a field open
|
{`I'm driven by the belief that technology should be a field open
|
||||||
to all. My approach combines technical expertise with a deep
|
to all. My approach combines technical expertise with a deep
|
||||||
commitment to diversity, equity, and inclusion, resulting in
|
commitment to diversity, equity, and inclusion, resulting in
|
||||||
solutions that not only drive engagement and innovation but also
|
solutions that not only drive engagement and innovation but also
|
||||||
break down barriers to entry in tech.
|
break down barriers to entry in tech.`}
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p className="mb-2">
|
<p className="mb-2">
|
||||||
Seeking opportunities to lead transformative projects that expand
|
{`Seeking opportunities to lead transformative projects that expand
|
||||||
access to tech education, foster inclusive community growth, and
|
access to tech education, foster inclusive community growth, and
|
||||||
empower individuals from all backgrounds to thrive in the tech
|
empower individuals from all backgrounds to thrive in the tech
|
||||||
industry. Let's connect to discuss how I can best support your
|
industry. Let's connect to discuss how I can best support your
|
||||||
organisation!
|
organisation!`}
|
||||||
</p>
|
</p>
|
||||||
</section>
|
</section>
|
||||||
</main>
|
</main>
|
||||||
</>
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1,49 +1,69 @@
|
|||||||
|
/**
|
||||||
|
* @copyright nhcarrigan
|
||||||
|
* @license Naomi's Public License
|
||||||
|
* @author Naomi Carrigan
|
||||||
|
*/
|
||||||
"use client";
|
"use client";
|
||||||
import { Activity } from "@/components/activity";
|
import { type JSX, useEffect, useState } from "react";
|
||||||
import { Review } from "@/components/review";
|
import { Activity } from "../../components/activity";
|
||||||
import { Rule } from "@/components/rule";
|
import { Rule } from "../../components/rule";
|
||||||
import { Testimonials } from "@/config/Testimonials";
|
|
||||||
import { useEffect, useState } from "react";
|
|
||||||
|
|
||||||
const Reviews = (): JSX.Element => {
|
/**
|
||||||
const [activity, setActivity] = useState<
|
* Renders the /activity page.
|
||||||
{
|
* @returns A React Component.
|
||||||
type: string;
|
*/
|
||||||
date: Date;
|
const ActivityComponent = (): JSX.Element => {
|
||||||
repo: string;
|
const [ activity, setActivity ] = useState<
|
||||||
|
Array<{
|
||||||
|
type: string;
|
||||||
|
date: Date;
|
||||||
|
repo: string;
|
||||||
repoName: string;
|
repoName: string;
|
||||||
}[]
|
}>
|
||||||
>([]);
|
>([]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
fetch("/api/activity")
|
void fetch("/api/activity").
|
||||||
.then((data) => data.json())
|
then(async(data) => {
|
||||||
.then((data) => setActivity(data));
|
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
||||||
|
return (await data.json()) as Array<{
|
||||||
|
type: string;
|
||||||
|
date: Date;
|
||||||
|
repo: string;
|
||||||
|
repoName: string;
|
||||||
|
}>;
|
||||||
|
}).
|
||||||
|
then((data) => {
|
||||||
|
setActivity(data);
|
||||||
|
});
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<main className="w-[95%] text-center
|
||||||
<main className="w-[95%] text-center max-w-4xl m-auto mt-16 mb-16 rounded-lg">
|
max-w-4xl m-auto mt-16 mb-16 rounded-lg">
|
||||||
<h1 className="text-5xl">Recent Activity</h1>
|
<h1 className="text-5xl">{`Recent Activity`}</h1>
|
||||||
<section>
|
<section>
|
||||||
<p className="mb-2">See what Naomi has been up to lately.</p>
|
<p className="mb-2">{`See what Naomi has been up to lately.`}</p>
|
||||||
<Rule />
|
<Rule />
|
||||||
<ol className="relative border-s border-[--primary] w-4/5 m-auto">
|
<ol className="relative border-s border-[--primary] w-4/5 m-auto">
|
||||||
{activity.map((act, i) => (
|
{activity.map((act, index) => {
|
||||||
|
return (
|
||||||
<Activity
|
<Activity
|
||||||
key={act.date.toString()}
|
|
||||||
type={act.type}
|
|
||||||
date={act.date}
|
date={act.date}
|
||||||
|
heart={index % 2 === 1
|
||||||
|
? "🩷"
|
||||||
|
: "🩵"}
|
||||||
|
key={act.date.toString()}
|
||||||
repo={act.repo}
|
repo={act.repo}
|
||||||
repoName={act.repoName}
|
repoName={act.repoName}
|
||||||
heart={i % 2 ? "🩷" : "🩵"}
|
type={act.type}
|
||||||
/>
|
/>
|
||||||
))}
|
);
|
||||||
</ol>
|
})}
|
||||||
</section>
|
</ol>
|
||||||
</main>
|
</section>
|
||||||
</>
|
</main>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default Reviews;
|
export default ActivityComponent;
|
||||||
|
@ -1,17 +1,50 @@
|
|||||||
import { getCodebergData } from "@/lib/codeberg";
|
/**
|
||||||
import { getGithubData } from "@/lib/github";
|
* @copyright nhcarrigan
|
||||||
|
* @license Naomi's Public License
|
||||||
|
* @author Naomi Carrigan
|
||||||
|
*/
|
||||||
import { NextResponse } from "next/server";
|
import { NextResponse } from "next/server";
|
||||||
|
import { getCodebergData } from "../../../lib/codeberg";
|
||||||
|
import { getGithubData } from "../../../lib/github";
|
||||||
|
|
||||||
export async function GET() {
|
/**
|
||||||
|
* 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 getCodebergData();
|
const codeberg = await getCodebergData();
|
||||||
const github = await getGithubData();
|
const github = await getGithubData();
|
||||||
|
|
||||||
const normalised: {
|
const normalised: Array<{
|
||||||
type: string;
|
type: string;
|
||||||
date: Date;
|
date: Date;
|
||||||
repo: string;
|
repo: string;
|
||||||
repoName: string;
|
repoName: string;
|
||||||
}[] = [...codeberg.map(i => ({ type: i.op_type, date: new Date(i.created), repo: i.repo.html_url, repoName: i.repo.full_name })), ...github.map(i => ({ type: i.type, date: new Date(i.created_at), repo: i.repo.url.replace("api.github.com/repos", "github.com"), repoName: i.repo.name }))]
|
}> = [
|
||||||
|
...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.sort((a, b) => new Date(b.date).getTime() - new Date(a.date).getTime()).slice(0, 100))
|
return NextResponse.json(
|
||||||
|
normalised.
|
||||||
|
toSorted((a, b) => {
|
||||||
|
return new Date(b.date).getTime() - new Date(a.date).getTime();
|
||||||
|
}).
|
||||||
|
slice(0, 100),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
@ -1,23 +1,45 @@
|
|||||||
import { ArtComponent } from "@/components/art";
|
/**
|
||||||
import { Rule } from "@/components/rule";
|
* @copyright nhcarrigan
|
||||||
import { Art } from "@/config/Art";
|
* @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 => {
|
const Arts = (): JSX.Element => {
|
||||||
return (
|
return (
|
||||||
<>
|
<main
|
||||||
<main className="w-[95%] text-center max-w-4xl m-auto mt-16 mb-16 rounded-lg">
|
className="w-[95%] text-center
|
||||||
<h1 className="text-5xl">Art</h1>
|
max-w-4xl m-auto mt-16 mb-16 rounded-lg"
|
||||||
<section>
|
>
|
||||||
<p className="mb-2">See various art depicting Naomi.</p>
|
<h1 className="text-5xl">{`Art`}</h1>
|
||||||
<Rule />
|
<section>
|
||||||
<div className="grid sm:grid-cols-2 lg:grid-cols-3 grid-cols-1 gap-y-5">
|
<p className="mb-2">{`See various art depicting Naomi.`}</p>
|
||||||
{Art.sort((a, b) => a.name.localeCompare(b.name)).map((art) => (
|
<Rule />
|
||||||
<ArtComponent key={art.name} name={art.name} img={art.img} artist={art.artist} url={art.url} alt={art.alt}/>
|
<div className="grid sm:grid-cols-2 lg:grid-cols-3 grid-cols-1 gap-y-5">
|
||||||
))}
|
{Art.toSorted((a, b) => {
|
||||||
</div>
|
return a.name.localeCompare(b.name);
|
||||||
</section>
|
}).map((art) => {
|
||||||
</main>
|
return (
|
||||||
</>
|
<ArtComponent
|
||||||
|
alt={art.alt}
|
||||||
|
artist={art.artist}
|
||||||
|
img={art.img}
|
||||||
|
key={art.name}
|
||||||
|
name={art.name}
|
||||||
|
url={art.url}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</main>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1,35 +1,45 @@
|
|||||||
import { Certification } from "@/components/cert";
|
/**
|
||||||
import { Rule } from "@/components/rule";
|
* @copyright nhcarrigan
|
||||||
import { Certifications } from "@/config/Certifications";
|
* @license Naomi's Public License
|
||||||
import { Charm } from "next/font/google";
|
* @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 => {
|
const Certs = (): JSX.Element => {
|
||||||
return (
|
return (
|
||||||
<>
|
<main className="w-[95%] text-center
|
||||||
<main className="w-[95%] text-center max-w-4xl m-auto mt-16 mb-16 rounded-lg">
|
max-w-4xl m-auto mt-16 mb-16 rounded-lg">
|
||||||
<h1 className="text-5xl">Certs</h1>
|
<h1 className="text-5xl">{`Certs`}</h1>
|
||||||
<section>
|
<section>
|
||||||
<p className="mb-2">
|
<p className="mb-2">
|
||||||
This page lists the professional certifications Naomi has obtained
|
{`This page lists the professional certifications Naomi has obtained
|
||||||
throughout her time as a developer.
|
throughout her time as a developer.`}
|
||||||
</p>
|
</p>
|
||||||
<Rule />
|
<Rule />
|
||||||
<div className="grid sm:grid-cols-2 lg:grid-cols-3 grid-cols-1 gap-y-5">
|
<div className="grid sm:grid-cols-2 lg:grid-cols-3 grid-cols-1 gap-y-5">
|
||||||
{Certifications.sort(
|
{Certifications.toSorted(
|
||||||
(a, b) => b.date.getTime() - a.date.getTime(),
|
(a, b) => {
|
||||||
).map((cert) => (
|
return b.date.getTime() - a.date.getTime();
|
||||||
<Certification
|
},
|
||||||
key={cert.name}
|
).map((cert) => {
|
||||||
name={cert.name}
|
return <Certification
|
||||||
fileName={cert.fileName}
|
date={cert.date}
|
||||||
issuer={cert.issuer}
|
fileName={cert.fileName}
|
||||||
date={cert.date}
|
issuer={cert.issuer}
|
||||||
/>
|
key={cert.name}
|
||||||
))}
|
name={cert.name}
|
||||||
</div>
|
/>;
|
||||||
</section>
|
})}
|
||||||
</main>
|
</div>
|
||||||
</>
|
</section>
|
||||||
|
</main>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1,58 +1,70 @@
|
|||||||
import { Rule } from "@/components/rule";
|
/**
|
||||||
import { Social } from "@/components/social";
|
* @copyright nhcarrigan
|
||||||
import { Donate, HireMe, Socials } from "@/config/Socials";
|
* @license Naomi's Public License
|
||||||
|
* @author Naomi Carrigan
|
||||||
|
*/
|
||||||
|
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 => {
|
const Contact = (): JSX.Element => {
|
||||||
return (
|
return (
|
||||||
<>
|
<main className="w-4/5 text-center max-w-4xl m-auto mt-16 mb-16 rounded-lg">
|
||||||
<main className="w-4/5 text-center max-w-4xl m-auto mt-16 mb-16 rounded-lg">
|
<h1 className="text-5xl">{`Contact Us`}</h1>
|
||||||
<h1 className="text-5xl">Contact Us</h1>
|
<p>
|
||||||
<p>
|
{`We offer many different ways to get in touch with us. This page lists
|
||||||
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
|
||||||
all of our available social media accounts. Use the buttons below to
|
choose your preferred method.`}
|
||||||
choose your preferred method.
|
</p>
|
||||||
</p>
|
<p>
|
||||||
<p>
|
{`Note that the items are sorted alphabetically, not by order of
|
||||||
Note that the items are sorted alphabetically, not by order of
|
response times. Monitoring levels and activity may vary by platform.`}
|
||||||
response times. Monitoring levels and activity may vary by platform.
|
</p>
|
||||||
</p>
|
<p>
|
||||||
<p>
|
{`With ${Socials.length.toLocaleString("en-GB")} choices, you shouldn't have any complaints!
|
||||||
With {Socials.length} choices, you shouldn't have any complaints!
|
:3`}
|
||||||
:3
|
</p>
|
||||||
</p>
|
<Rule />
|
||||||
<Rule />
|
<section>
|
||||||
<section>
|
<div>
|
||||||
<div>
|
{[ HireMe, Donate ].map(
|
||||||
{[HireMe, Donate].map(
|
({ link, label, alt, icon, color, background }) => {
|
||||||
({ link, label, alt, icon, color, background }) => (
|
return <Social
|
||||||
<Social
|
alt={alt}
|
||||||
key={label}
|
background={background}
|
||||||
link={link}
|
color={color}
|
||||||
label={label}
|
icon={icon}
|
||||||
alt={alt}
|
key={label}
|
||||||
icon={icon}
|
label={label}
|
||||||
color={color}
|
link={link}
|
||||||
background={background}
|
/>;
|
||||||
/>
|
}
|
||||||
),
|
,
|
||||||
)}
|
)}
|
||||||
{Socials.sort((a, b) => a.label.localeCompare(b.label)).map(
|
{Socials.toSorted((a, b) => {
|
||||||
({ link, label, alt, icon, color, background }) => (
|
return a.label.localeCompare(b.label);
|
||||||
<Social
|
}).map(
|
||||||
key={label}
|
({ link, label, alt, icon, color, background }) => {
|
||||||
link={link}
|
return <Social
|
||||||
label={label}
|
alt={alt}
|
||||||
alt={alt}
|
background={background}
|
||||||
icon={icon}
|
color={color}
|
||||||
color={color}
|
icon={icon}
|
||||||
background={background}
|
key={label}
|
||||||
/>
|
label={label}
|
||||||
),
|
link={link}
|
||||||
)}
|
/>;
|
||||||
</div>
|
}
|
||||||
</section>
|
,
|
||||||
</main>
|
)}
|
||||||
</>
|
</div>
|
||||||
|
</section>
|
||||||
|
</main>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1,26 +1,44 @@
|
|||||||
import { Certification } from "@/components/cert";
|
/**
|
||||||
import { Game } from "@/components/game";
|
* @copyright nhcarrigan
|
||||||
import { Rule } from "@/components/rule";
|
* @license Naomi's Public License
|
||||||
import { Certifications } from "@/config/Certifications";
|
* @author Naomi Carrigan
|
||||||
import { Games } from "@/config/Games";
|
*/
|
||||||
import { Charm } from "next/font/google";
|
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 => {
|
const Gamez = (): JSX.Element => {
|
||||||
return (
|
return (
|
||||||
<>
|
<main
|
||||||
<main className="w-[95%] text-center max-w-4xl m-auto mt-16 mb-16 rounded-lg">
|
className="w-[95%] text-center
|
||||||
<h1 className="text-5xl">Games</h1>
|
max-w-4xl m-auto mt-16 mb-16 rounded-lg"
|
||||||
<section>
|
>
|
||||||
<p className="mb-2">See how Naomi has appeared in various games.</p>
|
<h1 className="text-5xl">{`Games`}</h1>
|
||||||
<Rule />
|
<section>
|
||||||
<div className="grid sm:grid-cols-2 lg:grid-cols-3 grid-cols-1 gap-y-5">
|
<p className="mb-2">{`See how Naomi has appeared in various games.`}</p>
|
||||||
{Games.sort((a, b) => a.name.localeCompare(b.name)).map((game) => (
|
<Rule />
|
||||||
<Game key={game.name} name={game.name} img={game.img} alt={game.alt} url={game.url} />
|
<div className="grid sm:grid-cols-2 lg:grid-cols-3 grid-cols-1 gap-y-5">
|
||||||
))}
|
{Games.toSorted((a, b) => {
|
||||||
</div>
|
return a.name.localeCompare(b.name);
|
||||||
</section>
|
}).map((game) => {
|
||||||
</main>
|
return (
|
||||||
</>
|
<Game
|
||||||
|
alt={game.alt}
|
||||||
|
img={game.img}
|
||||||
|
key={game.name}
|
||||||
|
name={game.name}
|
||||||
|
url={game.url}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</main>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1,75 +1,91 @@
|
|||||||
import type { Metadata } from "next";
|
/**
|
||||||
|
* @copyright nhcarrigan
|
||||||
|
* @license Naomi's Public License
|
||||||
|
* @author Naomi Carrigan
|
||||||
|
*/
|
||||||
import { Inter } from "next/font/google";
|
import { Inter } from "next/font/google";
|
||||||
import "./globals.css";
|
|
||||||
import { ClientNavigation } from "@/components/navigation";
|
|
||||||
import Script from "next/script";
|
import Script from "next/script";
|
||||||
|
// eslint-disable-next-line import/default, import/no-named-as-default, import/no-named-as-default-member
|
||||||
import PlausibleProvider from "next-plausible";
|
import PlausibleProvider from "next-plausible";
|
||||||
import { ClientFooter } from "@/components/footer";
|
import { Footer } from "../components/footer";
|
||||||
|
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";
|
||||||
|
|
||||||
const inter = Inter({ subsets: ["latin"] });
|
// eslint-disable-next-line new-cap
|
||||||
|
const inter = Inter({ subsets: [ "latin" ] });
|
||||||
|
|
||||||
export const metadata: Metadata = {
|
const metadata: Metadata = {
|
||||||
title: "Naomi's Portfolio",
|
|
||||||
description:
|
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.",
|
"This page tells you everything you could ever want to know about Naomi and her consulting firm nhcarrigan.",
|
||||||
openGraph: {
|
openGraph: {
|
||||||
images: "https://cdn.nhcarrigan.com/background.png",
|
images: "https://cdn.nhcarrigan.com/background.png",
|
||||||
},
|
},
|
||||||
|
title: "Naomi's Portfolio",
|
||||||
twitter: {
|
twitter: {
|
||||||
card: "summary_large_image",
|
card: "summary_large_image",
|
||||||
site: "@naomi_lgbt",
|
|
||||||
images: "https://cdn.nhcarrigan.com/background.png",
|
images: "https://cdn.nhcarrigan.com/background.png",
|
||||||
|
site: "@naomi_lgbt",
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
export default function RootLayout({
|
/**
|
||||||
|
* 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,
|
children,
|
||||||
}: Readonly<{
|
}: Readonly<{
|
||||||
children: React.ReactNode;
|
children: ReactNode;
|
||||||
}>) {
|
}>): JSX.Element => {
|
||||||
return (
|
return (
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<Script
|
|
||||||
strategy="beforeInteractive"
|
|
||||||
src="https://widgets.tree-nation.com/js/widgets/v1/widgets.min.js?v=1.0"
|
|
||||||
></Script>
|
|
||||||
<PlausibleProvider
|
<PlausibleProvider
|
||||||
domain="nhcarrigan.com"
|
|
||||||
customDomain="https://analytics.nhcarrigan.com"
|
customDomain="https://analytics.nhcarrigan.com"
|
||||||
|
domain="nhcarrigan.com"
|
||||||
trackFileDownloads={true}
|
trackFileDownloads={true}
|
||||||
trackOutboundLinks={true}
|
trackOutboundLinks={true}
|
||||||
>
|
>
|
||||||
<link
|
<link
|
||||||
rel="icon"
|
|
||||||
href="https://cdn.nhcarrigan.com/logo.png"
|
href="https://cdn.nhcarrigan.com/logo.png"
|
||||||
|
rel="icon"
|
||||||
sizes="any"
|
sizes="any"
|
||||||
/>
|
/>
|
||||||
<body className={inter.className}>
|
<body className={inter.className}>
|
||||||
<header>
|
<header>
|
||||||
<ClientNavigation />
|
<Navigation />
|
||||||
</header>
|
</header>
|
||||||
{children}
|
{children}
|
||||||
<video
|
<video
|
||||||
src="https://cdn.nhcarrigan.com/overlay.webm"
|
autoPlay={true}
|
||||||
autoPlay
|
|
||||||
loop
|
|
||||||
muted
|
|
||||||
playsInline
|
|
||||||
className="fixed top-0 left-0 w-full h-full object-cover opacity-25"
|
className="fixed top-0 left-0 w-full h-full object-cover opacity-25"
|
||||||
|
loop={true}
|
||||||
|
muted={true}
|
||||||
|
playsInline={true}
|
||||||
|
src="https://cdn.nhcarrigan.com/overlay.webm"
|
||||||
style={{ pointerEvents: "none" }}
|
style={{ pointerEvents: "none" }}
|
||||||
/>
|
/>
|
||||||
<footer>
|
<footer>
|
||||||
<ClientFooter />
|
<Footer />
|
||||||
</footer>
|
</footer>
|
||||||
</body>
|
</body>
|
||||||
<Script
|
<Script
|
||||||
type="text/javascript"
|
async={true}
|
||||||
|
defer={true}
|
||||||
id="hs-script-loader"
|
id="hs-script-loader"
|
||||||
async
|
|
||||||
defer
|
|
||||||
src="//js.hs-scripts.com/47086586.js"
|
src="//js.hs-scripts.com/47086586.js"
|
||||||
|
type="text/javascript"
|
||||||
></Script>
|
></Script>
|
||||||
</PlausibleProvider>
|
</PlausibleProvider>
|
||||||
</html>
|
</html>
|
||||||
);
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
|
export { metadata };
|
||||||
|
export default RootLayout;
|
||||||
|
@ -1,87 +1,221 @@
|
|||||||
|
/**
|
||||||
|
* @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 => {
|
const Manifesto = (): JSX.Element => {
|
||||||
return (
|
return (
|
||||||
<main className="w-4/5 text-center max-w-4xl m-auto mt-16 mb-16 rounded-lg">
|
<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>
|
<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 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>
|
<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>
|
<h2 className="text-2xl">{`I. We Are the Lions`}</h2>
|
||||||
<ol>
|
<ol>
|
||||||
<li>Our manes are diverse: short, long, neon, natural - each strand a testament to our journey.</li>
|
<li>
|
||||||
<li>We prowl through life with grace, strength, and an occasional stumble (because even lionesses trip sometimes, darling).</li>
|
{`Our manes are diverse: short, long, neon, natural - each strand a
|
||||||
<li>Our roars echo through boardrooms, classrooms, and everywhere we have been told to stay silent.</li>
|
testament to our journey.`}
|
||||||
<li>We fiercely protect our pride - our chosen family, our allies, our community.</li>
|
</li>
|
||||||
<li>Like lions, we bask in the sun of our authenticity, soaking up the warmth of self-acceptance.</li>
|
<li>
|
||||||
</ol>
|
{`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>
|
<h2 className="text-2xl">{`II. We Are the Witches`}</h2>
|
||||||
<ol>
|
<ol>
|
||||||
<li>Our spellbook is filled with incantations of self-affirmation and hexes against transphobia.</li>
|
<li>
|
||||||
<li>We stir cauldrons of change, mixing potions of progress and elixirs of equality.</li>
|
{`Our spellbook is filled with incantations of self-affirmation and
|
||||||
<li>Our wands (be they makeup brushes, pens, or literal wands) cast spells of transformation.</li>
|
hexes against transphobia.`}
|
||||||
<li>We commune with the spirits of our trans ancestors, drawing strength from their legacy.</li>
|
</li>
|
||||||
<li>In our coven, every body is sacred, every identity valid, every expression magical.</li>
|
<li>
|
||||||
</ol>
|
{`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>
|
<h2 className="text-2xl">{`III. We Have the Audacity`}</h2>
|
||||||
<ol>
|
<ol>
|
||||||
<li>We have the audacity to exist loudly in a world that wishes us to be quiet.</li>
|
<li>
|
||||||
<li>We dare to love our bodies, curves, edges, and all, defying those who say we should not.</li>
|
{`We have the audacity to exist loudly in a world that wishes us to be
|
||||||
<li>We boldly claim our place in women's spaces, sports, and narratives.</li>
|
quiet.`}
|
||||||
<li>We redefine beauty standards with every strut, sashay, and hair flip.</li>
|
</li>
|
||||||
<li>We have the gall to demand respect, rights, and recognition - and honey, we look fabulous doing it.</li>
|
<li>
|
||||||
</ol>
|
{`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>
|
<h2 className="text-2xl">{`IV. Our Decrees`}</h2>
|
||||||
<ol>
|
<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>
|
||||||
<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>
|
{`We decree that gender is a playground, not a prison. Swing on the
|
||||||
<li>We declare our right to safe spaces, medical care, and public restrooms without fear or judgment.</li>
|
monkey bars of masculinity, slide down the curves of femininity, or
|
||||||
<li>We assert our humanity in the face of legislation that tries to erase us. Our existence is not up for debate.</li>
|
build sandcastles of androgyny.`}
|
||||||
<li>We affirm our right to joy, love, and celebration. Our lives are not just about struggle - we're here to thrive, baby!</li>
|
</li>
|
||||||
</ol>
|
<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>
|
<h2 className="text-2xl">{`V. Our Commitments`}</h2>
|
||||||
<ol>
|
<ol>
|
||||||
<li>We vow to lift as we climb, ensuring no trans sibling is left behind.</li>
|
<li>
|
||||||
<li>We pledge to celebrate the diversity within our community - every shade, shape, and expression of transness.</li>
|
{`We vow to lift as we climb, ensuring no trans sibling is left behind.`}
|
||||||
<li>We promise to continue educating, even when it's exhausting, because knowledge is the enemy of ignorance.</li>
|
</li>
|
||||||
<li>We commit to loving ourselves fiercely, even on days when the world makes it hard.</li>
|
<li>
|
||||||
<li>We dedicate ourselves to creating art, music, literature, and memes that tell our stories and make our voices heard.</li>
|
{`We pledge to celebrate the diversity within our community - every
|
||||||
</ol>
|
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>
|
<h2 className="text-2xl">{`VI. The Transfemme Toolbox`}</h2>
|
||||||
<ol>
|
<ol>
|
||||||
<li>Eyeliner sharp enough to wing and to slay our enemies.</li>
|
<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>
|
||||||
<li>Heels high enough to reach new heights (and flats comfortable enough for when the revolution requires running).</li>
|
{`A vocabulary expansive enough to articulate our identities and to
|
||||||
<li>A chosen name that feels like home and a dead name composted for future growth.</li>
|
eloquently tell transphobes where to go.`}
|
||||||
<li>A support network of fellow lions, witches, and audacious bitches to remind us we're not alone.</li>
|
</li>
|
||||||
</ol>
|
<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>
|
<h2 className="text-2xl">{`VII. Our Vision of the Future`}</h2>
|
||||||
<p>In our ideal world:</p>
|
<p>{`In our ideal world:`}</p>
|
||||||
<ol>
|
<ol>
|
||||||
<li>Gender reveal parties are replaced by "I'll reveal my gender when I'm good and ready" parties.</li>
|
<li>
|
||||||
<li>The only time we're asked about our genitals is by our doctors or consensual partners.</li>
|
{`Gender reveal parties are replaced by "I'll reveal my gender when I'm
|
||||||
<li>Trans joy is as commonplace as cis assumptions once were.</li>
|
good and ready" parties.`}
|
||||||
<li>Our stories are told by us, not about us, in media, literature, and history books.</li>
|
</li>
|
||||||
<li>The audacity of our existence is celebrated, not merely tolerated.</li>
|
<li>
|
||||||
</ol>
|
{`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>
|
<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>
|
||||||
|
{`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.
|
<p>
|
||||||
To those who don't understand us: we invite you to listen, to learn, and to expand your world.
|
{`To those who support us: we see you, we appreciate you, we invite you to
|
||||||
To those who oppose us: your time is up, your reign is over, the future is gloriously, unapologetically trans.</p>
|
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>
|
||||||
|
{`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-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>
|
<p className="text-3xl">
|
||||||
</main>
|
{`Long live the transfemme revolution! 🦁✨👑💄🏳️⚧️`}
|
||||||
|
</p>
|
||||||
|
</main>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1,134 +1,172 @@
|
|||||||
import { Rule } from "@/components/rule";
|
/**
|
||||||
|
* @copyright nhcarrigan
|
||||||
|
* @license Naomi's Public License
|
||||||
|
* @author Naomi Carrigan
|
||||||
|
*/
|
||||||
import Image from "next/image";
|
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 => {
|
const Manual = (): JSX.Element => {
|
||||||
return (
|
return (
|
||||||
<>
|
<main className="w-4/5 text-center max-w-4xl m-auto mt-16 mb-16 rounded-lg">
|
||||||
<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>
|
||||||
<h1 className="text-5xl">Naomi's User Manual</h1>
|
<p className="text-3xl">{`Model T42-P9000`}</p>
|
||||||
<p className="text-3xl">Model T42-P9000</p>
|
<section>
|
||||||
<section>
|
<p className="mb-2">
|
||||||
<p className="mb-2">
|
{`Hiya! This page is meant to give you a run-down of what working with
|
||||||
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
|
||||||
me is like. It's like a li'l insight into the way I best
|
interact with people and perform on a team.`}
|
||||||
interact with people and perform on a team.
|
</p>
|
||||||
</p>
|
<Image
|
||||||
<Image
|
alt="If you knew I was so unstable, why'd you hire me?"
|
||||||
className="m-auto"
|
className="m-auto"
|
||||||
src="https://cdn.nhcarrigan.com/hire.jpeg"
|
height={500}
|
||||||
alt="If you knew I was so unstable, why'd you hire me?"
|
src="https://cdn.nhcarrigan.com/hire.jpeg"
|
||||||
width={500}
|
width={500}
|
||||||
height={500}
|
/>
|
||||||
/>
|
<Rule />
|
||||||
<Rule />
|
</section>
|
||||||
</section>
|
<section>
|
||||||
<section>
|
<h2 className="text-3xl">{`My Values`}</h2>
|
||||||
<h2 className="text-3xl">My Values</h2>
|
<p className="mb-2">
|
||||||
<p className="mb-2">
|
{`I tend to be very firm in my values, to the degree that I shy away
|
||||||
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.`}
|
||||||
from organisations or projects which do not align with my ethics.
|
</p>
|
||||||
</p>
|
<ul className="w-4/5 m-auto">
|
||||||
<ul className="w-4/5 m-auto">
|
<li
|
||||||
<li className="mb-2 relative before:content-['🩵'] before:absolute before:left-[-1em]">
|
className="mb-2 relative before:content-['🩵']
|
||||||
First and foremost, do not pass judgement. I will not begrudge you
|
before:absolute before:left-[-1em]"
|
||||||
for your religious beliefs, political alignments, or any other
|
>
|
||||||
aspects of your life. And I expect the same courtesy in return.
|
{`First and foremost, do not pass judgement. I will not begrudge you
|
||||||
You do not have to accept who I am, or support my choices, but we
|
for your religious beliefs, political alignments, or any other
|
||||||
need to maintain a respectful and cordial professional
|
aspects of your life. And I expect the same courtesy in return.
|
||||||
relationship. Expressing hateful, mean-spirited, or vitriolic
|
You do not have to accept who I am, or support my choices, but we
|
||||||
comments does not foster such an environment, and my tolerance for
|
need to maintain a respectful and cordial professional
|
||||||
such is nil.
|
relationship. Expressing hateful, mean-spirited, or vitriolic
|
||||||
</li>
|
comments does not foster such an environment, and my tolerance for
|
||||||
<li className="mb-2 relative before:content-['🩵'] before:absolute before:left-[-1em]">
|
such is nil.`}
|
||||||
Second, we shall do no harm. I very strongly believe that
|
</li>
|
||||||
technology is meant to advance our society, not regress it.
|
<li
|
||||||
Software should not be used to automate people's careers
|
className="mb-2 relative before:content-['🩵']
|
||||||
away, or replace creative works with pale imitations, or
|
before:absolute before:left-[-1em]"
|
||||||
harass/target someone, or restrict access to information.
|
>
|
||||||
</li>
|
{`Second, we shall do no harm. I very strongly believe that
|
||||||
</ul>
|
technology is meant to advance our society, not regress it.
|
||||||
<Rule />
|
Software should not be used to automate people's careers
|
||||||
</section>
|
away, or replace creative works with pale imitations, or
|
||||||
<section>
|
harass/target someone, or restrict access to information.`}
|
||||||
<h2 className="text-3xl">Environment</h2>
|
</li>
|
||||||
<p className="mb-2">
|
</ul>
|
||||||
I have found that I best thrive and produce the greatest works in
|
<Rule />
|
||||||
specific environments.
|
</section>
|
||||||
</p>
|
<section>
|
||||||
<ul className="w-4/5 m-auto">
|
<h2 className="text-3xl">{`Environment`}</h2>
|
||||||
<li className="mb-2 relative before:content-['🩵'] before:absolute before:left-[-1em]">
|
<p className="mb-2">
|
||||||
Ideas should be freely discussed, challenged, and evaluated. I am
|
{`I have found that I best thrive and produce the greatest works in
|
||||||
not a "yes girl" to blindly follow orders. If I hear a
|
specific environments.`}
|
||||||
plan that I think misses the mark, I will absolutely voice my
|
</p>
|
||||||
concerns. And I welcome the same scrutiny in return. Discussion
|
<ul className="w-4/5 m-auto">
|
||||||
needs to be constructive and fruitful - if we're going around
|
<li
|
||||||
in circles, it's time to table it and sleep on our thoughts.
|
className="mb-2 relative before:content-['🩵']
|
||||||
</li>
|
before:absolute before:left-[-1em]"
|
||||||
<li className="mb-2 relative before:content-['🩵'] before:absolute before:left-[-1em]">
|
>
|
||||||
We are not our ideas, however. "This is bad and you should
|
{`Ideas should be freely discussed, challenged, and evaluated. I am
|
||||||
feel bad" helps no one. "I'm not sure that is the
|
not a "yes girl" to blindly follow orders. If I hear a
|
||||||
best approach, can we consider doing this instead?" keeps the
|
plan that I think misses the mark, I will absolutely voice my
|
||||||
conversation focused on the right things and moving forward.
|
concerns. And I welcome the same scrutiny in return. Discussion
|
||||||
</li>
|
needs to be constructive and fruitful - if we're going around
|
||||||
<li className="mb-2 relative before:content-['🩵'] before:absolute before:left-[-1em]">
|
in circles, it's time to table it and sleep on our thoughts.`}
|
||||||
ADHD means my productivity is highly fluctuating. There are days
|
</li>
|
||||||
where I can sit and bang out a week of work in 16 hours, and there
|
<li
|
||||||
are days where I stare mindlessly at the screen and then realise
|
className="mb-2 relative before:content-['🩵']
|
||||||
the sun has set already. Flexibility in both schedule and
|
before:absolute before:left-[-1em]"
|
||||||
deadlines is very important to me.
|
>
|
||||||
</li>
|
{`We are not our ideas, however. "This is bad and you should
|
||||||
<li className="mb-2 relative before:content-['🩵'] before:absolute before:left-[-1em]">
|
feel bad" helps no one. "I'm not sure that is the
|
||||||
Likewise, insomnia can rear its ugly head and absolutely wreck my
|
best approach, can we consider doing this instead?" keeps the
|
||||||
sleep schedule without any warning. Asynchronous comms are always
|
conversation focused on the right things and moving forward.`}
|
||||||
preferred over meetings, but if a meeting must happen the
|
</li>
|
||||||
afternoon hours are the best. Too early and I'll likely fail
|
<li
|
||||||
to wake up. Too late and I might be incoherent.
|
className="mb-2 relative before:content-['🩵']
|
||||||
</li>
|
before:absolute before:left-[-1em]"
|
||||||
<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%
|
{`ADHD means my productivity is highly fluctuating. There are days
|
||||||
make it pretty and load every single task ever on there. I'm
|
where I can sit and bang out a week of work in 16 hours, and there
|
||||||
a sucker for organising workloads and the easiest way for me to be
|
are days where I stare mindlessly at the screen and then realise
|
||||||
transparent about the work I'm doing is to just let you look
|
the sun has set already. Flexibility in both schedule and
|
||||||
at a task board. If you say "what did you do yesterday"
|
deadlines is very important to me.`}
|
||||||
I will not remember this for I have slept since then.
|
</li>
|
||||||
</li>
|
<li
|
||||||
</ul>
|
className="mb-2 relative before:content-['🩵']
|
||||||
<Rule />
|
before:absolute before:left-[-1em]"
|
||||||
</section>
|
>
|
||||||
<section>
|
{`Likewise, insomnia can rear its ugly head and absolutely wreck my
|
||||||
<h2 className="text-3xl">Communication</h2>
|
sleep schedule without any warning. Asynchronous comms are always
|
||||||
<p>
|
preferred over meetings, but if a meeting must happen the
|
||||||
As with many people, there are certain approaches to communication
|
afternoon hours are the best. Too early and I'll likely fail
|
||||||
that are more effective for me.
|
to wake up. Too late and I might be incoherent.`}
|
||||||
</p>
|
</li>
|
||||||
<ul className="w-4/5 m-auto">
|
<li
|
||||||
<li className="mb-2 relative before:content-['🩵'] before:absolute before:left-[-1em]">
|
className="mb-2 relative before:content-['🩵']
|
||||||
Don't just say "hello" in my DMs or ping me without
|
before:absolute before:left-[-1em]"
|
||||||
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
|
{`If given something like a Trello or a Monday board, I will 100%
|
||||||
last part.
|
make it pretty and load every single task ever on there. I'm
|
||||||
</li>
|
a sucker for organising workloads and the easiest way for me to be
|
||||||
<li className="mb-2 relative before:content-['🩵'] before:absolute before:left-[-1em]">
|
transparent about the work I'm doing is to just let you look
|
||||||
I have generalised anxiety disorder. Please for the love of all
|
at a task board. If you say "what did you do yesterday"
|
||||||
things, do NOT say "we need to talk" or "do you
|
I will not remember this for I have slept since then.`}
|
||||||
have time to meet". I will 100% sit there right up until the
|
</li>
|
||||||
meeting starts stressing about getting fired and not actually
|
</ul>
|
||||||
getting any work done. If you need to call me out, just rip the
|
<Rule />
|
||||||
bandage off and come out of the gate with it.
|
</section>
|
||||||
</li>
|
<section>
|
||||||
<li className="mb-2 relative before:content-['🩵'] before:absolute before:left-[-1em]">
|
<h2 className="text-3xl">{`Communication`}</h2>
|
||||||
I dunno if you noticed the tone changed in this document about a
|
<p>
|
||||||
million times. That's pretty much Naomi in a nutshell.
|
{`As with many people, there are certain approaches to communication
|
||||||
I'll go from collected and eloquent to manic and sending
|
that are more effective for me.`}
|
||||||
messages faster than Discord can process. I try my hardest to stay
|
</p>
|
||||||
professional, but ADHD makes that very hard. I'll swear
|
<ul className="w-4/5 m-auto">
|
||||||
sometimes, I'll say totally off-the-wall things. But I really
|
<li
|
||||||
do try!
|
className="mb-2 relative before:content-['🩵']
|
||||||
</li>
|
before:absolute before:left-[-1em]"
|
||||||
</ul>
|
>
|
||||||
</section>
|
{`Don't just say "hello" in my DMs or ping me without
|
||||||
</main>
|
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>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1,55 +1,68 @@
|
|||||||
"use client";
|
/**
|
||||||
import { NavItems } from "@/config/NavItems";
|
* @copyright nhcarrigan
|
||||||
|
* @license Naomi's Public License
|
||||||
|
* @author Naomi Carrigan
|
||||||
|
*/
|
||||||
import Image from "next/image";
|
import Image from "next/image";
|
||||||
import React, { useEffect, useState } from "react";
|
import React, { type JSX } from "react";
|
||||||
|
import { NavItems } from "../config/NavItems";
|
||||||
|
|
||||||
export default function Home() {
|
/**
|
||||||
const [isDarkMode, setIsDarkMode] = useState(false);
|
* Renders the main React component.
|
||||||
|
* @returns A JSX element.
|
||||||
useEffect(() => {
|
*/
|
||||||
const savedTheme = localStorage.getItem("theme");
|
const Home = (): JSX.Element => {
|
||||||
const prefersDark = window.matchMedia(
|
|
||||||
"(prefers-color-scheme: dark)",
|
|
||||||
).matches;
|
|
||||||
const isDark = savedTheme === "dark" || (!savedTheme && prefersDark);
|
|
||||||
document.documentElement.classList.toggle("dark", isDark);
|
|
||||||
setIsDarkMode(isDark);
|
|
||||||
}, []);
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<div className="absolute top-0 right-[33vw] z-100 w-[100vh] h-[100vh] rotate-90 hidden lg:block">
|
<div
|
||||||
<svg viewBox="0 0 500 500" className="absolute">
|
className="absolute top-0 right-[33vw] z-100
|
||||||
|
w-[100vh] h-[100vh] rotate-90 hidden lg:block"
|
||||||
|
>
|
||||||
|
<svg className="absolute" viewBox="0 0 500 500">
|
||||||
<path
|
<path
|
||||||
d="M0,100 C150,200 350,0 500,100 L500,00 L0,0 Z"
|
d="M0,100 C150,200 350,0 500,100 L500,00 L0,0 Z"
|
||||||
style={{ stroke: "none", fill: "var(--foreground)" }}
|
style={{ fill: "var(--foreground)", stroke: "none" }}
|
||||||
></path>
|
></path>
|
||||||
</svg>
|
</svg>
|
||||||
</div>
|
</div>
|
||||||
<main className="grid grid-cols-[2fr,1fr] min-h-screen">
|
<main className="grid grid-cols-[2fr,1fr] min-h-screen">
|
||||||
<section className="bg-[--background] text-[--foreground] flex flex-col items-left justify-center text-left pl-5">
|
<section
|
||||||
<h1 className="text-4xl mb-2">Naomi Carrigan</h1>
|
className="bg-[--background] text-[--foreground]
|
||||||
|
flex flex-col items-left justify-center text-left pl-5"
|
||||||
|
>
|
||||||
|
<h1 className="text-4xl mb-2">{`Naomi Carrigan`}</h1>
|
||||||
<Image
|
<Image
|
||||||
src="https://cdn.nhcarrigan.com/profile.png"
|
|
||||||
alt="Naomi Carrigan"
|
alt="Naomi Carrigan"
|
||||||
width={200}
|
|
||||||
height={200}
|
|
||||||
className="rounded-full"
|
className="rounded-full"
|
||||||
|
height={200}
|
||||||
|
src="https://cdn.nhcarrigan.com/profile.png"
|
||||||
|
width={200}
|
||||||
/>
|
/>
|
||||||
<p className="text-3xl">Software Engineer</p>
|
<p className="text-3xl">{`Software Engineer`}</p>
|
||||||
<p className="text-3xl">Community Manager</p>
|
<p className="text-3xl">{`Community Manager`}</p>
|
||||||
</section>
|
</section>
|
||||||
<section className="bg-[--foreground] text-[--background] flex flex-col items-center justify-center">
|
<section
|
||||||
{NavItems.map((item, index) => (
|
className="bg-[--foreground] text-[--background]
|
||||||
<a
|
flex flex-col items-center justify-center"
|
||||||
key={item.href}
|
>
|
||||||
href={item.href}
|
{NavItems.map((item, index) => {
|
||||||
className="block py-2 px-4 text-2xl hover:bg-[--background] hover:text-[--foreground]"
|
return (
|
||||||
>
|
<a
|
||||||
{index % 2 ? "🩷" : "🩵"} {item.text}
|
className="block py-2 px-4 text-2xl
|
||||||
</a>
|
hover:bg-[--background] hover:text-[--foreground]"
|
||||||
))}
|
href={item.href}
|
||||||
|
key={item.href}
|
||||||
|
>
|
||||||
|
{index % 2 === 1
|
||||||
|
? "🩷"
|
||||||
|
: "🩵"} {item.text}
|
||||||
|
</a>
|
||||||
|
);
|
||||||
|
})}
|
||||||
</section>
|
</section>
|
||||||
</main>
|
</main>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
|
export default Home;
|
||||||
|
@ -1,32 +1,41 @@
|
|||||||
import { Partner } from "@/components/partner";
|
/**
|
||||||
import { Rule } from "@/components/rule";
|
* @copyright nhcarrigan
|
||||||
import { Partners } from "@/config/Partners";
|
* @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 => {
|
const Polycule = (): JSX.Element => {
|
||||||
return (
|
return (
|
||||||
<>
|
<main className="w-[95%] text-center
|
||||||
<main className="w-[95%] text-center max-w-4xl m-auto mt-16 mb-16 rounded-lg">
|
max-w-4xl m-auto mt-16 mb-16 rounded-lg">
|
||||||
<h1 className="text-5xl">Naomi's Polycule</h1>
|
<h1 className="text-5xl">{`Naomi's Polycule`}</h1>
|
||||||
<section>
|
<section>
|
||||||
<p className="mb-2">
|
<p className="mb-2">
|
||||||
Meet the people who love and support Naomi to the ends of the earth.
|
{`Meet the people who love and support Naomi to the ends of the earth.`}
|
||||||
</p>
|
</p>
|
||||||
<Rule />
|
<Rule />
|
||||||
<div className="w-full">
|
<div className="w-full">
|
||||||
{Partners.map((member) => (
|
{Partners.map((member) => {
|
||||||
<Partner
|
return <Partner
|
||||||
key={member.name}
|
anniversary={member.anniversary}
|
||||||
name={member.name}
|
avatar={member.avatar}
|
||||||
url={member.url}
|
key={member.name}
|
||||||
avatar={member.avatar}
|
name={member.name}
|
||||||
anniversary={member.anniversary}
|
relationship={member.relationship}
|
||||||
relationship={member.relationship}
|
url={member.url}
|
||||||
/>
|
/>;
|
||||||
))}
|
})}
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
</main>
|
</main>
|
||||||
</>
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1,39 +1,47 @@
|
|||||||
import { Certification } from "@/components/cert";
|
/**
|
||||||
import { Review } from "@/components/review";
|
* @copyright nhcarrigan
|
||||||
import { Rule } from "@/components/rule";
|
* @license Naomi's Public License
|
||||||
import { Certifications } from "@/config/Certifications";
|
* @author Naomi Carrigan
|
||||||
import { Testimonials } from "@/config/Testimonials";
|
*/
|
||||||
import { Charm } from "next/font/google";
|
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 => {
|
const Reviews = (): JSX.Element => {
|
||||||
return (
|
return (
|
||||||
<>
|
<main className="w-[95%] text-center max-w-4xl
|
||||||
<main className="w-[95%] text-center max-w-4xl m-auto mt-16 mb-16 rounded-lg">
|
m-auto mt-16 mb-16 rounded-lg">
|
||||||
<h1 className="text-5xl">Client Reviews</h1>
|
<h1 className="text-5xl">{`Client Reviews`}</h1>
|
||||||
<section>
|
<section>
|
||||||
<p className="mb-2">
|
<p className="mb-2">
|
||||||
We think we're pretty great to work with, but don't take
|
{`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.
|
our word for it. Here's what our clients have to say.`}
|
||||||
</p>
|
</p>
|
||||||
<Rule />
|
<Rule />
|
||||||
<ol className="relative border-s border-[--primary] w-4/5 m-auto">
|
<ol className="relative border-s border-[--primary] w-4/5 m-auto">
|
||||||
{Testimonials.sort(
|
{Testimonials.toSorted(
|
||||||
(a, b) => b.date.getTime() - a.date.getTime(),
|
(a, b) => {
|
||||||
).map((review) => (
|
return b.date.getTime() - a.date.getTime();
|
||||||
<Review
|
},
|
||||||
key={review.date.toISOString()}
|
).map((review) => {
|
||||||
name={review.name}
|
return <Review
|
||||||
date={review.date}
|
content={review.content}
|
||||||
content={review.content}
|
date={review.date}
|
||||||
sourceIcon={review.sourceIcon}
|
key={review.date.toISOString()}
|
||||||
sourceUrl={review.sourceUrl}
|
name={review.name}
|
||||||
sourceName={review.sourceName}
|
sourceIcon={review.sourceIcon}
|
||||||
/>
|
sourceName={review.sourceName}
|
||||||
))}
|
sourceUrl={review.sourceUrl}
|
||||||
</ol>
|
/>;
|
||||||
</section>
|
})}
|
||||||
</main>
|
</ol>
|
||||||
</>
|
</section>
|
||||||
|
</main>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1,37 +1,41 @@
|
|||||||
import { Certification } from "@/components/cert";
|
/**
|
||||||
import { Game } from "@/components/game";
|
* @copyright nhcarrigan
|
||||||
import { Member } from "@/components/member";
|
* @license Naomi's Public License
|
||||||
import { Rule } from "@/components/rule";
|
* @author Naomi Carrigan
|
||||||
import { Certifications } from "@/config/Certifications";
|
*/
|
||||||
import { Games } from "@/config/Games";
|
import { Member } from "../../components/member";
|
||||||
import { TeamMembers } from "@/config/TeamMembers";
|
import { Rule } from "../../components/rule";
|
||||||
import { Charm } from "next/font/google";
|
import { TeamMembers } from "../../config/TeamMembers";
|
||||||
|
import type { JSX } from "react";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Renders the /team page.
|
||||||
|
* @returns A React Component.
|
||||||
|
*/
|
||||||
const Team = (): JSX.Element => {
|
const Team = (): JSX.Element => {
|
||||||
return (
|
return (
|
||||||
<>
|
<main className="w-[95%] text-center
|
||||||
<main className="w-[95%] text-center max-w-4xl m-auto mt-16 mb-16 rounded-lg">
|
max-w-4xl m-auto mt-16 mb-16 rounded-lg">
|
||||||
<h1 className="text-5xl">Our Team</h1>
|
<h1 className="text-5xl">{`Our Team`}</h1>
|
||||||
<section>
|
<section>
|
||||||
<p className="mb-2">
|
<p className="mb-2">
|
||||||
Meet the people behind nhcarrigan's success!
|
{`Meet the people behind nhcarrigan's success!`}
|
||||||
</p>
|
</p>
|
||||||
<Rule />
|
<Rule />
|
||||||
<div className="w-full">
|
<div className="w-full">
|
||||||
{TeamMembers.map((member) => (
|
{TeamMembers.map((member) => {
|
||||||
<Member
|
return <Member
|
||||||
key={member.name}
|
avatar={member.avatar}
|
||||||
name={member.name}
|
joinDate={member.joinDate}
|
||||||
url={member.url}
|
key={member.name}
|
||||||
avatar={member.avatar}
|
name={member.name}
|
||||||
joinDate={member.joinDate}
|
role={member.role}
|
||||||
role={member.role}
|
url={member.url}
|
||||||
/>
|
/>;
|
||||||
))}
|
})}
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
</main>
|
</main>
|
||||||
</>
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1,92 +1,103 @@
|
|||||||
import { Job } from "@/components/job";
|
/**
|
||||||
import { Rule } from "@/components/rule";
|
* @copyright nhcarrigan
|
||||||
import { Social } from "@/components/social";
|
* @license Naomi's Public License
|
||||||
import { Jobs } from "@/config/Jobs";
|
* @author Naomi Carrigan
|
||||||
import { Donate, HireMe, Socials } from "@/config/Socials";
|
*/
|
||||||
import { Volunteer } from "@/icons/Volunteer";
|
|
||||||
import { faCalendar, faTasks } from "@fortawesome/free-solid-svg-icons";
|
import { faCalendar, faTasks } from "@fortawesome/free-solid-svg-icons";
|
||||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
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 => {
|
const Work = (): JSX.Element => {
|
||||||
return (
|
return (
|
||||||
<>
|
<main className="w-4/5 text-center max-w-4xl m-auto mt-16 mb-16 rounded-lg">
|
||||||
<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>
|
||||||
<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>
|
<p>
|
||||||
We run a software engineering and community management firm known as
|
{`Our work is listed here in reverse chronological order. The symbols
|
||||||
nhcarrigan.
|
and colours have a specific meaning:`}
|
||||||
</p>
|
</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>{`Planned`}</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 />
|
<Rule />
|
||||||
<section>
|
</section>
|
||||||
<h2 className="text-3xl">Legend</h2>
|
<section>
|
||||||
<p>
|
<h2 className="text-3xl">{`Timeline`}</h2>
|
||||||
Our work is listed here in reverse chronological order. The symbols
|
<ol className="relative border-s border-[--primary] w-4/5 m-auto">
|
||||||
and colours have a specific meaning:
|
{Jobs.toSorted((a, b) => {
|
||||||
</p>
|
return b.start.getTime() - a.start.getTime();
|
||||||
<table className="m-auto w-1/2">
|
}).map(
|
||||||
<thead>
|
(job) => {
|
||||||
<tr>
|
return <Job
|
||||||
<th>Symbol</th>
|
company={job.company}
|
||||||
<th>Meaning</th>
|
description={job.description}
|
||||||
</tr>
|
end={job.end}
|
||||||
</thead>
|
key={`${job.title} - ${job.company}`}
|
||||||
<tbody>
|
link={job.link}
|
||||||
<tr>
|
logo={job.logo}
|
||||||
<td>
|
start={job.start}
|
||||||
<FontAwesomeIcon className="h-14" icon={faCalendar} />
|
title={job.title}
|
||||||
</td>
|
type={job.type}
|
||||||
<td>Fixed-Rate Contract (hourly/salary)</td>
|
/>;
|
||||||
</tr>
|
}
|
||||||
<tr>
|
,
|
||||||
<td>
|
)}
|
||||||
<FontAwesomeIcon className="h-14" icon={faTasks} />
|
</ol>
|
||||||
</td>
|
</section>
|
||||||
<td>Project-based Contract</td>
|
</main>
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
<FontAwesomeIcon className="h-14" icon={Volunteer} />
|
|
||||||
</td>
|
|
||||||
<td>Planned</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.sort((a, b) => b.start.getTime() - a.start.getTime()).map(
|
|
||||||
(job) => (
|
|
||||||
<Job
|
|
||||||
key={job.title + " - " + job.company}
|
|
||||||
title={job.title}
|
|
||||||
company={job.company}
|
|
||||||
start={job.start}
|
|
||||||
end={job.end}
|
|
||||||
link={job.link}
|
|
||||||
type={job.type}
|
|
||||||
description={job.description}
|
|
||||||
logo={job.logo}
|
|
||||||
/>
|
|
||||||
),
|
|
||||||
)}
|
|
||||||
</ol>
|
|
||||||
</section>
|
|
||||||
</main>
|
|
||||||
</>
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1,50 +1,75 @@
|
|||||||
import { IconDefinition } from "@fortawesome/fontawesome-svg-core";
|
/**
|
||||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
* @copyright nhcarrigan
|
||||||
import { Rule } from "./rule";
|
* @license Naomi's Public License
|
||||||
|
* @author Naomi Carrigan
|
||||||
|
*/
|
||||||
|
import type { JSX } from "react";
|
||||||
|
|
||||||
interface ActivityProps {
|
interface ActivityProperties {
|
||||||
type: string;
|
readonly type: string;
|
||||||
date: Date;
|
readonly date: Date;
|
||||||
repo: string;
|
readonly repo: string;
|
||||||
repoName: string;
|
readonly repoName: string;
|
||||||
heart: string;
|
readonly heart: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
const TypeToString: Record<string, string> = {
|
const TypeToString: Record<string, string> = {
|
||||||
commit_repo: "committed to",
|
DeleteEvent: "deleted a branch on",
|
||||||
delete_branch: "deleted a branch on",
|
IssueCommentEvent: "commented on",
|
||||||
merge_pull_request: "merged a PR in",
|
IssuesEvent: "created or updated an issue in",
|
||||||
create_pull_request: "created a PR in",
|
PullRequestEvent: "created or merged a PR in",
|
||||||
create_branch: "created a branch in",
|
|
||||||
PushEvent: "committed to",
|
|
||||||
DeleteEvent: "deleted a branch on",
|
|
||||||
PullRequestEvent: "created or merged a PR in",
|
|
||||||
PullRequestReviewEvent: "reviewed a PR in",
|
|
||||||
PullRequestReviewCommentEvent: "commented on a PR in",
|
PullRequestReviewCommentEvent: "commented on a PR in",
|
||||||
IssueCommentEvent: "commented on",
|
PullRequestReviewEvent: "reviewed a PR in",
|
||||||
IssuesEvent: "created or updated an issue in",
|
PushEvent: "committed to",
|
||||||
close_issue: "closed an issue in",
|
close_issue: "closed an issue in",
|
||||||
create_issue: "created 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",
|
||||||
};
|
};
|
||||||
|
|
||||||
export const Activity = (props: ActivityProps): JSX.Element => {
|
const getType = (type: string): string => {
|
||||||
const { type, date, repo, repoName, heart } = props;
|
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 (
|
return (
|
||||||
<li className="ms-6">
|
<li className="ms-6">
|
||||||
<span className="absolute flex items-center justify-center w-6 h-6 rounded-full -start-3">
|
<span
|
||||||
|
className="absolute flex items-center
|
||||||
|
justify-center w-6 h-6 rounded-full -start-3"
|
||||||
|
>
|
||||||
{heart}
|
{heart}
|
||||||
</span>
|
</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">
|
<div
|
||||||
<time className="mb-1 text-xs font-normal text-gray-400 sm:order-last sm:mb-0">
|
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")}
|
{date.toLocaleString("en-GB")}
|
||||||
</time>
|
</time>
|
||||||
<div className="text-sm font-normal text-gray-500 lex dark:text-gray-300">
|
<div
|
||||||
Naomi has {TypeToString[type] ?? "performed a " + type}{" "}
|
className="text-sm font-normal
|
||||||
|
text-gray-500 lex dark:text-gray-300"
|
||||||
|
>
|
||||||
|
{`Naomi has ${getType(type)} `}
|
||||||
<a
|
<a
|
||||||
href={repo}
|
|
||||||
target="_blank"
|
|
||||||
rel="noopener noreferrer"
|
|
||||||
className="font-semibold text-[#abfcec] hover:underline"
|
className="font-semibold text-[#abfcec] hover:underline"
|
||||||
|
href={repo}
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
target="_blank"
|
||||||
>
|
>
|
||||||
{repoName}
|
{repoName}
|
||||||
</a>{" "}
|
</a>{" "}
|
||||||
|
@ -1,30 +1,47 @@
|
|||||||
|
/**
|
||||||
|
* @copyright nhcarrigan
|
||||||
|
* @license Naomi's Public License
|
||||||
|
* @author Naomi Carrigan
|
||||||
|
*/
|
||||||
import Image from "next/image";
|
import Image from "next/image";
|
||||||
|
import type { JSX } from "react";
|
||||||
|
|
||||||
interface ArtProps {
|
interface ArtProperties {
|
||||||
name: string;
|
readonly name: string;
|
||||||
img: string;
|
readonly img: string;
|
||||||
artist: string;
|
readonly artist: string;
|
||||||
url: string;
|
readonly url: string;
|
||||||
alt: string;
|
readonly alt: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const ArtComponent = (props: ArtProps): JSX.Element => {
|
/**
|
||||||
const { name, img, artist, url, alt } = props;
|
* 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 (
|
return (
|
||||||
<div className="w-[300px] h-[300px] border-2 border-solid border-[--foreground] m-auto text-center items-center">
|
<div className="w-[300px] h-[300px] border-2
|
||||||
<p className="text-l">{name} by <a className="underline" href={url} target="_blank" rel="noreferrer">{artist}</a></p>
|
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
|
<a
|
||||||
href={`https://cdn.nhcarrigan.com/art/${img}`}
|
href={`https://cdn.nhcarrigan.com/art/${img}`}
|
||||||
target="_blank"
|
|
||||||
rel="noreferrer"
|
rel="noreferrer"
|
||||||
|
target="_blank"
|
||||||
>
|
>
|
||||||
<Image
|
<Image
|
||||||
src={`https://cdn.nhcarrigan.com/art/${img}`}
|
|
||||||
alt={alt}
|
alt={alt}
|
||||||
width={250}
|
|
||||||
height={250}
|
|
||||||
className="m-auto object-contain max-h-[250px] max-w-[250px]"
|
className="m-auto object-contain max-h-[250px] max-w-[250px]"
|
||||||
|
height={250}
|
||||||
|
src={`https://cdn.nhcarrigan.com/art/${img}`}
|
||||||
|
width={250}
|
||||||
/>
|
/>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,44 +1,48 @@
|
|||||||
import { Volunteer } from "@/icons/Volunteer";
|
/**
|
||||||
import {
|
* @copyright nhcarrigan
|
||||||
faCalendar,
|
* @license Naomi's Public License
|
||||||
faQuestionCircle,
|
* @author Naomi Carrigan
|
||||||
faTasks,
|
*/
|
||||||
} from "@fortawesome/free-solid-svg-icons";
|
|
||||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
|
||||||
import Image from "next/image";
|
import Image from "next/image";
|
||||||
import { useState } from "react";
|
import type { JSX } from "react";
|
||||||
|
|
||||||
interface CertProps {
|
interface CertProperties {
|
||||||
name: string;
|
readonly name: string;
|
||||||
fileName: string;
|
readonly fileName: string;
|
||||||
issuer: string;
|
readonly issuer: string;
|
||||||
date: Date;
|
readonly date: Date;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const Certification = (props: CertProps): JSX.Element => {
|
/**
|
||||||
const { name, fileName, issuer, date } = props;
|
* 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 (
|
return (
|
||||||
<div className="w-[300px] h-[300px] border-2 border-solid border-[--foreground] m-auto text-center items-center">
|
<div className="w-[300px] h-[300px] border-2
|
||||||
|
border-solid border-[--foreground] m-auto text-center items-center">
|
||||||
<p className="text-xl">{name}</p>
|
<p className="text-xl">{name}</p>
|
||||||
<a
|
<a
|
||||||
href={`https://cdn.nhcarrigan.com/certifications/${fileName}`}
|
href={`https://cdn.nhcarrigan.com/certifications/${fileName}`}
|
||||||
target="_blank"
|
|
||||||
rel="noreferrer"
|
rel="noreferrer"
|
||||||
|
target="_blank"
|
||||||
>
|
>
|
||||||
<Image
|
<Image
|
||||||
src={`https://cdn.nhcarrigan.com/certifications/${fileName}`}
|
|
||||||
alt={name}
|
alt={name}
|
||||||
width={250}
|
|
||||||
height={250}
|
|
||||||
className="m-auto"
|
className="m-auto"
|
||||||
|
height={250}
|
||||||
|
src={`https://cdn.nhcarrigan.com/certifications/${fileName}`}
|
||||||
|
width={250}
|
||||||
/>
|
/>
|
||||||
</a>
|
</a>
|
||||||
<p>{issuer}</p>
|
<p>{issuer}</p>
|
||||||
<p>
|
<p>
|
||||||
{date.toLocaleDateString("en-GB", {
|
{date.toLocaleDateString("en-GB", {
|
||||||
month: "long",
|
month: "long",
|
||||||
year: "numeric",
|
year: "numeric",
|
||||||
})}
|
})}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,31 +1,46 @@
|
|||||||
|
/**
|
||||||
|
* @copyright nhcarrigan
|
||||||
|
* @license Naomi's Public License
|
||||||
|
* @author Naomi Carrigan
|
||||||
|
*/
|
||||||
"use client";
|
"use client";
|
||||||
import React from "react";
|
import { faComments } from "@fortawesome/free-solid-svg-icons";
|
||||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||||
import {
|
|
||||||
faComments,
|
|
||||||
} from "@fortawesome/free-solid-svg-icons";
|
|
||||||
import { usePathname } from "next/navigation";
|
import { usePathname } from "next/navigation";
|
||||||
import Script from "next/script";
|
import Script from "next/script";
|
||||||
|
import React, { type JSX } from "react";
|
||||||
|
|
||||||
const Footer = (): JSX.Element => {
|
/**
|
||||||
return (
|
* Conditionally renders the footer component when
|
||||||
<>
|
* not on the home page.
|
||||||
<div className="fixed w-full bottom-0 z-50 flex justify-between items-center h-14 px-4 bg-[--background] text-[--foreground]">
|
* @returns A JSX element.
|
||||||
<p>© Naomi Carrigan</p>
|
*/
|
||||||
<a href="https://chat.nhcarrigan.com" target="_blank" rel="noreferrer">
|
export const Footer = (): JSX.Element | null => {
|
||||||
<FontAwesomeIcon icon={faComments} size="lg" />
|
|
||||||
</a>
|
|
||||||
<div className="h-4/5" id="tree-nation-offset-website"></div>
|
|
||||||
<Script id="tree-nation">{`TreeNationOffsetWebsite({code: 'a17464e0cd351220', lang: 'en', theme: 'dark'}).render('#tree-nation-offset-website');`}</Script>
|
|
||||||
</div>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export function ClientFooter() {
|
|
||||||
const pathname = usePathname();
|
const pathname = usePathname();
|
||||||
const isRootPath = pathname === "/";
|
const isRootPath = pathname === "/";
|
||||||
|
|
||||||
if (isRootPath) return null;
|
if (isRootPath) {
|
||||||
return <Footer />;
|
return null;
|
||||||
}
|
}
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
className="fixed w-full bottom-0 z-50 flex
|
||||||
|
justify-between items-center h-14 px-4
|
||||||
|
bg-[--background] text-[--foreground]"
|
||||||
|
>
|
||||||
|
<p>{`© Naomi Carrigan`}</p>
|
||||||
|
<a href="https://chat.nhcarrigan.com" rel="noreferrer" target="_blank">
|
||||||
|
<FontAwesomeIcon icon={faComments} size="lg" />
|
||||||
|
</a>
|
||||||
|
<div className="h-4/5" id="tree-nation-offset-website"></div>
|
||||||
|
<Script
|
||||||
|
src="https://widgets.tree-nation.com/js/widgets/v1/widgets.min.js?v=1.0"
|
||||||
|
strategy="beforeInteractive"
|
||||||
|
></Script>
|
||||||
|
<Script
|
||||||
|
id="tree-nation"
|
||||||
|
strategy="afterInteractive"
|
||||||
|
>{`TreeNationOffsetWebsite({code: 'a17464e0cd351220', lang: 'en', theme: 'dark'}).render('#tree-nation-offset-website');`}</Script>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
@ -1,36 +1,48 @@
|
|||||||
|
/**
|
||||||
|
* @copyright nhcarrigan
|
||||||
|
* @license Naomi's Public License
|
||||||
|
* @author Naomi Carrigan
|
||||||
|
*/
|
||||||
import Image from "next/image";
|
import Image from "next/image";
|
||||||
|
import type { JSX } from "react";
|
||||||
|
|
||||||
interface GameProps {
|
interface GameProperties {
|
||||||
name: string;
|
readonly name: string;
|
||||||
img: string;
|
readonly img: string;
|
||||||
url: string;
|
readonly url: string;
|
||||||
alt: string;
|
readonly alt: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const Game = (props: GameProps): JSX.Element => {
|
/**
|
||||||
const { name, img, url, alt } = props;
|
* 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 (
|
return (
|
||||||
<div className="w-[300px] h-[300px] border-2 border-solid border-[--foreground] m-auto text-center items-center">
|
<div className="w-[300px] h-[300px] border-2
|
||||||
|
border-solid border-[--foreground] m-auto text-center items-center">
|
||||||
<a
|
<a
|
||||||
href={url}
|
|
||||||
target="_blank"
|
|
||||||
rel="noopener noreferrer"
|
|
||||||
className="text-xl underline"
|
className="text-xl underline"
|
||||||
|
href={url}
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
target="_blank"
|
||||||
>
|
>
|
||||||
<p>{name}</p>
|
<p>{name}</p>
|
||||||
</a>
|
</a>
|
||||||
<a
|
<a
|
||||||
href={`https://cdn.nhcarrigan.com/games/${img}`}
|
href={`https://cdn.nhcarrigan.com/games/${img}`}
|
||||||
target="_blank"
|
|
||||||
rel="noreferrer"
|
rel="noreferrer"
|
||||||
|
target="_blank"
|
||||||
>
|
>
|
||||||
<Image
|
<Image
|
||||||
src={`https://cdn.nhcarrigan.com/games/${img}`}
|
|
||||||
alt={alt}
|
alt={alt}
|
||||||
width={250}
|
|
||||||
height={250}
|
|
||||||
className="m-auto object-contain max-h-[250px] max-w-[250px]"
|
className="m-auto object-contain max-h-[250px] max-w-[250px]"
|
||||||
|
height={250}
|
||||||
|
src={`https://cdn.nhcarrigan.com/games/${img}`}
|
||||||
|
width={250}
|
||||||
/>
|
/>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,85 +1,111 @@
|
|||||||
|
/**
|
||||||
|
* @copyright nhcarrigan
|
||||||
|
* @license Naomi's Public License
|
||||||
|
* @author Naomi Carrigan
|
||||||
|
*/
|
||||||
"use client";
|
"use client";
|
||||||
import { Volunteer } from "@/icons/Volunteer";
|
|
||||||
import {
|
import {
|
||||||
faCalendar,
|
faCalendar,
|
||||||
faQuestionCircle,
|
faQuestionCircle,
|
||||||
faTasks,
|
faTasks,
|
||||||
} from "@fortawesome/free-solid-svg-icons";
|
} from "@fortawesome/free-solid-svg-icons";
|
||||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||||
import { useState } from "react";
|
import { type JSX, useCallback, useState } from "react";
|
||||||
|
import { Volunteer } from "../icons/Volunteer";
|
||||||
|
|
||||||
interface JobProps {
|
interface JobProperties {
|
||||||
title: string;
|
readonly title: string;
|
||||||
company: string;
|
readonly company: string;
|
||||||
start: Date;
|
readonly start: Date;
|
||||||
end: Date | null;
|
readonly end: Date | null;
|
||||||
link: string;
|
readonly link: string;
|
||||||
type: "volunteer" | "fixed" | "project" | "hypothetical";
|
readonly type: "volunteer" | "fixed" | "project" | "hypothetical";
|
||||||
description: string;
|
readonly description: string;
|
||||||
logo: string;
|
readonly logo: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
const IconMap = {
|
const IconMap = {
|
||||||
volunteer: Volunteer,
|
fixed: faCalendar,
|
||||||
fixed: faCalendar,
|
|
||||||
project: faTasks,
|
|
||||||
hypothetical: faQuestionCircle,
|
hypothetical: faQuestionCircle,
|
||||||
|
project: faTasks,
|
||||||
|
volunteer: Volunteer,
|
||||||
};
|
};
|
||||||
|
|
||||||
export const Job = (props: JobProps): JSX.Element => {
|
const getColor
|
||||||
const { title, company, start, end, link, type, description, logo } = props;
|
= (type: JobProperties["type"], end: JobProperties["end"]): string => {
|
||||||
const [showDescription, setShowDescription] = useState(false);
|
if (type === "hypothetical") {
|
||||||
const toggleDescription = () => {
|
return "text-[--primary]";
|
||||||
setShowDescription(!showDescription);
|
}
|
||||||
};
|
if (end) {
|
||||||
const color =
|
return "text-[--former]";
|
||||||
type === "hypothetical"
|
}
|
||||||
? "text-[--primary]"
|
return "text-[--current]";
|
||||||
: end
|
};
|
||||||
? "text-[--former]"
|
|
||||||
: "text-[--current]";
|
|
||||||
const border =
|
|
||||||
type === "hypothetical"
|
|
||||||
? "border-[--primary]"
|
|
||||||
: end
|
|
||||||
? "border-[--former]"
|
|
||||||
: "border-[--current]";
|
|
||||||
|
|
||||||
const borderStyle = end ? "border-dashed border-2" : "border-double border-4";
|
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 (
|
return (
|
||||||
<li className={`mb-10 ms-6 ${color}`}>
|
<li className={`mb-10 ms-6 ${color}`}>
|
||||||
<span
|
<span
|
||||||
className={`absolute flex items-center justify-center w-6 h-6 bg-[--background] rounded-full -start-3 ${color}`}
|
className={`absolute flex items-center justify-center w-6 h-6 bg-[--background] rounded-full -start-3 ${color}`}
|
||||||
>
|
>
|
||||||
<FontAwesomeIcon icon={IconMap[type]} className="text-3xl" />
|
<FontAwesomeIcon className="text-3xl" icon={IconMap[type]} />
|
||||||
</span>
|
</span>
|
||||||
<h3 className={`flex items-center mb-1 text-lg font-semibold`}>
|
<h3 className={`flex items-center mb-1 text-lg font-semibold`}>
|
||||||
{title} for {company}
|
{`${title} for ${company}`}
|
||||||
</h3>
|
</h3>
|
||||||
<time className="block mb-2 text-sm font-normal leading-none">
|
<time className="block mb-2 text-sm font-normal leading-none">
|
||||||
{start.toLocaleDateString("en-US", {
|
{start.toLocaleDateString("en-US", {
|
||||||
month: "long",
|
month: "long",
|
||||||
year: "numeric",
|
year: "numeric",
|
||||||
})}{" "}
|
})}{" - "}
|
||||||
-{" "}
|
|
||||||
{end
|
{end
|
||||||
? end.toLocaleDateString("en-US", {
|
? end.toLocaleDateString("en-US", {
|
||||||
month: "long",
|
month: "long",
|
||||||
year: "numeric",
|
year: "numeric",
|
||||||
})
|
})
|
||||||
: "Present"}
|
: "Present"}
|
||||||
</time>
|
</time>
|
||||||
{showDescription && (
|
{showDescription
|
||||||
<div
|
? <div
|
||||||
className="mb-4 text-base font-normal"
|
className="mb-4 text-base font-normal"
|
||||||
|
// eslint-disable-next-line react/no-danger
|
||||||
dangerouslySetInnerHTML={{ __html: description }}
|
dangerouslySetInnerHTML={{ __html: description }}
|
||||||
></div>
|
></div>
|
||||||
)}
|
: null}
|
||||||
<button
|
<button
|
||||||
onClick={toggleDescription}
|
|
||||||
className={`inline-flex items-center px-4 py-2 text-sm font-medium ${borderStyle} ${border}`}
|
className={`inline-flex items-center px-4 py-2 text-sm font-medium ${borderStyle} ${border}`}
|
||||||
|
onClick={toggleDescription}
|
||||||
|
type="button"
|
||||||
>
|
>
|
||||||
{showDescription ? "Hide Details" : "Show Details"}
|
{showDescription
|
||||||
|
? "Hide Details"
|
||||||
|
: "Show Details"}
|
||||||
</button>
|
</button>
|
||||||
</li>
|
</li>
|
||||||
);
|
);
|
||||||
|
@ -1,27 +1,41 @@
|
|||||||
|
/**
|
||||||
|
* @copyright nhcarrigan
|
||||||
|
* @license Naomi's Public License
|
||||||
|
* @author Naomi Carrigan
|
||||||
|
*/
|
||||||
import Image from "next/image";
|
import Image from "next/image";
|
||||||
import { useState } from "react";
|
import type { JSX } from "react";
|
||||||
|
|
||||||
interface MemberProps {
|
interface MemberProperties {
|
||||||
name: string;
|
readonly name: string;
|
||||||
avatar: string;
|
readonly avatar: string;
|
||||||
role: string;
|
readonly role: string;
|
||||||
url: string;
|
readonly url: string;
|
||||||
joinDate: Date;
|
readonly joinDate: Date;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const Member = (props: MemberProps): JSX.Element => {
|
/**
|
||||||
const { name, avatar, role, url, joinDate } = props;
|
* 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 (
|
return (
|
||||||
<div className="flex items-start gap-2.5 pb-10 w-full">
|
<div className="flex items-start gap-2.5 pb-10 w-full">
|
||||||
<Image
|
<Image
|
||||||
className="rounded-full"
|
|
||||||
src={`https://cdn.nhcarrigan.com/avatars/${avatar}`}
|
|
||||||
alt={`${name}'s avatar.`}
|
alt={`${name}'s avatar.`}
|
||||||
width={75}
|
className="rounded-full"
|
||||||
height={75}
|
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
|
||||||
|
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>
|
<div>
|
||||||
<a
|
<a
|
||||||
className="text-sm font-semibold text-[#abfcec]"
|
className="text-sm font-semibold text-[#abfcec]"
|
||||||
@ -33,7 +47,7 @@ export const Member = (props: MemberProps): JSX.Element => {
|
|||||||
<p className="text-sm font-normal text-gray-500 dark:text-gray-400">
|
<p className="text-sm font-normal text-gray-500 dark:text-gray-400">
|
||||||
{joinDate.toLocaleDateString("en-GB", {
|
{joinDate.toLocaleDateString("en-GB", {
|
||||||
month: "long",
|
month: "long",
|
||||||
year: "numeric",
|
year: "numeric",
|
||||||
})}
|
})}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,84 +1,108 @@
|
|||||||
|
/**
|
||||||
|
* @copyright nhcarrigan
|
||||||
|
* @license Naomi's Public License
|
||||||
|
* @author Naomi Carrigan
|
||||||
|
*/
|
||||||
"use client";
|
"use client";
|
||||||
import React, { useState, useEffect } from "react";
|
|
||||||
import Image from "next/image";
|
|
||||||
import { Rule } from "./rule";
|
|
||||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
|
||||||
import {
|
import {
|
||||||
faBars,
|
faBars,
|
||||||
faTimes,
|
faTimes,
|
||||||
faSun,
|
faSun,
|
||||||
faMoon,
|
faMoon,
|
||||||
} from "@fortawesome/free-solid-svg-icons";
|
} from "@fortawesome/free-solid-svg-icons";
|
||||||
import { NavItems } from "@/config/NavItems";
|
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||||
|
import Image from "next/image";
|
||||||
import { usePathname } from "next/navigation";
|
import { usePathname } from "next/navigation";
|
||||||
|
import React, { type JSX, useState, useEffect, useCallback } from "react";
|
||||||
|
import { NavItems } from "../config/NavItems";
|
||||||
|
import { Rule } from "./rule";
|
||||||
|
|
||||||
const Navigation = (): JSX.Element => {
|
/**
|
||||||
const [isOpen, setIsOpen] = useState(false);
|
* Conditionally renders the navigation component when
|
||||||
const [isDarkMode, setIsDarkMode] = useState(false);
|
* not on the home page.
|
||||||
|
* @returns A JSX element.
|
||||||
|
*/
|
||||||
|
export const Navigation = (): JSX.Element | null => {
|
||||||
|
const [ isOpen, setIsOpen ] = useState(false);
|
||||||
|
const [ isDarkMode, setIsDarkMode ] = useState(false);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const savedTheme = localStorage.getItem("theme");
|
const storedTheme = localStorage.getItem("theme");
|
||||||
const prefersDark = window.matchMedia(
|
if (storedTheme === "dark") {
|
||||||
"(prefers-color-scheme: dark)",
|
document.documentElement.classList.add("dark");
|
||||||
).matches;
|
setIsDarkMode(true);
|
||||||
const isDark = savedTheme === "dark" || (!savedTheme && prefersDark);
|
} else {
|
||||||
document.documentElement.classList.toggle("dark", isDark);
|
document.documentElement.classList.remove("dark");
|
||||||
setIsDarkMode(isDark);
|
setIsDarkMode(false);
|
||||||
|
}
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const toggleMenu = () => {
|
const toggleMenu = useCallback((): void => {
|
||||||
setIsOpen(!isOpen);
|
setIsOpen(!isOpen);
|
||||||
};
|
}, [ isOpen ]);
|
||||||
|
|
||||||
const toggleDarkMode = () => {
|
const toggleDarkMode = useCallback((): void => {
|
||||||
document.documentElement.classList.toggle("dark", !isDarkMode);
|
document.documentElement.classList.toggle("dark", !isDarkMode);
|
||||||
localStorage.setItem("theme", !isDarkMode ? "dark" : "light");
|
localStorage.setItem("theme", isDarkMode
|
||||||
|
? "light"
|
||||||
|
: "dark");
|
||||||
setIsDarkMode(!isDarkMode);
|
setIsDarkMode(!isDarkMode);
|
||||||
};
|
}, [ isDarkMode ]);
|
||||||
|
|
||||||
|
const pathname = usePathname();
|
||||||
|
const isRootPath = pathname === "/";
|
||||||
|
|
||||||
|
if (isRootPath) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="fixed w-full top-0 z-50">
|
<div className="fixed w-full top-0 z-50">
|
||||||
<nav className="w-full flex justify-between items-center h-14 px-4 bg-[--background] text-[--foreground]">
|
<nav
|
||||||
|
className="w-full flex justify-between
|
||||||
|
items-center h-14 px-4 bg-[--background] text-[--foreground]"
|
||||||
|
>
|
||||||
<a href="/">
|
<a href="/">
|
||||||
<Image
|
<Image
|
||||||
src="https://cdn.nhcarrigan.com/logo.png"
|
|
||||||
alt="nhcarrigan's logo"
|
alt="nhcarrigan's logo"
|
||||||
width={50}
|
|
||||||
height={50}
|
height={50}
|
||||||
|
src="https://cdn.nhcarrigan.com/logo.png"
|
||||||
|
width={50}
|
||||||
/>
|
/>
|
||||||
</a>
|
</a>
|
||||||
<div className="flex items-center">
|
<div className="flex items-center">
|
||||||
<button onClick={toggleDarkMode} className="mr-4">
|
<button className="mr-4" onClick={toggleDarkMode} type="button">
|
||||||
<FontAwesomeIcon icon={isDarkMode ? faSun : faMoon} size="lg" />
|
<FontAwesomeIcon icon={isDarkMode
|
||||||
|
? faSun
|
||||||
|
: faMoon} size="lg" />
|
||||||
</button>
|
</button>
|
||||||
<button onClick={toggleMenu}>
|
<button onClick={toggleMenu} type="button">
|
||||||
<FontAwesomeIcon icon={isOpen ? faTimes : faBars} size="2x" />
|
<FontAwesomeIcon icon={isOpen
|
||||||
|
? faTimes
|
||||||
|
: faBars} size="2x" />
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
{isOpen && (
|
{isOpen
|
||||||
<div className="bg-[--background] text-[--foreground]">
|
? <div className="bg-[--background] text-[--foreground]">
|
||||||
{NavItems.map((item, index) => (
|
{NavItems.map((item, index) => {
|
||||||
<a
|
return (
|
||||||
key={item.href}
|
<a
|
||||||
href={item.href}
|
className="block py-2 px-4 text-2xl hover:bg-[--foreground]
|
||||||
className="block py-2 px-4 text-2xl hover:bg-[--foreground] hover:text-[--background]"
|
hover:text-[--background]"
|
||||||
onClick={() => setIsOpen(false)}
|
href={item.href}
|
||||||
>
|
key={item.href}
|
||||||
{index % 2 ? "🩷" : "🩵"} {item.text}
|
onClick={toggleMenu}
|
||||||
</a>
|
>
|
||||||
))}
|
{index % 2 === 1
|
||||||
|
? "🩷"
|
||||||
|
: "🩵"} {item.text}
|
||||||
|
</a>
|
||||||
|
);
|
||||||
|
})}
|
||||||
</div>
|
</div>
|
||||||
)}
|
: null}
|
||||||
<Rule />
|
<Rule />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export function ClientNavigation() {
|
|
||||||
const pathname = usePathname();
|
|
||||||
const isRootPath = pathname === "/";
|
|
||||||
|
|
||||||
if (isRootPath) return null;
|
|
||||||
return <Navigation />;
|
|
||||||
}
|
|
||||||
|
@ -1,27 +1,39 @@
|
|||||||
|
/**
|
||||||
|
* @copyright nhcarrigan
|
||||||
|
* @license Naomi's Public License
|
||||||
|
* @author Naomi Carrigan
|
||||||
|
*/
|
||||||
import Image from "next/image";
|
import Image from "next/image";
|
||||||
import { useState } from "react";
|
import type { JSX } from "react";
|
||||||
|
|
||||||
interface PartnerProps {
|
interface PartnerProperties {
|
||||||
name: string;
|
readonly name: string;
|
||||||
avatar: string;
|
readonly avatar: string;
|
||||||
relationship: string;
|
readonly relationship: string;
|
||||||
url: string;
|
readonly url: string;
|
||||||
anniversary: Date;
|
readonly anniversary: Date;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const Partner = (props: PartnerProps): JSX.Element => {
|
/**
|
||||||
const { name, avatar, relationship, url, anniversary } = props;
|
* 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 (
|
return (
|
||||||
<div className="flex items-start gap-2.5 pb-10 w-full">
|
<div className="flex items-start gap-2.5 pb-10 w-full">
|
||||||
<Image
|
<Image
|
||||||
className="rounded-full"
|
|
||||||
src={`https://cdn.nhcarrigan.com/avatars/${avatar}`}
|
|
||||||
alt={`${name}'s avatar.`}
|
alt={`${name}'s avatar.`}
|
||||||
width={75}
|
className="rounded-full"
|
||||||
height={75}
|
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 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>
|
<div>
|
||||||
<a
|
<a
|
||||||
className="text-sm font-semibold text-[#abfcec]"
|
className="text-sm font-semibold text-[#abfcec]"
|
||||||
@ -32,9 +44,9 @@ export const Partner = (props: PartnerProps): JSX.Element => {
|
|||||||
</a>
|
</a>
|
||||||
<p className="text-sm font-normal text-gray-500 dark:text-gray-400">
|
<p className="text-sm font-normal text-gray-500 dark:text-gray-400">
|
||||||
{anniversary.toLocaleDateString("en-GB", {
|
{anniversary.toLocaleDateString("en-GB", {
|
||||||
|
day: "numeric",
|
||||||
month: "long",
|
month: "long",
|
||||||
year: "numeric",
|
year: "numeric",
|
||||||
day: "numeric",
|
|
||||||
})}
|
})}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,39 +1,54 @@
|
|||||||
import { IconDefinition } from "@fortawesome/fontawesome-svg-core";
|
/**
|
||||||
|
* @copyright nhcarrigan
|
||||||
|
* @license Naomi's Public License
|
||||||
|
* @author Naomi Carrigan
|
||||||
|
*/
|
||||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||||
import { Rule } from "./rule";
|
import { Rule } from "./rule";
|
||||||
|
import type { IconDefinition } from "@fortawesome/fontawesome-svg-core";
|
||||||
|
import type { JSX } from "react";
|
||||||
|
|
||||||
interface ReviewProps {
|
interface ReviewProperties {
|
||||||
name: string;
|
readonly name: string;
|
||||||
date: Date;
|
readonly date: Date;
|
||||||
content: string;
|
readonly content: string;
|
||||||
sourceIcon: IconDefinition;
|
readonly sourceIcon: IconDefinition;
|
||||||
sourceUrl: string;
|
readonly sourceUrl: string;
|
||||||
sourceName: string;
|
readonly sourceName: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const Review = (props: ReviewProps): JSX.Element => {
|
/**
|
||||||
const { name, date, content, sourceIcon, sourceUrl, sourceName } = props;
|
* 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 (
|
return (
|
||||||
<li className="mb-10 ms-6">
|
<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">
|
<span className="absolute flex items-center justify-center
|
||||||
|
w-6 h-6 bg-[--background] text-[--foreground] rounded-full -start-3">
|
||||||
<FontAwesomeIcon icon={sourceIcon} />
|
<FontAwesomeIcon icon={sourceIcon} />
|
||||||
</span>
|
</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">
|
<div className="items-center justify-between p-4 bg-white
|
||||||
<time className="mb-1 text-xs font-normal text-gray-400 sm:order-last sm:mb-0">
|
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")}
|
{date.toLocaleDateString("en-GB")}
|
||||||
</time>
|
</time>
|
||||||
<div className="text-md font-normal text-gray-500 dark:text-gray-300">
|
<div className="text-md font-normal text-gray-500 dark:text-gray-300">
|
||||||
Review from{" "}
|
{`Review from `}
|
||||||
<a
|
<a
|
||||||
href={sourceUrl}
|
|
||||||
target="_blank"
|
|
||||||
rel="noopener noreferrer"
|
|
||||||
className="font-semibold text-[#abfcec] hover:underline"
|
className="font-semibold text-[#abfcec] hover:underline"
|
||||||
|
href={sourceUrl}
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
target="_blank"
|
||||||
>
|
>
|
||||||
{name}
|
{name}
|
||||||
</a>{" "}
|
</a>{` via `}
|
||||||
via{" "}
|
<span className="bg-gray-100 text-gray-800 text-xs font-normal
|
||||||
<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">
|
me-2 px-2.5 py-0.5 rounded dark:bg-gray-600 dark:text-gray-300">
|
||||||
{sourceName}
|
{sourceName}
|
||||||
</span>
|
</span>
|
||||||
<Rule />
|
<Rule />
|
||||||
|
@ -1,5 +1,14 @@
|
|||||||
import styles from "./rule.module.css";
|
/**
|
||||||
|
* @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 => {
|
export const Rule = (): JSX.Element => {
|
||||||
return <hr className="border-dashed border-2 border-[--primary-color]"></hr>;
|
return <hr className="border-dashed border-2 border-[--primary-color]"></hr>;
|
||||||
};
|
};
|
||||||
|
@ -1,32 +1,44 @@
|
|||||||
import { IconDefinition } from "@fortawesome/fontawesome-svg-core";
|
/**
|
||||||
|
* @copyright nhcarrigan
|
||||||
|
* @license Naomi's Public License
|
||||||
|
* @author Naomi Carrigan
|
||||||
|
*/
|
||||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||||
|
import type { IconDefinition } from "@fortawesome/fontawesome-svg-core";
|
||||||
|
import type { JSX } from "react";
|
||||||
|
|
||||||
interface SocialProps {
|
interface SocialProperties {
|
||||||
icon: IconDefinition;
|
readonly icon: IconDefinition;
|
||||||
link: string;
|
readonly link: string;
|
||||||
label: string;
|
readonly label: string;
|
||||||
alt: string;
|
readonly alt: string;
|
||||||
color: string;
|
readonly color: string;
|
||||||
background: string;
|
readonly background: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const Social = (props: SocialProps): JSX.Element => {
|
/**
|
||||||
const { icon, link, label, alt, background, color } = props;
|
* 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 (
|
return (
|
||||||
<a
|
<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"
|
|
||||||
style={{
|
|
||||||
borderColor: color,
|
|
||||||
color,
|
|
||||||
background,
|
|
||||||
}}
|
|
||||||
href={link}
|
|
||||||
target="_blank"
|
|
||||||
rel="noreferrer"
|
|
||||||
aria-label={label}
|
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 icon={icon} aria-label={alt} size="3x" />
|
<FontAwesomeIcon aria-label={alt} icon={icon} size="3x" />
|
||||||
<strong>{label}</strong>
|
<strong>{label}</strong>
|
||||||
</a>
|
</a>
|
||||||
);
|
);
|
||||||
|
@ -1,85 +1,94 @@
|
|||||||
export const Art: {
|
/**
|
||||||
name: string;
|
* @copyright nhcarrigan
|
||||||
img: string;
|
* @license Naomi's Public License
|
||||||
artist: string;
|
* @author Naomi Carrigan
|
||||||
url: string;
|
*/
|
||||||
alt: string;
|
|
||||||
}[] = [
|
/**
|
||||||
{
|
* List of art to render.
|
||||||
name: "Avatar",
|
*/
|
||||||
img: "profile.png",
|
export const Art: Array<{
|
||||||
artist: "Jazzybee",
|
name: string;
|
||||||
url: "https://jazzybee.itch.io/sdvcharactercreator",
|
img: 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: string;
|
||||||
},
|
url: string;
|
||||||
{
|
alt: string;
|
||||||
name: "AI Bot",
|
}> = [
|
||||||
img: "ai-bot.png",
|
{
|
||||||
artist: "Picrew",
|
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.",
|
||||||
url: "https://picrew.me/en/image_maker/1382748",
|
artist: "Jazzybee",
|
||||||
alt: "Anime-style illustration of a character wearing a large brown witch hat decorated with roses and hanging charms against a cloudy background."
|
img: "profile.png",
|
||||||
},
|
name: "Avatar",
|
||||||
{
|
url: "https://jazzybee.itch.io/sdvcharactercreator",
|
||||||
name: "Mod Bot",
|
},
|
||||||
img: "mod-bot.png",
|
{
|
||||||
artist: "Picrew",
|
alt: "Anime-style illustration of a character wearing a large brown witch hat decorated with roses and hanging charms against a cloudy background.",
|
||||||
url: "https://picrew.me/en/image_maker/27700",
|
artist: "Picrew",
|
||||||
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."
|
img: "ai-bot.png",
|
||||||
},
|
name: "AI Bot",
|
||||||
{
|
url: "https://picrew.me/en/image_maker/1382748",
|
||||||
name: "Translation Bot",
|
},
|
||||||
img: "translation-bot.png",
|
{
|
||||||
artist: "Picrew",
|
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.",
|
||||||
url: "https://picrew.me/en/image_maker/3595",
|
artist: "Picrew",
|
||||||
alt: "Anime-style portrait of a character with wavy brown hair, glasses, and a black lacy top, winking and smiling"
|
img: "mod-bot.png",
|
||||||
},
|
name: "Mod Bot",
|
||||||
{
|
url: "https://picrew.me/en/image_maker/27700",
|
||||||
name: "Task Bot",
|
},
|
||||||
img: "task-bot.png",
|
{
|
||||||
artist: "Picrew",
|
alt: "Anime-style portrait of a character with wavy brown hair, glasses, and a black lacy top, winking and smiling",
|
||||||
url: "https://picrew.me/en/image_maker/700620",
|
artist: "Picrew",
|
||||||
alt: "Anime-style character with brown hair and glasses wearing a teal hat and shirt with a heart design, smiling excitedly"
|
img: "translation-bot.png",
|
||||||
},
|
name: "Translation Bot",
|
||||||
{
|
url: "https://picrew.me/en/image_maker/3595",
|
||||||
name: "Boost Monitor Bot",
|
},
|
||||||
img: "boost-bot.png",
|
{
|
||||||
artist: "Picrew",
|
alt: "Anime-style character with brown hair and glasses wearing a teal hat and shirt with a heart design, smiling excitedly",
|
||||||
url: "https://picrew.me/en/image_maker/1310292",
|
artist: "Picrew",
|
||||||
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."
|
img: "task-bot.png",
|
||||||
},
|
name: "Task Bot",
|
||||||
{
|
url: "https://picrew.me/en/image_maker/700620",
|
||||||
name: "Social Media Bridge",
|
},
|
||||||
img: "bridge.png",
|
{
|
||||||
artist: "Picrew",
|
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.",
|
||||||
url: "https://picrew.me/en/image_maker/21208",
|
artist: "Picrew",
|
||||||
alt: "Anime-style portrait of a character with blonde and black hair, blushing cheeks, and teary blue eyes, smiling against a turquoise background."
|
img: "boost-bot.png",
|
||||||
},
|
name: "Boost Monitor Bot",
|
||||||
{
|
url: "https://picrew.me/en/image_maker/1310292",
|
||||||
name: "Trick or Treat",
|
},
|
||||||
img: "trick-or-treat.png",
|
{
|
||||||
artist: "Picrew",
|
alt: "Anime-style portrait of a character with blonde and black hair, blushing cheeks, and teary blue eyes, smiling against a turquoise background.",
|
||||||
url: "https://picrew.me/en/image_maker/1712061",
|
artist: "Picrew",
|
||||||
alt: "Gothic anime-style portrait of a character with purple eyeshadow, spider hair clip, and choker necklace in a forest setting"
|
img: "bridge.png",
|
||||||
},
|
name: "Social Media Bridge",
|
||||||
{
|
url: "https://picrew.me/en/image_maker/21208",
|
||||||
name: "Padoru",
|
},
|
||||||
img: "padoru.png",
|
{
|
||||||
artist: "Picrew",
|
alt: "Gothic anime-style portrait of a character with purple eyeshadow, spider hair clip, and choker necklace in a forest setting",
|
||||||
url: "https://picrew.me/en/image_maker/1843743",
|
artist: "Picrew",
|
||||||
alt: "Cartoon character in a blue winter outfit with a pointed hat, holding a bloody sack, against a pink snowflake background"
|
img: "trick-or-treat.png",
|
||||||
},
|
name: "Trick or Treat",
|
||||||
{
|
url: "https://picrew.me/en/image_maker/1712061",
|
||||||
name: "Trans Pride",
|
},
|
||||||
img: "trans.png",
|
{
|
||||||
artist: "Picrew",
|
alt: "Cartoon character in a blue winter outfit with a pointed hat, holding a bloody sack, against a pink snowflake background",
|
||||||
url: "https://picrew.me/en/image_maker/100365/",
|
artist: "Picrew",
|
||||||
alt: "Cartoon portrait of a character with brown hair and glasses, smiling against a transgender flag heart background"
|
img: "padoru.png",
|
||||||
},
|
name: "Padoru",
|
||||||
{
|
url: "https://picrew.me/en/image_maker/1843743",
|
||||||
name: "Alt-text Generator",
|
},
|
||||||
img: "alt-text.png",
|
{
|
||||||
artist: "Picrew",
|
alt: "Cartoon portrait of a character with brown hair and glasses, smiling against a transgender flag heart background",
|
||||||
url: "https://picrew.me/en/image_maker/2003689/",
|
artist: "Picrew",
|
||||||
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."
|
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/",
|
||||||
|
},
|
||||||
|
];
|
||||||
|
@ -1,97 +1,106 @@
|
|||||||
export const Certifications: {
|
/**
|
||||||
name: string;
|
* @copyright nhcarrigan
|
||||||
|
* @license Naomi's Public License
|
||||||
|
* @author Naomi Carrigan
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* List of certifications to render.
|
||||||
|
*/
|
||||||
|
export const Certifications: Array<{
|
||||||
|
name: string;
|
||||||
fileName: string;
|
fileName: string;
|
||||||
issuer: string;
|
issuer: string;
|
||||||
date: Date;
|
date: Date;
|
||||||
}[] = [
|
}> = [
|
||||||
{
|
{
|
||||||
name: "Responsive Web Design",
|
date: new Date("April 17 2020"),
|
||||||
fileName: "responsive-web-design.png",
|
fileName: "responsive-web-design.png",
|
||||||
issuer: "freeCodeCamp",
|
issuer: "freeCodeCamp",
|
||||||
date: new Date("April 17 2020")
|
name: "Responsive Web Design",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "JavaScript Algorithms and Data Structures",
|
date: new Date("April 24, 2020"),
|
||||||
fileName: "javascript.png",
|
fileName: "javascript.png",
|
||||||
issuer: "freeCodeCamp",
|
issuer: "freeCodeCamp",
|
||||||
date: new Date("April 24, 2020")
|
name: "JavaScript Algorithms and Data Structures",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Front End Libraries",
|
date: new Date("April 28, 2020"),
|
||||||
fileName: "front-end-libs.png",
|
fileName: "front-end-libs.png",
|
||||||
issuer: "freeCodeCamp",
|
issuer: "freeCodeCamp",
|
||||||
date: new Date("April 28, 2020")
|
name: "Front End Libraries",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Information Security and Quality Assurance",
|
date: new Date("May 19, 2020"),
|
||||||
fileName: "infosec.png",
|
fileName: "infosec.png",
|
||||||
issuer: "freeCodeCamp",
|
issuer: "freeCodeCamp",
|
||||||
date: new Date("May 19, 2020")
|
name: "Information Security and Quality Assurance",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Full Stack Developer",
|
date: new Date("May 25, 2020"),
|
||||||
fileName: "legacy-full-stack.png",
|
fileName: "legacy-full-stack.png",
|
||||||
issuer: "freeCodeCamp",
|
issuer: "freeCodeCamp",
|
||||||
date: new Date("May 25, 2020")
|
name: "Full Stack Developer",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Data Visualisation",
|
date: new Date("May 25, 2020"),
|
||||||
fileName: "data-visualisation.png",
|
fileName: "data-visualisation.png",
|
||||||
issuer: "freeCodeCamp",
|
issuer: "freeCodeCamp",
|
||||||
date: new Date("May 25, 2020")
|
name: "Data Visualisation",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Back End Development and APIs",
|
date: new Date("May 8 2020"),
|
||||||
fileName: "back-end-dev.png",
|
fileName: "back-end-dev.png",
|
||||||
issuer: "freeCodeCamp",
|
issuer: "freeCodeCamp",
|
||||||
date: new Date("May 8 2020")
|
name: "Back End Development and APIs",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Quality Assurance",
|
date: new Date("July 3 2020"),
|
||||||
fileName: "quality-assurance.png",
|
fileName: "quality-assurance.png",
|
||||||
issuer: "freeCodeCamp",
|
issuer: "freeCodeCamp",
|
||||||
date: new Date("July 3 2020")
|
name: "Quality Assurance",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Legacy Front End",
|
date: new Date("August 14 2020"),
|
||||||
fileName: "legacy-front-end.png",
|
fileName: "legacy-front-end.png",
|
||||||
issuer: "freeCodeCamp",
|
issuer: "freeCodeCamp",
|
||||||
date: new Date("August 14 2020")
|
name: "Legacy Front End",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Scientific Computing with Python",
|
date: new Date("July 3, 2020"),
|
||||||
fileName: "scientific-computing.png",
|
fileName: "scientific-computing.png",
|
||||||
issuer: "freeCodeCamp",
|
issuer: "freeCodeCamp",
|
||||||
date: new Date("July 3, 2020")
|
name: "Scientific Computing with Python",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Node.js Developer",
|
date: new Date("May 9 2024"),
|
||||||
fileName: "mongo-nodejs.jpg",
|
fileName: "mongo-nodejs.jpg",
|
||||||
issuer: "MongoDB",
|
issuer: "MongoDB",
|
||||||
date: new Date("May 9 2024")
|
name: "Node.js Developer",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Self-Managed Database Admin",
|
date: new Date("May 9 2024"),
|
||||||
fileName: "mongo-self-admin.jpg",
|
fileName: "mongo-self-admin.jpg",
|
||||||
issuer: "MongoDB",
|
issuer: "MongoDB",
|
||||||
date: new Date("May 9 2024")
|
name: "Self-Managed Database Admin",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Data Modelling",
|
date: new Date("May 9 2024"),
|
||||||
fileName: "mongo-data-model.jpg",
|
fileName: "mongo-data-model.jpg",
|
||||||
issuer: "MongoDB",
|
issuer: "MongoDB",
|
||||||
date: new Date("May 9 2024")
|
name: "Data Modelling",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Atlas Database Admin",
|
date: new Date("May 9 2024"),
|
||||||
fileName: "mongo-atlas-admin.jpg",
|
fileName: "mongo-atlas-admin.jpg",
|
||||||
issuer: "MongoDB",
|
issuer: "MongoDB",
|
||||||
date: new Date("May 9 2024")
|
name: "Atlas Database Admin",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "E-Commerce Modernisation and Personalisation",
|
date: new Date("May 9 2024"),
|
||||||
fileName: "ecommerce-retail.jpg",
|
fileName: "ecommerce-retail.jpg",
|
||||||
issuer: "MongoDB",
|
issuer: "MongoDB",
|
||||||
date: new Date("May 9 2024")
|
name: "E-Commerce Modernisation and Personalisation",
|
||||||
}
|
},
|
||||||
];
|
];
|
||||||
|
@ -1,109 +1,118 @@
|
|||||||
export const Games: {
|
/**
|
||||||
|
* @copyright nhcarrigan
|
||||||
|
* @license Naomi's Public License
|
||||||
|
* @author Naomi Carrigan
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* List of screenshots from games to render.
|
||||||
|
*/
|
||||||
|
export const Games: Array<{
|
||||||
name: string;
|
name: string;
|
||||||
img: string;
|
img: string;
|
||||||
url: string;
|
url: string;
|
||||||
alt: 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",
|
name: "Bloody Spell",
|
||||||
img: "bloody-spell.jpg",
|
url: "https://store.steampowered.com/app/992300/_Bloody_Spell/",
|
||||||
url: "https://store.steampowered.com/app/992300/_Bloody_Spell/",
|
|
||||||
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."
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
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",
|
name: "Dynasty Warriors 9: Empires",
|
||||||
img: "dw-9.jpg",
|
url: "https://store.steampowered.com/app/1341200/DYNASTY_WARRIORS_9_Empires/",
|
||||||
url: "https://store.steampowered.com/app/1341200/DYNASTY_WARRIORS_9_Empires/",
|
|
||||||
alt: "Animated character in a purple traditional Chinese robe wielding a large sword in a wooden temple-like structure with ornate pillars and lanterns."
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
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",
|
name: "Soul Calibur VI",
|
||||||
img: "soul-calibur.jpg",
|
url: "https://store.steampowered.com/app/544750/SOULCALIBUR_VI/",
|
||||||
url: "https://store.steampowered.com/app/544750/SOULCALIBUR_VI/",
|
|
||||||
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."
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
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",
|
name: "Star Wars: The Old Republic",
|
||||||
img: "swtor.jpg",
|
url: "https://store.steampowered.com/app/1286830/STAR_WARS_The_Old_Republic/",
|
||||||
url: "https://store.steampowered.com/app/1286830/STAR_WARS_The_Old_Republic/",
|
|
||||||
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."
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
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",
|
name: "Idling to Rule the Gods",
|
||||||
img: "idling-god.png",
|
url: "https://store.steampowered.com/app/466170/Idling_to_Rule_the_Gods/",
|
||||||
url: "https://store.steampowered.com/app/466170/Idling_to_Rule_the_Gods/",
|
|
||||||
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."
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
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",
|
name: "Nioh 2",
|
||||||
img: "nioh-2.jpg",
|
url: "https://store.steampowered.com/app/1325200/Nioh_2__The_Complete_Edition/",
|
||||||
url: "https://store.steampowered.com/app/1325200/Nioh_2__The_Complete_Edition/",
|
|
||||||
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."
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
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",
|
name: "Deathly Stillness",
|
||||||
img: "deathly-stillness.jpg",
|
url: "https://store.steampowered.com/app/1727650/Deathly_Stillness/",
|
||||||
url: "https://store.steampowered.com/app/1727650/Deathly_Stillness/",
|
|
||||||
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."
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
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",
|
name: "Once Human",
|
||||||
img: "once-human.jpg",
|
url: "https://store.steampowered.com/app/2139460/Once_Human/",
|
||||||
url: "https://store.steampowered.com/app/2139460/Once_Human/",
|
|
||||||
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."
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
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",
|
name: "Fallout 4",
|
||||||
img: "fallout-4.jpg",
|
url: "https://store.steampowered.com/app/377160/Fallout_4/",
|
||||||
url: "https://store.steampowered.com/app/377160/Fallout_4/",
|
|
||||||
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."
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
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",
|
name: "Guild Wars 2",
|
||||||
img: "gw2.png",
|
url: "https://store.steampowered.com/app/1284210/Guild_Wars_2/",
|
||||||
url: "https://store.steampowered.com/app/1284210/Guild_Wars_2/",
|
|
||||||
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."
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
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",
|
name: "Neverwinter Nights",
|
||||||
img: "nwn.jpg",
|
url: "https://store.steampowered.com/app/704450/Neverwinter_Nights_Enhanced_Edition/",
|
||||||
url: "https://store.steampowered.com/app/704450/Neverwinter_Nights_Enhanced_Edition/",
|
|
||||||
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."
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
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",
|
name: "Lords of the Fallen",
|
||||||
img: "lords-of-the-fallen.jpg",
|
url: "https://store.steampowered.com/app/1501750/Lords_of_the_Fallen/",
|
||||||
url: "https://store.steampowered.com/app/1501750/Lords_of_the_Fallen/",
|
|
||||||
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."
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
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",
|
name: "VRoid",
|
||||||
img: "vroid.png",
|
url: "https://store.steampowered.com/app/1486350/VRoid_Studio_v1294/",
|
||||||
url: "https://store.steampowered.com/app/1486350/VRoid_Studio_v1294/",
|
|
||||||
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."
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
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",
|
name: "Koikatsu",
|
||||||
img: "koikatsu.png",
|
url: "https://store.steampowered.com/app/1073440/__Koikatsu_Party/",
|
||||||
url: "https://store.steampowered.com/app/1073440/__Koikatsu_Party/",
|
|
||||||
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."
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
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",
|
name: "Kingdoms of Amalur",
|
||||||
img: "amalur.jpg",
|
url: "https://store.steampowered.com/app/1041720/Kingdoms_of_Amalur_ReReckoning/",
|
||||||
url: "https://store.steampowered.com/app/1041720/Kingdoms_of_Amalur_ReReckoning/",
|
|
||||||
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."
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
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",
|
name: "Encased",
|
||||||
img: "encased.jpg",
|
url: "https://store.steampowered.com/app/921800/Encased_A_SciFi_PostApocalyptic_RPG/",
|
||||||
url: "https://store.steampowered.com/app/921800/Encased_A_SciFi_PostApocalyptic_RPG/",
|
|
||||||
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."
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
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",
|
name: "Demonologist",
|
||||||
img: "demonologist.jpg",
|
url: "https://store.steampowered.com/app/1929610/Demonologist/",
|
||||||
url: "https://store.steampowered.com/app/1929610/Demonologist/",
|
},
|
||||||
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."
|
|
||||||
}
|
|
||||||
];
|
];
|
||||||
|
@ -1,75 +1,81 @@
|
|||||||
export const Jobs: {
|
/**
|
||||||
title: string;
|
* @copyright nhcarrigan
|
||||||
|
* @license Naomi's Public License
|
||||||
|
* @author Naomi Carrigan
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* List of professional work to render.
|
||||||
|
*/
|
||||||
|
export const Jobs: Array<{
|
||||||
|
title: string;
|
||||||
company: string;
|
company: string;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set ALL dates to the 5th. These are not exact days, but intended to avoid month discrepancies
|
* Set ALL dates to the 5th. These are not exact days, but intended to avoid month discrepancies
|
||||||
* when dealing with timezones.
|
* when dealing with timezones.
|
||||||
*/
|
*/
|
||||||
start: Date;
|
start: Date;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set ALL dates to the 5th. These are not exact days, but intended to avoid month discrepancies
|
* Set ALL dates to the 5th. These are not exact days, but intended to avoid month discrepancies
|
||||||
* when dealing with timezones.
|
* when dealing with timezones.
|
||||||
*/
|
*/
|
||||||
end: Date | null;
|
end: Date | null;
|
||||||
link: string;
|
link: string;
|
||||||
type: "volunteer" | "fixed" | "project" | "hypothetical";
|
type: "volunteer" | "fixed" | "project" | "hypothetical";
|
||||||
description: string;
|
description: string;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* File name of logo.
|
* File name of logo.
|
||||||
*/
|
*/
|
||||||
logo: string;
|
logo: string;
|
||||||
}[] = [
|
}> = [
|
||||||
{
|
{
|
||||||
title: "Consultant",
|
company: "Your Company!",
|
||||||
company: "Your Company!",
|
|
||||||
start: new Date(Date.now()),
|
|
||||||
end: null,
|
|
||||||
link: "https://topmate.io/nhcarrigan/913920",
|
|
||||||
type: "hypothetical",
|
|
||||||
logo: "future.jpeg",
|
|
||||||
description: `You could be our next client! Hit the "Contact" link and use the "Hire Us" button to get in touch!`,
|
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",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "Started Journey",
|
|
||||||
company: "nhcarrigan",
|
company: "nhcarrigan",
|
||||||
start: new Date("April 5 2020"),
|
|
||||||
end: null,
|
|
||||||
link: "https://naomi.lgbt",
|
|
||||||
type: "hypothetical",
|
|
||||||
logo: "nhcarrigan.jpeg",
|
|
||||||
description:
|
description:
|
||||||
"Began my journey learning to code, starting from the top of the freeCodeCamp curriculum.",
|
"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",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "Development Lead",
|
company: "Artists For Palestine",
|
||||||
company: "Artists For Palestine",
|
|
||||||
start: new Date("November 5 2023"),
|
|
||||||
end: null,
|
|
||||||
link: "https://art4palestine.org",
|
|
||||||
type: "volunteer",
|
|
||||||
logo: "a4p.jpeg",
|
|
||||||
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.
|
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.`,
|
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",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "Community Moderator",
|
company: "AngelRose",
|
||||||
company: "AngelRose",
|
|
||||||
start: new Date("September 5 2023"),
|
|
||||||
end: null,
|
|
||||||
link: "https://discord.gg/kYpjgEB",
|
|
||||||
type: "volunteer",
|
|
||||||
logo: "angel.png",
|
|
||||||
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.`,
|
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",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "Community Bot Engineer",
|
company: "Deepgram",
|
||||||
company: "Deepgram",
|
|
||||||
start: new Date("July 5 2023"),
|
|
||||||
end: new Date("June 4 2024"),
|
|
||||||
link: "https://deepgram.com",
|
|
||||||
type: "project",
|
|
||||||
logo: "deepgram.jpeg",
|
|
||||||
description: `<div class="pl-4">
|
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>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>
|
||||||
|
|
||||||
@ -112,15 +118,15 @@ Additionally, I guided and mentored other developers in the design and coding of
|
|||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>`,
|
</div>`,
|
||||||
|
end: new Date("June 4 2024"),
|
||||||
|
link: "https://deepgram.com",
|
||||||
|
logo: "deepgram.jpeg",
|
||||||
|
start: new Date("July 5 2023"),
|
||||||
|
title: "Community Bot Engineer",
|
||||||
|
type: "project",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "Twitch Integration Engineer",
|
company: "BigBadBeaver Productions",
|
||||||
company: "BigBadBeaver Productions",
|
|
||||||
start: new Date("May 5 2023"),
|
|
||||||
end: new Date("January 5 2024"),
|
|
||||||
link: "https://linktr.ee/bigbadbeaver",
|
|
||||||
type: "project",
|
|
||||||
logo: "beaver.png",
|
|
||||||
description: `<div class="pl-4">
|
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>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>
|
||||||
|
|
||||||
@ -160,15 +166,15 @@ Additionally, I guided and mentored other developers in the design and coding of
|
|||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>`,
|
</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",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "Community Manager and Open-Source Engineer",
|
company: "Sema Software",
|
||||||
company: "Sema Software",
|
|
||||||
start: new Date("May 5 2022"),
|
|
||||||
end: new Date("September 5 2022"),
|
|
||||||
link: "https://www.semasoftware.com",
|
|
||||||
type: "fixed",
|
|
||||||
logo: "sema.jpeg",
|
|
||||||
description: `<div class="pl-4">
|
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>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>
|
||||||
|
|
||||||
@ -207,15 +213,15 @@ Additionally, I guided and mentored other developers in the design and coding of
|
|||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>`,
|
</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",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "Community Manager",
|
company: "4C",
|
||||||
company: "4C",
|
|
||||||
start: new Date("May 5 2022"),
|
|
||||||
end: new Date("November 5 2022"),
|
|
||||||
link: "https://discord.com/invite/ns5x8bTz25",
|
|
||||||
type: "fixed",
|
|
||||||
logo: "4c.png",
|
|
||||||
description: `<div class="pl-4">
|
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>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>
|
||||||
|
|
||||||
@ -248,15 +254,15 @@ Additionally, I guided and mentored other developers in the design and coding of
|
|||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>`,
|
</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",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "Community Manager",
|
company: "TweetShift",
|
||||||
company: "TweetShift",
|
|
||||||
start: new Date("January 5 2022"),
|
|
||||||
end: new Date("May 5 2023"),
|
|
||||||
link: "https://tweetshift.com",
|
|
||||||
type: "fixed",
|
|
||||||
logo: "tweetshift.png",
|
|
||||||
description: `<div class="pl-4">
|
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>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>
|
||||||
|
|
||||||
@ -297,14 +303,15 @@ Additionally, I guided and mentored other developers in the design and coding of
|
|||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>`,
|
</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",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "Senior Integrations Engineer",
|
company: "Rythm",
|
||||||
company: "Rythm",
|
|
||||||
start: new Date("April 5 2022"),
|
|
||||||
end: new Date("November 5, 2024"),
|
|
||||||
link: "https://rythm.fm",
|
|
||||||
type: "fixed",
|
|
||||||
description: `<div class="pl-4">
|
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>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>
|
||||||
|
|
||||||
@ -346,16 +353,15 @@ Additionally, I guided and mentored other developers in the design and coding of
|
|||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>`,
|
</div>`,
|
||||||
logo: "rythm.jpeg",
|
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",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "Community Manager and Infrastructure Engineer",
|
company: "Streamcord",
|
||||||
company: "Streamcord",
|
|
||||||
start: new Date("August 5 2021"),
|
|
||||||
end: null,
|
|
||||||
link: "https://streamcord.io",
|
|
||||||
type: "fixed",
|
|
||||||
logo: "streamcord.jpeg",
|
|
||||||
description: `<div class="pl-4">
|
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>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>
|
||||||
|
|
||||||
@ -396,89 +402,89 @@ Additionally, I guided and mentored other developers in the design and coding of
|
|||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>`,
|
</div>`,
|
||||||
|
end: null,
|
||||||
|
link: "https://streamcord.io",
|
||||||
|
logo: "streamcord.jpeg",
|
||||||
|
start: new Date("August 5 2021"),
|
||||||
|
title: "Community Manager and Infrastructure Engineer",
|
||||||
|
type: "fixed",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "Community Moderator",
|
company: "Battlesnake",
|
||||||
company: "Battlesnake",
|
|
||||||
start: new Date("June 5 2021"),
|
|
||||||
end: new Date("November 5 2022"),
|
|
||||||
link: "https://play.battlesnake.com",
|
|
||||||
type: "volunteer",
|
|
||||||
logo: "battlesnake.jpeg",
|
|
||||||
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.
|
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.`,
|
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",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "Discord Administrator and Platform Engineering Manager",
|
company: "Caylus Crew",
|
||||||
company: "Caylus Crew",
|
|
||||||
start: new Date("June 5 2021"),
|
|
||||||
end: null,
|
|
||||||
link: "https://discord.gg/infinite",
|
|
||||||
type: "volunteer",
|
|
||||||
logo: "caylus.png",
|
|
||||||
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.
|
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.`,
|
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",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "Integrations Engineer",
|
company: "Xcentric Collective",
|
||||||
company: "Xcentric Collective",
|
|
||||||
start: new Date("April 5 2021"),
|
|
||||||
end: new Date("July 5 2023"),
|
|
||||||
link: "http://discord.gg/U3jQVYNbJt",
|
|
||||||
type: "volunteer",
|
|
||||||
logo: "xcentric.jpg",
|
|
||||||
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.
|
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.`,
|
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",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "Hacktoberfest Community Moderator",
|
company: "DigitalOcean",
|
||||||
company: "DigitalOcean",
|
|
||||||
start: new Date("April 5 2021"),
|
|
||||||
end: new Date("November 5 2024"),
|
|
||||||
link: "https://hacktoberfest.com",
|
|
||||||
type: "volunteer",
|
|
||||||
logo: "digitalocean.jpeg",
|
|
||||||
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.
|
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.`,
|
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",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "Discord Administrator",
|
company: "EddieHub",
|
||||||
company: "EddieHub",
|
|
||||||
start: new Date("January 5 2021"),
|
|
||||||
end: new Date("May 5 2023"),
|
|
||||||
link: "https://www.eddiehub.org",
|
|
||||||
type: "volunteer",
|
|
||||||
logo: "eddiehub.jpeg",
|
|
||||||
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.
|
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.
|
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.`,
|
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",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "Discord Administrator and Lead Integrations Engineer",
|
company: "Commit Your Code",
|
||||||
company: "Commit Your Code",
|
|
||||||
start: new Date("December 5 2020"),
|
|
||||||
end: null,
|
|
||||||
link: "https://discord.gg/StwJYeq",
|
|
||||||
type: "volunteer",
|
|
||||||
logo: "cyc.jpeg",
|
|
||||||
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.
|
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.`,
|
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",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "Educational Developer and Community Manager",
|
company: "freeCodeCamp",
|
||||||
company: "freeCodeCamp",
|
|
||||||
start: new Date("December 5, 2020"),
|
|
||||||
end: null,
|
|
||||||
link: "https://freecodecamp.org",
|
|
||||||
type: "fixed",
|
|
||||||
logo: "fcc.jpeg",
|
|
||||||
description: `<div class="pl-4">
|
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>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>
|
||||||
|
|
||||||
@ -518,119 +524,119 @@ To enhance community security, I built a robust verification system that signifi
|
|||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>`,
|
</div>`,
|
||||||
|
end: null,
|
||||||
|
link: "https://freecodecamp.org",
|
||||||
|
logo: "fcc.jpeg",
|
||||||
|
start: new Date("December 5, 2020"),
|
||||||
|
title: "Educational Developer and Community Manager",
|
||||||
|
type: "fixed",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "Discord Moderator",
|
company: "Virtual Insanity",
|
||||||
company: "Virtual Insanity",
|
|
||||||
start: new Date("May 5 2024"),
|
|
||||||
end: null,
|
|
||||||
link: "https://discord.com/invite/GDYNGnrGUs",
|
|
||||||
type: "volunteer",
|
|
||||||
logo: "troopy.png",
|
|
||||||
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.`,
|
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",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "Discord Administrator and Integrations Engineer",
|
company: "Azuliah (VTuber)",
|
||||||
company: "Azuliah (VTuber)",
|
|
||||||
start: new Date("December 5 2023"),
|
|
||||||
end: new Date("April 5 2024"),
|
|
||||||
link: "https://discord.com/invite/XNSy8PMvyy",
|
|
||||||
type: "volunteer",
|
|
||||||
logo: "azuliah.jpg",
|
|
||||||
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.
|
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.`,
|
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",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "Discord Moderator",
|
company: "Rion Kuroko (VTuber)",
|
||||||
company: "Rion Kuroko (VTuber)",
|
|
||||||
start: new Date("Nov 5 2023"),
|
|
||||||
end: new Date("Jan 5 2024"),
|
|
||||||
link: "https://discord.com",
|
|
||||||
type: "volunteer",
|
|
||||||
logo: "rion.jpg",
|
|
||||||
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.
|
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.`,
|
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",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "Senior Discord Moderator",
|
company: "Rythm",
|
||||||
company: "Rythm",
|
|
||||||
start: new Date("Feb 5 2022"),
|
|
||||||
end: new Date("July 5 2022"),
|
|
||||||
link: "https://discord.com/invite/rythm",
|
|
||||||
type: "volunteer",
|
|
||||||
logo: "rythm.jpeg",
|
|
||||||
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.
|
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.`,
|
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",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "Technical Support Staff",
|
company: "TweetShift",
|
||||||
company: "TweetShift",
|
|
||||||
start: new Date("Oct 5 2021"),
|
|
||||||
end: new Date("Jan 5 2022"),
|
|
||||||
link: "https://discord.com/invite/zdfQhjc",
|
|
||||||
type: "volunteer",
|
|
||||||
logo: "tweetshift.png",
|
|
||||||
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.
|
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.`,
|
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",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "Discord Moderator",
|
company: "Rythm",
|
||||||
company: "Rythm",
|
|
||||||
start: new Date("Sept 5 2021"),
|
|
||||||
end: new Date("Feb 5 2022"),
|
|
||||||
link: "https://discord.com/invite/rythm",
|
|
||||||
type: "volunteer",
|
|
||||||
logo: "rythm.jpeg",
|
|
||||||
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.
|
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.`,
|
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",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "Technical Support Staff",
|
company: "Streamcord",
|
||||||
company: "Streamcord",
|
|
||||||
start: new Date("Mar 5 2021"),
|
|
||||||
end: new Date("Aug 5 2021"),
|
|
||||||
link: "https://discord.com/invite/streamcord",
|
|
||||||
type: "volunteer",
|
|
||||||
logo: "streamcord.jpeg",
|
|
||||||
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.
|
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.`,
|
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",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "Community Moderator",
|
company: "freeCodeCamp",
|
||||||
company: "freeCodeCamp",
|
|
||||||
start: new Date("Jun 5 2020"),
|
|
||||||
end: new Date("Dec 5 2020"),
|
|
||||||
link: "https://discord.com/invite/freecodecamp-org-official-fi-fo-692816967895220344",
|
|
||||||
type: "volunteer",
|
|
||||||
logo: "fcc.jpeg",
|
|
||||||
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.
|
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.`,
|
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",
|
title: "Community Moderator",
|
||||||
company: "FruitPursuits",
|
type: "volunteer",
|
||||||
start: new Date("March 5 2024"),
|
|
||||||
end: null,
|
|
||||||
link: "https://discord.gg/xcy2fRsC5K",
|
|
||||||
type: "volunteer",
|
|
||||||
logo: "fruit.png",
|
|
||||||
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.`,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "Developer Experience Consultant",
|
company: "FruitPursuits",
|
||||||
company: "Deepgram",
|
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.`,
|
||||||
start: new Date("June 5 2024"),
|
end: null,
|
||||||
end: null,
|
link: "https://discord.gg/xcy2fRsC5K",
|
||||||
link: "https://deepgram.com",
|
logo: "fruit.png",
|
||||||
type: "fixed",
|
start: new Date("March 5 2024"),
|
||||||
logo: "deepgram.jpeg",
|
title: "Community Moderator",
|
||||||
|
type: "volunteer",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
company: "Deepgram",
|
||||||
description: `
|
description: `
|
||||||
<div class="pl-4">
|
<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>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>
|
||||||
@ -672,15 +678,15 @@ I engaged with and moderated the community on the forum and Discord server, fost
|
|||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>`,
|
</div>`,
|
||||||
|
end: null,
|
||||||
|
link: "https://deepgram.com",
|
||||||
|
logo: "deepgram.jpeg",
|
||||||
|
start: new Date("June 5 2024"),
|
||||||
|
title: "Developer Experience Consultant",
|
||||||
|
type: "fixed",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "Service Operations Manager",
|
company: "Safeway",
|
||||||
company: "Safeway",
|
|
||||||
start: new Date("5 August 2009"),
|
|
||||||
end: new Date("5 April 2020"),
|
|
||||||
link: "https://www.safeway.com",
|
|
||||||
type: "fixed",
|
|
||||||
logo: "safeway.png",
|
|
||||||
description: `<div class="pl-4">
|
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>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>
|
||||||
|
|
||||||
@ -719,15 +725,15 @@ I engaged with and moderated the community on the forum and Discord server, fost
|
|||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>`,
|
</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",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "Student",
|
company: "Vancouver School of Arts and Academics",
|
||||||
company: "Vancouver School of Arts and Academics",
|
|
||||||
start: new Date("5 September 2001"),
|
|
||||||
end: new Date("5 June 2009"),
|
|
||||||
link: "https://arts.vansd.org/",
|
|
||||||
type: "volunteer",
|
|
||||||
logo: "vsaa.png",
|
|
||||||
description: `<div class="pl-4">
|
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>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>
|
||||||
|
|
||||||
@ -761,5 +767,11 @@ I engaged with and moderated the community on the forum and Discord server, fost
|
|||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>`,
|
</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",
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
@ -1,3 +1,13 @@
|
|||||||
|
/**
|
||||||
|
* @copyright nhcarrigan
|
||||||
|
* @license Naomi's Public License
|
||||||
|
* @author Naomi Carrigan
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Navigation items to render on home page and
|
||||||
|
* on main navbar.
|
||||||
|
*/
|
||||||
export const NavItems = [
|
export const NavItems = [
|
||||||
{ href: "/about", text: "About" },
|
{ href: "/about", text: "About" },
|
||||||
{ href: "/manual", text: "User Manual" },
|
{ href: "/manual", text: "User Manual" },
|
||||||
@ -5,11 +15,13 @@ export const NavItems = [
|
|||||||
{ href: "/contact", text: "Contact" },
|
{ href: "/contact", text: "Contact" },
|
||||||
{ href: "/certs", text: "Certifications" },
|
{ href: "/certs", text: "Certifications" },
|
||||||
{ href: "/reviews", text: "Reviews" },
|
{ href: "/reviews", text: "Reviews" },
|
||||||
{ href: "/games", text: "Games"},
|
{ href: "/games", text: "Games" },
|
||||||
{ href: "/team", text: "Our Team" },
|
{ href: "/team", text: "Our Team" },
|
||||||
{ href: "/polycule", text: "Polycule"},
|
{ href: "/polycule", text: "Polycule" },
|
||||||
{ href: "/activity", text: "Activity"},
|
{ href: "/activity", text: "Activity" },
|
||||||
{ href: "/art", text: "Art"},
|
{ href: "/art", text: "Art" },
|
||||||
{ href: "https://nhcarrigan.creator-spring.com/", text: "Merch"},
|
{ href: "https://nhcarrigan.creator-spring.com/", text: "Merch" },
|
||||||
{ href: "/manifesto", text: "Transfemme Manifesto"},
|
{ href: "/manifesto", text: "Transfemme Manifesto" },
|
||||||
].sort((a, b) => a.text.localeCompare(b.text));
|
].sort((a, b) => {
|
||||||
|
return a.text.localeCompare(b.text);
|
||||||
|
});
|
||||||
|
@ -1,29 +1,40 @@
|
|||||||
export const Partners: {
|
/**
|
||||||
name: string;
|
* @copyright nhcarrigan
|
||||||
avatar: string;
|
* @license Naomi's Public License
|
||||||
|
* @author Naomi Carrigan
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* List of polycule members to render.
|
||||||
|
*/
|
||||||
|
export const Partners: Array<{
|
||||||
|
name: string;
|
||||||
|
avatar: string;
|
||||||
relationship: string;
|
relationship: string;
|
||||||
url: string;
|
url: string;
|
||||||
anniversary: Date;
|
anniversary: Date;
|
||||||
}[] = [
|
}> = [
|
||||||
{
|
{
|
||||||
name: "Sadashi",
|
anniversary: new Date("January 1, 2023"),
|
||||||
avatar: "dashi.png",
|
avatar: "dashi.png",
|
||||||
relationship: "Romantic Partner",
|
name: "Sadashi",
|
||||||
url: "https://chat.nhcarrigan.com",
|
relationship: "Romantic Partner",
|
||||||
anniversary: new Date("January 1, 2023")
|
url: "https://chat.nhcarrigan.com",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Rain",
|
anniversary: new Date("November 17, 2023"),
|
||||||
avatar: "estel.png",
|
avatar: "estel.png",
|
||||||
relationship: "Fiancée",
|
name: "Rain",
|
||||||
url: "https://chat.nhcarrigan.com",
|
relationship: "Fiancée",
|
||||||
anniversary: new Date("November 17, 2023")
|
url: "https://chat.nhcarrigan.com",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Kaitlyn",
|
anniversary: new Date("October 1, 2023"),
|
||||||
avatar: "fruit.png",
|
avatar: "fruit.png",
|
||||||
relationship: "Queer-Platonic Partner",
|
name: "Kaitlyn",
|
||||||
url: "https://kaitlyn.nhcarrigan.com",
|
relationship: "Queer-Platonic Partner",
|
||||||
anniversary: new Date("October 1, 2023")
|
url: "https://kaitlyn.nhcarrigan.com",
|
||||||
},
|
},
|
||||||
].sort((a, b) => a.anniversary.getTime() - b.anniversary.getTime())
|
].sort((a, b) => {
|
||||||
|
return a.anniversary.getTime() - b.anniversary.getTime();
|
||||||
|
});
|
||||||
|
@ -1,17 +1,8 @@
|
|||||||
import { Codeberg } from "@/icons/Codeberg";
|
/**
|
||||||
import { Fiverr } from "@/icons/Fiverr";
|
* @copyright nhcarrigan
|
||||||
import { Gather } from "@/icons/Gather";
|
* @license Naomi's Public License
|
||||||
import { Gog } from "@/icons/Gog";
|
* @author Naomi Carrigan
|
||||||
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 { Saylor } from "@/icons/Saylor";
|
|
||||||
import { TeeSpring } from "@/icons/TeeSpring";
|
|
||||||
import { TreeNation } from "@/icons/TreeNation";
|
|
||||||
import { VRoid } from "@/icons/VRoid";
|
|
||||||
import { IconDefinition } from "@fortawesome/fontawesome-svg-core";
|
|
||||||
import {
|
import {
|
||||||
faAngellist,
|
faAngellist,
|
||||||
faBluesky,
|
faBluesky,
|
||||||
@ -56,20 +47,33 @@ import {
|
|||||||
faMoneyBill,
|
faMoneyBill,
|
||||||
faUniversity,
|
faUniversity,
|
||||||
} from "@fortawesome/free-solid-svg-icons";
|
} from "@fortawesome/free-solid-svg-icons";
|
||||||
|
import { Codeberg } from "../icons/Codeberg";
|
||||||
|
import { Fiverr } from "../icons/Fiverr";
|
||||||
|
import { Gather } from "../icons/Gather";
|
||||||
|
import { Gog } from "../icons/Gog";
|
||||||
|
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 { Saylor } from "../icons/Saylor";
|
||||||
|
import { TeeSpring } from "../icons/TeeSpring";
|
||||||
|
import { TreeNation } from "../icons/TreeNation";
|
||||||
|
import { VRoid } from "../icons/VRoid";
|
||||||
|
import type { IconDefinition } from "@fortawesome/fontawesome-svg-core";
|
||||||
|
|
||||||
export const HireMe: {
|
/**
|
||||||
icon: IconDefinition;
|
* Custom button with gradient for hire CTA.
|
||||||
link: string;
|
*/
|
||||||
label: string;
|
const HireMe: {
|
||||||
alt: string;
|
icon: IconDefinition;
|
||||||
color: string;
|
link: string;
|
||||||
|
label: string;
|
||||||
|
alt: string;
|
||||||
|
color: string;
|
||||||
background: string;
|
background: string;
|
||||||
} = {
|
} = {
|
||||||
icon: faBriefcase,
|
alt: "Briefcase Icon",
|
||||||
link: "https://docs.nhcarrigan.com/#/hire",
|
|
||||||
label: "Hire Us!",
|
|
||||||
alt: "Briefcase Icon",
|
|
||||||
color: "#003600",
|
|
||||||
background: `linear-gradient(
|
background: `linear-gradient(
|
||||||
90deg,
|
90deg,
|
||||||
#5bcefa,
|
#5bcefa,
|
||||||
@ -78,21 +82,24 @@ export const HireMe: {
|
|||||||
#f5a9b8,
|
#f5a9b8,
|
||||||
#5bcefa
|
#5bcefa
|
||||||
)`,
|
)`,
|
||||||
|
color: "#003600",
|
||||||
|
icon: faBriefcase,
|
||||||
|
label: "Hire Us!",
|
||||||
|
link: "https://docs.nhcarrigan.com/#/hire",
|
||||||
};
|
};
|
||||||
|
|
||||||
export const Donate: {
|
/**
|
||||||
icon: IconDefinition;
|
* Custom button with gradient for Donate CTA.
|
||||||
link: string;
|
*/
|
||||||
label: string;
|
const Donate: {
|
||||||
alt: string;
|
icon: IconDefinition;
|
||||||
color: string;
|
link: string;
|
||||||
|
label: string;
|
||||||
|
alt: string;
|
||||||
|
color: string;
|
||||||
background: string;
|
background: string;
|
||||||
} = {
|
} = {
|
||||||
icon: faMoneyBill,
|
alt: "Money Icon",
|
||||||
link: "https://docs.nhcarrigan.com/#/donate",
|
|
||||||
label: "Donate 💜",
|
|
||||||
alt: "Money Icon",
|
|
||||||
color: "#003600",
|
|
||||||
background: `linear-gradient(
|
background: `linear-gradient(
|
||||||
90deg,
|
90deg,
|
||||||
rgba(255, 0, 0, 1) 0%,
|
rgba(255, 0, 0, 1) 0%,
|
||||||
@ -107,430 +114,439 @@ export const Donate: {
|
|||||||
rgba(255, 154, 0, 1) 90%,
|
rgba(255, 154, 0, 1) 90%,
|
||||||
rgba(255, 0, 0, 1) 100%
|
rgba(255, 0, 0, 1) 100%
|
||||||
)`,
|
)`,
|
||||||
|
color: "#003600",
|
||||||
|
icon: faMoneyBill,
|
||||||
|
label: "Donate 💜",
|
||||||
|
link: "https://docs.nhcarrigan.com/#/donate",
|
||||||
};
|
};
|
||||||
|
|
||||||
export const Socials: {
|
/**
|
||||||
icon: IconDefinition;
|
* List of social media buttons to render.
|
||||||
link: string;
|
*/
|
||||||
label: string;
|
const Socials: Array<{
|
||||||
alt: string;
|
icon: IconDefinition;
|
||||||
color: string;
|
link: string;
|
||||||
|
label: string;
|
||||||
|
alt: string;
|
||||||
|
color: string;
|
||||||
background: string;
|
background: string;
|
||||||
}[] = [
|
}> = [
|
||||||
{
|
{
|
||||||
label: "Codeberg",
|
alt: "Codeberg Logo",
|
||||||
link: "https://codeberg.org/naomi-lgbt",
|
|
||||||
alt: "Codeberg Logo",
|
|
||||||
icon: Codeberg,
|
|
||||||
background: "#0B3049",
|
background: "#0B3049",
|
||||||
color: "#B5DDFF",
|
color: "#B5DDFF",
|
||||||
|
icon: Codeberg,
|
||||||
|
label: "Codeberg",
|
||||||
|
link: "https://codeberg.org/naomi-lgbt",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "GitHub",
|
alt: "GitHub Logo",
|
||||||
link: "https://github.com/nhcarrigan",
|
|
||||||
alt: "GitHub Logo",
|
|
||||||
icon: faGithub,
|
|
||||||
background: "#333",
|
background: "#333",
|
||||||
color: "#FFF",
|
color: "#FFF",
|
||||||
|
icon: faGithub,
|
||||||
|
label: "GitHub",
|
||||||
|
link: "https://github.com/nhcarrigan",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "Discord",
|
alt: "Discord Logo",
|
||||||
link: "https://chat.naomi.lgbt",
|
|
||||||
alt: "Discord Logo",
|
|
||||||
icon: faDiscord,
|
|
||||||
background: "#7289DA",
|
background: "#7289DA",
|
||||||
color: "#FFF",
|
color: "#FFF",
|
||||||
|
icon: faDiscord,
|
||||||
|
label: "Discord",
|
||||||
|
link: "https://chat.naomi.lgbt",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "Matrix",
|
alt: "Element Logo",
|
||||||
link: "https://matrix.to/#/#naomi:matrix.org",
|
|
||||||
alt: "Element Logo",
|
|
||||||
icon: Matrix,
|
|
||||||
background: "#29B6F6",
|
background: "#29B6F6",
|
||||||
color: "#FFF",
|
color: "#FFF",
|
||||||
|
icon: Matrix,
|
||||||
|
label: "Matrix",
|
||||||
|
link: "https://matrix.to/#/#naomi:matrix.org",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "IRC",
|
alt: "Hash symbol",
|
||||||
link: "https://docs.nhcarrigan.com/about/contact/#33-irc-channels",
|
|
||||||
alt: "Hash symbol",
|
|
||||||
icon: faHashtag,
|
|
||||||
background: "#000",
|
background: "#000",
|
||||||
color: "#FFF",
|
color: "#FFF",
|
||||||
|
icon: faHashtag,
|
||||||
|
label: "IRC",
|
||||||
|
link: "https://docs.nhcarrigan.com/about/contact/#33-irc-channels",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "Slack",
|
alt: "Slack Logo",
|
||||||
link: "https://join.slack.com/t/naomi-lgbt/signup",
|
|
||||||
alt: "Slack Logo",
|
|
||||||
icon: faSlack,
|
|
||||||
background: "#4A154B",
|
background: "#4A154B",
|
||||||
color: "#FFF",
|
color: "#FFF",
|
||||||
|
icon: faSlack,
|
||||||
|
label: "Slack",
|
||||||
|
link: "https://join.slack.com/t/naomi-lgbt/signup",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "Reddit",
|
alt: "Reddit Logo",
|
||||||
link: "https://reddit.com/r/nhcarrigan",
|
|
||||||
alt: "Reddit Logo",
|
|
||||||
icon: faReddit,
|
|
||||||
background: "#FF4500",
|
background: "#FF4500",
|
||||||
color: "#FFF",
|
color: "#FFF",
|
||||||
|
icon: faReddit,
|
||||||
|
label: "Reddit",
|
||||||
|
link: "https://reddit.com/r/nhcarrigan",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "Blog",
|
alt: "Hashnode Logo",
|
||||||
link: "https://blog.nhcarrigan.com",
|
|
||||||
alt: "Hashnode Logo",
|
|
||||||
icon: faHashnode,
|
|
||||||
background: "#2962FF",
|
background: "#2962FF",
|
||||||
color: "#FFF",
|
color: "#FFF",
|
||||||
|
icon: faHashnode,
|
||||||
|
label: "Blog",
|
||||||
|
link: "https://blog.nhcarrigan.com",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "LinkedIn",
|
alt: "LinkedIn Logo",
|
||||||
link: "https://linkedin.com/in/naomi-lgbt",
|
|
||||||
alt: "LinkedIn Logo",
|
|
||||||
icon: faLinkedinIn,
|
|
||||||
background: "#0077B5",
|
background: "#0077B5",
|
||||||
color: "#FFF",
|
color: "#FFF",
|
||||||
|
icon: faLinkedinIn,
|
||||||
|
label: "LinkedIn",
|
||||||
|
link: "https://linkedin.com/in/naomi-lgbt",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "Peerlist",
|
alt: "Peerlist Logo",
|
||||||
link: "https://resume.nhcarrigan.com",
|
|
||||||
alt: "Peerlist Logo",
|
|
||||||
icon: Peerlist,
|
|
||||||
background: "rgb(33, 150, 83)",
|
background: "rgb(33, 150, 83)",
|
||||||
color: "#FFF",
|
color: "#FFF",
|
||||||
|
icon: Peerlist,
|
||||||
|
label: "Peerlist",
|
||||||
|
link: "https://resume.nhcarrigan.com",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "Polywork",
|
alt: "Polywork Logo",
|
||||||
link: "https://polywork.nhcarrigan.com/",
|
|
||||||
alt: "Polywork Logo",
|
|
||||||
icon: Polywork,
|
|
||||||
background: "#7C3AED",
|
background: "#7C3AED",
|
||||||
color: "#FFF",
|
color: "#FFF",
|
||||||
|
icon: Polywork,
|
||||||
|
label: "Polywork",
|
||||||
|
link: "https://polywork.nhcarrigan.com/",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "Fiverr",
|
alt: "Fiverr Logo",
|
||||||
link: "https://www.fiverr.com/nhcarrigan",
|
|
||||||
alt: "Fiverr Logo",
|
|
||||||
icon: Fiverr,
|
|
||||||
background: "#1DBF73",
|
background: "#1DBF73",
|
||||||
color: "#FFF",
|
color: "#FFF",
|
||||||
|
icon: Fiverr,
|
||||||
|
label: "Fiverr",
|
||||||
|
link: "https://www.fiverr.com/nhcarrigan",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "Mastodon",
|
alt: "Mastodon Logo",
|
||||||
link: "https://mastodon.social/@naomi_lgbt",
|
|
||||||
alt: "Mastodon Logo",
|
|
||||||
icon: faMastodon,
|
|
||||||
background: "#2B90D9",
|
background: "#2B90D9",
|
||||||
color: "#FFF",
|
color: "#FFF",
|
||||||
|
icon: faMastodon,
|
||||||
|
label: "Mastodon",
|
||||||
|
link: "https://mastodon.social/@naomi_lgbt",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "X (Twitter)",
|
alt: "X Logo",
|
||||||
link: "https://x.com/naomi_lgbt",
|
|
||||||
alt: "X Logo",
|
|
||||||
icon: faXTwitter,
|
|
||||||
background: "#1DA1F2",
|
background: "#1DA1F2",
|
||||||
color: "#FFF",
|
color: "#FFF",
|
||||||
|
icon: faXTwitter,
|
||||||
|
label: "X (Twitter)",
|
||||||
|
link: "https://x.com/naomi_lgbt",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "Steam",
|
alt: "Steam Logo",
|
||||||
link: "https://steamcommunity.com/id/naomi-lgbt/",
|
|
||||||
alt: "Steam Logo",
|
|
||||||
icon: faSteam,
|
|
||||||
background: "rgb(27, 40, 56)",
|
background: "rgb(27, 40, 56)",
|
||||||
color: "rgb(199, 213, 224)",
|
color: "rgb(199, 213, 224)",
|
||||||
|
icon: faSteam,
|
||||||
|
label: "Steam",
|
||||||
|
link: "https://steamcommunity.com/id/naomi-lgbt/",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "Twitch",
|
alt: "Twitch Logo",
|
||||||
link: "https://www.twitch.tv/naomilgbt/",
|
|
||||||
alt: "Twitch Logo",
|
|
||||||
icon: faTwitch,
|
|
||||||
background: "#6441A4",
|
background: "#6441A4",
|
||||||
color: "#FFF",
|
color: "#FFF",
|
||||||
|
icon: faTwitch,
|
||||||
|
label: "Twitch",
|
||||||
|
link: "https://www.twitch.tv/naomilgbt/",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "HLTB",
|
alt: "How Long to Beat Logo",
|
||||||
link: "https://howlongtobeat.com/user/naomi_lgbt",
|
|
||||||
alt: "How Long to Beat Logo",
|
|
||||||
icon: faGamepad,
|
|
||||||
background: "#333",
|
background: "#333",
|
||||||
color: "#FFF",
|
color: "#FFF",
|
||||||
|
icon: faGamepad,
|
||||||
|
label: "HLTB",
|
||||||
|
link: "https://howlongtobeat.com/user/naomi_lgbt",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "Snapchat",
|
alt: "Snapchat Logo",
|
||||||
link: "https://www.snapchat.com/add/naomi-lgbt",
|
|
||||||
alt: "Snapchat Logo",
|
|
||||||
icon: faSnapchat,
|
|
||||||
background: "#FFFC00",
|
background: "#FFFC00",
|
||||||
color: "#000",
|
color: "#000",
|
||||||
|
icon: faSnapchat,
|
||||||
|
label: "Snapchat",
|
||||||
|
link: "https://www.snapchat.com/add/naomi-lgbt",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "GOG",
|
alt: "GOG Logo",
|
||||||
link: "https://www.gog.com/u/naomi-lgbt",
|
|
||||||
alt: "GOG Logo",
|
|
||||||
icon: Gog,
|
|
||||||
background: "#863A3A",
|
background: "#863A3A",
|
||||||
color: "#FFF",
|
color: "#FFF",
|
||||||
|
icon: Gog,
|
||||||
|
label: "GOG",
|
||||||
|
link: "https://www.gog.com/u/naomi-lgbt",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "Itch.io",
|
alt: "Itch.io Logo",
|
||||||
link: "https://nhcarrigan.itch.io/",
|
|
||||||
alt: "Itch.io Logo",
|
|
||||||
icon: faItchIo,
|
|
||||||
background: "#FA5C5C",
|
background: "#FA5C5C",
|
||||||
color: "#FFF",
|
color: "#FFF",
|
||||||
|
icon: faItchIo,
|
||||||
|
label: "Itch.io",
|
||||||
|
link: "https://nhcarrigan.itch.io/",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "Lichess",
|
alt: "Lichess Logo",
|
||||||
link: "https://lichess.org/@/naomi-lgbt",
|
|
||||||
alt: "Lichess Logo",
|
|
||||||
icon: faChessKnight,
|
|
||||||
background: "#000",
|
background: "#000",
|
||||||
color: "#FFF",
|
color: "#FFF",
|
||||||
|
icon: faChessKnight,
|
||||||
|
label: "Lichess",
|
||||||
|
link: "https://lichess.org/../naomi-lgbt",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "Saylor Academy",
|
alt: "Saylor Academy Logo",
|
||||||
link: "https://learn.saylor.org/user/profile.php?id=2074619",
|
|
||||||
alt: "Saylor Academy Logo",
|
|
||||||
icon: Saylor,
|
|
||||||
background: "#469dcc",
|
background: "#469dcc",
|
||||||
color: "#183140",
|
color: "#183140",
|
||||||
|
icon: Saylor,
|
||||||
|
label: "Saylor Academy",
|
||||||
|
link: "https://learn.saylor.org/user/profile.php?id=2074619",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "Paypal",
|
alt: "Paypal Logo",
|
||||||
link: "https://paypal.me/nhcarrigan",
|
|
||||||
alt: "Paypal Logo",
|
|
||||||
icon: faPaypal,
|
|
||||||
background: "#003087",
|
background: "#003087",
|
||||||
color: "#FFF",
|
color: "#FFF",
|
||||||
|
icon: faPaypal,
|
||||||
|
label: "Paypal",
|
||||||
|
link: "https://paypal.me/nhcarrigan",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "Ko-Fi",
|
alt: "Ko-Fi Logo",
|
||||||
link: "https://ko-fi.com/nhcarrigan",
|
|
||||||
alt: "Ko-Fi Logo",
|
|
||||||
icon: Kofi,
|
|
||||||
background: "#FF5E5B",
|
background: "#FF5E5B",
|
||||||
color: "#FFF",
|
color: "#FFF",
|
||||||
|
icon: Kofi,
|
||||||
|
label: "Ko-Fi",
|
||||||
|
link: "https://ko-fi.com/nhcarrigan",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "Patreon",
|
alt: "Patreon Logo",
|
||||||
link: "https://patreon.com/nhcarrigan",
|
|
||||||
alt: "Patreon Logo",
|
|
||||||
icon: faPatreon,
|
|
||||||
background: "#F96854",
|
background: "#F96854",
|
||||||
color: "#FFF",
|
color: "#FFF",
|
||||||
|
icon: faPatreon,
|
||||||
|
label: "Patreon",
|
||||||
|
link: "https://patreon.com/nhcarrigan",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "freeCodeCamp",
|
alt: "freeCodeCamp Logo",
|
||||||
link: "https://forum.freecodecamp.org/u/nhcarrigan/summary",
|
|
||||||
alt: "freeCodeCamp Logo",
|
|
||||||
icon: faFreeCodeCamp,
|
|
||||||
background: "#0a0a23",
|
background: "#0a0a23",
|
||||||
color: "#FFF",
|
color: "#FFF",
|
||||||
|
icon: faFreeCodeCamp,
|
||||||
|
label: "freeCodeCamp",
|
||||||
|
link: "https://forum.freecodecamp.org/u/nhcarrigan/summary",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "NPM",
|
alt: "NPM Logo",
|
||||||
link: "https://www.npmjs.com/~nhcarrigan",
|
|
||||||
alt: "NPM Logo",
|
|
||||||
icon: faNpm,
|
|
||||||
background: "#CB3837",
|
background: "#CB3837",
|
||||||
color: "#FFF",
|
color: "#FFF",
|
||||||
|
icon: faNpm,
|
||||||
|
label: "NPM",
|
||||||
|
link: "https://www.npmjs.com/~nhcarrigan",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "GatherTown",
|
alt: "GatherTown Logo",
|
||||||
link: "https://app.gather.town/invite?token=CiIvbSnrQiW-akXFSPL_",
|
|
||||||
alt: "GatherTown Logo",
|
|
||||||
icon: Gather,
|
|
||||||
background: "#7B68EE",
|
background: "#7B68EE",
|
||||||
color: "#FFF",
|
color: "#FFF",
|
||||||
|
icon: Gather,
|
||||||
|
label: "GatherTown",
|
||||||
|
link: "https://app.gather.town/invite?token=CiIvbSnrQiW-akXFSPL_",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "VRoid",
|
alt: "VRoid Logo",
|
||||||
link: "https://hub.vroid.com/en/characters/6033404747153826650/models/3483506204509065121",
|
|
||||||
alt: "VRoid Logo",
|
|
||||||
icon: VRoid,
|
|
||||||
color: "#000",
|
|
||||||
background: "#ffe100",
|
background: "#ffe100",
|
||||||
|
color: "#000",
|
||||||
|
icon: VRoid,
|
||||||
|
label: "VRoid",
|
||||||
|
link: "https://hub.vroid.com/en/characters/6033404747153826650/models/3483506204509065121",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "Pixiv",
|
alt: "Pixiv Logo",
|
||||||
link: "https://www.pixiv.net/en/users/77818154",
|
|
||||||
alt: "Pixiv Logo",
|
|
||||||
icon: Pixiv,
|
|
||||||
background: "#0096FA",
|
background: "#0096FA",
|
||||||
color: "#FFF",
|
color: "#FFF",
|
||||||
|
icon: Pixiv,
|
||||||
|
label: "Pixiv",
|
||||||
|
link: "https://www.pixiv.net/en/users/77818154",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "Email",
|
alt: "Email Icon",
|
||||||
link: "https://docs.nhcarrigan.com/about/contact/#7-email-communication",
|
|
||||||
alt: "Email Icon",
|
|
||||||
icon: faEnvelope,
|
|
||||||
background: "#000000",
|
background: "#000000",
|
||||||
color: "#FFF",
|
color: "#FFF",
|
||||||
|
icon: faEnvelope,
|
||||||
|
label: "Email",
|
||||||
|
link: "https://docs.nhcarrigan.com/about/contact/#7-email-communication",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "Coursera",
|
alt: "University Icon",
|
||||||
link: "https://www.coursera.org/learner/naomi-lgbt",
|
|
||||||
alt: "University Icon",
|
|
||||||
icon: faUniversity,
|
|
||||||
background: "#0056D2",
|
background: "#0056D2",
|
||||||
color: "#FFF",
|
color: "#FFF",
|
||||||
|
icon: faUniversity,
|
||||||
|
label: "Coursera",
|
||||||
|
link: "https://www.coursera.org/learner/naomi-lgbt",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "Udemy",
|
alt: "University Icon",
|
||||||
link: "https://www.udemy.com/user/naomi-carrigan/",
|
|
||||||
alt: "University Icon",
|
|
||||||
icon: faUniversity,
|
|
||||||
background: "#EC5252",
|
background: "#EC5252",
|
||||||
color: "#FFF",
|
color: "#FFF",
|
||||||
|
icon: faUniversity,
|
||||||
|
label: "Udemy",
|
||||||
|
link: "https://www.udemy.com/user/naomi-carrigan/",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "Gravatar",
|
alt: "Wordpress Logo",
|
||||||
link: "https://gravatar.com/nhcarrigan",
|
|
||||||
alt: "Wordpress Logo",
|
|
||||||
icon: faWordpress,
|
|
||||||
background: "#1E8EDE",
|
background: "#1E8EDE",
|
||||||
color: "#FFF",
|
color: "#FFF",
|
||||||
|
icon: faWordpress,
|
||||||
|
label: "Gravatar",
|
||||||
|
link: "https://gravatar.com/nhcarrigan",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "PC Part Picker",
|
alt: "Computer Icon",
|
||||||
link: "https://pcpartpicker.com/user/nhcarrigan/",
|
|
||||||
alt: "Computer Icon",
|
|
||||||
icon: faComputer,
|
|
||||||
background: "#000",
|
background: "#000",
|
||||||
color: "#FFF",
|
color: "#FFF",
|
||||||
|
icon: faComputer,
|
||||||
|
label: "PC Part Picker",
|
||||||
|
link: "https://pcpartpicker.com/user/nhcarrigan/",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "Throne",
|
alt: "Gift Icon",
|
||||||
link: "https://throne.com/naomilgbt",
|
|
||||||
alt: "Gift Icon",
|
|
||||||
icon: faGift,
|
|
||||||
background: "#000",
|
background: "#000",
|
||||||
color: "#FFF",
|
color: "#FFF",
|
||||||
|
icon: faGift,
|
||||||
|
label: "Throne",
|
||||||
|
link: "https://throne.com/naomilgbt",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "Stripe",
|
alt: "Stripe Logo",
|
||||||
link: "https://buy.stripe.com/cN24iTfqu1j6b3afZ2",
|
|
||||||
alt: "Stripe Logo",
|
|
||||||
icon: faStripe,
|
|
||||||
background: "#6772E5",
|
background: "#6772E5",
|
||||||
color: "#FFF",
|
color: "#FFF",
|
||||||
|
icon: faStripe,
|
||||||
|
label: "Stripe",
|
||||||
|
link: "https://buy.stripe.com/cN24iTfqu1j6b3afZ2",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "Signal",
|
alt: "Signal Logo",
|
||||||
link: "https://signal.me/#eu/YGo6ag7kAwkdfkw863-J4qLK3VyKn8uWLhvyX60Jx5J0qrDZnz1B_aLrjM9yAMe6",
|
|
||||||
alt: "Signal Logo",
|
|
||||||
icon: faSignalMessenger,
|
|
||||||
background: "#FFF",
|
background: "#FFF",
|
||||||
color: "#3A76F0",
|
color: "#3A76F0",
|
||||||
|
icon: faSignalMessenger,
|
||||||
|
label: "Signal",
|
||||||
|
link: "https://signal.me/#eu/YGo6ag7kAwkdfkw863-J4qLK3VyKn8uWLhvyX60Jx5J0qrDZnz1B_aLrjM9yAMe6",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "WellFound",
|
alt: "Angellist Logo",
|
||||||
link: "https://wellfound.com/u/naomi-h-carrigan",
|
|
||||||
alt: "Angellist Logo",
|
|
||||||
icon: faAngellist,
|
|
||||||
background: "#000",
|
background: "#000",
|
||||||
color: "#FFF",
|
color: "#FFF",
|
||||||
|
icon: faAngellist,
|
||||||
|
label: "WellFound",
|
||||||
|
link: "https://wellfound.com/u/naomi-h-carrigan",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "ProtonDB",
|
alt: "ProtonDB Logo",
|
||||||
link: "https://www.protondb.com/users/1717755560",
|
|
||||||
alt: "ProtonDB Logo",
|
|
||||||
icon: faAtom,
|
|
||||||
background: "#000",
|
background: "#000",
|
||||||
color: "#FFF",
|
color: "#FFF",
|
||||||
|
icon: faAtom,
|
||||||
|
label: "ProtonDB",
|
||||||
|
link: "https://www.protondb.com/users/1717755560",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "Merch",
|
alt: "TeeSpring Logo",
|
||||||
link: "https://nhcarrigan.creator-spring.com/",
|
|
||||||
alt: "TeeSpring Logo",
|
|
||||||
icon: TeeSpring,
|
|
||||||
background: "#000",
|
background: "#000",
|
||||||
color: "#FFF",
|
color: "#FFF",
|
||||||
|
icon: TeeSpring,
|
||||||
|
label: "Merch",
|
||||||
|
link: "https://nhcarrigan.creator-spring.com/",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "BlueSky",
|
alt: "BlueSky Logo",
|
||||||
link: "https://bsky.app/profile/naomi-lgbt.bsky.social",
|
|
||||||
alt: "BlueSky Logo",
|
|
||||||
icon: faBluesky,
|
|
||||||
background: "#1DA1F2",
|
background: "#1DA1F2",
|
||||||
color: "#FFF",
|
color: "#FFF",
|
||||||
|
icon: faBluesky,
|
||||||
|
label: "BlueSky",
|
||||||
|
link: "https://bsky.app/profile/naomi-lgbt.bsky.social",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "Telegram",
|
alt: "Telegram Logo",
|
||||||
link: "https://t.me/naomi_lgbt",
|
|
||||||
alt: "Telegram Logo",
|
|
||||||
icon: faTelegramPlane,
|
|
||||||
background: "#0088cc",
|
background: "#0088cc",
|
||||||
color: "#FFF",
|
color: "#FFF",
|
||||||
|
icon: faTelegramPlane,
|
||||||
|
label: "Telegram",
|
||||||
|
link: "https://t.me/naomi_lgbt",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "WhatsApp",
|
alt: "WhatsApp Logo",
|
||||||
link: "https://wa.me/qr/WCGJIID7UKWIE1",
|
|
||||||
alt: "WhatsApp Logo",
|
|
||||||
icon: faWhatsapp,
|
|
||||||
background: "#25D366",
|
background: "#25D366",
|
||||||
color: "#FFF",
|
color: "#FFF",
|
||||||
|
icon: faWhatsapp,
|
||||||
|
label: "WhatsApp",
|
||||||
|
link: "https://wa.me/qr/WCGJIID7UKWIE1",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "Google Chat",
|
alt: "Google Chat Logo",
|
||||||
link: "https://chat.google.com/room/AAAAK270m3M",
|
|
||||||
alt: "Google Chat Logo",
|
|
||||||
icon: faGooglePlus,
|
|
||||||
background: "#DB4437",
|
background: "#DB4437",
|
||||||
color: "#FFF",
|
color: "#FFF",
|
||||||
|
icon: faGooglePlus,
|
||||||
|
label: "Google Chat",
|
||||||
|
link: "https://chat.google.com/room/AAAAK270m3M",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "Tree Nation",
|
alt: "Tree Nation Logo",
|
||||||
link: "https://tree-nation.com/profile/naomi-carrigan",
|
|
||||||
alt: "Tree Nation Logo",
|
|
||||||
icon: TreeNation,
|
|
||||||
background: "#FFF",
|
background: "#FFF",
|
||||||
color: "#55C1A8",
|
color: "#55C1A8",
|
||||||
|
icon: TreeNation,
|
||||||
|
label: "Tree Nation",
|
||||||
|
link: "https://tree-nation.com/profile/naomi-carrigan",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "Meetup",
|
alt: "Meetup Logo",
|
||||||
link: "https://www.meetup.com/members/437962584/",
|
|
||||||
alt: "Meetup Logo",
|
|
||||||
icon: faMeetup,
|
|
||||||
background: "#FF6D00",
|
background: "#FF6D00",
|
||||||
color: "#FFF",
|
color: "#FFF",
|
||||||
|
icon: faMeetup,
|
||||||
|
label: "Meetup",
|
||||||
|
link: "https://www.meetup.com/members/437962584/",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "Tumblr",
|
alt: "Tumblr Logo",
|
||||||
link: "https://www.tumblr.com/naomi-lgbt",
|
|
||||||
alt: "Tumblr Logo",
|
|
||||||
icon: faTumblr,
|
|
||||||
background: "#36465D",
|
background: "#36465D",
|
||||||
color: "#FFF",
|
color: "#FFF",
|
||||||
|
icon: faTumblr,
|
||||||
|
label: "Tumblr",
|
||||||
|
link: "https://www.tumblr.com/naomi-lgbt",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "YouTube",
|
alt: "YouTube Logo",
|
||||||
link: "https://www.youtube.com/@naomilgbt",
|
|
||||||
alt: "YouTube Logo",
|
|
||||||
icon: faYoutube,
|
|
||||||
background: "#FF0000",
|
background: "#FF0000",
|
||||||
color: "#FFF",
|
color: "#FFF",
|
||||||
|
icon: faYoutube,
|
||||||
|
label: "YouTube",
|
||||||
|
link: "https://www.youtube.com/@naomilgbt",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "Tiktok",
|
alt: "Tiktok Logo",
|
||||||
link: "https://www.tiktok.com/@naomilgbt",
|
|
||||||
alt: "Tiktok Logo",
|
|
||||||
icon: faTiktok,
|
|
||||||
background: "#000",
|
background: "#000",
|
||||||
color: "#FFF",
|
color: "#FFF",
|
||||||
|
icon: faTiktok,
|
||||||
|
label: "Tiktok",
|
||||||
|
link: "https://www.tiktok.com/@naomilgbt",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "Threads",
|
alt: "Threads Logo",
|
||||||
link: "https://www.threads.net/@naomi.lgbt",
|
|
||||||
alt: "Threads Logo",
|
|
||||||
icon: faThreads,
|
|
||||||
background: "#000",
|
background: "#000",
|
||||||
color: "#FFF",
|
color: "#FFF",
|
||||||
|
icon: faThreads,
|
||||||
|
label: "Threads",
|
||||||
|
link: "https://www.threads.net/@naomi.lgbt",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "Instagram",
|
alt: "Instagram Logo",
|
||||||
link: "https://www.instagram.com/naomi.lgbt/",
|
|
||||||
alt: "Instagram Logo",
|
|
||||||
icon: faInstagram,
|
|
||||||
background: "#C13584",
|
background: "#C13584",
|
||||||
color: "#FFF",
|
color: "#FFF",
|
||||||
}
|
icon: faInstagram,
|
||||||
|
label: "Instagram",
|
||||||
|
link: "https://www.instagram.com/naomi.lgbt/",
|
||||||
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
|
export { HireMe, Donate, Socials };
|
||||||
|
@ -1,36 +1,45 @@
|
|||||||
export const TeamMembers: {
|
/**
|
||||||
name: string;
|
* @copyright nhcarrigan
|
||||||
avatar: string;
|
* @license Naomi's Public License
|
||||||
role: string;
|
* @author Naomi Carrigan
|
||||||
url: string;
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* List of nhcarrigan team members to render.
|
||||||
|
*/
|
||||||
|
export const TeamMembers: Array<{
|
||||||
|
name: string;
|
||||||
|
avatar: string;
|
||||||
|
role: string;
|
||||||
|
url: string;
|
||||||
joinDate: Date;
|
joinDate: Date;
|
||||||
}[] = [
|
}> = [
|
||||||
{
|
{
|
||||||
name: "Naomi Carrigan",
|
avatar: "naomi.png",
|
||||||
avatar: "naomi.png",
|
joinDate: new Date("April 1, 2020"),
|
||||||
role: "Founder / CEO",
|
name: "Naomi Carrigan",
|
||||||
url: "https://chat.nhcarrigan.com",
|
role: "Founder / CEO",
|
||||||
joinDate: new Date("April 1, 2020")
|
url: "https://chat.nhcarrigan.com",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Denna",
|
avatar: "denna.png",
|
||||||
avatar: "denna.png",
|
joinDate: new Date("April 2, 2020"),
|
||||||
role: "Chief Financial Officer",
|
name: "Denna",
|
||||||
url: "https://denna.nhcarrigan.com",
|
role: "Chief Financial Officer",
|
||||||
joinDate: new Date("April 2, 2020")
|
url: "https://denna.nhcarrigan.com",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Tim",
|
avatar: "tim.png",
|
||||||
avatar: "tim.png",
|
joinDate: new Date("April 2, 2020"),
|
||||||
role: "Chief Technical Officer",
|
name: "Tim",
|
||||||
url: "https://chat.nhcarrigan.com",
|
role: "Chief Technical Officer",
|
||||||
joinDate: new Date("April 2, 2020")
|
url: "https://chat.nhcarrigan.com",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Anna",
|
avatar: "anna.png",
|
||||||
avatar: "anna.png",
|
joinDate: new Date("August 29, 2023"),
|
||||||
role: "Software Engineering Intern",
|
name: "Anna",
|
||||||
url: "https://chat.nhcarrigan.com",
|
role: "Software Engineering Intern",
|
||||||
joinDate: new Date("August 29, 2023")
|
url: "https://chat.nhcarrigan.com",
|
||||||
}
|
},
|
||||||
]
|
];
|
||||||
|
@ -1,82 +1,90 @@
|
|||||||
import { IconDefinition } from "@fortawesome/fontawesome-svg-core";
|
/**
|
||||||
|
* @copyright nhcarrigan
|
||||||
|
* @license Naomi's Public License
|
||||||
|
* @author Naomi Carrigan
|
||||||
|
*/
|
||||||
import { faLinkedin } from "@fortawesome/free-brands-svg-icons";
|
import { faLinkedin } from "@fortawesome/free-brands-svg-icons";
|
||||||
|
import type { IconDefinition } from "@fortawesome/fontawesome-svg-core";
|
||||||
|
|
||||||
export const Testimonials: {
|
/**
|
||||||
name: string;
|
* List of reviews to render.
|
||||||
date: Date;
|
*/
|
||||||
content: string;
|
export const Testimonials: Array<{
|
||||||
|
name: string;
|
||||||
|
date: Date;
|
||||||
|
content: string;
|
||||||
sourceIcon: IconDefinition;
|
sourceIcon: IconDefinition;
|
||||||
sourceUrl: string;
|
sourceUrl: string;
|
||||||
sourceName: string;
|
sourceName: string;
|
||||||
}[] = [
|
}> = [
|
||||||
{
|
{
|
||||||
name: "Eddie Jaoude",
|
|
||||||
date: new Date("June 30, 2023"),
|
|
||||||
content:
|
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.",
|
"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,
|
sourceIcon: faLinkedin,
|
||||||
sourceUrl: "https://www.linkedin.com/in/naomi-lgbt/details/recommendations/",
|
sourceName: "LinkedIn",
|
||||||
sourceName: "LinkedIn"
|
sourceUrl: "https://www.linkedin.com/in/naomi-lgbt/details/recommendations/",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Danny Thompson",
|
|
||||||
date: new Date("July 6 2023"),
|
|
||||||
content:
|
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.",
|
"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,
|
sourceIcon: faLinkedin,
|
||||||
sourceUrl: "https://www.linkedin.com/in/naomi-lgbt/details/recommendations/",
|
sourceName: "LinkedIn",
|
||||||
sourceName: "LinkedIn"
|
sourceUrl: "https://www.linkedin.com/in/naomi-lgbt/details/recommendations/",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Francez Urmatan",
|
|
||||||
date: new Date("May 2 2024"),
|
|
||||||
content:
|
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!",
|
"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,
|
sourceIcon: faLinkedin,
|
||||||
sourceUrl: "https://www.linkedin.com/in/naomi-lgbt/details/recommendations/",
|
sourceName: "LinkedIn",
|
||||||
sourceName: "LinkedIn"
|
sourceUrl: "https://www.linkedin.com/in/naomi-lgbt/details/recommendations/",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Katey Berry",
|
|
||||||
date: new Date("May 14 2024"),
|
|
||||||
content:
|
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!",
|
"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,
|
sourceIcon: faLinkedin,
|
||||||
sourceUrl: "https://www.linkedin.com/in/naomi-lgbt/details/recommendations/",
|
sourceName: "LinkedIn",
|
||||||
sourceName: "LinkedIn"
|
sourceUrl: "https://www.linkedin.com/in/naomi-lgbt/details/recommendations/",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Kaitlyn Nichols",
|
|
||||||
date: new Date("May 30, 2024"),
|
|
||||||
content:
|
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.",
|
"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,
|
sourceIcon: faLinkedin,
|
||||||
sourceUrl: "https://www.linkedin.com/in/naomi-lgbt/details/recommendations/",
|
sourceName: "LinkedIn",
|
||||||
sourceName: "LinkedIn"
|
sourceUrl: "https://www.linkedin.com/in/naomi-lgbt/details/recommendations/",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Alix Takada Sharp",
|
|
||||||
date: new Date("July 15, 2024"),
|
|
||||||
content:
|
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.",
|
"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,
|
sourceIcon: faLinkedin,
|
||||||
sourceUrl: "https://www.linkedin.com/in/naomi-lgbt/details/recommendations/",
|
sourceName: "LinkedIn",
|
||||||
sourceName: "LinkedIn"
|
sourceUrl: "https://www.linkedin.com/in/naomi-lgbt/details/recommendations/",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Chris Ohman",
|
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"),
|
date: new Date("September 27, 2024"),
|
||||||
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.",
|
name: "Chris Ohman",
|
||||||
sourceIcon: faLinkedin,
|
sourceIcon: faLinkedin,
|
||||||
sourceUrl: "https://www.linkedin.com/in/naomi-lgbt/details/recommendations/",
|
sourceName: "LinkedIn",
|
||||||
sourceName: "LinkedIn"
|
sourceUrl: "https://www.linkedin.com/in/naomi-lgbt/details/recommendations/",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Alexis Madsen",
|
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"),
|
date: new Date("October 28 2024"),
|
||||||
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.",
|
name: "Alexis Madsen",
|
||||||
sourceIcon: faLinkedin,
|
sourceIcon: faLinkedin,
|
||||||
sourceUrl: "https://www.linkedin.com/in/naomi-lgbt/details/recommendations/",
|
sourceName: "LinkedIn",
|
||||||
sourceName: "LinkedIn"
|
sourceUrl: "https://www.linkedin.com/in/naomi-lgbt/details/recommendations/",
|
||||||
}
|
},
|
||||||
];
|
];
|
||||||
|
@ -1,8 +1,15 @@
|
|||||||
import { IconDefinition } from "@fortawesome/fontawesome-svg-core";
|
/**
|
||||||
|
* @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 = {
|
export const Codeberg: IconDefinition = {
|
||||||
prefix: "xxx",
|
|
||||||
iconName: "yyy",
|
|
||||||
icon: [
|
icon: [
|
||||||
474,
|
474,
|
||||||
474,
|
474,
|
||||||
@ -59,6 +66,8 @@ export const Codeberg: IconDefinition = {
|
|||||||
331.00,465.00 315.85,409.00 315.85,409.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
|
315.85,409.00 283.85,289.00 283.85,289.00
|
||||||
283.85,289.00 257.12,189.00 257.12,189.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`
|
257.12,189.00 244.00,138.00 244.00,138.00 Z`,
|
||||||
]
|
],
|
||||||
|
iconName: "yyy",
|
||||||
|
prefix: "xxx",
|
||||||
} as never;
|
} as never;
|
||||||
|
@ -1,8 +1,15 @@
|
|||||||
import { IconDefinition } from "@fortawesome/fontawesome-svg-core";
|
/**
|
||||||
|
* @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 = {
|
export const Fiverr: IconDefinition = {
|
||||||
prefix: "xxx",
|
|
||||||
iconName: "yyy",
|
|
||||||
icon: [
|
icon: [
|
||||||
300,
|
300,
|
||||||
300,
|
300,
|
||||||
@ -49,6 +56,8 @@ export const Fiverr: IconDefinition = {
|
|||||||
138.00,106.78 137.73,101.98 139.34,98.01
|
138.00,106.78 137.73,101.98 139.34,98.01
|
||||||
143.35,88.13 153.31,89.00 162.00,89.00
|
143.35,88.13 153.31,89.00 162.00,89.00
|
||||||
162.00,89.00 176.00,89.00 176.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`
|
176.00,89.00 176.00,58.00 176.00,58.00 Z`,
|
||||||
]
|
],
|
||||||
|
iconName: "yyy",
|
||||||
|
prefix: "xxx",
|
||||||
} as never;
|
} as never;
|
||||||
|
@ -1,8 +1,15 @@
|
|||||||
import { IconDefinition } from "@fortawesome/fontawesome-svg-core";
|
/**
|
||||||
|
* @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 = {
|
export const Gather: IconDefinition = {
|
||||||
prefix: "xxx",
|
|
||||||
iconName: "yyy",
|
|
||||||
icon: [
|
icon: [
|
||||||
38,
|
38,
|
||||||
42,
|
42,
|
||||||
@ -69,6 +76,8 @@ export const Gather: IconDefinition = {
|
|||||||
25.00,39.00 27.00,39.00 27.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
|
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,38.00 28.00,36.00 28.00,36.00
|
||||||
28.00,36.00 27.00,35.00 27.00,35.00 Z`
|
28.00,36.00 27.00,35.00 27.00,35.00 Z`,
|
||||||
]
|
],
|
||||||
|
iconName: "yyy",
|
||||||
|
prefix: "xxx",
|
||||||
} as never;
|
} as never;
|
||||||
|
@ -1,13 +1,22 @@
|
|||||||
import { IconDefinition } from "@fortawesome/fontawesome-svg-core";
|
/**
|
||||||
|
* @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 = {
|
export const Gog: IconDefinition = {
|
||||||
prefix: "xxx",
|
|
||||||
iconName: "yyy",
|
|
||||||
icon: [
|
icon: [
|
||||||
34,
|
34,
|
||||||
31,
|
31,
|
||||||
[],
|
[],
|
||||||
"U+E002",
|
"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`
|
`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;
|
} as never;
|
||||||
|
@ -1,8 +1,15 @@
|
|||||||
import { IconDefinition } from "@fortawesome/fontawesome-svg-core";
|
/**
|
||||||
|
* @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 = {
|
export const Kofi: IconDefinition = {
|
||||||
prefix: "xxx",
|
|
||||||
iconName: "yyy",
|
|
||||||
icon: [
|
icon: [
|
||||||
245,
|
245,
|
||||||
162,
|
162,
|
||||||
@ -63,6 +70,8 @@ export const Kofi: IconDefinition = {
|
|||||||
C 186.51,82.86 192.10,81.90 196.79,76.90
|
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
|
204.64,68.51 202.92,52.32 192.96,46.23
|
||||||
188.79,43.68 184.66,44.00 180.00,44.00
|
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`
|
180.00,44.00 180.00,83.00 180.00,83.00 Z`,
|
||||||
]
|
],
|
||||||
|
iconName: "yyy",
|
||||||
|
prefix: "xxx",
|
||||||
} as never;
|
} as never;
|
||||||
|
@ -1,8 +1,15 @@
|
|||||||
import { IconDefinition } from "@fortawesome/fontawesome-svg-core";
|
/**
|
||||||
|
* @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 = {
|
export const Matrix: IconDefinition = {
|
||||||
prefix: "xxx",
|
|
||||||
iconName: "yyy",
|
|
||||||
icon: [
|
icon: [
|
||||||
342,
|
342,
|
||||||
342,
|
342,
|
||||||
@ -56,6 +63,8 @@ export const Matrix: IconDefinition = {
|
|||||||
119.62,325.74 86.75,295.86 70.60,256.00
|
119.62,325.74 86.75,295.86 70.60,256.00
|
||||||
70.60,256.00 66.29,243.00 66.29,243.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
|
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`
|
60.14,203.20 59.71,189.94 78.00,184.53 Z`,
|
||||||
]
|
],
|
||||||
|
iconName: "yyy",
|
||||||
|
prefix: "xxx",
|
||||||
} as never;
|
} as never;
|
||||||
|
@ -1,8 +1,15 @@
|
|||||||
import { IconDefinition } from "@fortawesome/fontawesome-svg-core";
|
/**
|
||||||
|
* @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 = {
|
export const Peerlist: IconDefinition = {
|
||||||
prefix: "xxx",
|
|
||||||
iconName: "yyy",
|
|
||||||
icon: [
|
icon: [
|
||||||
512,
|
512,
|
||||||
512,
|
512,
|
||||||
@ -122,6 +129,8 @@ export const Peerlist: IconDefinition = {
|
|||||||
258.53,264.02 277.96,264.47 284.58,259.01
|
258.53,264.02 277.96,264.47 284.58,259.01
|
||||||
289.25,255.16 289.06,244.57 289.00,239.00
|
289.25,255.16 289.06,244.57 289.00,239.00
|
||||||
288.79,221.67 275.23,207.53 259.00,203.16
|
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`
|
253.08,201.56 247.07,202.00 241.00,202.00 Z`,
|
||||||
]
|
],
|
||||||
|
iconName: "yyy",
|
||||||
|
prefix: "xxx",
|
||||||
} as never;
|
} as never;
|
||||||
|
@ -1,8 +1,15 @@
|
|||||||
import { IconDefinition } from "@fortawesome/fontawesome-svg-core";
|
/**
|
||||||
|
* @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 = {
|
export const Pixiv: IconDefinition = {
|
||||||
prefix: "xxx",
|
|
||||||
iconName: "yyy",
|
|
||||||
icon: [
|
icon: [
|
||||||
900,
|
900,
|
||||||
900,
|
900,
|
||||||
@ -90,6 +97,8 @@ export const Pixiv: IconDefinition = {
|
|||||||
320.00,248.81 342.00,237.22 342.00,237.22
|
320.00,248.81 342.00,237.22 342.00,237.22
|
||||||
367.65,225.16 397.00,216.77 425.00,212.42
|
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
|
425.00,212.42 450.00,209.21 450.00,209.21 Z
|
||||||
`
|
`,
|
||||||
]
|
],
|
||||||
|
iconName: "yyy",
|
||||||
|
prefix: "xxx",
|
||||||
} as never;
|
} as never;
|
||||||
|
@ -1,13 +1,20 @@
|
|||||||
import { IconDefinition } from "@fortawesome/fontawesome-svg-core";
|
/**
|
||||||
|
* @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 = {
|
export const Polywork: IconDefinition = {
|
||||||
prefix: "xxx",
|
|
||||||
iconName: "yyy",
|
|
||||||
icon: [
|
icon: [
|
||||||
225, // SVG view box width
|
225,
|
||||||
225, // SVG view box height
|
225,
|
||||||
[],
|
[],
|
||||||
"U+E002", // probably not important for SVG and JS approach
|
"U+E002",
|
||||||
`M 153.00,155.00
|
`M 153.00,155.00
|
||||||
C 153.00,177.49 155.16,201.18 134.00,215.78
|
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
|
117.90,226.88 101.50,224.00 83.00,224.00
|
||||||
@ -71,6 +78,8 @@ export const Polywork: IconDefinition = {
|
|||||||
83.00,158.00 83.00,213.00 83.00,213.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
|
83.00,213.00 106.00,213.00 106.00,213.00
|
||||||
110.59,212.99 113.55,213.02 118.00,211.45
|
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`
|
143.85,202.34 141.00,180.01 141.00,158.00 Z`,
|
||||||
]
|
],
|
||||||
|
iconName: "yyy",
|
||||||
|
prefix: "xxx",
|
||||||
} as never;
|
} as never;
|
||||||
|
@ -1,8 +1,15 @@
|
|||||||
import { IconDefinition } from "@fortawesome/fontawesome-svg-core";
|
/**
|
||||||
|
* @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 = {
|
export const Saylor: IconDefinition = {
|
||||||
prefix: "xxx",
|
|
||||||
iconName: "yyy",
|
|
||||||
icon: [
|
icon: [
|
||||||
171,
|
171,
|
||||||
134,
|
134,
|
||||||
@ -56,6 +63,8 @@ export const Saylor: IconDefinition = {
|
|||||||
M 99.00,105.00
|
M 99.00,105.00
|
||||||
C 99.00,105.00 98.00,105.00 98.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
|
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`
|
99.00,106.00 99.00,105.00 99.00,105.00 Z`,
|
||||||
]
|
],
|
||||||
|
iconName: "yyy",
|
||||||
|
prefix: "xxx",
|
||||||
} as never;
|
} as never;
|
||||||
|
@ -1,8 +1,15 @@
|
|||||||
import { IconDefinition } from "@fortawesome/fontawesome-svg-core";
|
/**
|
||||||
|
* @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 = {
|
export const TeeSpring: IconDefinition = {
|
||||||
prefix: "xxx",
|
|
||||||
iconName: "yyy",
|
|
||||||
icon: [
|
icon: [
|
||||||
475,
|
475,
|
||||||
545,
|
545,
|
||||||
@ -62,4 +69,6 @@ export const TeeSpring: IconDefinition = {
|
|||||||
151.90,337.62 201.72,367.04 243.00,373.56
|
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`,
|
254.27,375.34 265.63,375.00 277.00,375.00 Z`,
|
||||||
],
|
],
|
||||||
|
iconName: "yyy",
|
||||||
|
prefix: "xxx",
|
||||||
} as never;
|
} as never;
|
||||||
|
@ -1,8 +1,15 @@
|
|||||||
import { IconDefinition } from "@fortawesome/fontawesome-svg-core";
|
/**
|
||||||
|
* @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 = {
|
export const TreeNation: IconDefinition = {
|
||||||
prefix: "xxx",
|
|
||||||
iconName: "yyy",
|
|
||||||
icon: [
|
icon: [
|
||||||
52,
|
52,
|
||||||
52,
|
52,
|
||||||
@ -134,6 +141,8 @@ export const TreeNation: IconDefinition = {
|
|||||||
M 23.00,34.00
|
M 23.00,34.00
|
||||||
C 23.00,34.00 22.00,34.00 22.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
|
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`
|
23.00,35.00 23.00,34.00 23.00,34.00 Z`,
|
||||||
]
|
],
|
||||||
|
iconName: "yyy",
|
||||||
|
prefix: "xxx",
|
||||||
} as never;
|
} as never;
|
||||||
|
@ -1,8 +1,15 @@
|
|||||||
import { IconDefinition } from "@fortawesome/fontawesome-svg-core";
|
/**
|
||||||
|
* @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 = {
|
export const VRoid: IconDefinition = {
|
||||||
prefix: "xxx",
|
|
||||||
iconName: "yyy",
|
|
||||||
icon: [
|
icon: [
|
||||||
280,
|
280,
|
||||||
280,
|
280,
|
||||||
@ -341,6 +348,8 @@ export const VRoid: IconDefinition = {
|
|||||||
86.00,263.00 72.00,264.00 72.00,264.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
|
72.00,264.00 167.00,264.00 167.00,264.00
|
||||||
167.00,264.00 194.00,264.00 194.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`
|
194.00,264.00 208.00,263.00 208.00,263.00 Z`,
|
||||||
]
|
],
|
||||||
|
iconName: "yyy",
|
||||||
|
prefix: "xxx",
|
||||||
} as never;
|
} as never;
|
||||||
|
@ -1,8 +1,15 @@
|
|||||||
import { IconDefinition } from "@fortawesome/fontawesome-svg-core";
|
/**
|
||||||
|
* @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 = {
|
export const Volunteer: IconDefinition = {
|
||||||
prefix: "xxx",
|
|
||||||
iconName: "yyy",
|
|
||||||
icon: [
|
icon: [
|
||||||
800,
|
800,
|
||||||
798,
|
798,
|
||||||
@ -178,6 +185,8 @@ export const Volunteer: IconDefinition = {
|
|||||||
352.06,530.24 370.17,544.94 390.00,545.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,545.00 390.00,559.00 390.00,559.00
|
||||||
390.00,559.00 410.00,559.00 410.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`
|
410.00,559.00 410.00,545.00 410.00,545.00 Z`,
|
||||||
]
|
],
|
||||||
|
iconName: "yyy",
|
||||||
|
prefix: "xxx",
|
||||||
} as never;
|
} as never;
|
||||||
|
@ -1,190 +1,204 @@
|
|||||||
|
/**
|
||||||
|
* @copyright nhcarrigan
|
||||||
|
* @license Naomi's Public License
|
||||||
|
* @author Naomi Carrigan
|
||||||
|
*/
|
||||||
interface ActivityData {
|
interface ActivityData {
|
||||||
id: number
|
id: number;
|
||||||
user_id: number
|
user_id: number;
|
||||||
op_type: string
|
op_type: string;
|
||||||
act_user_id: number
|
act_user_id: number;
|
||||||
act_user: ActUser
|
act_user: ActUser;
|
||||||
repo_id: number
|
repo_id: number;
|
||||||
repo: Repo
|
repo: Repo;
|
||||||
comment_id: number
|
comment_id: number;
|
||||||
comment?: Comment
|
comment?: Comment;
|
||||||
ref_name: string
|
ref_name: string;
|
||||||
is_private: boolean
|
is_private: boolean;
|
||||||
content: string
|
content: string;
|
||||||
created: string
|
created: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface ActUser {
|
interface ActUser {
|
||||||
id: number
|
id: number;
|
||||||
login: string
|
login: string;
|
||||||
login_name: string
|
login_name: string;
|
||||||
source_id: number
|
source_id: number;
|
||||||
full_name: string
|
full_name: string;
|
||||||
email: string
|
email: string;
|
||||||
avatar_url: string
|
avatar_url: string;
|
||||||
html_url: string
|
html_url: string;
|
||||||
language: string
|
language: string;
|
||||||
is_admin: boolean
|
is_admin: boolean;
|
||||||
last_login: string
|
last_login: string;
|
||||||
created: string
|
created: string;
|
||||||
restricted: boolean
|
restricted: boolean;
|
||||||
active: boolean
|
active: boolean;
|
||||||
prohibit_login: boolean
|
prohibit_login: boolean;
|
||||||
location: string
|
location: string;
|
||||||
pronouns: string
|
pronouns: string;
|
||||||
website: string
|
website: string;
|
||||||
description: string
|
description: string;
|
||||||
visibility: string
|
visibility: string;
|
||||||
followers_count: number
|
followers_count: number;
|
||||||
following_count: number
|
following_count: number;
|
||||||
starred_repos_count: number
|
starred_repos_count: number;
|
||||||
username: string
|
username: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface Repo {
|
interface Repo {
|
||||||
id: number
|
id: number;
|
||||||
owner: Owner
|
owner: Owner;
|
||||||
name: string
|
name: string;
|
||||||
full_name: string
|
full_name: string;
|
||||||
description: string
|
description: string;
|
||||||
empty: boolean
|
empty: boolean;
|
||||||
private: boolean
|
private: boolean;
|
||||||
fork: boolean
|
fork: boolean;
|
||||||
template: boolean
|
template: boolean;
|
||||||
parent: any
|
parent: unknown;
|
||||||
mirror: boolean
|
mirror: boolean;
|
||||||
size: number
|
size: number;
|
||||||
language: string
|
language: string;
|
||||||
languages_url: string
|
languages_url: string;
|
||||||
html_url: string
|
html_url: string;
|
||||||
url: string
|
url: string;
|
||||||
link: string
|
link: string;
|
||||||
ssh_url: string
|
ssh_url: string;
|
||||||
clone_url: string
|
clone_url: string;
|
||||||
original_url: string
|
original_url: string;
|
||||||
website: string
|
website: string;
|
||||||
stars_count: number
|
stars_count: number;
|
||||||
forks_count: number
|
forks_count: number;
|
||||||
watchers_count: number
|
watchers_count: number;
|
||||||
open_issues_count: number
|
open_issues_count: number;
|
||||||
open_pr_counter: number
|
open_pr_counter: number;
|
||||||
release_counter: number
|
release_counter: number;
|
||||||
default_branch: string
|
default_branch: string;
|
||||||
archived: boolean
|
archived: boolean;
|
||||||
created_at: string
|
created_at: string;
|
||||||
updated_at: string
|
updated_at: string;
|
||||||
archived_at: string
|
archived_at: string;
|
||||||
permissions: Permissions
|
permissions: Permissions;
|
||||||
has_issues: boolean
|
has_issues: boolean;
|
||||||
external_tracker: ExternalTracker
|
external_tracker: ExternalTracker;
|
||||||
has_wiki: boolean
|
has_wiki: boolean;
|
||||||
wiki_branch: string
|
wiki_branch: string;
|
||||||
globally_editable_wiki: boolean
|
globally_editable_wiki: boolean;
|
||||||
has_pull_requests: boolean
|
has_pull_requests: boolean;
|
||||||
has_projects: boolean
|
has_projects: boolean;
|
||||||
has_releases: boolean
|
has_releases: boolean;
|
||||||
has_packages: boolean
|
has_packages: boolean;
|
||||||
has_actions: boolean
|
has_actions: boolean;
|
||||||
ignore_whitespace_conflicts: boolean
|
ignore_whitespace_conflicts: boolean;
|
||||||
allow_merge_commits: boolean
|
allow_merge_commits: boolean;
|
||||||
allow_rebase: boolean
|
allow_rebase: boolean;
|
||||||
allow_rebase_explicit: boolean
|
allow_rebase_explicit: boolean;
|
||||||
allow_squash_merge: boolean
|
allow_squash_merge: boolean;
|
||||||
allow_fast_forward_only_merge: boolean
|
allow_fast_forward_only_merge: boolean;
|
||||||
allow_rebase_update: boolean
|
allow_rebase_update: boolean;
|
||||||
default_delete_branch_after_merge: boolean
|
default_delete_branch_after_merge: boolean;
|
||||||
default_merge_style: string
|
default_merge_style: string;
|
||||||
default_allow_maintainer_edit: boolean
|
default_allow_maintainer_edit: boolean;
|
||||||
avatar_url: string
|
avatar_url: string;
|
||||||
internal: boolean
|
internal: boolean;
|
||||||
mirror_interval: string
|
mirror_interval: string;
|
||||||
object_format_name: string
|
object_format_name: string;
|
||||||
mirror_updated: string
|
mirror_updated: string;
|
||||||
repo_transfer: any
|
repo_transfer: unknown;
|
||||||
topics: any
|
topics: unknown;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface Owner {
|
interface Owner {
|
||||||
id: number
|
id: number;
|
||||||
login: string
|
login: string;
|
||||||
login_name: string
|
login_name: string;
|
||||||
source_id: number
|
source_id: number;
|
||||||
full_name: string
|
full_name: string;
|
||||||
email: string
|
email: string;
|
||||||
avatar_url: string
|
avatar_url: string;
|
||||||
html_url: string
|
html_url: string;
|
||||||
language: string
|
language: string;
|
||||||
is_admin: boolean
|
is_admin: boolean;
|
||||||
last_login: string
|
last_login: string;
|
||||||
created: string
|
created: string;
|
||||||
restricted: boolean
|
restricted: boolean;
|
||||||
active: boolean
|
active: boolean;
|
||||||
prohibit_login: boolean
|
prohibit_login: boolean;
|
||||||
location: string
|
location: string;
|
||||||
pronouns: string
|
pronouns: string;
|
||||||
website: string
|
website: string;
|
||||||
description: string
|
description: string;
|
||||||
visibility: string
|
visibility: string;
|
||||||
followers_count: number
|
followers_count: number;
|
||||||
following_count: number
|
following_count: number;
|
||||||
starred_repos_count: number
|
starred_repos_count: number;
|
||||||
username: string
|
username: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface Permissions {
|
interface Permissions {
|
||||||
admin: boolean
|
admin: boolean;
|
||||||
push: boolean
|
push: boolean;
|
||||||
pull: boolean
|
pull: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface ExternalTracker {
|
interface ExternalTracker {
|
||||||
external_tracker_url: string
|
external_tracker_url: string;
|
||||||
external_tracker_format: string
|
external_tracker_format: string;
|
||||||
external_tracker_style: string
|
external_tracker_style: string;
|
||||||
external_tracker_regexp_pattern: string
|
external_tracker_regexp_pattern: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface Comment {
|
interface Comment {
|
||||||
id: number
|
id: number;
|
||||||
html_url: string
|
html_url: string;
|
||||||
pull_request_url: string
|
pull_request_url: string;
|
||||||
issue_url: string
|
issue_url: string;
|
||||||
user: any
|
user: unknown;
|
||||||
original_author: string
|
original_author: string;
|
||||||
original_author_id: number
|
original_author_id: number;
|
||||||
body: string
|
body: string;
|
||||||
assets: any[]
|
assets: Array<unknown>;
|
||||||
created_at: string
|
created_at: string;
|
||||||
updated_at: string
|
updated_at: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class Codeberg {
|
class Codeberg {
|
||||||
private cache: ActivityData[];
|
private cache: Array<ActivityData>;
|
||||||
private lastUpdate: Date | null = null;
|
private lastUpdate: Date | null = null;
|
||||||
constructor() {
|
public constructor() {
|
||||||
this.cache = [];
|
this.cache = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async getActivities(): Promise<Array<ActivityData>> {
|
||||||
|
// Stale after 6 hours
|
||||||
|
if (this.lastUpdate && Date.now()
|
||||||
|
- this.lastUpdate.getTime() < 6 * 60 * 60 * 1000) {
|
||||||
|
return this.cache;
|
||||||
|
}
|
||||||
|
return await this.refreshData().then(() => {
|
||||||
|
return this.cache;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
private async refreshData(): Promise<Codeberg> {
|
private async refreshData(): Promise<Codeberg> {
|
||||||
const response = await fetch("https://codeberg.org/api/v1/users/naomi-lgbt/activities/feeds?only-performed-by=true");
|
const response = await
|
||||||
const data = await response.json() as ActivityData[];
|
// 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 data = await response.json() as Array<ActivityData>;
|
||||||
this.cache = data;
|
this.cache = data;
|
||||||
this.lastUpdate = new Date();
|
this.lastUpdate = new Date();
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async getActivities(): Promise<ActivityData[]> {
|
|
||||||
// Stale after 6 hours
|
|
||||||
if (this.lastUpdate && (new Date().getTime() - this.lastUpdate.getTime()) < 6 * 60 * 60 * 1000) {
|
|
||||||
return this.cache;
|
|
||||||
}
|
|
||||||
return this.refreshData().then(() => this.cache);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const instantiated = new Codeberg();
|
const instantiated = new Codeberg();
|
||||||
|
|
||||||
export const getCodebergData = async (): Promise<ActivityData[]> => {
|
/**
|
||||||
|
* Fetches and caches the Codeberg activity.
|
||||||
|
* @returns An array of activity objects.
|
||||||
|
*/
|
||||||
|
export const getCodebergData = async(): Promise<Array<ActivityData>> => {
|
||||||
return await instantiated.getActivities();
|
return await instantiated.getActivities();
|
||||||
}
|
};
|
||||||
|
1161
src/lib/github.ts
1161
src/lib/github.ts
File diff suppressed because it is too large
Load Diff
@ -1,11 +1,12 @@
|
|||||||
{
|
{
|
||||||
|
"extends": "@nhcarrigan/typescript-config",
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"lib": ["dom", "dom.iterable", "esnext"],
|
"lib": [
|
||||||
"allowJs": true,
|
"dom",
|
||||||
"skipLibCheck": true,
|
"dom.iterable",
|
||||||
"strict": true,
|
"esnext"
|
||||||
|
],
|
||||||
"noEmit": true,
|
"noEmit": true,
|
||||||
"esModuleInterop": true,
|
|
||||||
"module": "esnext",
|
"module": "esnext",
|
||||||
"moduleResolution": "bundler",
|
"moduleResolution": "bundler",
|
||||||
"resolveJsonModule": true,
|
"resolveJsonModule": true,
|
||||||
@ -18,9 +19,19 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"paths": {
|
"paths": {
|
||||||
"@/*": ["./src/*"]
|
"@/*": [
|
||||||
}
|
"./src/*"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"allowJs": true
|
||||||
},
|
},
|
||||||
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
|
"include": [
|
||||||
"exclude": ["node_modules"]
|
"next-env.d.ts",
|
||||||
|
"**/*.ts",
|
||||||
|
"**/*.tsx",
|
||||||
|
".next/types/**/*.ts"
|
||||||
|
],
|
||||||
|
"exclude": [
|
||||||
|
"node_modules"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user