Updates
This commit is contained in:
parent
8f5abed48d
commit
3b9fa373bc
@ -7,6 +7,7 @@ export const work = {
|
||||
description: "Clould-based SQL data management system.",
|
||||
href: "https://datasquirel.com",
|
||||
image: "/images/work/devops/server-management.png",
|
||||
metrics: [""],
|
||||
technologies: [
|
||||
"Node JS",
|
||||
"SQL",
|
||||
@ -24,6 +25,11 @@ export const work = {
|
||||
description: "Mortgage Broker in Utah",
|
||||
href: "https://summitlending.com",
|
||||
image: "/images/work/devops/server-management.png",
|
||||
metrics: [
|
||||
"500+ leads/month",
|
||||
"~10 deploys/week",
|
||||
"99.99% uptime",
|
||||
],
|
||||
technologies: [
|
||||
"Next JS",
|
||||
"Tailwind CSS",
|
||||
@ -38,6 +44,7 @@ export const work = {
|
||||
description: "A new age of remote work. Targeted at developers",
|
||||
href: "https://coderank.net",
|
||||
image: "/images/work/devops/server-management.png",
|
||||
metrics: [""],
|
||||
technologies: [
|
||||
"Next JS",
|
||||
"Docker",
|
||||
@ -49,6 +56,7 @@ export const work = {
|
||||
title: "Mediajury",
|
||||
description: "The ultimate debate platform",
|
||||
href: "https://mediajury.org",
|
||||
metrics: [""],
|
||||
technologies: [
|
||||
"SQL",
|
||||
"MariaDB",
|
||||
@ -64,6 +72,7 @@ export const work = {
|
||||
title: "Circlenav",
|
||||
description: "The AI search engine done right",
|
||||
href: "https://circlenav.net",
|
||||
metrics: [""],
|
||||
technologies: [
|
||||
"SearXNG",
|
||||
"NextJS",
|
||||
@ -81,6 +90,7 @@ export const work = {
|
||||
title: "TurboCI",
|
||||
description: "Cloud VPS orchestrator that runs any workload",
|
||||
href: "https://turboci.tben.me",
|
||||
metrics: [""],
|
||||
technologies: [
|
||||
"Bun",
|
||||
"Shell",
|
||||
@ -98,6 +108,7 @@ export const work = {
|
||||
"Self Hosted Email solution for all my personal projects",
|
||||
href: "https://box.mailben.xyz/mail",
|
||||
image: "/images/work/devops/server-management.png",
|
||||
metrics: [""],
|
||||
technologies: ["Linux", "Docker", "Mailinabox"],
|
||||
},
|
||||
{
|
||||
@ -106,6 +117,7 @@ export const work = {
|
||||
"Self Hosted repository for Git projects, NPM modules, Docker images, and more",
|
||||
href: "https://git.tben.me/tben",
|
||||
image: "/images/work/devops/server-management.png",
|
||||
metrics: [""],
|
||||
technologies: ["Gitea", "Linux"],
|
||||
},
|
||||
],
|
||||
@ -118,6 +130,7 @@ export const work = {
|
||||
title: "TurboCI",
|
||||
description: "Cloud VPS orchestrator that runs any workload",
|
||||
href: "https://turboci.tben.me",
|
||||
metrics: [""],
|
||||
technologies: [
|
||||
"Bun",
|
||||
"Shell",
|
||||
@ -135,6 +148,7 @@ export const work = {
|
||||
"The easiest way to synchronize local and remote directories in real time",
|
||||
href: "https://git.tben.me/Moduletrace/turbo-sync",
|
||||
image: "/images/work/devops/server-management.png",
|
||||
metrics: [""],
|
||||
technologies: ["Node JS", "Bun JS", "Shell Scripting", "Rsync"],
|
||||
},
|
||||
{
|
||||
@ -142,6 +156,7 @@ export const work = {
|
||||
description: "Run multiple concurrent processes",
|
||||
href: "https://git.tben.me/Moduletrace/batchrun",
|
||||
image: "/images/work/devops/server-management.png",
|
||||
metrics: [""],
|
||||
technologies: ["Node JS"],
|
||||
},
|
||||
],
|
||||
|
||||
@ -10,15 +10,29 @@ export default function AboutSection() {
|
||||
return (
|
||||
<Section>
|
||||
<Stack className="w-full max-w-full xl:max-w-[50vw]">
|
||||
<H2 className="leading-snug">About Me</H2>
|
||||
<H2 className="leading-snug">
|
||||
I Build & Operate Production Systems
|
||||
</H2>
|
||||
<Span>
|
||||
I'm passionate and dedicated to solving problems using the
|
||||
best technologies available.
|
||||
I'm Benjamin Toby. DevOps/Platform engineer and CTO at
|
||||
Summit Lending. I design, deploy, and operate infrastructure
|
||||
that supports real businesses:
|
||||
</Span>
|
||||
<ul className="space-y-4">
|
||||
<li>Automated CI/CD pipelines (TurboCI)</li>
|
||||
<li>Multi-cloud deployments (AWS, GCP, Azure, Hetzner)</li>
|
||||
<li>NGINX hardening, TLS, caching, rate limiting</li>
|
||||
<li>Full-stack delivery (Next.js, Bun, SQL)</li>
|
||||
</ul>
|
||||
<Span>
|
||||
I focus on measurable outcomes: faster deployments, lower
|
||||
costs, fewer incidents.
|
||||
</Span>
|
||||
|
||||
<Link className="dotted-text" href="/about">
|
||||
<Row>
|
||||
<UserRoundSearch size={19} />
|
||||
<Span>Learn More About Me</Span>
|
||||
<Span>View Resume</Span>
|
||||
</Row>
|
||||
</Link>
|
||||
</Stack>
|
||||
|
||||
@ -6,10 +6,11 @@ import Span from "@/components/lib/layout/Span";
|
||||
import Stack from "@/components/lib/layout/Stack";
|
||||
import { work } from "../(data)/work";
|
||||
import Link from "@/components/lib/layout/Link";
|
||||
import React from "react";
|
||||
import React, { Fragment } from "react";
|
||||
import Row from "@/components/lib/layout/Row";
|
||||
import Divider from "@/components/lib/layout/Divider";
|
||||
import { twMerge } from "tailwind-merge";
|
||||
import { CheckCircle2, Circle } from "lucide-react";
|
||||
|
||||
type Props = {
|
||||
noTitle?: boolean;
|
||||
@ -19,7 +20,7 @@ type Props = {
|
||||
export default function MyWorkSection({ noTitle, expand }: Props) {
|
||||
const categories = Object.keys(work) as (keyof typeof work)[];
|
||||
const [category, setCategory] = React.useState<keyof typeof work>(
|
||||
categories[0]
|
||||
categories[0],
|
||||
);
|
||||
|
||||
if (expand) {
|
||||
@ -53,7 +54,7 @@ export default function MyWorkSection({ noTitle, expand }: Props) {
|
||||
key={index}
|
||||
/>
|
||||
);
|
||||
}
|
||||
},
|
||||
)}
|
||||
</div>
|
||||
</Stack>
|
||||
@ -88,7 +89,7 @@ export default function MyWorkSection({ noTitle, expand }: Props) {
|
||||
"cursor-pointer",
|
||||
isActive
|
||||
? ""
|
||||
: "opacity-40 hover:opacity-70"
|
||||
: "opacity-40 hover:opacity-70",
|
||||
)}
|
||||
onClick={() => setCategory(ctgr)}
|
||||
>
|
||||
@ -134,11 +135,30 @@ export function MyWorkPortfolioCard({
|
||||
{portfolio.href}
|
||||
</Link>
|
||||
<Span>{portfolio.description}</Span>
|
||||
{portfolio.technologies?.[0] && (
|
||||
{portfolio.metrics?.[0] && (
|
||||
<Fragment>
|
||||
<Divider />
|
||||
<Row className="gap-4">
|
||||
{portfolio.metrics.map((tch, _i) => (
|
||||
<React.Fragment key={_i}>
|
||||
<Row>
|
||||
<CheckCircle2 size={15} />
|
||||
<Span className="text-xs dark:text-white/40">
|
||||
{tch}
|
||||
</Span>
|
||||
</Row>
|
||||
</React.Fragment>
|
||||
))}
|
||||
</Row>
|
||||
</Fragment>
|
||||
)}
|
||||
{portfolio.technologies?.[0] && (
|
||||
<Fragment>
|
||||
<Divider />
|
||||
<Row className="gap-4 opacity-60">
|
||||
{portfolio.technologies.map((tch, _i) => (
|
||||
<React.Fragment key={_i}>
|
||||
<Span className="text-sm dark:text-white/40">
|
||||
<Span className="text-xs dark:text-white/40">
|
||||
{tch}
|
||||
</Span>
|
||||
{_i < portfolio.technologies.length - 1 && (
|
||||
@ -147,6 +167,7 @@ export function MyWorkPortfolioCard({
|
||||
</React.Fragment>
|
||||
))}
|
||||
</Row>
|
||||
</Fragment>
|
||||
)}
|
||||
</Stack>
|
||||
</Card>
|
||||
|
||||
53
components/pages/Home/(sections)/footer-cta-section.tsx
Normal file
53
components/pages/Home/(sections)/footer-cta-section.tsx
Normal file
@ -0,0 +1,53 @@
|
||||
import Button from "@/components/lib/layout/Button";
|
||||
import H2 from "@/components/lib/layout/H2";
|
||||
import Row from "@/components/lib/layout/Row";
|
||||
import Section from "@/components/lib/layout/Section";
|
||||
import Span from "@/components/lib/layout/Span";
|
||||
import Stack from "@/components/lib/layout/Stack";
|
||||
import { Contact, Mail } from "lucide-react";
|
||||
|
||||
export default function FooterCTASection() {
|
||||
return (
|
||||
<Section>
|
||||
<Stack className="w-full max-w-full xl:max-w-[50vw] gap-8">
|
||||
<H2 className="leading-snug">Need Help With Infrastructure?</H2>
|
||||
<Span>
|
||||
Whether it's CI/CD, cost optimization, or production
|
||||
hardening, I can help.
|
||||
</Span>
|
||||
|
||||
<Row className="items-stretch flex-col md:flex-row w-full md:w-auto gap-4">
|
||||
<Button
|
||||
title="Contact Me"
|
||||
beforeIcon={
|
||||
<Contact size={17} className="font-normal" />
|
||||
}
|
||||
href="/contact"
|
||||
className="grow w-full"
|
||||
>
|
||||
Schedule a Call
|
||||
</Button>
|
||||
<Button
|
||||
title="View My Work"
|
||||
beforeIcon={<Mail size={17} className="font-normal" />}
|
||||
href={`mailto:${process.env.NEXT_PUBLIC_EMAIL_ADDRESS}`}
|
||||
className="grow w-full bg-transparent!"
|
||||
variant="outlined"
|
||||
>
|
||||
Email Me
|
||||
</Button>
|
||||
{/* <Button
|
||||
beforeIcon={
|
||||
<ScrollText size={17} className="font-normal" />
|
||||
}
|
||||
href="/contact"
|
||||
variant="outlined"
|
||||
className="grow w-full"
|
||||
>
|
||||
Resume
|
||||
</Button> */}
|
||||
</Row>
|
||||
</Stack>
|
||||
</Section>
|
||||
);
|
||||
}
|
||||
@ -1,21 +1,42 @@
|
||||
import LucideIcon from "@/components/lib/elements/lucide-icon";
|
||||
import Button from "@/components/lib/layout/Button";
|
||||
import Divider from "@/components/lib/layout/Divider";
|
||||
import H1 from "@/components/lib/layout/H1";
|
||||
import Row from "@/components/lib/layout/Row";
|
||||
import Section from "@/components/lib/layout/Section";
|
||||
import Span from "@/components/lib/layout/Span";
|
||||
import Stack from "@/components/lib/layout/Stack";
|
||||
import { Contact, ScrollText } from "lucide-react";
|
||||
import { Contact, ScrollText, Terminal } from "lucide-react";
|
||||
|
||||
export default function Main() {
|
||||
return (
|
||||
<Section>
|
||||
<Stack className="w-full max-w-full xl:max-w-[50vw]">
|
||||
<Span>Howdy Tech Enthusiasts! I'm Benjamin Toby</Span>
|
||||
<H1 className="leading-snug">
|
||||
Software Engineer, DevOps Engineer, Full Stack Developer,
|
||||
Software Architect, Philosopher, Solar Energy Enthusiast.
|
||||
<Span>Benjamin Toby</Span>
|
||||
<H1 className="leading-snug m-0!">
|
||||
DevOps & Platform Engineer
|
||||
</H1>
|
||||
<Row className="items-stretch flex-col md:flex-row w-full md:w-auto">
|
||||
<Span className="text-xl">
|
||||
I help teams ship faster, cut infrastructure costs, and
|
||||
achieve reliable production systems.
|
||||
</Span>
|
||||
<Row className="my-4 gap-6">
|
||||
<Row>
|
||||
<LucideIcon name="CheckCircle2" size={20} />
|
||||
<Span>99.99% uptime targets</Span>
|
||||
</Row>
|
||||
<Divider vertical />
|
||||
<Row>
|
||||
<LucideIcon name="CheckCircle2" size={20} />
|
||||
<Span>~10 deployments/week</Span>
|
||||
</Row>
|
||||
<Divider vertical />
|
||||
<Row>
|
||||
<LucideIcon name="CheckCircle2" size={20} />
|
||||
<Span>Over 80% Operations cost reduction</Span>
|
||||
</Row>
|
||||
</Row>
|
||||
<Row className="items-stretch flex-col md:flex-row w-full md:w-auto gap-4">
|
||||
<Button
|
||||
title="Contact Me"
|
||||
beforeIcon={
|
||||
@ -24,7 +45,18 @@ export default function Main() {
|
||||
href="/contact"
|
||||
className="grow w-full"
|
||||
>
|
||||
Contact Me
|
||||
Book a Consultation
|
||||
</Button>
|
||||
<Button
|
||||
title="View My Work"
|
||||
beforeIcon={
|
||||
<Terminal size={17} className="font-normal" />
|
||||
}
|
||||
href="/work"
|
||||
className="grow w-full bg-transparent!"
|
||||
variant="outlined"
|
||||
>
|
||||
View My Work
|
||||
</Button>
|
||||
{/* <Button
|
||||
beforeIcon={
|
||||
|
||||
@ -1,27 +1,76 @@
|
||||
import Button from "@/components/lib/layout/Button";
|
||||
import Divider from "@/components/lib/layout/Divider";
|
||||
import H1 from "@/components/lib/layout/H1";
|
||||
import H2 from "@/components/lib/layout/H2";
|
||||
import Link from "@/components/lib/layout/Link";
|
||||
import P from "@/components/lib/layout/P";
|
||||
import Row from "@/components/lib/layout/Row";
|
||||
import Section from "@/components/lib/layout/Section";
|
||||
import Span from "@/components/lib/layout/Span";
|
||||
import Stack from "@/components/lib/layout/Stack";
|
||||
import { Mail } from "lucide-react";
|
||||
import { Terminal } from "lucide-react";
|
||||
|
||||
export default function Main() {
|
||||
return (
|
||||
<Section>
|
||||
<Stack className="w-full max-w-full xl:max-w-[50vw]">
|
||||
<Stack className="w-full max-w-full xl:max-w-[50vw] gap-8">
|
||||
{/* <Span className="leading-snug -mb-6 text-sm">
|
||||
I Build & Operate Production Systems
|
||||
</Span> */}
|
||||
<H1 className="leading-snug">About Me</H1>
|
||||
<Span>
|
||||
I'm a man of few words. My{" "}
|
||||
<Link href="/skills" className="dotted-text">
|
||||
Skills
|
||||
</Link>{" "}
|
||||
and{" "}
|
||||
<Link href="/work" className="dotted-text">
|
||||
Work
|
||||
</Link>{" "}
|
||||
speak for themselves.
|
||||
I'm Benjamin Toby, a DevOps/Platform engineer and CTO at
|
||||
Summit Lending. I build and operate production systems that
|
||||
support real businesses.
|
||||
</Span>
|
||||
|
||||
<Divider />
|
||||
|
||||
<H2>What I Do</H2>
|
||||
<Span>I focus on infrastructure and reliability:</Span>
|
||||
<ul className="space-y-4">
|
||||
<li>CI/CD automation and deployment pipelines</li>
|
||||
<li>Multi-cloud architecture (AWS, GCP, Azure, Hetzner)</li>
|
||||
<li>NGINX hardening, TLS, caching, rate limiting</li>
|
||||
<li>Full-stack delivery with Next.js, Bun, and SQL</li>
|
||||
</ul>
|
||||
|
||||
<Divider />
|
||||
|
||||
<H2>Background</H2>
|
||||
<P>
|
||||
I started as a full-stack developer and moved into DevOps
|
||||
and platform engineering out of necessity, building systems
|
||||
that could scale without breaking. That led to Summit
|
||||
Lending, where I manage all engineering, from infrastructure
|
||||
to product.
|
||||
</P>
|
||||
<P>
|
||||
Along the way I built TurboCI, a deployment orchestration
|
||||
tool, and Datasquirel, a cloud SQL platform. I write about
|
||||
what I learn on my <a href="/blog">blog</a>.
|
||||
</P>
|
||||
|
||||
<Divider />
|
||||
|
||||
<Span>
|
||||
I focus on measurable outcomes: faster deployments, lower
|
||||
costs, fewer incidents.
|
||||
</Span>
|
||||
|
||||
<Row className="items-stretch flex-col md:flex-row w-full md:w-auto gap-4">
|
||||
<Button
|
||||
title="View My Work"
|
||||
beforeIcon={
|
||||
<Terminal size={17} className="font-normal" />
|
||||
}
|
||||
href="/work"
|
||||
className="grow w-full bg-transparent!"
|
||||
variant="outlined"
|
||||
>
|
||||
View My Work
|
||||
</Button>
|
||||
</Row>
|
||||
</Stack>
|
||||
</Section>
|
||||
);
|
||||
|
||||
@ -4,6 +4,7 @@ import AboutSection from "@/components/pages/Home/(sections)/AboutSection";
|
||||
import Divider from "@/components/lib/layout/Divider";
|
||||
import MySkillsSection from "@/components/pages/Home/(sections)/MySkillsSection";
|
||||
import MyWorkSection from "@/components/pages/Home/(sections)/MyWorkSection";
|
||||
import FooterCTASection from "@/components/pages/Home/(sections)/footer-cta-section";
|
||||
|
||||
export default function Home() {
|
||||
return (
|
||||
@ -20,6 +21,8 @@ export default function Home() {
|
||||
<MySkillsSection />
|
||||
<Divider />
|
||||
<MyWorkSection />
|
||||
<Divider />
|
||||
<FooterCTASection />
|
||||
</Layout>
|
||||
);
|
||||
}
|
||||
|
||||
@ -7,5 +7,5 @@ Allow: /
|
||||
Sitemap: https://www.tben.me/sitemap.xml
|
||||
|
||||
# Optional: disallow common non-content paths (uncomment if needed)
|
||||
# Disallow: /api/
|
||||
# Disallow: /_next/
|
||||
Disallow: /api/
|
||||
Disallow: /_next/
|
||||
|
||||
Loading…
Reference in New Issue
Block a user