diff --git a/.github/workflows/autodeploy.yml b/.github/workflows/autodeploy.yml index a950a15..8d1bba2 100644 --- a/.github/workflows/autodeploy.yml +++ b/.github/workflows/autodeploy.yml @@ -1,35 +1,36 @@ name: deploy-front-end on: - push: - branches: [main] + push: + branches: [main] - # Allows you to run this workflow manually from the Actions tab - workflow_dispatch: + # Allows you to run this workflow manually from the Actions tab + workflow_dispatch: # A workflow run is made up of one or more jobs that can run sequentially or in parallel jobs: - publish: - runs-on: ubuntu-latest - steps: - # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it - - name: Check out repo - uses: actions/checkout@v2 - # Node is required for npm - - name: Set up Node - uses: actions/setup-node@v2 - with: - node-version: "16.15.1" - # Install and build Docusaurus website - - name: Build Resume - run: | - npm install - npm run build - - name: Deploy to GitHub Pages - if: success() - uses: crazy-max/ghaction-github-pages@v2 - with: - target_branch: gh-pages - build_dir: public - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + publish: + runs-on: ubuntu-latest + steps: + # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it + - name: Check out repo + uses: actions/checkout@v2 + + - name: Set up Bun + uses: oven-sh/setup-bun@v1 + with: + bun-version: "1.1.4" + + - name: Build Resume + run: | + bun install + bun run build + + - name: Deploy to GitHub Pages + if: success() + uses: crazy-max/ghaction-github-pages@v2 + with: + target_branch: gh-pages + build_dir: dist + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.gitignore b/.gitignore index da93220..a547bf3 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,24 @@ -/node_modules/ -/public/build/ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* +node_modules +dist +dist-ssr +*.local + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea .DS_Store +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? diff --git a/Bornais_Jeremie_Resume.pdf b/Bornais_Jeremie_Resume.pdf deleted file mode 100644 index d7ad243..0000000 Binary files a/Bornais_Jeremie_Resume.pdf and /dev/null differ diff --git a/LICENSE b/LICENSE index ca7b488..786bffc 100644 --- a/LICENSE +++ b/LICENSE @@ -1,21 +1,22 @@ -MIT License - -Copyright (c) 2022 Jeremie Bornais - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. +MIT License + +Copyright (c) 2024 Isaac Kilbourne +Copyright (c) 2022 Jeremie Bornais + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md index 5e33a49..96522d5 100644 --- a/README.md +++ b/README.md @@ -1,34 +1,20 @@ -# Svelte-Resume +# svelte-resume + +> **Svelte**: from French *svelte*, "slim, slender" +> +> **Resume**: from French *résumé*, "a summary, summing up, recapitulation" Resume for Jeremie Bornais, created in Svelte. ## Get started -Install the dependencies... - -```bash -cd resume -npm install -``` +This project uses [Bun](bun.sh), so you will need to [install Bun](https://bun.sh/) if you have not already. -...then start [Rollup](https://rollupjs.org): +Then just two commands: -```bash -npm run dev -``` - -Navigate to [localhost:8080](http://localhost:8080). +1. `bun install` to install dependencies +2. `bun run dev` to run a development server ## This is a Website, not a Resume Yes, this is a website. BUT, it is also a resume. To turn this into an actual file, simply 'print' the webpage, and save to PDF! - -## Building and running in production mode - -To create an optimised version of the app: - -```bash -npm run build -``` - -You can run the newly built app with `npm run start`. This uses [sirv](https://github.com/lukeed/sirv). diff --git a/bun.lockb b/bun.lockb new file mode 100644 index 0000000..af8bf3f Binary files /dev/null and b/bun.lockb differ diff --git a/index.html b/index.html new file mode 100644 index 0000000..5201a17 --- /dev/null +++ b/index.html @@ -0,0 +1,18 @@ +<!DOCTYPE html> +<html lang="en"> + <head> + <meta charset="utf-8" /> + <meta name="viewport" content="width=device-width,initial-scale=1" /> + + <title>Kilbourne_Isaac_Resume</title> + <script + src="https://kit.fontawesome.com/22fc08ce26.js" + crossorigin="anonymous" + ></script> + </head> + + <body> + <div id="app"></div> + <script type="module" src="/src/main.ts"></script> + </body> +</html> diff --git a/package.json b/package.json index fd88a32..a9d712d 100644 --- a/package.json +++ b/package.json @@ -1,23 +1,21 @@ { - "name": "resume", - "version": "1.0.0", - "private": true, - "scripts": { - "build": "rollup -c", - "dev": "rollup -c -w", - "start": "sirv public --no-clear" - }, - "devDependencies": { - "@rollup/plugin-commonjs": "^17.0.0", - "@rollup/plugin-node-resolve": "^11.0.0", - "rollup": "^2.3.4", - "rollup-plugin-css-only": "^3.1.0", - "rollup-plugin-livereload": "^2.0.0", - "rollup-plugin-svelte": "^7.0.0", - "rollup-plugin-terser": "^7.0.0", - "svelte": "^3.0.0" - }, - "dependencies": { - "sirv-cli": "^2.0.0" - } + "name": "resume", + "private": true, + "version": "0.0.0", + "type": "module", + "scripts": { + "dev": "vite", + "build": "vite build", + "preview": "vite preview", + "check": "svelte-check --tsconfig ./tsconfig.json" + }, + "devDependencies": { + "@sveltejs/vite-plugin-svelte": "^3.0.2", + "@tsconfig/svelte": "^5.0.2", + "svelte": "^4.2.12", + "svelte-check": "^3.6.7", + "tslib": "^2.6.2", + "typescript": "^5.2.2", + "vite": "^5.2.0" + } } diff --git a/public/education.json b/public/education.json deleted file mode 100644 index ae5d5f2..0000000 --- a/public/education.json +++ /dev/null @@ -1,25 +0,0 @@ -[ - { - "school": "University of Windsor", - "degree": "Bachelors of Computer Science (Honours)", - "duration": "September 2019 - October 2023", - "points": [ - { - "text": "<b>97.40%</b> Major Average, <b>97.25%</b> Cumulative Average" - }, - { - "text": "Recipient of the President's Scholarship, Eleanor Catherine Wallace Memorial Scholarship, and Foresters Scholarship" - } - ] - }, - { - "school": "Business Career College", - "degree": "Life License Qualification Program (LLQP)", - "duration": "August 2023 - October 2023", - "points": [ - { - "text": "Completed the LLQP program to obtain my Ontario Life Insurance and Accident & Sickness Insurance licenses" - } - ] - } -] \ No newline at end of file diff --git a/public/experience.json b/public/experience.json deleted file mode 100644 index 86031f0..0000000 --- a/public/experience.json +++ /dev/null @@ -1,72 +0,0 @@ -[ - { - "title": "Software Engineer Intern", - "company": "Publicis Sapient", - "time": "June 2022 - August 2022", - "location": "Toronto, ON", - "points": [ - { - "text": "Created and deployed a <b>GraphQL</b> API using <b>Java, Spring Boot, and PostgreSQL</b> for a personal budgeting mobile app." - }, - { - "text": "Used <b>GitHub Actions</b> to set up automated <b>CI/CD</b> workflows." - } - ] - }, - { - "title": "Software Developer Intern", - "company": "Assent Inc.", - "time": "January 2022 - April 2022", - "location": "Ottawa, ON", - "points": [ - { - "text": "Used <b>Angular and SCSS</b> to create and update front-end components, adhering to strict styling standards." - }, - { - "text": "Used <b>C# and .NET Core</b> to create API endpoints, unit tests, component tests, and integration tests." - } - ] - }, - { - "title": "Software Developer Intern", - "company": "Green Shield Canada", - "time": "May 2021 - August 2021", - "location": "Windsor, ON", - "points": [ - { - "text": "Used <b>Oracle PL/SQL</b> to create Data Reports and Extracts" - } - ] - }, - { - "title": "Research Software Developer", - "company": "University of Windsor", - "time": "June 2020 - April 2023", - "location": "Windsor, ON", - "points": [ - { - "text": "Developed a <b>web application</b> for the analysis and presentation of experimental SAS data" - }, - { - "text": "Achieved <b>100X faster compute time</b> of select elements" - }, - { - "text": "Using <b>Flask, Bootstrap, NumPy, SciPy, and Matplotlib</b>" - } - ] - }, - { - "title": "Teaching Assistant", - "company": "University of Windsor", - "time": "September 2020 - June 2023", - "location": "Windsor, ON", - "points": [ - { - "text": "Responsible for lab instruction, marking, and holding office hours for <b>4 core undergraduate courses</b>" - }, - { - "text": "<b>Built and deployed a web application</b> that grades assignments</b>" - } - ] - } -] diff --git a/public/extracurricular.json b/public/extracurricular.json deleted file mode 100644 index a5a91ad..0000000 --- a/public/extracurricular.json +++ /dev/null @@ -1,14 +0,0 @@ -[ - { - "title": "President | Computer Science Society", - "description": "Led a team of 20 volunteers to create applications, organize events, and represent over 900 undergraduate students (2021-2023)" - }, - { - "title": "Co-Founder and Technical Lead | WinHacks", - "description": "MLH Hackathon (winhacks.ca) (2020-2022)" - }, - { - "title": "Co-Founder and Technical Lead | BorderHacks", - "description": "MLH Hackathon (borderhacks.com) (2020-2021)" - } -] diff --git a/public/favicon.png b/public/favicon.png deleted file mode 100644 index 7e6f5eb..0000000 Binary files a/public/favicon.png and /dev/null differ diff --git a/public/global.css b/public/global.css deleted file mode 100644 index 975bea6..0000000 --- a/public/global.css +++ /dev/null @@ -1,74 +0,0 @@ -html, body { - margin: 0; - padding: 0; - position: relative; -} - -body { - color: #000; - margin: 0.25in 0.5in; - padding: 8px; - box-sizing: border-box; - font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif; -} - -h1 { - margin: 0; - padding: 0; -} - -hr { - border-top: solid 4px #000 !important; - margin: 4px; -} - -a{ - text-decoration: none; - color: #000; -} - -h3.primary-heading { - font-size: 16px; - font-weight: 400; - margin: 5px 0px; -} - -h4.secondary-heading { - font-size: 14px; - font-weight: 600; - margin: 5px 0px; -} - -.icon-row{ - display: flex; - justify-content: space-between; -} - -.icon-row > span{ - font-size: 12px; - padding-right: 20px; -} - -.point-text { - font-size: 12px; -} - -.dotted-separator { - border:none; - border-top: 1px dashed #888; - margin: 10px 0px; -} - -i { - margin-right: 3px; -} - -ul { - padding-left: 0; - margin: 5px 0px; - list-style-type: none; -} - -.tiny-adjust{ - margin-top: 3px; -} \ No newline at end of file diff --git a/public/header.json b/public/header.json deleted file mode 100644 index 968a6f0..0000000 --- a/public/header.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "name": "Jeremie Bornais", - "email": "jeremiejbornais@gmail.com", - "phone": "(226) 350-2944", - "website": "jeremie.bornais.ca", - "github": "jere-mie", - "linkedin": "jeremie-bornais" -} diff --git a/public/index.html b/public/index.html deleted file mode 100644 index b7931ba..0000000 --- a/public/index.html +++ /dev/null @@ -1,18 +0,0 @@ -<!DOCTYPE html> -<html lang="en"> -<head> - <meta charset='utf-8'> - <meta name='viewport' content='width=device-width,initial-scale=1'> - - <title>Bornais_Jeremie_Resume</title> - - <link rel='icon' type='image/png' href='https://f.m.bornais.ca/logo.png'> - <link rel='stylesheet' href='./global.css'> - <link rel='stylesheet' href='./build/bundle.css'> - <script src="https://kit.fontawesome.com/22fc08ce26.js" crossorigin="anonymous"></script> - <script defer src='./build/bundle.js'></script> -</head> - -<body> -</body> -</html> diff --git a/public/projects.json b/public/projects.json deleted file mode 100644 index b791df2..0000000 --- a/public/projects.json +++ /dev/null @@ -1,47 +0,0 @@ -[ - { - "title": "Automagic Websites", - "link": "https://github.com/jere-mie/automagic-websites", - "points": [ - { - "text": "Full stack web application featuring <b>user authentication</b>" - }, - { - "text": "Allows users to <b>create, host, and export</b> their own personal website" - }, - { - "text": "Made with <b>Python, Flask, SQLAlchemy, Bootstrap</b>" - } - ] - }, - { - "title": "UWindsor API", - "link": "https://github.com/jere-mie/uwindsor-api", - "points": [ - { - "text": "<b>REST API</b> created to enable developers to create applications for the UWindsor community" - }, - { - "text": "Serves course, staff and building data related to the University of Windsor" - }, - { - "text": "Made with <b>Go, Gin, and SQLX</b>" - } - ] - }, - { - "title": "Easy-MASM", - "link": "https://github.com/jere-mie/easy-masm", - "points": [ - { - "text": "Automated system for assembling, linking, and executing <b>MASM32</b> programs" - }, - { - "text": "Used by over <b>500 students</b>" - }, - { - "text": "Made with <b>Docker, bash and batch</b>" - } - ] - } -] diff --git a/public/skills.json b/public/skills.json deleted file mode 100644 index de30f2a..0000000 --- a/public/skills.json +++ /dev/null @@ -1,18 +0,0 @@ -[ - { - "type": "PROGRAMMING", - "list": "Python, JavaScript, Go, Java, C#, HTML, CSS, SCSS, C++, SQL, C, Ruby" - }, - { - "type": "FRAMEWORKS", - "list": "Flask, React Native, Svelte, Angular, React.js, Gin, .NET Core, Spring Boot, Bootstrap, Ruby on Rails" - }, - { - "type": "TECHNOLOGIES", - "list": "Git, Linux, Docker, Caddy Server, GraphQL, REST API, OAuth2, CI/CD, GitHub Actions" - }, - { - "type": "CLOUD", - "list": "Google Cloud Platform, Microsoft Azure, DigitalOcean, Heroku" - } -] diff --git a/public/text.json b/public/text.json deleted file mode 100644 index eca14a5..0000000 --- a/public/text.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "text":"Bachelors of Computer Science (Honours), University of Windsor, September 2019 - October 2023, 97.25% GPA" -} \ No newline at end of file diff --git a/rollup.config.js b/rollup.config.js deleted file mode 100644 index e8965ec..0000000 --- a/rollup.config.js +++ /dev/null @@ -1,76 +0,0 @@ -import svelte from 'rollup-plugin-svelte'; -import commonjs from '@rollup/plugin-commonjs'; -import resolve from '@rollup/plugin-node-resolve'; -import livereload from 'rollup-plugin-livereload'; -import { terser } from 'rollup-plugin-terser'; -import css from 'rollup-plugin-css-only'; - -const production = !process.env.ROLLUP_WATCH; - -function serve() { - let server; - - function toExit() { - if (server) server.kill(0); - } - - return { - writeBundle() { - if (server) return; - server = require('child_process').spawn('npm', ['run', 'start', '--', '--dev'], { - stdio: ['ignore', 'inherit', 'inherit'], - shell: true - }); - - process.on('SIGTERM', toExit); - process.on('exit', toExit); - } - }; -} - -export default { - input: 'src/main.js', - output: { - sourcemap: true, - format: 'iife', - name: 'app', - file: 'public/build/bundle.js' - }, - plugins: [ - svelte({ - compilerOptions: { - // enable run-time checks when not in production - dev: !production - } - }), - // we'll extract any component CSS out into - // a separate file - better for performance - css({ output: 'bundle.css' }), - - // If you have external dependencies installed from - // npm, you'll most likely need these plugins. In - // some cases you'll need additional configuration - - // consult the documentation for details: - // https://github.com/rollup/plugins/tree/master/packages/commonjs - resolve({ - browser: true, - dedupe: ['svelte'] - }), - commonjs(), - - // In dev mode, call `npm run start` once - // the bundle has been generated - !production && serve(), - - // Watch the `public` directory and refresh the - // browser on changes when not in production - !production && livereload('public'), - - // If we're building for production (npm run build - // instead of npm run dev), minify - production && terser() - ], - watch: { - clearScreen: false - } -}; diff --git a/scripts/setupTypeScript.js b/scripts/setupTypeScript.js deleted file mode 100644 index 133658a..0000000 --- a/scripts/setupTypeScript.js +++ /dev/null @@ -1,121 +0,0 @@ -// @ts-check - -/** This script modifies the project to support TS code in .svelte files like: - - <script lang="ts"> - export let name: string; - </script> - - As well as validating the code for CI. - */ - -/** To work on this script: - rm -rf test-template template && git clone sveltejs/template test-template && node scripts/setupTypeScript.js test-template -*/ - -const fs = require("fs") -const path = require("path") -const { argv } = require("process") - -const projectRoot = argv[2] || path.join(__dirname, "..") - -// Add deps to pkg.json -const packageJSON = JSON.parse(fs.readFileSync(path.join(projectRoot, "package.json"), "utf8")) -packageJSON.devDependencies = Object.assign(packageJSON.devDependencies, { - "svelte-check": "^2.0.0", - "svelte-preprocess": "^4.0.0", - "@rollup/plugin-typescript": "^8.0.0", - "typescript": "^4.0.0", - "tslib": "^2.0.0", - "@tsconfig/svelte": "^2.0.0" -}) - -// Add script for checking -packageJSON.scripts = Object.assign(packageJSON.scripts, { - "check": "svelte-check --tsconfig ./tsconfig.json" -}) - -// Write the package JSON -fs.writeFileSync(path.join(projectRoot, "package.json"), JSON.stringify(packageJSON, null, " ")) - -// mv src/main.js to main.ts - note, we need to edit rollup.config.js for this too -const beforeMainJSPath = path.join(projectRoot, "src", "main.js") -const afterMainTSPath = path.join(projectRoot, "src", "main.ts") -fs.renameSync(beforeMainJSPath, afterMainTSPath) - -// Switch the app.svelte file to use TS -const appSveltePath = path.join(projectRoot, "src", "App.svelte") -let appFile = fs.readFileSync(appSveltePath, "utf8") -appFile = appFile.replace("<script>", '<script lang="ts">') -appFile = appFile.replace("export let name;", 'export let name: string;') -fs.writeFileSync(appSveltePath, appFile) - -// Edit rollup config -const rollupConfigPath = path.join(projectRoot, "rollup.config.js") -let rollupConfig = fs.readFileSync(rollupConfigPath, "utf8") - -// Edit imports -rollupConfig = rollupConfig.replace(`'rollup-plugin-terser';`, `'rollup-plugin-terser'; -import sveltePreprocess from 'svelte-preprocess'; -import typescript from '@rollup/plugin-typescript';`) - -// Replace name of entry point -rollupConfig = rollupConfig.replace(`'src/main.js'`, `'src/main.ts'`) - -// Add preprocessor -rollupConfig = rollupConfig.replace( - 'compilerOptions:', - 'preprocess: sveltePreprocess({ sourceMap: !production }),\n\t\t\tcompilerOptions:' -); - -// Add TypeScript -rollupConfig = rollupConfig.replace( - 'commonjs(),', - 'commonjs(),\n\t\ttypescript({\n\t\t\tsourceMap: !production,\n\t\t\tinlineSources: !production\n\t\t}),' -); -fs.writeFileSync(rollupConfigPath, rollupConfig) - -// Add TSConfig -const tsconfig = `{ - "extends": "@tsconfig/svelte/tsconfig.json", - - "include": ["src/**/*"], - "exclude": ["node_modules/*", "__sapper__/*", "public/*"] -}` -const tsconfigPath = path.join(projectRoot, "tsconfig.json") -fs.writeFileSync(tsconfigPath, tsconfig) - -// Add global.d.ts -const dtsPath = path.join(projectRoot, "src", "global.d.ts") -fs.writeFileSync(dtsPath, `/// <reference types="svelte" />`) - -// Delete this script, but not during testing -if (!argv[2]) { - // Remove the script - fs.unlinkSync(path.join(__filename)) - - // Check for Mac's DS_store file, and if it's the only one left remove it - const remainingFiles = fs.readdirSync(path.join(__dirname)) - if (remainingFiles.length === 1 && remainingFiles[0] === '.DS_store') { - fs.unlinkSync(path.join(__dirname, '.DS_store')) - } - - // Check if the scripts folder is empty - if (fs.readdirSync(path.join(__dirname)).length === 0) { - // Remove the scripts folder - fs.rmdirSync(path.join(__dirname)) - } -} - -// Adds the extension recommendation -fs.mkdirSync(path.join(projectRoot, ".vscode"), { recursive: true }) -fs.writeFileSync(path.join(projectRoot, ".vscode", "extensions.json"), `{ - "recommendations": ["svelte.svelte-vscode"] -} -`) - -console.log("Converted to TypeScript.") - -if (fs.existsSync(path.join(projectRoot, "node_modules"))) { - console.log("\nYou will need to re-run your dependency manager to get started.") -} diff --git a/src/App.svelte b/src/App.svelte deleted file mode 100644 index 8373baf..0000000 --- a/src/App.svelte +++ /dev/null @@ -1,34 +0,0 @@ -<script> - import Header from './Header.svelte'; - import Education from './Education.svelte'; - import Experience from "./Experience.svelte"; - import Skills from './Skills.svelte'; - import Projects from './Projects.svelte'; - import Extracurricular from './Extracurricular.svelte'; - import Tiny from './Tiny.svelte' -</script> - -<Header /> -<main> - <div style="width: 50%"> - <Tiny/> - <Experience /> - <Extracurricular /> - </div> - - <div style="width: 45%;"> - <div class="tiny-adjust"></div> - <Education /> - <Skills /> - <Projects /> - </div> -</main> - -<style> - main { - margin: 0; - padding: 0; - display: flex; - justify-content: space-between - } -</style> \ No newline at end of file diff --git a/src/Education.svelte b/src/Education.svelte deleted file mode 100644 index e099c4e..0000000 --- a/src/Education.svelte +++ /dev/null @@ -1,39 +0,0 @@ -<script> - import Title from './Title.svelte'; - - const getEdu = async () => { - let res = await fetch("./education.json"); - let edus = await res.json(); - return edus; - } - const eduPromise = getEdu(); -</script> - - -<div class="education"> - <Title name="Education"/> - {#await eduPromise} - <p>Loading education...</p> - {:then edus} - {#each edus as edu} - <div class="education"> - <h3 class="primary-heading">{edu.degree}</h3> - <h4 class="secondary-heading">{edu.school}</h4> - <div class="icon-row" style="width: 100%;"> - <span> - <i class="fa fa-calendar"></i> - {edu.duration} - </span> - </div> - <ul> - {#each edu.points as point} - <li class="point-text">- {@html point.text}</li> - {/each} - </ul> - </div> - {#if edu != edus[edus.length - 1]} - <div class="dotted-separator"></div> - {/if} - {/each} - {/await} -</div> diff --git a/src/Experience.svelte b/src/Experience.svelte deleted file mode 100644 index 581b342..0000000 --- a/src/Experience.svelte +++ /dev/null @@ -1,42 +0,0 @@ -<script> - import Title from "./Title.svelte"; - const getJobs = async () => { - let res = await fetch("./experience.json"); - let jobs = await res.json(); - return jobs; - } - const jobPromise = getJobs(); - -</script> - -<div class="experience"> - <Title name="Experience"/> - {#await jobPromise} - <p>Loading experience...</p> - {:then jobs} - {#each jobs as job} - <div class="job"> - <h3 class="primary-heading">{job.title}</h3> - <h4 class="secondary-heading">{job.company}</h4> - <div class="icon-row" style="width: 100%;"> - <span> - <i class="fa fa-calendar"></i> - {job.time} - </span> - <span> - <i class="fa fa-map-marker"></i> - {job.location} - </span> - </div> - <ul> - {#each job.points as point} - <li class="point-text">- {@html point.text}</li> - {/each} - </ul> - </div> - {#if job != jobs[jobs.length - 1]} - <div class="dotted-separator"></div> - {/if} - {/each} - {/await} -</div> diff --git a/src/Extracurricular.svelte b/src/Extracurricular.svelte deleted file mode 100644 index 792b3e3..0000000 --- a/src/Extracurricular.svelte +++ /dev/null @@ -1,23 +0,0 @@ -<script> - import Title from "./Title.svelte"; - const getExtra = async () => { - let res = await fetch("./extracurricular.json"); - let extras = await res.json(); - return extras; - } - const extraPromise = getExtra(); - -</script> - -<div class="extracurricular"> - <Title name="Extracurricular"/> - {#await extraPromise} - <p>Loading extracurricular...</p> - {:then extras} - <ul> - {#each extras as extra} - <li class="point-text">- <b>{extra.title}</b>: {@html extra.description}</li> - {/each} - </ul> - {/await} -</div> diff --git a/src/Header.svelte b/src/Header.svelte deleted file mode 100644 index 713ce42..0000000 --- a/src/Header.svelte +++ /dev/null @@ -1,57 +0,0 @@ -<script> - const getInfo = async () => { - let res = await fetch("./header.json"); - let info = await res.json(); - return info; - } - const infoPromise = getInfo(); -</script> -{#await infoPromise} - <p>Loading info...</p> -{:then info} -<h1>{info.name}</h1> -<div class="links"> - <span> - <i class="fa fa-envelope"></i> - <a href="mailto:{info.email}" target="_blank">{info.email}</a> - </span> - <span> - <i class="fa fa-phone"></i> - {info.phone} - </span> - <span> - <i class="fa fa-link"></i> - <a href="https://{info.website}" target="_blank">{info.website}</a> - </span> - <span> - <i class="fa fa-github"></i> - <a href="https://github.com/{info.github}" target="_blank">{info.github}</a> - </span> - <span> - <i class="fa fa-linkedin"></i> - <a href="https://linkedin.com/in/{info.linkedin}" target="_blank">{info.linkedin}</a> - </span> -</div> -{/await} - - -<style> - h1{ - font-size: 2.5rem; - font-weight: 500; - text-transform: uppercase; - margin-bottom: 15px; - } - - .links { - display: flex; - justify-content: left; - padding-bottom: 15px; - } - .links > span { - font-size: 12px; - font-weight: 600; - padding-right: 15px; - } - -</style> \ No newline at end of file diff --git a/src/Projects.svelte b/src/Projects.svelte deleted file mode 100644 index c754e10..0000000 --- a/src/Projects.svelte +++ /dev/null @@ -1,37 +0,0 @@ -<script> - import Title from './Title.svelte'; - const getProjects = async () => { - let res = await fetch("./projects.json"); - let projects = await res.json(); - return projects; - } - const projectPromise = getProjects(); - -</script> - -<div class="projects"> - <Title name="Projects"/> - {#await projectPromise} - <p>Loading projects...</p> - {:then projects} - {#each projects as project} - <div class="project"> - <h4 class="secondary-heading"><a href="{project.link}"><i class="fa fa-github"></i>{project.title}</a></h4> - <ul> - {#each project.points as point} - <li class="point-text">- {@html point.text}</li> - {/each} - </ul> - </div> - {#if project != projects[projects.length - 1]} - <div class="dotted-separator"></div> - {/if} - {/each} - {/await} -</div> - -<style> - .project { - padding-bottom: 3px; - } -</style> \ No newline at end of file diff --git a/src/Resume.svelte b/src/Resume.svelte new file mode 100644 index 0000000..ee224b7 --- /dev/null +++ b/src/Resume.svelte @@ -0,0 +1,66 @@ +<script lang="ts"> + import type { Resume } from "./lib/types"; + + import Header from "./components/Header.svelte"; + import Tiny from "./components/Tiny.svelte"; + import Section from "./components/Section.svelte"; + import Education from "./components/sections/Education.svelte"; + import Experience from "./components/sections/Experience.svelte"; + import Extracurricular from "./components/sections/Extracurricular.svelte"; + import Skills from "./components/sections/Skills.svelte"; + import Projects from "./components/sections/Projects.svelte"; + + // Import resume data + import data from "./resume.json"; +</script> + +<Header info={data.info}></Header> + +<main> + <div style="width: 50%"> + {#if data.tiny_text} + <Tiny>{data.tiny_text}</Tiny> + {/if} + + {#if data.experience} + <Section name="Experience"> + <Experience items={data.experience} /> + </Section> + {/if} + + {#if data.extracurricular} + <Section name="Extracurricular"> + <Extracurricular items={data.extracurricular} /> + </Section> + {/if} + </div> + + <div style="width: 45%;"> + {#if data.education} + <Section name="Education"> + <Education items={data.education} /> + </Section> + {/if} + + {#if data.skills} + <Section name="Skills"> + <Skills items={data.skills} /> + </Section> + {/if} + + {#if data.projects} + <Section name="Projects"> + <Projects items={data.projects} /> + </Section> + {/if} + </div> +</main> + +<style> + main { + margin: 0; + padding: 0; + display: flex; + justify-content: space-between; + } +</style> diff --git a/src/Skills.svelte b/src/Skills.svelte deleted file mode 100644 index afb20ef..0000000 --- a/src/Skills.svelte +++ /dev/null @@ -1,29 +0,0 @@ -<script> - import Title from "./Title.svelte"; - const getSkills = async () => { - let res = await fetch("./skills.json"); - let skills = await res.json(); - return skills; - } - const skillsPromise = getSkills(); - -</script> - -<div class="skills"> - <Title name="Skills"/> - {#await skillsPromise} - <p>Loading skills...</p> - {:then skills} - <ul> - {#each skills as skill} - <li class="skill"><b>{skill.type}</b>: {skill.list}</li> - {/each} - </ul> - {/await} -</div> - -<style> - .skill{ - font-size: 14px; - } -</style> \ No newline at end of file diff --git a/src/Tiny.svelte b/src/Tiny.svelte deleted file mode 100644 index 106d8fd..0000000 --- a/src/Tiny.svelte +++ /dev/null @@ -1,25 +0,0 @@ -<script> - const getText = async () => { - let res = await fetch("./text.json"); - let text = await res.json(); - return text; - } - const textPromise = getText(); -</script> - - -<div class="tiny"> - {#await textPromise} - <p>Loading tiny text...</p> - {:then text} - <p>{text.text}</p> - {/await} -</div> - -<style> - .tiny, p{ - font-size: 1px; - color: #fff; - -webkit-print-color-adjust: exact - } -</style> \ No newline at end of file diff --git a/src/Title.svelte b/src/Title.svelte deleted file mode 100644 index 93d6248..0000000 --- a/src/Title.svelte +++ /dev/null @@ -1,13 +0,0 @@ -<script> - export let name; -</script> - -<h1>{name}</h1> -<hr> -<style> - h1 { - font-weight: 600; - text-transform: uppercase; - font-size: 1.5rem; - } -</style> \ No newline at end of file diff --git a/src/components/DetailItem.svelte b/src/components/DetailItem.svelte new file mode 100644 index 0000000..af181d5 --- /dev/null +++ b/src/components/DetailItem.svelte @@ -0,0 +1,7 @@ +<li class="item-text">- <slot /></li> + +<style> + .item-text { + font-size: 12px; + } +</style> diff --git a/src/components/DetailList.svelte b/src/components/DetailList.svelte new file mode 100644 index 0000000..cbb46b2 --- /dev/null +++ b/src/components/DetailList.svelte @@ -0,0 +1,3 @@ +<ul> + <slot /> +</ul> diff --git a/src/components/DottedRule.svelte b/src/components/DottedRule.svelte new file mode 100644 index 0000000..aa8c464 --- /dev/null +++ b/src/components/DottedRule.svelte @@ -0,0 +1,9 @@ +<div class="dotted-separator"></div> + +<style> + .dotted-separator { + border: none; + border-top: 1px dashed #888; + margin: 10px 0px; + } +</style> diff --git a/src/components/Header.svelte b/src/components/Header.svelte new file mode 100644 index 0000000..254db0d --- /dev/null +++ b/src/components/Header.svelte @@ -0,0 +1,67 @@ +<script lang="ts"> + import type { Info } from "../lib/types"; + + export let info: Info; +</script> + +<h1>{info.name}</h1> + +<div class="links"> + <span> + <i class="fa fa-envelope"></i> + <a href="mailto:{info.email}" target="_blank">{info.email}</a> + </span> + + {#if info.phone} + <span> + <i class="fa fa-phone"></i> + {info.phone} + </span> + {/if} + + {#if info.website} + <span> + <i class="fa fa-link"></i> + <a href="https://{info.website}" target="_blank">{info.website}</a> + </span> + {/if} + + {#if info.github} + <span> + <i class="fa fa-github"></i> + <a href="https://github.com/{info.github}" target="_blank"> + {info.github} + </a> + </span> + {/if} + + {#if info.linkedin} + <span> + <i class="fa fa-linkedin"></i> + <a href="https://linkedin.com/in/{info.linkedin}" target="_blank"> + {info.linkedin} + </a> + </span> + {/if} +</div> + +<style> + h1 { + font-size: 2.5rem; + font-weight: 500; + text-transform: uppercase; + margin-bottom: 15px; + } + + .links { + display: flex; + justify-content: left; + padding-bottom: 15px; + } + + .links > span { + font-size: 12px; + font-weight: 600; + padding-right: 15px; + } +</style> diff --git a/src/components/LoadingSpinner.svelte b/src/components/LoadingSpinner.svelte new file mode 100644 index 0000000..3b4e92e --- /dev/null +++ b/src/components/LoadingSpinner.svelte @@ -0,0 +1,42 @@ +<script lang="ts"> + import type { HTMLAttributes } from "svelte/elements"; + + export let color: string = "gray"; +</script> + +<div class="spinner" style={"color: " + color}></div> + +<style> + .spinner, + .spinner:after { + box-sizing: border-box; + } + + .spinner { + display: inline-block; + width: 80px; + height: 80px; + } + + .spinner:after { + content: " "; + display: block; + width: 64px; + height: 64px; + margin: 8px; + border-radius: 50%; + border: 6.4px solid currentColor; + border-color: currentColor transparent currentColor transparent; + animation: spin 1.2s linear infinite; + } + + @keyframes spin { + 0% { + transform: rotate(0deg); + } + + 100% { + transform: rotate(360deg); + } + } +</style> diff --git a/src/components/PrimaryHeading.svelte b/src/components/PrimaryHeading.svelte new file mode 100644 index 0000000..36cd519 --- /dev/null +++ b/src/components/PrimaryHeading.svelte @@ -0,0 +1,9 @@ +<h3 class="primary-heading"><slot /></h3> + +<style> + h3.primary-heading { + font-size: 16px; + font-weight: 400; + margin: 5px 0px; + } +</style> diff --git a/src/components/SecondaryHeading.svelte b/src/components/SecondaryHeading.svelte new file mode 100644 index 0000000..e7d14ac --- /dev/null +++ b/src/components/SecondaryHeading.svelte @@ -0,0 +1,9 @@ +<h4 class="secondary-heading"><slot /></h4> + +<style> + h4.secondary-heading { + font-size: 14px; + font-weight: 600; + margin: 5px 0px; + } +</style> diff --git a/src/components/Section.svelte b/src/components/Section.svelte new file mode 100644 index 0000000..a902ec7 --- /dev/null +++ b/src/components/Section.svelte @@ -0,0 +1,17 @@ +<script lang="ts"> + export let name: string; +</script> + +<div class={name}> + <h1>{name || ""}</h1> + <hr /> + <slot /> +</div> + +<style> + h1 { + font-weight: 600; + text-transform: uppercase; + font-size: 1.5rem; + } +</style> diff --git a/src/components/Tiny.svelte b/src/components/Tiny.svelte new file mode 100644 index 0000000..51534bb --- /dev/null +++ b/src/components/Tiny.svelte @@ -0,0 +1,23 @@ +<p class="tiny"> + <slot /> +</p> + +<style> + p.tiny { + --height: 3px; + --font-size: calc(var(--height) / 3); + + font-size: var(--font-size); + height: var(--height); + overflow: hidden; + + color: #fff; + + -webkit-print-color-adjust: exact; + print-color-adjust: exact; + + margin: 0px; + margin-top: calc(-1 * var(--height)); + padding: 0px; + } +</style> diff --git a/src/components/sections/Education.svelte b/src/components/sections/Education.svelte new file mode 100644 index 0000000..b29d6a0 --- /dev/null +++ b/src/components/sections/Education.svelte @@ -0,0 +1,38 @@ +<script lang="ts"> + import type { Education } from "../../lib/types"; + import { dateRange } from "../../lib/util"; + + import PrimaryHeading from "../PrimaryHeading.svelte"; + import SecondaryHeading from "../SecondaryHeading.svelte"; + import DetailList from "../DetailList.svelte"; + import DetailItem from "../DetailItem.svelte"; + import DottedRule from "../DottedRule.svelte"; + + export let items: Education[]; +</script> + +{#each items as education, index} + <div class="education"> + <PrimaryHeading>{education.certification}</PrimaryHeading> + <SecondaryHeading>{education.location}</SecondaryHeading> + + <div class="icon-row" style="width: 100%;"> + <span> + <i class="fa fa-calendar"></i> + {dateRange(education.start, education.end)} + </span> + </div> + + {#if education.details} + <DetailList> + {#each education.details as detail} + <DetailItem>{@html detail}</DetailItem> + {/each} + </DetailList> + {/if} + </div> + + {#if index < items.length - 1} + <DottedRule /> + {/if} +{/each} diff --git a/src/components/sections/Experience.svelte b/src/components/sections/Experience.svelte new file mode 100644 index 0000000..30da597 --- /dev/null +++ b/src/components/sections/Experience.svelte @@ -0,0 +1,42 @@ +<script lang="ts"> + import type { Experience } from "../../lib/types"; + import { dateRange } from "../../lib/util"; + import DetailItem from "../DetailItem.svelte"; + import DetailList from "../DetailList.svelte"; + import DottedRule from "../DottedRule.svelte"; + import PrimaryHeading from "../PrimaryHeading.svelte"; + import SecondaryHeading from "../SecondaryHeading.svelte"; + + export let items: Experience[]; +</script> + +{#each items as position, index} + <div class="job"> + <PrimaryHeading>{position.title}</PrimaryHeading> + <SecondaryHeading>{position.company}</SecondaryHeading> + + <div class="icon-row" style="width: 100%;"> + <span> + <i class="fa fa-calendar"></i> + {dateRange(position.start, position.end)} + </span> + + {#if position.location} + <span> + <i class="fa fa-map-marker"></i> + {position.location} + </span> + {/if} + </div> + + <DetailList> + {#each position.details as detailLine} + <DetailItem>{@html detailLine}</DetailItem> + {/each} + </DetailList> + </div> + + {#if index < items.length - 1} + <DottedRule /> + {/if} +{/each} diff --git a/src/components/sections/Extracurricular.svelte b/src/components/sections/Extracurricular.svelte new file mode 100644 index 0000000..81ba681 --- /dev/null +++ b/src/components/sections/Extracurricular.svelte @@ -0,0 +1,16 @@ +<script lang="ts"> + import type { Extracurricular } from "../../lib/types"; + import DetailItem from "../DetailItem.svelte"; + import DetailList from "../DetailList.svelte"; + + export let items: Extracurricular[]; +</script> + +<DetailList> + {#each items as item} + <DetailItem> + <b>{[item.title, item.location].filter((x) => x).join(" | ")}</b>: {@html item.description} + </DetailItem> + {/each} +</DetailList> +<ul></ul> diff --git a/src/components/sections/Projects.svelte b/src/components/sections/Projects.svelte new file mode 100644 index 0000000..124cbff --- /dev/null +++ b/src/components/sections/Projects.svelte @@ -0,0 +1,36 @@ +<script lang="ts"> + import type { Project } from "../../lib/types"; + import DetailItem from "../DetailItem.svelte"; + import DetailList from "../DetailList.svelte"; + import DottedRule from "../DottedRule.svelte"; + import SecondaryHeading from "../SecondaryHeading.svelte"; + + export let items: Project[]; +</script> + +{#each items as project, index} + <div class="project"> + <SecondaryHeading> + <a href={project.link}> + <i class="fa fa-github"></i> + {project.title} + </a> + </SecondaryHeading> + + <DetailList> + {#each project.details as detail} + <DetailItem>{@html detail}</DetailItem> + {/each} + </DetailList> + </div> + + {#if index < items.length - 1} + <DottedRule /> + {/if} +{/each} + +<style> + .project { + padding-bottom: 3px; + } +</style> diff --git a/src/components/sections/Skills.svelte b/src/components/sections/Skills.svelte new file mode 100644 index 0000000..61da324 --- /dev/null +++ b/src/components/sections/Skills.svelte @@ -0,0 +1,21 @@ +<script lang="ts"> + import type { Skill } from "../../lib/types"; + import DetailList from "../DetailList.svelte"; + + export let items: Skill[]; +</script> + +<DetailList> + {#each items as skill} + <ul class="skill"> + <b>{skill.category}</b>: + {skill.items.join(", ")} + </ul> + {/each} +</DetailList> + +<style> + .skill { + font-size: 14px; + } +</style> diff --git a/src/global.css b/src/global.css new file mode 100644 index 0000000..89f44f0 --- /dev/null +++ b/src/global.css @@ -0,0 +1,50 @@ +html, +body { + margin: 0; + padding: 0; + position: relative; +} + +body { + color: #000; + margin: 0.25in 0.5in; + padding: 8px; + box-sizing: border-box; + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, + Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif; +} + +h1 { + margin: 0; + padding: 0; +} + +hr { + border-top: solid 4px #000 !important; + margin: 4px; +} + +a { + text-decoration: none; + color: #000; +} + +.icon-row { + display: flex; + justify-content: space-between; +} + +.icon-row > span { + font-size: 12px; + padding-right: 20px; +} + +i { + margin-right: 3px; +} + +ul { + padding-left: 0; + margin: 5px 0px; + list-style-type: none; +} diff --git a/src/lib/types.ts b/src/lib/types.ts new file mode 100644 index 0000000..f54b8b4 --- /dev/null +++ b/src/lib/types.ts @@ -0,0 +1,52 @@ +export interface Resume { + info: Info; + tiny_text?: string; + education?: Education[]; + experience?: Experience[]; + extracurricular?: Extracurricular[]; + projects?: Project[]; + skills?: Skill[]; +} + +export interface Education { + certification: string; + location: string; + details?: string[]; + start: string; + end?: string; +} + +export interface Experience { + title: string; + company: string; + location: string; + details: string[]; + start: string; + end?: string; +} + +export interface Extracurricular { + title: string; + description: string; + location?: string; +} + +export interface Info { + name: string; + website?: string; + email: string; + phone?: string; + github?: string; + linkedin?: string; +} + +export interface Project { + title: string; + link: string; + details: string[]; +} + +export interface Skill { + category: string; + items: string[]; +} diff --git a/src/lib/util.ts b/src/lib/util.ts new file mode 100644 index 0000000..202e15a --- /dev/null +++ b/src/lib/util.ts @@ -0,0 +1,7 @@ +export const dateRange = (start: string, end: string | undefined): string => { + if (!end) { + return start; + } + + return start + " - " + end; +}; diff --git a/src/main.js b/src/main.js deleted file mode 100644 index d80e9a3..0000000 --- a/src/main.js +++ /dev/null @@ -1,7 +0,0 @@ -import App from './App.svelte'; - -const app = new App({ - target: document.body, -}); - -export default app; \ No newline at end of file diff --git a/src/main.ts b/src/main.ts new file mode 100644 index 0000000..3536797 --- /dev/null +++ b/src/main.ts @@ -0,0 +1,8 @@ +import "./global.css"; +import Resume from "./Resume.svelte"; + +const resume = new Resume({ + target: document.getElementById("app")!, +}); + +export default resume; diff --git a/src/resume.json b/src/resume.json new file mode 100644 index 0000000..e14c065 --- /dev/null +++ b/src/resume.json @@ -0,0 +1,192 @@ +{ + "$schema": "resume.schema.json", + "info": { + "name": "Jeremie Bornais", + "email": "jeremiejbornais@gmail.com", + "phone": "(226) 350-2944", + "website": "jeremie.bornais.ca", + "github": "jere-mie", + "linkedin": "jeremie-bornais" + }, + "tiny_text": "Bachelors of Computer Science (Honours), University of Windsor, September 2019 - October 2023, 97.25% GPA", + "education": [ + { + "location": "University of Windsor", + "certification": "Bachelors of Computer Science (Honours)", + "start": "September 2019", + "end": "October 2023", + "details": [ + "<b>97.40%</b> Major Average, <b>97.25%</b> Cumulative Average", + "Recipient of the President's Scholarship, Eleanor Catherine Wallace Memorial Scholarship, and Foresters Scholarship" + ] + }, + { + "location": "Business Career College", + "certification": "Life License Qualification Program (LLQP)", + "start": "August 2023", + "end": "October 2023", + "details": [ + "Completed the LLQP program to obtain my Ontario Life Insurance and Accident & Sickness Insurance licenses" + ] + } + ], + "experience": [ + { + "title": "Software Engineer Intern", + "company": "Publicis Sapient", + "start": "June 2022", + "end": "August 2022", + "location": "Toronto, ON", + "details": [ + "Created and deployed a <b>GraphQL</b> API using <b>Java, Spring Boot, and PostgreSQL</b> for a personal budgeting mobile app.", + "Used <b>GitHub Actions</b> to set up automated <b>CI/CD</b> workflows." + ] + }, + { + "title": "Software Developer Intern", + "company": "Assent Inc.", + "start": "January 2022", + "end": "April 2022", + "location": "Ottawa, ON", + "details": [ + "Used <b>Angular and SCSS</b> to create and update front-end components, adhering to strict styling standards.", + "Used <b>C# and .NET Core</b> to create API endpoints, unit tests, component tests, and integration tests." + ] + }, + { + "title": "Software Developer Intern", + "company": "Green Shield Canada", + "start": "May 2021", + "end": "August 2021", + "location": "Windsor, ON", + "details": [ + "Used <b>Oracle PL/SQL</b> to create Data Reports and Extracts" + ] + }, + { + "title": "Research Software Developer", + "company": "University of Windsor", + "start": "June 2020", + "end": "April 2023", + "location": "Windsor, ON", + "details": [ + "Developed a <b>web application</b> for the analysis and presentation of experimental SAS data", + "Achieved <b>100X faster compute time</b> of select elements", + "Using <b>Flask, Bootstrap, NumPy, SciPy, and Matplotlib</b>" + ] + }, + { + "title": "Teaching Assistant", + "company": "University of Windsor", + "start": "September 2020", + "end": "June 2023", + "location": "Windsor, ON", + "details": [ + "Responsible for lab instruction, marking, and holding office hours for <b>4 core undergraduate courses</b>", + "<b>Built and deployed a web application</b> that grades assignments</b>" + ] + } + ], + "skills": [ + { + "category": "Programming", + "items": [ + "Python", + "JavaScript", + "Go", + "Java", + "C#", + "HTML", + "CSS", + "SCSS", + "C++", + "SQL", + "C", + "Ruby" + ] + }, + { + "category": "Frameworks", + "items": [ + "Flask", + "React Native", + "Svelte", + "Angular", + "React.js", + "Gin", + ".NET Core", + "Spring Boot", + "Bootstrap", + "Ruby on Rails" + ] + }, + { + "category": "Technologies", + "items": [ + "Git", + "Linux", + "Docker", + "Caddy Server", + "GraphQL", + "REST API", + "OAuth2", + "CI/CD", + "GitHub Actions" + ] + }, + { + "category": "Cloud", + "items": [ + "Google Cloud Platform", + "Microsoft Azure", + "DigitalOcean", + "Heroku" + ] + } + ], + "projects": [ + { + "title": "Automagic Websites", + "link": "https://github.com/jere-mie/automagic-websites", + "details": [ + "Full stack web application featuring <b>user authentication</b>", + "Allows users to <b>create, host, and export</b> their own personal website", + "Made with <b>Python, Flask, SQLAlchemy, Bootstrap</b>" + ] + }, + { + "title": "UWindsor API", + "link": "https://github.com/jere-mie/uwindsor-api", + "details": [ + "<b>REST API</b> created to enable developers to create applications for the UWindsor community", + "Serves course, staff and building data related to the University of Windsor", + "Made with <b>Go, Gin, and SQLX</b>" + ] + }, + { + "title": "Easy-MASM", + "link": "https://github.com/jere-mie/easy-masm", + "details": [ + "Automated system for assembling, linking, and executing <b>MASM32</b> programs", + "Used by over <b>500 students</b>", + "Made with <b>Docker, bash and batch</b>" + ] + } + ], + "extracurricular": [ + { + "title": "President", + "description": "Led a team of 20 volunteers to create applications, organize events, and represent over 900 undergraduate students (2021-2023)" + }, + { + "title": "Co-Founder and Technical Lead", + "description": "MLH Hackathon (winhacks.ca) (2020-2022)", + "location": "WinHacks" + }, + { + "title": "Co-Founder and Technical Lead", + "description": "MLH Hackathon (borderhacks.com) (2020-2021)", + "location": "BorderHacks" + } + ] +} diff --git a/src/resume.schema.json b/src/resume.schema.json new file mode 100644 index 0000000..171902e --- /dev/null +++ b/src/resume.schema.json @@ -0,0 +1,192 @@ +{ + "$comment": "Schema for resume.json", + "properties": { + "education": { + "items": { + "properties": { + "certification": { + "description": "The name of the certification, such as 'Bachelors of Computer Science (Honours)'", + "type": "string" + }, + "details": { + "$ref": "#/definitions/array[string]", + "description": "Extra information about the education/certification" + }, + "end": { + "description": "The month/year you finished receiving education", + "type": "string" + }, + "location": { + "description": "Where the education was received, such as a university or bootcamp", + "type": "string" + }, + "start": { + "description": "The month/year you started receiving education", + "type": "string" + } + }, + "required": [ + "location", + "certification", + "start" + ], + "type": "object" + }, + "minItems": 1, + "type": "array" + }, + "experience": { + "items": { + "properties": { + "company": { + "description": "The company you worked for", + "type": "string" + }, + "details": { + "$ref": "#/definitions/array[string]", + "description": "Extra information about the experience, such as tools used or quantative improvements made" + }, + "end": { + "description": "When you ended", + "type": "string" + }, + "location": { + "description": "The location you worked from", + "type": "string" + }, + "title": { + "description": "The title you held", + "type": "string" + }, + "start": { + "description": "When you started", + "type": "string" + } + }, + "required": [ + "company", + "details", + "start", + "title" + ], + "type": "object" + }, + "minItems": 1, + "type": "array" + }, + "extracurricular": { + "items": { + "properties": { + "description": { + "description": "Description of the extracurricular activity", + "type": "string" + }, + "location": { + "description": "Location of the extracurricular activity", + "type": "string" + }, + "title": { + "description": "Title of the extracurricular activity", + "type": "string" + } + }, + "required": [ + "title", + "description" + ], + "type": "object" + }, + "minItems": 1, + "type": "array" + }, + "info": { + "description": "The most important information on your resume, such as name and contact.", + "properties": { + "email": { + "description": "Your email address", + "type": "string" + }, + "github": { + "description": "Your GitHub profile name", + "type": "string" + }, + "linkedin": { + "description": "Your LinkedIn profile name", + "type": "string" + }, + "name": { + "description": "Your full name", + "type": "string" + }, + "phone": { + "description": "Your phone number", + "type": "string" + }, + "website": { + "description": "Your website. It is recommended you do not include http(s)://, for readability.", + "type": "string" + } + }, + "required": [ + "name", + "email" + ], + "type": "object" + }, + "projects": { + "items": { + "properties": { + "details": { + "$ref": "#/definitions/array[string]", + "description": "Details about the project, such as which technologies you used." + }, + "link": { + "description": "Link to the project. If possible, the link should point to a live demo.", + "type": "string" + }, + "title": { + "description": "The title of the project.", + "type": "string" + } + }, + "required": [ + "title", + "details" + ], + "type": "object" + }, + "minItems": 1, + "type": "array" + }, + "skills": { + "type": "array", + "items": { + "type": "object", + "properties": { + "category": { + "type": "string", + "description": "The name of the skill category. For example, 'Languages'" + }, + "items": { + "$ref": "#/definitions/array[string]", + "description": "The items in the skill category. For example, Java, C++, Python" + } + } + }, + "minItems": 1 + }, + "tiny_text": { + "description": "This text is imprinted near the top of the resume in tiny white text. Can be useful to optimize for automated systems.", + "type": "string" + } + }, + "definitions": { + "array[string]": { + "default": [], + "items": { + "type": "string" + }, + "type": "array" + } + } +} diff --git a/src/vite-env.d.ts b/src/vite-env.d.ts new file mode 100644 index 0000000..4078e74 --- /dev/null +++ b/src/vite-env.d.ts @@ -0,0 +1,2 @@ +/// <reference types="svelte" /> +/// <reference types="vite/client" /> diff --git a/svelte.config.js b/svelte.config.js new file mode 100644 index 0000000..b0683fd --- /dev/null +++ b/svelte.config.js @@ -0,0 +1,7 @@ +import { vitePreprocess } from '@sveltejs/vite-plugin-svelte' + +export default { + // Consult https://svelte.dev/docs#compile-time-svelte-preprocess + // for more information about preprocessors + preprocess: vitePreprocess(), +} diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..5fb548f --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,20 @@ +{ + "extends": "@tsconfig/svelte/tsconfig.json", + "compilerOptions": { + "target": "ESNext", + "useDefineForClassFields": true, + "module": "ESNext", + "resolveJsonModule": true, + /** + * Typecheck JS in `.svelte` and `.js` files by default. + * Disable checkJs if you'd like to use dynamic types in JS. + * Note that setting allowJs false does not prevent the use + * of JS in `.svelte` files. + */ + "allowJs": true, + "checkJs": true, + "isolatedModules": true + }, + "include": ["src/**/*.ts", "src/**/*.js", "src/**/*.svelte"], + "references": [{ "path": "./tsconfig.node.json" }] +} diff --git a/tsconfig.node.json b/tsconfig.node.json new file mode 100644 index 0000000..d02c37d --- /dev/null +++ b/tsconfig.node.json @@ -0,0 +1,10 @@ +{ + "compilerOptions": { + "composite": true, + "skipLibCheck": true, + "module": "ESNext", + "moduleResolution": "bundler", + "strict": true + }, + "include": ["vite.config.ts"] +} diff --git a/vite.config.ts b/vite.config.ts new file mode 100644 index 0000000..5ac8ecf --- /dev/null +++ b/vite.config.ts @@ -0,0 +1,7 @@ +import { defineConfig } from "vite"; +import { svelte } from "@sveltejs/vite-plugin-svelte"; + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [svelte()], +});