diff --git a/.gitignore b/.gitignore new file mode 100644 index 000000000..68b21f0aa --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +/node_modules +.DS_Store diff --git a/README 2.md b/README 2.md new file mode 100644 index 000000000..1337bcfd8 --- /dev/null +++ b/README 2.md @@ -0,0 +1,3 @@ +# Jacqueline's Personal Website +This is a personal website built using the Hack4Impact Starter Pack! +[Visit it Here!](https://jlinnie.github.io) diff --git a/blog.html b/blog.html new file mode 100644 index 000000000..2053f3d27 --- /dev/null +++ b/blog.html @@ -0,0 +1,34 @@ + + + + + Blog + + + + + + +
+

Blog

+
+ + + +
+ + + + diff --git a/blogs/post.html b/blogs/post.html new file mode 100644 index 000000000..3215809a1 --- /dev/null +++ b/blogs/post.html @@ -0,0 +1,32 @@ + + + + Blog Post + + + + + + + +
+

+

+ +

+
+ + + + \ No newline at end of file diff --git a/blogs/post.js b/blogs/post.js new file mode 100644 index 000000000..f67aa0c2e --- /dev/null +++ b/blogs/post.js @@ -0,0 +1,14 @@ +const params = new URLSearchParams(window.location.search); +const slug = params.get("slug"); + +const blog = blogs.find(b => b.slug === slug); + + document.getElementById("post-title").textContent = blog.title; + document.getElementById("post-page-title").textContent = blog.title; + document.getElementById("post-date").textContent = blog.date; + + const img = document.getElementById("post-image"); + img.src = blog.image; + img.alt = blog.imageAlt; + + document.getElementById("post-content").textContent = blog.description; diff --git a/contact.html b/contact.html new file mode 100644 index 000000000..3a951a37c --- /dev/null +++ b/contact.html @@ -0,0 +1,51 @@ + + + + + Contact Information + + + + + + +
+

Contact Information

+
+

+ + + + + + + + + + + +
+ + +
+ + + diff --git a/images/sexy_shrek_by_sailormoonrocko_dg5ur4h-fullview.jpg b/images/sexy_shrek_by_sailormoonrocko_dg5ur4h-fullview.jpg new file mode 100644 index 000000000..a3ffa4857 Binary files /dev/null and b/images/sexy_shrek_by_sailormoonrocko_dg5ur4h-fullview.jpg differ diff --git a/images/tennisbird.webp b/images/tennisbird.webp new file mode 100644 index 000000000..0b4a3e5e2 Binary files /dev/null and b/images/tennisbird.webp differ diff --git a/index.html b/index.html new file mode 100644 index 000000000..cf22eaf3d --- /dev/null +++ b/index.html @@ -0,0 +1,44 @@ + + + + + Personal Website + + + + + +
+
+ +
+

Jacqueline Bartholomew's Personal Website

+
+
+ sexy shrek> +
+ +
+ +

Welcome to my personal website! I'm Jacqueline Bartholomew, a current undergraduate student and apiring developer at + Cal Poly San Luis Obispo. This site is a space where I share my ideas, projects, and creative experiments as I keep learning and growing. Take a look around and get to know what I’ve been working on!

+
+
+
+ + + + diff --git a/portfolio.html b/portfolio.html new file mode 100644 index 000000000..88f57212a --- /dev/null +++ b/portfolio.html @@ -0,0 +1,44 @@ + + + + + Portfolio + + + + + + +
+

Portfolio

+
+ sexy shrek>
+
+

+ random text for first paragraph +

+

+ random text for second paragraph +

+ Learn More +
+ + + + +
+ + + diff --git a/resume.html b/resume.html new file mode 100644 index 000000000..b6e0decce --- /dev/null +++ b/resume.html @@ -0,0 +1,87 @@ + + + + + Resume + + + + + + +
+

Resume

+ Download Resume +
+

Education

+
+

Title Here

+ +
+

Coursework

+
+

Title Here

+ +
    +
  • This is a special example course that tests the limit of this page to see how much it can handle
  • +
  • Example Course 2
  • +
+
+

Skills

+
+

Title Here

+ +
    +
  • Example Skill 1
  • +
  • Example Skill 2
  • +
+
+

Projects

+
+

Title

+ +

Description Here

+
+

Experience

+ +
+

Title Here

+ +

Description Here

+
+ +
+

Title Here for the second one

+ +

If you're looking for random paragraphs, you've come to the right place. When a random word or a random sentence isn't quite enough, the next logical step is to find a random paragraph. We created the Random Paragraph Generator with you in mind. The process is quite simple. Choose the number of random paragraphs you'd like to see and click the button. Your chosen number of paragraphs will instantly appear. + +

+
+
+ +
+
+
+
+
+ + + + +
+ + + diff --git a/src/blog.d.ts b/src/blog.d.ts new file mode 100644 index 000000000..221acd4c7 --- /dev/null +++ b/src/blog.d.ts @@ -0,0 +1,2 @@ +export {}; +//# sourceMappingURL=blog.d.ts.map \ No newline at end of file diff --git a/src/blog.d.ts.map b/src/blog.d.ts.map new file mode 100644 index 000000000..53fcf9550 --- /dev/null +++ b/src/blog.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"blog.d.ts","sourceRoot":"","sources":["blog.ts"],"names":[],"mappings":""} \ No newline at end of file diff --git a/src/blog.js b/src/blog.js new file mode 100644 index 000000000..8b8ce0eb3 --- /dev/null +++ b/src/blog.js @@ -0,0 +1,45 @@ +const blogs = [ + { + title: "My First Blog Post", + date: "2025-10-28", + description: "This is my first blog post where I talk about blog stuff!", + image: "./images/tennisbird.webp", + imageAlt: "Tennis bird", + slug: "my-first-blog-post", + }, + { + title: "My Second Blog Post", + date: "2025-10-27", + description: "This is my second blog post where I talk about more blog stuff", + image: "./images/learning-ts.png", + imageAlt: "second image", + slug: "learning-typescript", + }, + { + title: "My Third Blog Post", + date: "2025-10-27", + description: "This is my third blog post where I talk about more blog stuff", + image: "./images/learning-ts.png", + imageAlt: "third image", + slug: "learning-typescript", + }, +]; + +document.addEventListener("DOMContentLoaded", () => { + const container = document.getElementById("blog-container"); + + if (container) { + blogs.forEach((blog) => { + const div = document.createElement("div"); + div.className = "blog-card"; + div.innerHTML = ` + +

${blog.title}

+

${blog.date}

+ ${blog.imageAlt} +
+ `; + container.appendChild(div); + }); + } +}); \ No newline at end of file diff --git a/src/blog.js.map b/src/blog.js.map new file mode 100644 index 000000000..3e5e863f2 --- /dev/null +++ b/src/blog.js.map @@ -0,0 +1 @@ +{"version":3,"file":"blog.js","sourceRoot":"","sources":["blog.ts"],"names":[],"mappings":";;AASC,MAAM,KAAK,GAAW;IACrB;QACE,KAAK,EAAE,oBAAoB;QAC3B,IAAI,EAAE,YAAY;QAClB,WAAW,EAAE,gFAAgF;QAC7F,KAAK,EAAE,yBAAyB;QAChC,QAAQ,EAAE,qCAAqC;QAC/C,IAAI,EAAE,oBAAoB;KAC3B;IACD;QACE,KAAK,EAAE,qBAAqB;QAC5B,IAAI,EAAE,YAAY;QAClB,WAAW,EAAE,mFAAmF;QAChG,KAAK,EAAE,0BAA0B;QACjC,QAAQ,EAAE,kCAAkC;QAC5C,IAAI,EAAE,qBAAqB;KAC5B;CACF,CAAC;AAEF,MAAM,SAAS,GAAG,QAAQ,CAAC,cAAc,CAAC,gBAAgB,CAAuB,CAAC;AAElF,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE;IACrB,MAAM,GAAG,GAAG,QAAQ,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;IAC1C,GAAG,CAAC,SAAS,GAAG;UACR,IAAI,CAAC,KAAK;SACX,IAAI,CAAC,IAAI;gBACF,IAAI,CAAC,KAAK,UAAU,IAAI,CAAC,QAAQ;SACxC,IAAI,CAAC,WAAW;GACtB,CAAC;IACF,IAAI,SAAS;QAAE,SAAS,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;AAC5C,CAAC,CAAC,CAAC"} \ No newline at end of file diff --git a/src/blog.ts b/src/blog.ts new file mode 100644 index 000000000..a9f65b879 --- /dev/null +++ b/src/blog.ts @@ -0,0 +1,58 @@ +// Define the shape of a blog post +type Blog = { + title: string; + date: string; + description: string; + image: string; + imageAlt: string; + slug: string; +}; + +// Blog data +const blogs: Blog[] = [ + { + title: "My First Blog Post", + date: "2025-10-28", + description: "This is my first blog post where I talk about blog stuff!", + image: "./images/tennisbird.webp", + imageAlt: "Tennis bird", + slug: "my-first-blog-post", + }, + { + title: "My Second Blog Post", + date: "2025-10-27", + description: "This is my second blog post where I talk about more blog stuff", + image: "./images/learning-ts.png", + imageAlt: "second image", + slug: "learning-typescript", + }, + { + title: "My Third Blog Post", + date: "2025-10-27", + description: "This is my third blog post where I talk about more blog stuff", + image: "./images/learning-ts.png", + imageAlt: "third image", + slug: "learning-typescript", + }, +]; + +// On load, populate the blog list ONLY if we're on blog.html +// (post.html won't have #blog-container, so this won't run there) +document.addEventListener("DOMContentLoaded", () => { + const container = document.getElementById("blog-container"); + + if (container) { + blogs.forEach((blog) => { + const div = document.createElement("div"); + div.className = "blog-card"; + div.innerHTML = ` + +

${blog.title}

+

${blog.date}

+ ${blog.imageAlt} +
+ `; + container.appendChild(div); + }); + } +}); \ No newline at end of file diff --git a/styles.css b/styles.css new file mode 100644 index 000000000..ffdcd667a --- /dev/null +++ b/styles.css @@ -0,0 +1,401 @@ +:root { + --cg-black: #2a2d2d; /* ink */ + --cg-blue: #6cc5ff; /* pastel sky */ + --cg-grey: #f9fbff; /* page background */ + --cg-white: #ffffff; + + /* palette accents */ + --cg-pink: #ffb3c7; /* bubblegum */ + --cg-lilac: #cdb4ff; /* soft lilac */ + --cg-mint: #b8f2e6; /* mint */ + --cg-lemon: #fff4a8; /* lemon */ + + /* cool shadow stuff */ + --radius-sm: 6px; + --radius-md: 12px; + --shadow-soft: 0 6px 20px rgba(0, 0, 0, 0.07); + --transition: 200ms ease; +} + +html { + height: 100%; +} + +body { + background: var(--cg-grey); + position: relative; + min-height: 100vh; + padding: 0; + margin: 0; + font-family: ui-rounded, system-ui, -apple-system, "Segoe UI Rounded", "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif; +} + +/* navigation */ + +.navbar { + position: -webkit-sticky; + position: sticky; + top: 0; + width: 100%; + height: 7%; + z-index: 10; + + display: flex; + justify-content: space-between; + align-items: center; + text-align: center; + + background-color: var(--cg-black); + color: var(--cg-white); + padding: 0px 0px; + background-image: linear-gradient(180deg, var(--cg-white), #fbfdff); + box-shadow: var(--shadow-soft); + + /* border: solid red; */ +} + +.nav-list { + display: flex; + flex-direction: row; + position: relative; + right: 30px; + list-style: none; + + /* border: solid blue; */ +} + +.navbar a { + color: var(--cg-blue); + font-weight: bold; + margin: 0 12px; + text-decoration: none; + letter-spacing: 2px; + + font-family: monospace; + transition: color var(--transition), text-decoration-color var(--transition); +} + +.navbar a:hover { + color: var(--cg-lilac); + text-decoration: underline; + text-decoration-thickness: 2px; + text-underline-offset: 3px; +} + +.navbar a:active { + color: var(--cg-pink); +} + +.logo a { + font-family: Georgia; + letter-spacing: 1px; +} + +.logo a:hover { + text-decoration: None; +} + +main { + padding: 0 20px 40px 20px; + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + max-width: 1200px; + gap: 20px; +} + +.page-title { + display: flex; + justify-content: center; + font-size: 40px; + font-family: Georgia; + background-image: linear-gradient(90deg, var(--cg-blue), var(--cg-pink), var(--cg-lilac)); + -webkit-background-clip: text; + background-clip: text; + color: transparent; +} + +/* portfolio grid */ + +.project { + display: flex; + flex-direction: row; + max-width: 100%; + margin: 1em 0 2em 0; + + /* border: 2px solid blue; */ + gap: 18px; + flex-wrap: wrap; +} + +.item-link { + width: 68%; + + /* border: 2px solid red; */ +} + +.project-image { + object-fit: cover; + width: 100%; + height: 500px; + flex-basis: 50px; + flex-grow: 2; + + /* border:2px solid black; */ + border-radius: var(--radius-md); + box-shadow: var(--shadow-soft); +} + +.project-details { + display: flex; + background: linear-gradient(180deg, #ffffff, #fffefe); + width: 30%; + height: 500px; + flex-shrink: 1; + padding: 0 20px; + border-radius: var(--radius-md); + box-shadow: var(--shadow-soft); + border: 1px solid rgba(0,0,0,0.05); + margin: 0px; + line-height: 1.5; + overflow: auto; + + flex-direction: column; + text-align: center; + justify-content: center; + + /* Debug border */ + /* border: 2px solid green; */ +} + +.project-details a { + color: var(--cg-black); + text-decoration: none; + font-weight: bold; + letter-spacing: 1px; + transition: color var(--transition), text-decoration-color var(--transition); +} + +.project-details a:hover { + color: var(--cg-pink); + text-decoration: underline; +} + +.project-details { + font-weight: lighter; +} + +.project-name { + font-weight: bold; + font-size: 20px; + color: var(--cg-black); +} + +/* CSS for home page */ + +.about { + display: flex; + align-items: center; + justify-content: space-between; + padding: 20px; + background: linear-gradient(180deg, #ffffff, #fbfbff); + border: 1px solid rgba(0,0,0,0.06); + border-radius: var(--radius-md); + box-shadow: var(--shadow-soft); + /* box-shadow: 0 0 10px rgba(0, 0, 0, 0.1); */ +} + +.about-image img { + max-width: 300px; + border-radius: var(--radius-sm); + /* box-shadow: 0 0 10px rgba(0, 0, 0, 0.2); */ +} + +.about-text { + flex: 1; + margin-left: 20px; +} + +.about-text h2 { + font-size: 24px; + margin-bottom: 10px; +} + +.about-text p { + font-size: 16px; + line-height: 1.5; +} + +/* CSS for resume page */ + +.button { + background-image: linear-gradient(180deg, var(--cg-blue), var(--cg-lilac)); + border: none; + color: var(--cg-white); + font-family: ui-rounded, system-ui, -apple-system, "Segoe UI Rounded", "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif; + padding: 8px 12px; + text-align: center; + border-radius: var(--radius-sm); + box-shadow: var(--shadow-soft); + transition: transform var(--transition), box-shadow var(--transition), opacity var(--transition); +} + +.button:hover { + opacity: 0.95; + transform: translateY(-1px); +} + +.resume h2 { + font-family: Georgia; + color: var(--cg-black); +} + +/* resume layout container */ +.resume { + display: flex; + flex-direction: column; + align-items: stretch; + width: 100%; + max-width: 800px; + background: linear-gradient(180deg, #ffffff, #fbfbff); + border: 1px solid rgba(0,0,0,0.06); + border-radius: var(--radius-md); + box-shadow: var(--shadow-soft); + padding: 24px 28px; + line-height: 1.5; +} + +/* each section title like Education / Skills / etc */ +.section-title { + font-family: Georgia; + font-size: 20px; + letter-spacing: 0.5px; + color: var(--cg-black); + background-image: linear-gradient(90deg, var(--cg-blue), var(--cg-pink)); + -webkit-background-clip: text; + background-clip: text; + color: transparent; + margin-top: 24px; + margin-bottom: 12px; +} + +/* one entry block */ +.entry { + background: var(--cg-white); + border: 1px solid rgba(0,0,0,0.05); + border-radius: var(--radius-sm); + box-shadow: var(--shadow-soft); + padding: 12px 16px; + margin-bottom: 16px; +} + +/* job / project / school name */ +.entry-title { + font-weight: bold; + font-size: 16px; + color: var(--cg-black); + margin: 0 0 4px 0; + font-family: ui-rounded, system-ui, -apple-system, "Segoe UI Rounded", "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif; + letter-spacing: 0.3px; +} + +/* dates, role, location line */ +.entry-info { + font-size: 14px; + color: #555; + margin: 0 0 8px 0; + font-family: monospace; + letter-spacing: 0.5px; +} + +/* description paragraph */ +.entry-description { + font-size: 14px; + color: var(--cg-black); + margin: 0; + line-height: 1.45; +} + +/* lists for coursework / skills */ +.course-list, +.skill-list { + list-style-type: square; + padding-left: 20px; + margin: 8px 0 0 0; + column-gap: 24px; + column-count: 2; + font-size: 14px; + color: var(--cg-black); + line-height: 1.4; +} + +.course-list li, +.skill-list li { + margin-bottom: 6px; +} + +/* position resume nicely on page */ +main.resume-page-wrapper { + width: 100%; + display: flex; + justify-content: center; + align-items: flex-start; + padding-top: 20px; + padding-bottom: 80px; +} + +/* CSS for contact form */ + +label { + display: block; + margin-bottom: 8px; + font-family: Georgia; + font-weight: bold; + color: var(--cg-black); +} + +input[type="text"], +input[type="email"], +textarea { + width: 100%; + padding: 10px; + margin-bottom: 15px; + border: 1px solid rgba(0,0,0,0.12); + border-radius: var(--radius-sm); + box-shadow: 0 1px 0 rgba(0,0,0,0.02) inset; + font-size: 16px; + resize: none; + transition: border-color var(--transition), box-shadow var(--transition); +} + +/* focus states */ +input[type="text"]:focus, +input[type="email"]:focus, +textarea:focus { + outline: none; + border-color: var(--cg-blue); + box-shadow: 0 0 0 4px color-mix(in oklab, var(--cg-blue) 30%, transparent); +} + +/* Add some spacing to the form */ +form { + width: 500px; + max-width: 92vw; + margin: 0 auto; +} + +/* CSS for footer */ + +.footer { + display: flex; + justify-content: center; + align-items: center; + background-image: linear-gradient(180deg, var(--cg-lilac), var(--cg-pink)); + color: #2a2d2d; + position: absolute; + bottom: 0; + width: 100%; + height: 2.5rem; + box-shadow: 0 -6px 16px rgba(0,0,0,0.06); +} \ No newline at end of file diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 000000000..cec4a3a4b --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,44 @@ +{ + // Visit https://aka.ms/tsconfig to read more about this file + "compilerOptions": { + // File Layout + // "rootDir": "./src", + // "outDir": "./dist", + + // Environment Settings + // See also https://aka.ms/tsconfig/module + "module": "nodenext", + "target": "esnext", + "types": [], + // For nodejs: + // "lib": ["esnext"], + // "types": ["node"], + // and npm install -D @types/node + + // Other Outputs + "sourceMap": true, + "declaration": true, + "declarationMap": true, + + // Stricter Typechecking Options + "noUncheckedIndexedAccess": true, + "exactOptionalPropertyTypes": true, + + // Style Options + // "noImplicitReturns": true, + // "noImplicitOverride": true, + // "noUnusedLocals": true, + // "noUnusedParameters": true, + // "noFallthroughCasesInSwitch": true, + // "noPropertyAccessFromIndexSignature": true, + + // Recommended Options + "strict": true, + "jsx": "react-jsx", + "verbatimModuleSyntax": true, + "isolatedModules": true, + "noUncheckedSideEffectImports": true, + "moduleDetection": "force", + "skipLibCheck": true, + } +}