Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update packages, update projects, layout improvements #1

Merged
merged 9 commits into from
Jan 17, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 0 additions & 3 deletions .eslintrc.json

This file was deleted.

40 changes: 34 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,40 @@
# michaelcummin.gs

This is the source-code that powers my personal portfolio, [https://michaelcummin.gs/](michaelcummin.gs)
Hey there! This is the source-code that powers my personal portfolio, [https://michaelcummin.gs/](michaelcummin.gs)

## How To Use
The site showcases my work, projects, and professional experience in a clean, user-friendly design.

In the project directory, you can run:
## Getting Started

### `npm run dev`
Clone the repository:

Runs the app in the development mode.\
Open [http://localhost:3000](http://localhost:3000) to view it in the browser.
```bash
git clone https://github.com/michaelcummings12/michaelcummin-gs.git
cd michaelcummin-gs
```

Install packages:

```bash
yarn install
```

Run the development server:

```bash
yarn run dev
```

## License

This project is licensed under the **Creative Commons Attribution-NonCommercial 4.0 International (CC BY-NC 4.0)** license. You are free to:

- **Share**: Copy and redistribute the material in any medium or format.
- **Adapt**: Remix, transform, and build upon the material.

Under the following terms:

- **Attribution**: You must give appropriate credit, provide a link to the license, and indicate if changes were made. You may do so in any reasonable manner, but not in any way that suggests the licensor endorses you or your use.
- **NonCommercial**: You may not use the material for commercial purposes.

For more details, visit [https://creativecommons.org/licenses/by-nc/4.0/](https://creativecommons.org/licenses/by-nc/4.0/).
19 changes: 19 additions & 0 deletions app/(springboard)/(projects)/about/SendMessageButton.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
"use client";
import { useRouter } from "next/navigation";
import { FunctionComponent } from "react";

export const SendMessageButton: FunctionComponent = () => {
const router = useRouter();
const onClick = () => {
router.push("/");
// ¯\_(ツ)_/¯
setTimeout(() => {
router.push("/contact");
}, 500);
};
return (
<button onClick={onClick} className="text-blue-500 hover:text-blue-700 transition-all hover:underline">
send me a message
</button>
);
};
49 changes: 49 additions & 0 deletions app/(springboard)/(projects)/about/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import Social from "@/components/Social";
import skyPortrait from "@/public/assets/sky_portrait_resized.jpg";
import { Metadata } from "next";
import Image from "next/image";
import { SendMessageButton } from "./SendMessageButton";

export const metadata: Metadata = {
title: "About | Michael Cummings"
};

export default function Page() {
return (
<div className="h-full w-full bg-white">
<div className="p-2 w-full h-1/2">
<div className="rounded-3xl overflow-hidden h-full w-full relative m-auto">
<Image src={skyPortrait} layout="fill" className="object-cover h-full w-full" quality={100} placeholder="blur" alt="Portrait of Michael Cummings against a city backdrop." />
</div>
</div>
<div className="w-full flex justify-center bg-white">
<div className="max-w-[680px] relative py-6 w-full lg:w-auto flex flex-col gap-8 px-2">
<div className="flex flex-col gap-4">
<div className="flex flex-row gap-3 lg:text-5xl text-4xl h-full">
<h1 className="font-semibold text-black">Hey,</h1>
<h1 className="text-black">I&apos;m Michael.</h1>
</div>
<Social />
</div>
<div className="leading-7 tracking-[0.02rem] text-lg flex flex-col gap-2 text-black">
<p>
I&apos;m a full-stack engineer with over six years of experience with AWS, Next.js, React, and TypeScript. From architecting scalable serverless backends to crafting visually engaging interfaces, I bring a holistic approach to every project.
My background with design tools like Adobe Illustrator, Adobe Photoshop, and Figma enables me to build brands from the ground up. I&apos;ve created everything from logos and style guidelines to high-fidelity product mockups.
</p>
<p>Beyond my professional roles, I&apos;ve collaborated with local Chicago brands to bring unique, cutting-edge digital experiences to life.</p>
<p>
Whether I&apos;m designing a custom logo, integrating sophisticated payment systems, or architecting secure, scalable infrastructure, my goal is to elevate the user experience and help brands stand out in a crowded digital landscape.
Ultimately, I thrive on solving complex technical challenges and delivering products that exceed expectations—from concept to completion.
</p>
<p>
Please feel free to <SendMessageButton /> or you can email me at
</p>
<a className="text-blue-500 hover:text-blue-700 transition-all hover:underline" href="mailto:[email protected]">
[email protected]
</a>
</div>
</div>
</div>
</div>
);
}
29 changes: 29 additions & 0 deletions app/(springboard)/(projects)/breaking-entering/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { CloudFunctions, ExternalIcon, Firestore, Nextjs } from "@/components/Icons";
import { DefaultLink } from "@/components/Link";
import { BreakingEnteringLogo } from "@/components/Logos";
import { ProjectPage } from "@/components/ProjectPage";
import { Technologies } from "@/types/project";
import { FunctionComponent } from "react";

const SITE_URL = "https://www.breaking-entering.com/";

const Header: FunctionComponent = () => (
<div className="flex flex-col gap-12">
<BreakingEnteringLogo className="w-full fill-white h-16 md:h-24" />
<DefaultLink icon={<ExternalIcon className="h-full fill-blue-600" />} className="bg-white text-blue-600 w-full" href={SITE_URL} label="Visit Breaking-Entering.com" />
</div>
);

const technologies: Technologies = [
{ name: "Firestore", icon: <Firestore className="fill-white h-full w-full" /> },
{ name: "Firebase Cloud Functions", icon: <CloudFunctions className="fill-white h-full w-full" /> },
{ name: "Next.js", icon: <Nextjs className="fill-white h-full w-full" /> }
];

export default function Page() {
return (
<ProjectPage technologies={technologies} backgroundColor="bg-white" headerColor="bg-blue-600" iconColor="bg-black" iconShadow="shadow-be" url={SITE_URL} timeline="September 2021 - December 2021" language="TypeScript">
<Header />
</ProjectPage>
);
}
33 changes: 33 additions & 0 deletions app/(springboard)/(projects)/chicago-care/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { ApiGateway, ExternalIcon, Fargate, Lambda, LightningBolt, MongoDb, Nextjs } from "@/components/Icons";
import { DefaultLink } from "@/components/Link";
import { ChicagoCareLogo } from "@/components/Logos";
import { ProjectPage } from "@/components/ProjectPage";
import { Technologies } from "@/types/project";
import { FunctionComponent } from "react";

const SITE_URL = "https://www.chicago.care/";

const Header: FunctionComponent = () => (
<div className="flex flex-col gap-12 bg-white">
<ChicagoCareLogo className="w-full h-12 md:h-16 drop-shadow" />
<DefaultLink icon={<ExternalIcon className="h-full fill-white" />} className="bg-sky-400 text-white" href={SITE_URL} label="Visit Chicago.care" />
</div>
);

const iconClass = "fill-sky-400 h-full w-full";
const technologies: Technologies = [
{ name: "API Gateway", icon: <ApiGateway className={iconClass} /> },
{ name: "AWS Fargate", icon: <Fargate className={iconClass} /> },
{ name: "AWS Lambda", icon: <Lambda className={iconClass} /> },
{ name: "MongoDB", icon: <MongoDb className={iconClass} /> },
{ name: "Next.js", icon: <Nextjs className={iconClass} /> },
{ name: "Server Side Rendering", icon: <LightningBolt className={iconClass} /> }
];

export default function Page() {
return (
<ProjectPage technologies={technologies} backgroundColor="bg-white" iconColor="bg-sky-400/20" iconShadow="shadow" url={SITE_URL} timeline="August 2022 - Present" language="TypeScript">
<Header />
</ProjectPage>
);
}
13 changes: 13 additions & 0 deletions app/(springboard)/(projects)/contact/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { CloseButton } from "@/components/CloseButton";
import ContactForm from "@/components/ContactForm";

export default function Page() {
return (
<div className="h-full w-full px-2 py-2 relative bg-gradient-to-br from-fuchsia-500 to-purple-700 flex flex-col items-center justify-center">
<CloseButton />
<div className="bg-white/60 rounded-3xl md:max-w-[680px] w-full h-full md:h-auto shadow-inset m-auto">
<ContactForm />
</div>
</div>
);
}
49 changes: 49 additions & 0 deletions app/(springboard)/(projects)/gcn/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import { AppSync, Braintree, DynamoDb, ExternalIcon, GraphQl, Nextjs } from "@/components/Icons";
import { DefaultLink } from "@/components/Link";
import { GcnLogo } from "@/components/Logos";
import { ProjectPage } from "@/components/ProjectPage";
import StarrySky from "@/components/StarrySky";
import { Technologies } from "@/types/project";
import { FunctionComponent } from "react";

const SITE_URL = "https://www.generalcomputing.io/";

const Header: FunctionComponent = () => {
return (
<>
<div className="h-full rounded-3xl shadow-gcnInset w-full border border-blue-500 p-12 flex items-center justify-center overflow-hidden absolute inset-0" />
<div className="flex flex-col gap-12 z-20">
<GcnLogo className="w-full fill-blue-500 h-12 md:h-16" />
<DefaultLink icon={<ExternalIcon className="h-full fill-white" />} className="w-full background-gcn text-white" href={SITE_URL} label="Visit GeneralComputing.io" />
</div>
<StarrySky />
</>
);
};

const iconClass = "fill-blue-500 h-full w-full";
const technologies: Technologies = [
{ name: "AWS AppSync", icon: <AppSync className={iconClass} /> },
{ name: "AWS DynamoDB", icon: <DynamoDb className={iconClass} /> },
{ name: "Braintree Payments", icon: <Braintree className={iconClass} /> },
{ name: "GraphQL", icon: <GraphQl className={iconClass} /> },
{ name: "Next.js", icon: <Nextjs className={iconClass} /> }
];

export default function Page() {
return (
<ProjectPage
technologies={technologies}
iconColor="bg-blue-500/25"
backgroundColor="bg-slate-900"
headerColor="bg-slate-900"
iconShadow="shadow-gcn"
ariaColor="white"
textColor="text-white"
url={SITE_URL}
timeline="January 2022 - March 2022"
language="TypeScript">
<Header />
</ProjectPage>
);
}
15 changes: 15 additions & 0 deletions app/(springboard)/(projects)/layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
"use client";
import { CloseButton } from "@/components/CloseButton";
import { motion } from "framer-motion";
import { usePathname } from "next/navigation";

export default function Layout({ children }: { children: React.ReactNode }) {
const pathname = usePathname();
const layoutId = pathname.split("/").pop();
return (
<motion.div layoutId={`card-${layoutId}`} initial={{ opacity: 0 }} animate={{ opacity: 1 }} exit={{ opacity: 0 }} transition={{ duration: 0.3 }} className="absolute h-full w-full inset-0 z-50">
<CloseButton />
{children}
</motion.div>
);
}
42 changes: 42 additions & 0 deletions app/(springboard)/(projects)/rhythm/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import { ExternalIcon, Ffmpeg, NextAuth, Nextjs, PostgreSql } from "@/components/Icons";
import { DefaultLink } from "@/components/Link";
import { RhythmLogo } from "@/components/Logos";
import { ProjectPage } from "@/components/ProjectPage";
import { Technologies } from "@/types/project";
import { FunctionComponent } from "react";

const SITE_URL = "https://www.rhythm.watch/";

const Header: FunctionComponent = () => (
<div className="flex flex-col gap-12">
<RhythmLogo className="w-full fill-white drop-shadow h-12 md:h-16" />
<DefaultLink icon={<ExternalIcon className="h-full fill-red-400" />} className="bg-white text-red-400 w-full" href={SITE_URL} label="Visit Rhythm.watch" />
</div>
);

const iconClass = "fill-black h-full w-full";
const technologies: Technologies = [
{ name: "Ffmpeg", icon: <Ffmpeg className={iconClass} /> },
{ name: "PostgreSQL", icon: <PostgreSql className={iconClass} /> },
{ name: "NextAuth.js", icon: <NextAuth className={iconClass} /> },
{ name: "Next.js", icon: <Nextjs className={iconClass} /> }
];

export default function Page() {
return (
<ProjectPage
ariaColor="white"
technologies={technologies}
backgroundColor="bg-black"
headerColor="bg-black"
iconColor="bg-white"
iconShadow="shadow"
url={SITE_URL}
timeline="December 2022 - Present"
language="TypeScript"
textColor="text-white"
linkColor="text-red-400">
<Header />
</ProjectPage>
);
}
10 changes: 10 additions & 0 deletions app/(springboard)/layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { SpringBoard } from "@/components/SpringBoard";

export default function Layout({ children }: { children: React.ReactNode }) {
return (
<>
<SpringBoard />
{children}
</>
);
}
3 changes: 3 additions & 0 deletions app/(springboard)/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export default function Page() {
return null;
}
22 changes: 12 additions & 10 deletions app/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,24 +1,16 @@
import { Analytics } from "@/components/Analytics";
import { Metadata, Viewport } from "next";
import { Overpass } from "next/font/google";
import "./globals.css";

export const metadata = {
export const metadata: Metadata = {
metadataBase: new URL("https://www.michaelcummin.gs"),
openGraph: {
locale: "en-US",
images: [{ url: "/meta_image.jpg", width: 1200, height: 630, type: "image/jpeg" }]
},
robots: "all",
referrer: "origin",
themeColor: "#000000",
colorScheme: "dark",
viewport: {
initialScale: 1,
minimumScale: 1,
maximumScale: 1,
width: "device-width",
height: "device-height"
},
icons: [
{
type: "image/png",
Expand All @@ -45,6 +37,16 @@ export const metadata = {
description: "Explore the work of Michael Cummings on his personal portfolio."
};

export const viewport: Viewport = {
initialScale: 1,
minimumScale: 1,
maximumScale: 1,
width: "device-width",
height: "device-height",
colorScheme: "dark",
themeColor: "#000000"
};

const overpass = Overpass({
subsets: ["latin"]
});
Expand Down
Loading