Skip to content
This repository was archived by the owner on Apr 16, 2026. It is now read-only.
Open
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
Binary file added .DS_Store
Binary file not shown.
6 changes: 6 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,12 @@ lerna-debug.log*
# Diagnostic reports (https://nodejs.org/api/report.html)
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json

.env
.env.local
.env.development.local
.env.test.local
.env.production.local

# Runtime data
pids
*.pid
Expand Down
29 changes: 13 additions & 16 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@

<div align="center">
<h1>andrewnelson.net | portfolio</h1>
<h1>riptidestar.com | portfolio</h1>
<p></p>
<img src="https://img.shields.io/badge/stability-beta-blue.svg" alt="Experimental">
<img src="https://vercelbadge.vercel.app/api/atlamors/portfolio-theme" alt="Vercel">
Expand All @@ -11,19 +11,6 @@

<img src="https://www.andrewnelson.net/img/preview.png">

## Updates
#### Dev Update — July 6th, 2023 🥰
We have relocated to a beautiful home in the suburbs of Langely, BC. There has been a LOT of work unpacking, organizing, and landscaping to get this home perfect for our two toddlers! I am hoping to resume development of the theme in the next couple months!

On a really interesting note, Webflow has launched a React component export tool. I am considering moving all component design and management over to Webflow for easier tooling for marketing teams and visual designers!
#### Dev Update — Feb 13th, 2023 [Updated: March 05th, 2023]
Jest has been setup, but no progress on building tests has been made. Life is busy atm!
#### Dev Update — Feb 10th, 2023
I am currently taking a short break in development of this theme. I am in the final phases of a job search, and getting ready to move into a bigger place to give some much needed room to my growing family! I am hoping to continue development before the end of next quarter!

## This website is still being developed! 🥳
The porftofolio application has currently hit the Beta phase and is ready to be forked if you are familiar with React and Next. The next release cycle will focus on a better DX—moving from local JSON to MongoDB, setting up Sanity for GUI page editing, Unit Testing with Jest, adding TypeScript, etc.

#### Next & App Architecure
- [ ] Next.js v13 : Waiting for /app/ folder to leave beta
- [ ] Sanity.io
Expand Down Expand Up @@ -51,8 +38,18 @@ The porftofolio application has currently hit the Beta phase and is ready to be

Fork, Install, Editing, and Deploy instructions coming soon(ish)!

This is my first open-source contribution, and it was also a great oppoortunity for me to learn!

It is my hope that by sharing this project it can give others a chance to enjoy learning Nextjs (and have as much fun as I did), and hopefully brings value to people as a portfolio and networking tool!

## Contact Form Email Setup (Resend)

To enable the contact form, set the following environment variable in your `.env.local` file:

```
RESEND_API_KEY=your_resend_api_key_here
```

- Get your API key from the [Resend dashboard](https://resend.com/).
- You must verify your sending domain in Resend to send from your own domain.
- The contact form will send submissions to kyle100@upenn.edu.


80 changes: 41 additions & 39 deletions components/blocks/projects/featured.jsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import Image from 'next/image'
import Link from 'next/link'

import { useEffect } from 'react'
import { m, useAnimation } from "framer-motion"
Expand Down Expand Up @@ -26,48 +27,50 @@ export default function FeaturedProject({ content }, index) {
}, [ controls, inView ] )

return (
<m.section
key={index}
className={css.project}
//framer-motion
ref={ref}
variants={container}
initial={[ "rest", "hidden" ]}
whileHover="hover"
animate={controls} >

<div className={css.details}>
<div className={css.projectHeader}>
<div className={css.header}>
<h3 className="highlight">{project}</h3><span className={css.privateOr}><i className="devicon-github-plain"></i>{repo}</span>
<Link href={url} passHref>
<m.section
key={index}
className={css.project}
//framer-motion
ref={ref}
variants={container}
initial={[ "rest", "hidden" ]}
whileHover="hover"
animate={controls} >

<div className={css.details}>
<div className={css.projectHeader}>
<div className={css.header}>
<h3 className="highlight">{project}</h3><span className={css.privateOr}><i className="devicon-github-plain"></i>{repo}</span>
</div>
<div className={css.description}>
<p><strong>{descriptionTitle}</strong> {description}</p>
</div>
<div className={css.stackContainer}>
<Badges list={stack} block="stack" fullContainer={false} color={false} />
</div>
<m.div variants={''} className={css.viewProject}>
<Icon icon={[ 'fad', 'arrow-right-to-bracket' ]} />
</m.div>
</div>
<div className={css.description}>
<p><strong>{descriptionTitle}</strong> {description}</p>
</div>
<div className={css.stackContainer}>
<Badges list={stack} block="stack" fullContainer={false} color={false} />
</div>
<m.div variants={''} className={css.viewProject}>
<Icon icon={[ 'fad', 'arrow-right-to-bracket' ]} />
</m.div>
</div>
</div>

<div className={css.imageContainer}>
<span className={`${css.imageAnimationContainer}`}>
{ images.map( ({key, url, hover, h, w }, index) => {
hover = ( hover === 'left' ) ? hoverLeft : hoverRight
return (
<m.div key={`${index}-${key}`} variants={item}>
<m.div variants={hover}>
<Image src={url} alt="x" height={h} width={w} />
<div className={css.imageContainer}>
<span className={`${css.imageAnimationContainer}`}>
{ images.map( ({key, url, hover, h, w }, index) => {
hover = ( hover === 'left' ) ? hoverLeft : hoverRight
return (
<m.div key={`${index}-${key}`} variants={item}>
<m.div variants={hover}>
<Image src={url} alt="x" height={h} width={w} />
</m.div>
</m.div>
</m.div>
)}
) }
</span>
</div>
</m.section>
)}
) }
</span>
</div>
</m.section>
</Link>
)
}

Expand Down Expand Up @@ -136,4 +139,3 @@ const hoverRight = {
x: 20
}
}

4 changes: 2 additions & 2 deletions components/layout/footer.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ export default function Footer() {
</li>
</ul>
</section>
<section className={css.github}>
{/* <section className={css.github}>
<a href={settings.portfolio.repo_html} rel="noreferrer" target="_blank">
<h5>{settings.portfolio.forkthis}</h5>
<ul>
Expand All @@ -83,7 +83,7 @@ export default function Footer() {
</li>
</ul>
</a>
</section>
</section> */}
</Container>
<canvas id="gradient-canvas" className={''} data-transition-in ></canvas>
</footer>
Expand Down
44 changes: 44 additions & 0 deletions components/redesign/Card.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import { motion } from 'framer-motion';
import styles from './Card.module.scss';

const cardVariants = {
hidden: {
opacity: 0,
y: 30
},
visible: {
opacity: 1,
y: 0,
transition: {
duration: 0.6,
ease: [0.25, 0.46, 0.45, 0.94],
},
},
};

export default function Card({
id,
title,
children,
className = '',
delay = 0
}) {
return (
<motion.section
id={id}
className={`${styles.card} ${className}`}
variants={cardVariants}
initial="hidden"
whileInView="visible"
viewport={{ once: true, margin: "-50px" }}
transition={{ delay }}
>
{title && (
<h2 className={styles.title}>{title}</h2>
)}
<div className={styles.content}>
{children}
</div>
</motion.section>
);
}
57 changes: 57 additions & 0 deletions components/redesign/Card.module.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
.card {
background: var(--bg-card);
border: 1px solid var(--border-color);
border-radius: var(--radius-lg);
padding: var(--space-8);
margin-bottom: var(--space-6);
transition: border-color var(--transition-base);

&:hover {
border-color: var(--border-hover);
}

@media (max-width: 640px) {
padding: var(--space-6);
margin-bottom: var(--space-4);
}
}

.title {
font-size: var(--text-2xl);
font-weight: 400;
margin-bottom: var(--space-6);
padding-bottom: var(--space-4);
border-bottom: 1px solid var(--border-color);
font-family: var(--font-sans);

@media (max-width: 640px) {
font-size: var(--text-xl);
margin-bottom: var(--space-4);
padding-bottom: var(--space-3);
}
}

.content {
p {
color: var(--text-secondary);
line-height: 1.7;

&:last-child {
margin-bottom: 0;
}
}

a {
color: var(--accent);
text-decoration: none;

&:hover {
text-decoration: underline;
}
}

strong {
color: var(--text-primary);
font-weight: 600;
}
}
Loading