Initial commit

Change-Id: I37de68424e6574d6df053ed504de3e11d43a866f
diff --git a/.envrc b/.envrc
new file mode 100644
index 0000000..2abed0b
--- /dev/null
+++ b/.envrc
@@ -0,0 +1,2 @@
+use flake .
+dotenv .env
\ No newline at end of file
diff --git a/.eslintrc.json b/.eslintrc.json
new file mode 100644
index 0000000..bffb357
--- /dev/null
+++ b/.eslintrc.json
@@ -0,0 +1,3 @@
+{
+  "extends": "next/core-web-vitals"
+}
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..0b0c386
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,39 @@
+# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
+
+/.direnv/
+.env
+
+# dependencies
+/node_modules
+/.pnp
+.pnp.js
+.yarn/install-state.gz
+
+# testing
+/coverage
+
+# next.js
+/.next/
+/out/
+
+# production
+/build
+
+# misc
+.DS_Store
+*.pem
+
+# debug
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+
+# local env files
+.env*.local
+
+# vercel
+.vercel
+
+# typescript
+*.tsbuildinfo
+next-env.d.ts
diff --git a/.gitreview b/.gitreview
new file mode 100644
index 0000000..7a5a36a
--- /dev/null
+++ b/.gitreview
@@ -0,0 +1,5 @@
+[gerrit]
+host=ssh.clicks.codes
+port=29418
+defaultbranch=main
+project=Coded/Resume.git
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..c403366
--- /dev/null
+++ b/README.md
@@ -0,0 +1,36 @@
+This is a [Next.js](https://nextjs.org/) project bootstrapped with [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app).
+
+## Getting Started
+
+First, run the development server:
+
+```bash
+npm run dev
+# or
+yarn dev
+# or
+pnpm dev
+# or
+bun dev
+```
+
+Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.
+
+You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file.
+
+This project uses [`next/font`](https://nextjs.org/docs/basic-features/font-optimization) to automatically optimize and load Inter, a custom Google Font.
+
+## Learn More
+
+To learn more about Next.js, take a look at the following resources:
+
+- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API.
+- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial.
+
+You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome!
+
+## Deploy on Vercel
+
+The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js.
+
+Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details.
diff --git a/app/favicon.ico b/app/favicon.ico
new file mode 100644
index 0000000..718d6fe
--- /dev/null
+++ b/app/favicon.ico
Binary files differ
diff --git a/app/globals.css b/app/globals.css
new file mode 100644
index 0000000..822712e
--- /dev/null
+++ b/app/globals.css
@@ -0,0 +1,18 @@
+@tailwind base;
+@tailwind components;
+@tailwind utilities;
+
+:root {
+  --foreground-rgb: 0, 0, 0;
+}
+
+body {
+  color: rgb(var(--foreground-rgb));
+  background: white
+}
+
+@layer utilities {
+  .text-balance {
+    text-wrap: balance;
+  }
+}
diff --git a/app/layout.tsx b/app/layout.tsx
new file mode 100644
index 0000000..2e00284
--- /dev/null
+++ b/app/layout.tsx
@@ -0,0 +1,22 @@
+import type { Metadata } from "next";
+import { Inter } from "next/font/google";
+import "./globals.css";
+
+const inter = Inter({ subsets: ["latin"] });
+
+export const metadata: Metadata = {
+  title: "Create Next App",
+  description: "Generated by create next app",
+};
+
+export default function RootLayout({
+  children,
+}: Readonly<{
+  children: React.ReactNode;
+}>) {
+  return (
+    <html lang="en">
+      <body className={`flex justify-center ${inter.className}${process.env.PRODUCTION ? " my-2 w-full items-center" : null}`}>{children}</body>
+    </html>
+  );
+}
diff --git a/app/page.tsx b/app/page.tsx
new file mode 100644
index 0000000..7158e27
--- /dev/null
+++ b/app/page.tsx
@@ -0,0 +1,144 @@
+import Work from "@/components/work";
+
+const summary = `
+  I'm a 20, going on 21, year old developer who's been programming since I was 11. I started with Python and have since taken my skills to both NodeJS and Rust.
+  I'm eager to make your acquaintance and put my skills to use in a collaborative environment.
+`
+
+export default function Home() {
+  return (
+    <main className={`flex min-h-screen ${process.env.PRODUCTION ? "w-1/2" : "w-full"} flex-col items-center p-2`}>
+      <div id="info" className="flex h-fit gap-2 my-2 justify-between w-full">
+        <div className="flex flex-col text-sm">
+          <h1 className="text-sm">Delaware, USA</h1>
+          <a href="mailto:coded@clicks.codes"><p>coded@clicks.codes</p></a>
+        </div>
+        <h1 className="text-2xl pl-40">Samuel Shuert</h1>
+        <div className="flex flex-col text-sm text-right">
+          <a href="https://linkedin.com/in/samuelshuert"><p className="underline">linkedin.com/in/samuelshuert</p></a>
+          <a href="https://github.com/TheCodedProf"><p className="underline">github.com/TheCodedProf</p></a>
+          <a href="https://git.clicks.codes/q/owner:coded"><p className="underline">git.clicks.codes/q/owner:coded</p></a>
+          <a href="https://app.codecrafters.io/users/TheCodedProf"><p className="underline">app.codecrafters.io/users/TheCodedProf</p></a>
+        </div>
+      </div>
+
+      <h1 className="self-start text-xl">Summary</h1>
+      <hr className="w-full border-t border-t-black mb-2"/>
+
+      <p className="text-sm mb-8 pl-4 text-left w-full">
+        {summary}
+      </p>
+
+      <h1 className="self-start text-xl">Work Experience</h1>
+      <hr className="w-full border-t border-t-black"/>
+
+      <div id="experience" className="flex flex-col h-fit gap-8 my-2 w-full mb-16">
+
+        <Work jobTitle={"Developer"} area={"Infrastructure"} projectName={"Clicks Nix"} dateFrom={"Aug 2022"} dateTo={"Current"} obsolete={false} >
+          <li>
+            Nix configuration for Clicks servers.
+          </li>
+          <li>
+            Responsible for general mainenance and major updates, depends on current needs.
+          </li>
+          <li>
+            Written in Nix
+          </li>
+        </Work>
+
+        <Work jobTitle={"Developer"} area={"Backend"} projectName={"Nucleus"} dateFrom={"Sep 2020"} dateTo={"Sep 2023"} obsolete={false}>
+          <li>Nucleus (Feb 2023 - Sep 2023)</li>
+          <ul className="ml-8 mt-2 list-disc text-sm mb-4">
+            <li>
+              Discord moderation bot. Rewritten with TypeScript.
+            </li>
+            <li>
+              I was responsible for database read/write and slash command registration.
+            </li>
+            <li>
+              Used Node.JS (w/ TypeScript), discord.js and MongoDB
+            </li>
+          </ul>
+          <li>Remote Server Management (RSM) Version 2 (Jan 2021 - Jan 2022)</li>
+          <ul className="ml-8 mt-2 list-disc text-sm mb-4">
+            <li>
+              Discord moderation bot. Additional features including NSFW image detection and checking for malware.
+            </li>
+            <li>
+              I was responsible for the guild settings flow, tesseract flow and clamav flow.
+            </li>
+            <li>
+              Used Python, discord.py and JSON
+            </li>
+          </ul>
+          <li>Remote Server Management (RSM) Version 1 (Sep 2020 - Jan 2021)</li>
+          <ul className="ml-8 mt-2 list-disc text-sm">
+            <li>
+              Discord moderation bot. Featuring readable UI and extra moderation features Discord does not have like tempbans.
+            </li>
+            <li>
+              I was responsible for the guild settings flow.
+            </li>
+            <li>
+              Used Python, discord.py and JSON
+            </li>
+          </ul>
+        </Work>
+
+        <Work jobTitle={"Developer"} area={"Backend"} projectName={"Innuendo"} dateFrom={"Jul 2020"} dateTo={"Current"} obsolete={false}>
+          <li>Innuendo (Dec 2023 - Current)</li>
+          <ul className="ml-8 mt-2 list-disc text-sm">
+            <li>
+              Cardboard Against Humankind remade in Rust
+            </li>
+            <li>
+              I'm the main developer for this project, in charge of coordinating other people the main game loop code.
+            </li>
+            <li>
+              Uses Rust, Serenity-rs + Poise, and Postgres
+            </li>
+          </ul>
+          <li>Cardboard Against Humankind (Jul 2020 - Sep 2021)</li>
+          <ul className="ml-8 mt-2 list-disc text-sm">
+            <li>
+              A Cards Against Humanity discord bot. Was invited to 2000+ servers and had ~400 congruent games at peak times.
+            </li>
+            <li>
+              I was responsible for writing the game loop and discord interactions.
+            </li>
+            <li>
+              Used Python, discord.py and JSON
+            </li>
+          </ul>
+        </Work>
+
+        <Work jobTitle={"Lead Developer"} area={"Full Stack"} projectName={"Infinite Stories"} dateFrom={"Oct 2021"} dateTo={"Jun 2022"} obsolete={true} >
+          <li>
+            Website that allowed writers to publish excerpts from their books online to get feedback
+          </li>
+          <li>
+            I was responsible for full website design, component creation, read/write to supabase, 
+          </li>
+          <li>
+            Used Next.JS for web development and Supabase for storage
+          </li>
+        </Work>
+      </div>
+
+      <h1 className="self-start text-xl">Certifications</h1>
+      <hr className="w-full border-t border-t-black"/>
+      
+      <div id="skills" className="flex flex-col h-fit gap-2 my-2 w-full mb-16">
+        <p className="text-sm"><strong>CodeCrafters: </strong>HTTP Server (Rust)</p>
+      </div>
+
+      <h1 className="self-start text-xl">Skills</h1>
+      <hr className="w-full border-t border-t-black"/>
+      
+      <div id="skills" className="flex flex-col h-fit gap-2 my-2 w-full">
+        <p className="text-sm"><strong>Languages: </strong>TypeScript, JavaScript, Rust, Nix, Python</p>
+        <p className="text-sm"><strong>Tools: </strong>MongoDB, Postgres, Supabase, Next.JS, Vercel, Git, Gerrit, GitHub, Google Cloud, Cloudflare (DNS, Workers, Zero Trust, cloudflared), AWS, Nix</p>
+      </div>
+    </main>
+  );
+}
diff --git a/bun.lockb b/bun.lockb
new file mode 100755
index 0000000..8489a14
--- /dev/null
+++ b/bun.lockb
Binary files differ
diff --git a/components/work.tsx b/components/work.tsx
new file mode 100644
index 0000000..4e614b2
--- /dev/null
+++ b/components/work.tsx
@@ -0,0 +1,32 @@
+interface WorkProps {
+    jobTitle: string
+    projectName: string
+    dateFrom: string
+    dateTo: string
+    children: React.ReactNode
+    obsolete: boolean
+    area: string
+}
+
+export default function Work(props: WorkProps) {
+    return (
+        <div>
+          <div className="grid-cols-3 grid-rows-1 w-full text-base grid">
+            <h1 className="text-left"><strong>{props.jobTitle}</strong></h1>    
+            <div className="flex justify-center text-center items-center gap-2">
+                <h1 className="text-base">{props.projectName}</h1>
+                <p className="w-fit bg-green-300 border border-green-700 text-xs rounded-lg px-1 text-center justify-center">{props.area}</p>
+                {
+                    props.obsolete ?
+                    <div className="bg-red-300 border border-red-700 text-xs rounded-lg px-1">Obsolete</div>
+                    : null
+                }
+            </div>
+            <h1 className="text-right">{props.dateFrom} - {props.dateTo}</h1>
+          </div>
+          <ul className="ml-8 mt-2 list-disc text-sm">
+            {props.children}
+          </ul>
+        </div>
+    )
+}
\ No newline at end of file
diff --git a/flake.lock b/flake.lock
new file mode 100644
index 0000000..b594637
--- /dev/null
+++ b/flake.lock
@@ -0,0 +1,61 @@
+{
+  "nodes": {
+    "flake-utils": {
+      "inputs": {
+        "systems": "systems"
+      },
+      "locked": {
+        "lastModified": 1705309234,
+        "narHash": "sha256-uNRRNRKmJyCRC/8y1RqBkqWBLM034y4qN7EprSdmgyA=",
+        "owner": "numtide",
+        "repo": "flake-utils",
+        "rev": "1ef2e671c3b0c19053962c07dbda38332dcebf26",
+        "type": "github"
+      },
+      "original": {
+        "owner": "numtide",
+        "repo": "flake-utils",
+        "type": "github"
+      }
+    },
+    "nixpkgs": {
+      "locked": {
+        "lastModified": 1707205916,
+        "narHash": "sha256-fmRJilYGlB7VCt3XsdYxrA0u8e/K84O5xYucerUY0iM=",
+        "owner": "NixOS",
+        "repo": "nixpkgs",
+        "rev": "8cc79aa39bbc6eaedaf286ae655b224c71e02907",
+        "type": "github"
+      },
+      "original": {
+        "owner": "NixOS",
+        "ref": "nixpkgs-unstable",
+        "repo": "nixpkgs",
+        "type": "github"
+      }
+    },
+    "root": {
+      "inputs": {
+        "flake-utils": "flake-utils",
+        "nixpkgs": "nixpkgs"
+      }
+    },
+    "systems": {
+      "locked": {
+        "lastModified": 1681028828,
+        "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
+        "owner": "nix-systems",
+        "repo": "default",
+        "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
+        "type": "github"
+      },
+      "original": {
+        "owner": "nix-systems",
+        "repo": "default",
+        "type": "github"
+      }
+    }
+  },
+  "root": "root",
+  "version": 7
+}
diff --git a/flake.nix b/flake.nix
new file mode 100644
index 0000000..fded9c1
--- /dev/null
+++ b/flake.nix
@@ -0,0 +1,14 @@
+{
+  description = "A basic flake with a shell";
+  inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable";
+  inputs.flake-utils.url = "github:numtide/flake-utils";
+
+  outputs = { self, nixpkgs, flake-utils }:
+    flake-utils.lib.eachDefaultSystem (system: let
+      pkgs = nixpkgs.legacyPackages.${system};
+    in {
+      devShells.default = pkgs.mkShell {
+        nativeBuildInputs = with pkgs; [nodejs_21 bun];
+      };
+    });
+}
diff --git a/next.config.mjs b/next.config.mjs
new file mode 100644
index 0000000..19db13e
--- /dev/null
+++ b/next.config.mjs
@@ -0,0 +1,12 @@
+/** @type {import('next').NextConfig} */
+const nextConfig = {
+    images: {
+        remotePatterns: [
+            {
+                hostname: "img.icons8.com"
+            }
+        ]
+    }
+};
+
+export default nextConfig;
diff --git a/package.json b/package.json
new file mode 100644
index 0000000..b7b4956
--- /dev/null
+++ b/package.json
@@ -0,0 +1,27 @@
+{
+  "name": "resume",
+  "version": "0.1.0",
+  "private": true,
+  "scripts": {
+    "dev": "next dev",
+    "build": "next build",
+    "start": "next start",
+    "lint": "next lint"
+  },
+  "dependencies": {
+    "react": "^18",
+    "react-dom": "^18",
+    "next": "14.1.0"
+  },
+  "devDependencies": {
+    "typescript": "^5",
+    "@types/node": "^20",
+    "@types/react": "^18",
+    "@types/react-dom": "^18",
+    "autoprefixer": "^10.0.1",
+    "postcss": "^8",
+    "tailwindcss": "^3.3.0",
+    "eslint": "^8",
+    "eslint-config-next": "14.1.0"
+  }
+}
diff --git a/postcss.config.js b/postcss.config.js
new file mode 100644
index 0000000..12a703d
--- /dev/null
+++ b/postcss.config.js
@@ -0,0 +1,6 @@
+module.exports = {
+  plugins: {
+    tailwindcss: {},
+    autoprefixer: {},
+  },
+};
diff --git a/public/next.svg b/public/next.svg
new file mode 100644
index 0000000..5174b28
--- /dev/null
+++ b/public/next.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 394 80"><path fill="#000" d="M262 0h68.5v12.7h-27.2v66.6h-13.6V12.7H262V0ZM149 0v12.7H94v20.4h44.3v12.6H94v21h55v12.6H80.5V0h68.7zm34.3 0h-17.8l63.8 79.4h17.9l-32-39.7 32-39.6h-17.9l-23 28.6-23-28.6zm18.3 56.7-9-11-27.1 33.7h17.8l18.3-22.7z"/><path fill="#000" d="M81 79.3 17 0H0v79.3h13.6V17l50.2 62.3H81Zm252.6-.4c-1 0-1.8-.4-2.5-1s-1.1-1.6-1.1-2.6.3-1.8 1-2.5 1.6-1 2.6-1 1.8.3 2.5 1a3.4 3.4 0 0 1 .6 4.3 3.7 3.7 0 0 1-3 1.8zm23.2-33.5h6v23.3c0 2.1-.4 4-1.3 5.5a9.1 9.1 0 0 1-3.8 3.5c-1.6.8-3.5 1.3-5.7 1.3-2 0-3.7-.4-5.3-1s-2.8-1.8-3.7-3.2c-.9-1.3-1.4-3-1.4-5h6c.1.8.3 1.6.7 2.2s1 1.2 1.6 1.5c.7.4 1.5.5 2.4.5 1 0 1.8-.2 2.4-.6a4 4 0 0 0 1.6-1.8c.3-.8.5-1.8.5-3V45.5zm30.9 9.1a4.4 4.4 0 0 0-2-3.3 7.5 7.5 0 0 0-4.3-1.1c-1.3 0-2.4.2-3.3.5-.9.4-1.6 1-2 1.6a3.5 3.5 0 0 0-.3 4c.3.5.7.9 1.3 1.2l1.8 1 2 .5 3.2.8c1.3.3 2.5.7 3.7 1.2a13 13 0 0 1 3.2 1.8 8.1 8.1 0 0 1 3 6.5c0 2-.5 3.7-1.5 5.1a10 10 0 0 1-4.4 3.5c-1.8.8-4.1 1.2-6.8 1.2-2.6 0-4.9-.4-6.8-1.2-2-.8-3.4-2-4.5-3.5a10 10 0 0 1-1.7-5.6h6a5 5 0 0 0 3.5 4.6c1 .4 2.2.6 3.4.6 1.3 0 2.5-.2 3.5-.6 1-.4 1.8-1 2.4-1.7a4 4 0 0 0 .8-2.4c0-.9-.2-1.6-.7-2.2a11 11 0 0 0-2.1-1.4l-3.2-1-3.8-1c-2.8-.7-5-1.7-6.6-3.2a7.2 7.2 0 0 1-2.4-5.7 8 8 0 0 1 1.7-5 10 10 0 0 1 4.3-3.5c2-.8 4-1.2 6.4-1.2 2.3 0 4.4.4 6.2 1.2 1.8.8 3.2 2 4.3 3.4 1 1.4 1.5 3 1.5 5h-5.8z"/></svg>
\ No newline at end of file
diff --git a/public/vercel.svg b/public/vercel.svg
new file mode 100644
index 0000000..d2f8422
--- /dev/null
+++ b/public/vercel.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 283 64"><path fill="black" d="M141 16c-11 0-19 7-19 18s9 18 20 18c7 0 13-3 16-7l-7-5c-2 3-6 4-9 4-5 0-9-3-10-7h28v-3c0-11-8-18-19-18zm-9 15c1-4 4-7 9-7s8 3 9 7h-18zm117-15c-11 0-19 7-19 18s9 18 20 18c6 0 12-3 16-7l-8-5c-2 3-5 4-8 4-5 0-9-3-11-7h28l1-3c0-11-8-18-19-18zm-10 15c2-4 5-7 10-7s8 3 9 7h-19zm-39 3c0 6 4 10 10 10 4 0 7-2 9-5l8 5c-3 5-9 8-17 8-11 0-19-7-19-18s8-18 19-18c8 0 14 3 17 8l-8 5c-2-3-5-5-9-5-6 0-10 4-10 10zm83-29v46h-9V5h9zM37 0l37 64H0L37 0zm92 5-27 48L74 5h10l18 30 17-30h10zm59 12v10l-3-1c-6 0-10 4-10 10v15h-9V17h9v9c0-5 6-9 13-9z"/></svg>
\ No newline at end of file
diff --git a/tailwind.config.ts b/tailwind.config.ts
new file mode 100644
index 0000000..7e4bd91
--- /dev/null
+++ b/tailwind.config.ts
@@ -0,0 +1,20 @@
+import type { Config } from "tailwindcss";
+
+const config: Config = {
+  content: [
+    "./pages/**/*.{js,ts,jsx,tsx,mdx}",
+    "./components/**/*.{js,ts,jsx,tsx,mdx}",
+    "./app/**/*.{js,ts,jsx,tsx,mdx}",
+  ],
+  theme: {
+    extend: {
+      backgroundImage: {
+        "gradient-radial": "radial-gradient(var(--tw-gradient-stops))",
+        "gradient-conic":
+          "conic-gradient(from 180deg at 50% 50%, var(--tw-gradient-stops))",
+      },
+    },
+  },
+  plugins: [],
+};
+export default config;
diff --git a/tsconfig.json b/tsconfig.json
new file mode 100644
index 0000000..e7ff90f
--- /dev/null
+++ b/tsconfig.json
@@ -0,0 +1,26 @@
+{
+  "compilerOptions": {
+    "lib": ["dom", "dom.iterable", "esnext"],
+    "allowJs": true,
+    "skipLibCheck": true,
+    "strict": true,
+    "noEmit": true,
+    "esModuleInterop": true,
+    "module": "esnext",
+    "moduleResolution": "bundler",
+    "resolveJsonModule": true,
+    "isolatedModules": true,
+    "jsx": "preserve",
+    "incremental": true,
+    "plugins": [
+      {
+        "name": "next"
+      }
+    ],
+    "paths": {
+      "@/*": ["./*"]
+    }
+  },
+  "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
+  "exclude": ["node_modules"]
+}