Compare commits

..

10 Commits

Author SHA1 Message Date
Gianmarco
ff876a0bbd ci: fixed CI on main
All checks were successful
Build Site Main / Build-Site (push) Successful in 1m51s
2025-06-21 10:14:16 +02:00
Gianmarco
521797dd12 feat: add corley and aws certification
Some checks failed
Build Site Develop / Build-Site (push) Failing after 5m41s
Build Site Main / Build-Site (push) Successful in 1m44s
2025-06-20 23:32:28 +02:00
9dd9940e55 testing ci
All checks were successful
Build Site Develop / Build-Site (push) Successful in 2m26s
2023-11-24 21:31:24 +01:00
297521efdc feat: add modal on img 2023-11-24 15:31:56 +01:00
bbdb1d4453 Merge pull request 'fixed minor navigation issues' (#3) from develop into main
All checks were successful
continuous-integration/drone Build is passing
Reviewed-on: #3
2023-05-28 12:23:32 +02:00
6d387986e0 fixed minor navigation issues
All checks were successful
continuous-integration/drone Build is passing
2023-05-28 12:13:11 +02:00
Gianmarco Pettinato
283ebb35c9 fixing header
All checks were successful
continuous-integration/drone Build is passing
2023-05-28 00:45:23 +02:00
Gianmarco Pettinato
eabc979c62 new picture
All checks were successful
continuous-integration/drone Build is passing
2023-05-27 19:44:17 +02:00
Gianmarco Pettinato
0d090ee2e6 [ci]: develop ci 2023-05-27 19:02:47 +02:00
Gianmarco Pettinato
1669eeff4d new theme done
All checks were successful
continuous-integration/drone Build is passing
2023-05-27 15:43:52 +02:00
60 changed files with 8442 additions and 19494 deletions

View File

@@ -1,29 +1,48 @@
--- ---
kind: pipeline kind: pipeline
type: docker type: docker
name: deploy name: deploy-production
steps: steps:
- name: build-site - name: build-site
image: node:latest image: node:16
commands: commands:
- npm install - npm install
- npm run build - npm run build
- name: deploy - name: deploy
image: mwienk/docker-lftp image: mwienk/docker-lftp
environment: environment:
USERNAME: pettinattk USERNAME: pettinattk
PASSWORD: PASSWORD:
from_secret: password from_secret: password
HOST: ftp.cluster027.hosting.ovh.net HOST: ftp.cluster027.hosting.ovh.net
commands: commands:
- "ls" - lftp -c "open -u $USERNAME,$PASSWORD $HOST; mirror -Rnev ./build ./www --ignore-time --parallel=10 --exclude .htaccess --exclude-glob .git* --exclude .git/"
- echo $USERNAME
- echo $HOST
- echo $PASSWORD
- lftp -c "open -u $USERNAME,$PASSWORD $HOST; mirror -Rnev ./build ./www --ignore-time --parallel=10 --exclude .htaccess --exclude-glob .git* --exclude .git/"
trigger: trigger:
branch: branch:
- main - main
---
kind: pipeline
type: docker
name: deploy-develop
steps:
- name: build-site
image: node:16
commands:
- npm install
- npm run build
- name: deploy
image: ictu/sshpass
environment:
SSHPASS:
from_secret: ssh_key
commands:
- sshpass -e rsync -arP -e "ssh -p 69 -o StrictHostKeyChecking=no" ./build/ root@192.168.178.25:/mnt/user/appdata/binhex-nginx/nginx/html/
trigger:
branch:
- develop

13
.eslintignore Normal file
View File

@@ -0,0 +1,13 @@
.DS_Store
node_modules
/build
/.svelte-kit
/package
.env
.env.*
!.env.example
# Ignore files for PNPM, NPM and YARN
pnpm-lock.yaml
package-lock.json
yarn.lock

20
.eslintrc copy.cjs Normal file
View File

@@ -0,0 +1,20 @@
module.exports = {
root: true,
parser: '@typescript-eslint/parser',
extends: ['eslint:recommended', 'plugin:@typescript-eslint/recommended', 'prettier'],
plugins: ['svelte3', '@typescript-eslint'],
ignorePatterns: ['*.cjs'],
overrides: [{ files: ['*.svelte'], processor: 'svelte3/svelte3' }],
settings: {
'svelte3/typescript': () => require('typescript')
},
parserOptions: {
sourceType: 'module',
ecmaVersion: 2020
},
env: {
browser: true,
es2017: true,
node: true
}
};

View File

@@ -0,0 +1,26 @@
name: Build Site Develop
on:
push:
branches:
- develop
jobs:
Build-Site:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Use Node.js
uses: actions/setup-node@v3
with:
node-version: '18.18.2'
- run: npm install
- run: npm run build
- name: Publish
uses: nogsantos/scp-deploy@master
with:
src: ./build/*
host: ${{ secrets.SSH_HOST }}
remote: /mnt/user/appdata/binhex-nginx/nginx/html/
port: 69
user: ${{ secrets.SSH_USER }}
key: ${{ secrets.SSH_KEY }}

View File

@@ -0,0 +1,28 @@
name: Build Site Main
on:
push:
branches:
- main
jobs:
Build-Site:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Use Node.js
uses: actions/setup-node@v3
with:
node-version: '16.x'
- run: npm install
- run: npm run build
- name: Upload via lftp (SFTP)
uses: xarses/lftp-upload-action@v0.2.0
with:
host: ${{ secrets.SFTP_HOST }}
port: 22
username: ${{ secrets.SFTP_USER }}
password: ${{ secrets.SFTP_PASSWORD }}
local_path: build/
remote_path: www

View File

@@ -0,0 +1,18 @@
name: Build Site PR
on:
pull_request:
branches:
- 'feat/**'
- 'develop'
jobs:
Build-Site:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Use Node.js
uses: actions/setup-node@v3
with:
node-version: '16.x'
- run: npm install
- run: npm run build

13
.prettierignore Normal file
View File

@@ -0,0 +1,13 @@
.DS_Store
node_modules
/build
/.svelte-kit
/package
.env
.env.*
!.env.example
# Ignore files for PNPM, NPM and YARN
pnpm-lock.yaml
package-lock.json
yarn.lock

9
.prettierrc copy Normal file
View File

@@ -0,0 +1,9 @@
{
"useTabs": true,
"singleQuote": true,
"trailingComma": "none",
"printWidth": 100,
"plugins": ["prettier-plugin-svelte"],
"pluginSearchDirs": ["."],
"overrides": [{ "files": "*.svelte", "options": { "parser": "svelte" } }]
}

1
keyboard.md Normal file
View File

@@ -0,0 +1 @@
"it":"Io passo molto tempo al PC e spesso non ho una corretta postura. Sperando di mitigare il problema, iniziai a cercare delle tastiere ergonomiche come quelle con il design *split*.\n La prima che trovai fu [Ergodox-EZ](https://ergodox-ez.com), ma il prezzo di più 300 euro mi fece desistere. Successivamente trovai il *subreddit* [r/ErgoMechBoards](https://www.reddit.com/r/ErgoMechKeyboards) e vidi molti modelli diversi, quello che mi piacque di più fu [lily58](https://github.com/kata0510/Lily58).\n Quindi, ordinai i pezzi da diversi negozi online. Presi da [Keyhive](https://keyhive.xyz) le parti base come il PCB e la guida per i tasti e da [CandyKeys](https://candykeys.com) gli switch, per quanto riguarda i keycaps li presi da Amazon ordinando dal meno caro.\n Quando tutti i pezzi arrivarono, con pazienza e dedizione saldai tutti i componenti e assemblai la tastiera. Per aggiungere un tocco personale, stampai con la mia stampante 3d la scocca che trovai su Thingverse.\n Come miglioramenti futuri, mi piacerebbe aggiungere un sistema per angolare la tastiera e risolvere il problema di pronazione dei polsi."

24767
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,48 +1,54 @@
{ {
"name": "mycv", "name": "mycv",
"version": "0.0.1", "version": "0.0.1",
"scripts": { "scripts": {
"update-model": "json2ts ./src/model/schema.json ./src/model/job.d.ts", "update-model": "json2ts ./src/lib/model/schemas/job.json ./src/lib/model/job.ts && json2ts ./src/lib/model/schemas/logo.json ./src/lib/model/logo.ts",
"dev": "svelte-kit dev --host 0.0.0.0", "dev": "vite dev",
"build": "svelte-kit build", "dev-exposed": "vite dev --host",
"preview": "svelte-kit preview", "build": "vite build",
"check": "svelte-check --tsconfig ./tsconfig.json", "postbuild": "npx svelte-sitemap --domain https://pettinato.eu",
"check:watch": "svelte-check --tsconfig ./tsconfig.json --watch", "preview": "vite preview",
"lint": "prettier --ignore-path .gitignore --check --plugin-search-dir=. . && eslint --ignore-path .gitignore .", "test": "playwright test",
"format": "prettier --ignore-path .gitignore --write --plugin-search-dir=. ." "check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
}, "check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
"devDependencies": { "test:unit": "vitest",
"@babel/preset-env": "^7.15.8", "lint": "prettier --plugin-search-dir . --check . && eslint .",
"@sveltejs/adapter-static": "^1.0.0-next.20", "format": "prettier --plugin-search-dir . --write ."
"@sveltejs/kit": "next", },
"@testing-library/jest-dom": "^5.14.1", "devDependencies": {
"@testing-library/svelte": "^3.0.3", "@playwright/test": "^1.28.1",
"@types/jest": "^27.0.2", "@sveltejs/adapter-auto": "^1.0.0",
"@typescript-eslint/eslint-plugin": "^4.31.1", "@sveltejs/adapter-static": "^1.0.5",
"@typescript-eslint/parser": "^4.31.1", "@sveltejs/kit": "^1.0.0",
"babel-jest": "^27.3.0", "@types/markdown-it": "^12.2.3",
"eslint": "^7.32.0", "@typescript-eslint/eslint-plugin": "^5.45.0",
"eslint-config-prettier": "^8.3.0", "@typescript-eslint/parser": "^5.45.0",
"eslint-plugin-svelte3": "^3.2.1", "eslint": "^8.28.0",
"jest": "^27.3.0", "eslint-config-prettier": "^8.5.0",
"prettier": "^2.4.1", "eslint-plugin-svelte3": "^4.0.0",
"prettier-plugin-svelte": "^2.4.0", "prettier": "^2.8.0",
"svelte": "^3.42.6", "prettier-plugin-svelte": "^2.8.1",
"svelte-check": "^2.2.6", "sass": "^1.57.1",
"svelte-jester": "^2.1.5", "svelte": "^3.54.0",
"svelte-meta-tags": "^2.5.5", "svelte-check": "^3.0.1",
"svelte-preprocess": "^4.9.4", "svelte-meta-tags": "^2.5.5",
"svelte-preprocess-markdown": "^2.7.3", "svelte-preprocess": "^4.9.4",
"svelte-scrollto": "^0.2.0", "svelte-preprocess-markdown": "^2.7.3",
"ts-jest": "^27.0.7", "tslib": "^2.4.1",
"tslib": "^2.3.1", "typescript": "^4.9.3",
"typescript": "^4.4.3" "vite": "^4.0.0",
}, "vitest": "^0.25.3"
"type": "module", },
"dependencies": { "type": "module",
"@fortawesome/fontawesome-free": "^5.15.4", "dependencies": {
"json-schema-to-typescript": "^10.1.5", "@fortawesome/fontawesome-svg-core": "^6.2.1",
"markdown-it": "^12.2.0", "@fortawesome/free-brands-svg-icons": "^6.2.1",
"punycode": "^2.1.1" "@fortawesome/free-solid-svg-icons": "^6.2.1",
} "@fortawesome/svelte-fontawesome": "^0.2.0",
"json-schema-to-typescript": "^10.1.5",
"markdown-it": "^12.2.0",
"punycode": "^2.1.1",
"svelte-sitemap": "^2.6.0",
"typesafe-i18n": "^5.20.0"
}
} }

11
playwright.config.ts Normal file
View File

@@ -0,0 +1,11 @@
import type { PlaywrightTestConfig } from '@playwright/test';
const config: PlaywrightTestConfig = {
webServer: {
command: 'npm run build && npm run preview',
port: 4173
},
testDir: 'tests'
};
export default config;

View File

@@ -1,15 +1,15 @@
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en"> <html lang="it">
<head>
<meta charset="utf-8" /> <head>
<link rel="icon" href="/favicon.png" /> <meta charset="utf-8" />
<link rel="stylesheet" href="/main.css"> <link rel="icon" href="%sveltekit.assets%/favicon.png" />
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css"> <meta name="viewport" content="width=device-width" />
<meta name="viewport" content="width=device-width, initial-scale=1" /> %sveltekit.head%
<title>Gianmarco Pettinato</title> </head>
%svelte.head%
</head> <body data-sveltekit-preload-data="hover">
<body id="svelte"> <div style="display: contents">%sveltekit.body%</div>
%svelte.body% </body>
</body>
</html> </html>

View File

@@ -9,14 +9,19 @@ $text-color: #011936;
$border-color: #256EFF; $border-color: #256EFF;
$button-border-color: #256EFF; $button-border-color: #256EFF;
$min-tablet: 768px; $min-tablet: 900px;
$min-desktop: 1024px; $min-desktop: 1024px;
$min-ultrawide: 1700px;
$default-border-radius:5px; $default-border-radius:5px;
$border-hover-color: #999;
$default-main-color: white;
$default-active-color: rgb(176, 176, 176);
:root { :root {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Open Sans", "Helvetica Neue", sans-serif; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Open Sans", "Helvetica Neue", sans-serif;
color: $text-color; color: $text-color;
background-color: $basecolor background-color: $basecolor;
} }
.box-with-shadow { .box-with-shadow {
@@ -31,6 +36,7 @@ $default-border-radius:5px;
width: 80%; width: 80%;
max-width: 1024px; max-width: 1024px;
} }
} }
.image-container{ .image-container{
@@ -42,9 +48,6 @@ $default-border-radius:5px;
max-width: 100%; max-width: 100%;
max-height: 300px; max-height: 300px;
object-fit: scale-down; object-fit: scale-down;
@media (prefers-color-scheme: light) {
background-color: $contrast;
}
} }
} }
@@ -61,4 +64,4 @@ button{
h1, h2, h3 { h1, h2, h3 {
font-weight: normal; font-weight: normal;
} }

View File

@@ -1,80 +0,0 @@
<script lang="ts"></script>
<div class="contacts">
<img src="/profile_pic.webp" alt="profile" class="profile" />
<div class="links">
<ul>
<li>
<a href="mailto://gianmarco@pettinato.eu"
><i class="fas fa-at" /> e-mail: gianmarco@pettinato.eu</a
>
</li>
<li>
<a href="https://t.me/jatus_93"><i class="fab fa-telegram-plane" /> telegram: @jatus_93</a>
</li>
<li>
<a href="https://twitter.com/jatus_93"><i class="fab fa-twitter" /> twitter: @jatus_93</a>
</li>
<li>
<a href="https://www.linkedin.com/in/gianmarco-pettinato/"
><i class="fab fa-linkedin-in" /> linkedin: Gianmarco Pettinato</a
>
</li>
</ul>
</div>
</div>
<style lang="scss">
@import '../app.scss';
img.profile {
border-radius: 50%;
max-width: 150px;
// border: solid 1px $border-color;
}
.contacts {
background-color: $basecolor2;
// border: solid 1px $border-color;
border-radius: $default-border-radius;
padding: 30px;
display: flex;
flex-direction: column;
justify-content: space-evenly;
align-items: center;
margin: auto;
}
.links {
text-align: left;
ul {
padding: 0;
list-style-type: none;
line-height: 20px;
white-space: nowrap;
li {
padding: 0;
margin: 10px;
margin-left: 0px;
margin-right: 0px;
a {
font-size: 18px !important;
}
}
}
}
@media (min-width: $min-tablet) {
.contacts {
flex-direction: row;
margin: auto;
}
.links {
ul {
li {
a {
font-size: auto !important;
}
}
}
}
}
</style>

View File

@@ -1,77 +0,0 @@
<script lang="ts">
import MarkdownIt from 'markdown-it';
const md = new MarkdownIt({
html: true,
xhtmlOut: true,
typographer: true,
breaks: true,
linkify: true
});
import type { Schema } from 'src/model/job';
export let job: Schema;
export let currentLanguage = '';
</script>
<div class="job-container">
<h3>{job.title[currentLanguage]}</h3>
<div class="image-container">
{#each job.images as image}
<img src={image} alt={image} loading="lazy" />
{/each}
</div>
<div class="text-content">
{@html md.render(job.content[currentLanguage])}
</div>
<div class="added-info">
{#if job.year.lenght != 0}
Date: {job.year.start}{#if job.year.end.length != 0}; {job.year.end} {/if}
{/if}
<div>
{#if job.collaborators.length != 0}
Collab:
{/if}
{#each job.collaborators as collaborator, index}
<a href={collaborator.ref}>{collaborator.name} {collaborator.surname}</a>{index !=
job.collaborators.length - 1
? ', '
: ''}
{/each}
</div>
<div>
{#if job.languages.length != 0}
Lang:
{/if}
{#each job.languages as language, index}
{language}{index != job.languages.length - 1 ? ', ' : ''}
{/each}
</div>
<div>
{#if job.tecnologies.length != 0}
Tech:
{/if}
{#each job.tecnologies as tecnology, index}
{tecnology}{index != job.tecnologies.length - 1 ? ', ' : ''}
{/each}
</div>
</div>
</div>
<style lang="scss">
@import '../app.scss';
.text-content {
margin: auto;
text-align: justify;
}
.added-info {
text-align: left;
font-size: smaller;
}
.job-container {
img {
background-color: $text-color;
}
display: flex;
flex-direction: column;
height: 100%;
}
</style>

View File

@@ -1,42 +0,0 @@
<script lang="ts">
import type { Schema } from 'src/model/job';
import JobElement from './JobElement.svelte';
export let currentLanguage = '';
export let isBlogContainer = false;
export let jobs: Schema[] = [];
</script>
<div class="jobs-container">
{#if isBlogContainer}
{#each jobs as job}
<a href="#" class="job-card"><JobElement {job} {currentLanguage} /></a>
{/each}
{:else}
{#each jobs as job}
<div class="job-card"><JobElement {job} {currentLanguage} /></div>
{/each}
{/if}
</div>
<style lang="scss">
@import '../app.scss';
.jobs-container {
display: flex;
justify-content: space-between;
flex-wrap: wrap;
padding: 10px;
}
.job-card {
background-color: $basecolor2;
border-radius: $default-border-radius;
padding: 10px 10px;
margin-bottom: 30px;
@media (min-width: $min-desktop) {
width: 29vw;
}
@media (min-width: 1400px) {
width: 400px;
}
display: inline;
}
</style>

View File

@@ -1,89 +0,0 @@
<script lang="ts">
import { scrollto } from 'svelte-scrollto';
export let currentLanguage = 'it';
export const menu = {
home: { it: 'Home', en: 'Home' },
job: { it: 'Esperienze', en: 'Experiences' },
school: { it: 'Formazione', en: 'Training' },
blog: { it: 'Blog', en: 'Blog' },
portfolio: { it: 'Portfolio', en: 'Portfolio' }
};
</script>
<div class="div-menu">
<div class="wrapper">
<a class="menu-element" href="/#top">
<span class="hide">{menu.home[currentLanguage]}</span><i class="fas fa-home" /></a
>
<a class="menu-element" href="#jobs"
><span class="hide">{menu.job[currentLanguage]}</span><i class="fas fa-user-tie" /></a
>
<a class="menu-element" href="#training"
><span class="hide">{menu.school[currentLanguage]}</span><i
class="fas fa-graduation-cap"
/></a
>
<a class="menu-element" href="#portfolio"
><span class="hide">{menu.portfolio[currentLanguage]}</span><i class="fas fa-user-clock" /></a
>
<a class="menu-element" href="/blog" alt={menu.blog[currentLanguage]}
><span class="hide">{menu.blog[currentLanguage]}</span><i class="fas fa-address-card" /></a
>
</div>
</div>
<style lang="scss">
@import '../app.scss';
@import '/node_modules/@fortawesome/fontawesome-free/css/all.css';
.hide {
@media (max-width: $min-tablet) {
position: absolute;
left: -10000px;
top: auto;
width: 1px;
height: 1px;
overflow: hidden;
}
}
.div-menu {
width: 100%;
max-width: 1024px;
}
.wrapper {
width: 100%;
display: flex;
}
a {
border-radius: $default-border-radius;
width: 50px;
margin: auto;
text-align: center;
padding: 5px;
i {
font-size: 22px;
margin: 5px;
}
}
a:hover {
background-color: $text-color;
color: white;
}
@media (min-width: $min-tablet) {
a {
width: 130px;
i {
font-size: unset;
}
}
}
@media (min-width: $min-desktop) {
a {
width: 150px;
}
}
</style>

View File

@@ -1,37 +0,0 @@
<script lang="ts"></script>
<div>
Hello
<div>
<h4>HTML</h4>
<div class="round_base">
<div class="inside"><div>percentage</div></div>
</div>
</div>
</div>
<style lang="scss">
.round_base {
width: 100px;
height: 100px;
background-color: yellow;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
outline: 0.1px solid black;
background-image: linear-gradient(to right, #000000 2px, blue 100%);
}
.inside {
width: 80px;
height: 80px;
background-color: white;
border-radius: 50%;
text-align: center;
vertical-align: middle;
outline: 0.1px solid black;
display: flex;
align-items: center;
justify-content: center;
}
</style>

View File

@@ -1,59 +1,55 @@
<script lang="ts"> <script lang="ts">
import Contacts from './Contacts.svelte'; import Contacts from './Contacts.svelte';
import Skills from './Skills.svelte'; export let currentLanguage: CurrentLanguage = 'it';
export let currentLanguage = 'it'; import { FontAwesomeIcon } from '@fortawesome/svelte-fontawesome';
import { faDownload } from '@fortawesome/free-solid-svg-icons';
import { library, findIconDefinition } from '@fortawesome/fontawesome-svg-core';
library.add(faDownload);
const downloadDefinition = findIconDefinition({ prefix: 'fas', iconName: 'download' });
import type { CurrentLanguage, LanguagePair } from '$lib/types';
const whoIt = const whoIt =
"Ciao! Sono Gianmarco Pettinato, mi sono laureato in scienze informatiche e sono uno sviluppatore full-stack.\ "Ciao! Sono Gianmarco Pettinato, mi sono laureato in scienze informatiche e sono uno sviluppatore.\
Ho famigliarità con diversi linguaggi e framework, sia front-end che back-end.\ Ho famigliarità con diversi linguaggi e framework, sia front-end che back-end.\
In particolare con C++ con Qt e TypeScript con Express, serverless, Angular, Vue.js e Svelte.\
Tra le mie competenze, oltre allo sviluppo software e alla manutenzione di sistemi linux, spicca la gestione di ambienti CI/CD, con pipeline automatiche e container come Docker.\ Tra le mie competenze, oltre allo sviluppo software e alla manutenzione di sistemi linux, spicca la gestione di ambienti CI/CD, con pipeline automatiche e container come Docker.\
Sono interessato in particolar modo all'ambiente dei dispositivi IoT e del wearble tech.\ Sono interessato in particolar modo all'ambiente dei dispositivi IoT e del wearble tech.\
Nel tempo libero mi dedico alla gestione del mio home sever e alla costruzione e manutenzione di computer.\ Nel tempo libero mi dedico alla gestione del mio home sever e alla costruzione e manutenzione di computer.";
Per maggiori informazioni non esitate a contattarmi.";
const whoEn = const whoEn =
"Hi! I'm Gianmarco Pettinato. I have a bachelor degree in computer science, and I'm a full-stack developer.\ "Hi! I'm Gianmarco Pettinato. I have a bachelor's degree in computer science, and I'm a developer.\
I know several languages and frameworks, either front-end or back-end.\ I know several languages and frameworks, front-end and back-end.\
In particular, I have experience in C++ with Qt and TypeScript with Express, serverless, Angular, Vue.js and Svelte.\
Among my skill-set, there is the administration of the CI/CD environment with Docker.\ Among my skill-set, there is the administration of the CI/CD environment with Docker.\
I'm interested in the IoT world and Wearable tech. In my free time, I like to manage my GNU/Linux home server and build PCs."; I'm interested in the IoT world and Wearable tech. In my free time, I like to manage my GNU/Linux home server and build PCs.";
const who = { const who: LanguagePair = {
it: whoIt, it: whoIt,
en: whoEn en: whoEn
}; };
const cvUrl: LanguagePair = { it: '/curriculum_it.pdf', en: '/curriculum_en.pdf' };
</script> </script>
<div class="aboutMe"> <div class="aboutMe">
<div class="title">
<h1>Gianmarco Pettinato</h1>
<h2>Software developer</h2>
</div>
<Contacts /> <Contacts />
<div class="whoIAm"> <div class="whoIAm">
<p> <p>
{who[currentLanguage]} {who[currentLanguage]}
</p> </p>
</div> </div>
<div class="cv"> <!-- <div class="cv">
<div> <div>
<a rel="external" href="/curriculum_it.pdf" <a rel="external" href={cvUrl[currentLanguage]}
>curriculum_it.pdf <i class="fas fa-download" /> >curriculum<i><FontAwesomeIcon icon={downloadDefinition} /></i>
</a> </a>
</div> </div>
<div> </div> -->
<a rel="external" href="/curriculum_en.pdf"
>curriculum_en.pdf <i class="fas fa-download" />
</a>
</div>
</div>
<Skills />
</div> </div>
<style lang="scss"> <style lang="scss">
@import '/node_modules/@fortawesome/fontawesome-free/css/all.css'; @import '../../app.scss';
@import '../app.scss';
.cv {
width: 80%;
margin: auto;
display: flex;
justify-content: space-evenly;
}
.whoIAm { .whoIAm {
margin: auto; margin: auto;
text-align: justify; text-align: justify;
@@ -62,7 +58,13 @@
background-color: $basecolor2; background-color: $basecolor2;
// border: solid 1px $border-color; // border: solid 1px $border-color;
border-radius: $default-border-radius; border-radius: $default-border-radius;
margin-top: 20px;
padding: 30px; padding: 30px;
margin: 10px; }
.title {
display: none;
@media (min-width: $min-tablet) {
display: unset;
}
} }
</style> </style>

View File

@@ -0,0 +1,102 @@
<script lang="ts">
import { FontAwesomeIcon } from '@fortawesome/svelte-fontawesome';
import { faAt } from '@fortawesome/free-solid-svg-icons';
import { faTelegramPlane, faTwitter, faLinkedin } from '@fortawesome/free-brands-svg-icons';
import * as svgCore from '@fortawesome/fontawesome-svg-core';
svgCore.library.add(faTelegramPlane);
svgCore.library.add(faTwitter);
svgCore.library.add(faLinkedin);
svgCore.library.add(faAt);
const telegramLookup: svgCore.IconLookup = { prefix: 'fab', iconName: 'telegram-plane' };
const twitterLookup: svgCore.IconLookup = { prefix: 'fab', iconName: 'twitter' };
const linkedinLookup: svgCore.IconLookup = { prefix: 'fab', iconName: 'linkedin' };
const atLookup: svgCore.IconLookup = { prefix: 'fas', iconName: 'at' };
const telegramIconDefinition: svgCore.IconDefinition = svgCore.findIconDefinition(telegramLookup);
const twitterIconDefinition: svgCore.IconDefinition = svgCore.findIconDefinition(twitterLookup);
const linkedinIconDefinition: svgCore.IconDefinition = svgCore.findIconDefinition(linkedinLookup);
const atIconDefinition: svgCore.IconDefinition = svgCore.findIconDefinition(atLookup);
</script>
<div class="contacts">
<img src="/profile_pic.webp" alt="profile" class="profile" />
<div class="links">
<ul>
<li>
<a href="mailto://gianmarco@pettinato.eu"
><i><FontAwesomeIcon icon={atIconDefinition} /></i> e-mail: gianmarco@pettinato.eu</a
>
</li>
<li>
<a href="https://t.me/jatus_93"
><i><FontAwesomeIcon icon={telegramIconDefinition} /></i> telegram: @jatus_93</a
>
</li>
<li>
<a href="https://twitter.com/jatus_93"
><i><FontAwesomeIcon icon={twitterIconDefinition} /></i> twitter: @jatus_93</a
>
</li>
<li>
<a href="https://www.linkedin.com/in/gianmarco-pettinato/"
><i><FontAwesomeIcon icon={linkedinIconDefinition} /></i> linkedin: Gianmarco Pettinato</a
>
</li>
</ul>
</div>
</div>
<style lang="scss">
@import '../../app.scss';
img.profile {
border-radius: 50%;
max-width: 150px;
// border: solid 1px $border-color;
}
.contacts {
border-radius: $default-border-radius;
padding: 30px;
display: flex;
flex-direction: column;
justify-content: space-evenly;
align-items: center;
margin: auto;
}
.links {
text-align: left;
ul {
padding: 0;
list-style-type: none;
line-height: 20px;
white-space: nowrap;
li {
padding: 0;
margin: 10px;
margin-left: 0px;
margin-right: 0px;
a {
font-size: 18px !important;
}
}
}
}
@media (min-width: $min-tablet) {
.contacts {
flex-direction: row;
margin: auto;
}
.links {
ul {
li {
a {
font-size: auto !important;
}
}
}
}
}
</style>

View File

@@ -0,0 +1,168 @@
<script lang="ts">
import MarkdownIt from 'markdown-it';
const md = new MarkdownIt({
html: true,
xhtmlOut: true,
typographer: true,
breaks: true,
linkify: true
});
import type { Job } from '$lib/model/job';
import type { CurrentLanguage } from '$lib/types';
export let job: Job;
export let currentLanguage: CurrentLanguage = 'it';
const dialogs: { [k: string]: HTMLDialogElement } = {};
export let modalOpen: boolean;
</script>
{#each job.images as image}
<!-- svelte-ignore a11y-click-events-have-key-events -->
<dialog
bind:this={dialogs[window.btoa(image)]}
on:scroll|preventDefault
on:click={() => {
dialogs[window.btoa(image)].close();
modalOpen = false;
}}
>
<img
src={image}
alt={image}
loading="lazy"
on:scroll={(e) => {
console.log(e);
}}
/>
</dialog>
{/each}
<div class="job-container">
<h3>{job.title[currentLanguage]}</h3>
<div class="image-container">
{#each job.images as image}
<!-- svelte-ignore a11y-click-events-have-key-events -->
<img
src={image}
alt={image}
loading="lazy"
on:click={() => {
dialogs[window.btoa(image)].showModal();
modalOpen = true;
}}
/>
{/each}
</div>
<div class="text-content">
{@html md.render(job.content[currentLanguage])}
</div>
<div class="added-info">
{#if job.year}
Date: {job.year.start}{#if job.year.end.length != 0}; {job.year.end} {/if}
{/if}
<div>
{#if job.collaborators.length != 0}
Collab:
{/if}
{#each job.collaborators as collaborator, index}
<a href={collaborator.ref}>{collaborator.name} {collaborator.surname}</a>{index !=
job.collaborators.length - 1
? ', '
: ''}
{/each}
</div>
<div>
{#if job.languages.length != 0}
Lang:
{/if}
{#each job.languages as language, index}
{language}{index != job.languages.length - 1 ? ', ' : ''}
{/each}
</div>
<div>
{#if job.technologies.length != 0}
Tech:
{/if}
{#each job.technologies as tecnology, index}
{tecnology}{index != job.technologies.length - 1 ? ', ' : ''}
{/each}
</div>
</div>
</div>
<style lang="scss">
@import '../../app.scss';
.text-content {
margin: auto;
text-align: justify;
}
.added-info {
text-align: left;
font-size: smaller;
}
.job-container {
width: 100%;
img {
background-color: $text-color;
cursor: zoom-in;
}
display: flex;
flex-direction: column;
height: 100%;
}
.hidden {
display: none;
}
.modal {
display: flex;
position: fixed;
position: -webkit-sticky;
top: 0;
left: 0;
z-index: 999;
background-color: rgba($color: #000000, $alpha: 0.4);
width: 100%;
height: 100%;
justify-content: center;
}
.modal-open {
overflow-y: hidden;
}
.modal-closed {
overflow-y: unset;
}
dialog {
img {
max-width: 80vw;
max-height: 80vh;
height: auto;
margin: auto;
background-color: $text-color;
}
}
dialog::backdrop {
background: rgba(0, 0, 0, 0.3);
}
dialog[open] {
animation: zoom 0.3s cubic-bezier(0.34, 1.56, 0.64, 1);
}
@keyframes zoom {
from {
transform: scale(0.95);
}
to {
transform: scale(1);
}
}
dialog[open]::backdrop {
animation: fade 0.2s ease-out;
}
@keyframes fade {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
</style>

View File

@@ -0,0 +1,45 @@
<script lang="ts">
import type { Job } from '$lib/model/job';
import type { CurrentLanguage } from '$lib/types';
import JobElement from './JobElement.svelte';
export let currentLanguage: CurrentLanguage = 'it';
export let jobs: Job[] = [];
export let modalOpen: boolean;
</script>
<div class="jobs-container">
{#each jobs as job}
<div class="job-card"><JobElement {job} {currentLanguage} bind:modalOpen /></div>
{/each}
{#if jobs.length % 2 !== 0}
<div class="job-card hide" />
{/if}
</div>
<style lang="scss">
@import '../../app.scss';
.jobs-container {
display: flex;
justify-content: space-between;
flex-wrap: wrap;
}
.job-card {
background-color: $basecolor2;
border-radius: $default-border-radius;
padding: 25pt 25pt;
margin-top: 1%;
margin-bottom: 1%;
@media (min-width: $min-desktop) {
width: 41%;
}
@media (min-width: 1333px) {
// width: 420px;
width: 42.5%;
}
display: inline;
}
.hide {
background: transparent;
}
</style>

View File

@@ -0,0 +1,105 @@
<script lang="ts">
import type { Handle, RequestEvent, ResolveOptions } from '@sveltejs/kit';
import type { CurrentLanguage } from '$lib/types';
import { FontAwesomeIcon } from '@fortawesome/svelte-fontawesome';
import * as svgIcons from '@fortawesome/free-solid-svg-icons';
import * as svgCore from '@fortawesome/fontawesome-svg-core';
let langSelectOpen = false;
let langSelect: Element;
export let currentLanguage: CurrentLanguage = 'en';
function setOpen() {
langSelectOpen = !langSelectOpen;
const animationLanguage = langSelect.animate([{ width: '0px' }, { width: '200px' }], {
duration: 100,
fill: 'both'
});
if (langSelectOpen) {
animationLanguage.play();
// animateConatiner.play();
} else {
animationLanguage.reverse();
// animateConatiner.reverse();
}
}
function setLanguage(value: CurrentLanguage) {
currentLanguage = value;
}
svgCore.library.add(svgIcons.faGlobeEurope);
const globeLookup: svgCore.IconLookup = { prefix: 'fas', iconName: 'globe-europe' };
const globeDefinition: svgCore.IconDefinition = svgCore.findIconDefinition(globeLookup);
const buttonLabel: { [key: CurrentLanguage[number]]: string } = {
it: 'seleziona la lingua',
en: 'select language'
};
</script>
<div class="language-selector">
<button on:click={setOpen}>
<FontAwesomeIcon icon={globeDefinition} size="2x" /><span>{buttonLabel[currentLanguage]}</span
></button
>
<div class="button-container" bind:this={langSelect}>
<button
class="custom-button {currentLanguage == 'it' ? 'custom-button-active' : ''}"
on:click={() => setLanguage('it')}
title="attiva lingua italiana">it</button
>
<button
class="custom-button {currentLanguage == 'en' ? 'custom-button-active' : ''}"
on:click={() => setLanguage('en')}
title="enable english language">en</button
>
</div>
</div>
<style lang="scss">
@import '../../app.scss';
.language-selector {
display: flex;
position: fixed;
flex-direction: row;
align-items: center;
background-color: $basecolor2;
border-radius: $default-border-radius;
font-size: 50px;
border-bottom: solid $border-hover-color 1px;
border-left: solid $border-hover-color 1px;
bottom: 70px;
right: 0;
}
.button-container {
display: flex;
justify-content: space-evenly;
width: 0px;
overflow: hidden;
}
button {
background: none;
border: none;
width: 60px;
height: 50px;
span {
border: 0;
clip: rect(0 0 0 0);
height: 1px;
margin: -1px;
overflow: hidden;
padding: 0;
position: absolute;
width: 1px;
}
}
.custom-button {
width: 100px;
font-size: large;
}
.custom-button-active {
background-color: $default-active-color;
outline: solid 1px;
}
</style>

View File

@@ -0,0 +1,51 @@
<script lang="ts">
import type { CurrentLanguage } from '$lib/types';
import MenuBig from './MenuBig.svelte';
import MenuMobile from './MenuMobile.svelte';
export let currentLanguage: CurrentLanguage = 'en';
</script>
<div class="menu-container default">
<div class="menu menu-desktop">
<MenuBig {currentLanguage} />
</div>
<div class="menu menu-mobile">
<MenuMobile {currentLanguage} />
</div>
</div>
<style lang="scss">
@import '../../app.scss';
.menu {
border-radius: $default-border-radius;
background-color: $basecolor2;
position: sticky;
position: -webkit-sticky;
top: 0px;
border-bottom: solid $border-hover-color 2px;
}
.menu-desktop {
display: none;
@media (min-width: $min-tablet) {
display: unset;
}
}
.menu-mobile {
@media (min-width: $min-tablet) {
display: none;
}
}
.menu-container {
border-radius: $default-border-radius;
padding: 0px;
margin: 10px;
position: sticky;
position: -webkit-sticky;
top: 0px;
margin: auto;
}
</style>

View File

@@ -0,0 +1,143 @@
<script lang="ts">
import { FontAwesomeIcon } from '@fortawesome/svelte-fontawesome';
import * as svgIcons from '@fortawesome/free-solid-svg-icons';
import * as svgCore from '@fortawesome/fontawesome-svg-core';
import type { CurrentLanguage, LanguagePair, MenuEntry } from '$lib/types';
svgCore.library.add(svgIcons.faHome);
svgCore.library.add(svgIcons.faUserTie);
svgCore.library.add(svgIcons.faGraduationCap);
svgCore.library.add(svgIcons.faUserClock);
svgCore.library.add(svgIcons.faAddressCard);
svgCore.library.add(svgIcons.faBars);
svgCore.library.add(svgIcons.faGlobeEurope);
const homeLookup: svgCore.IconLookup = { prefix: 'fas', iconName: 'home' };
const userTieLookup: svgCore.IconLookup = { prefix: 'fas', iconName: 'user-tie' };
const graduationCapLookup: svgCore.IconLookup = { prefix: 'fas', iconName: 'graduation-cap' };
const userClockLookUp: svgCore.IconLookup = { prefix: 'fas', iconName: 'user-clock' };
const addressCardLookUp: svgCore.IconLookup = { prefix: 'fas', iconName: 'address-card' };
const homeIconDefinition: svgCore.IconDefinition = svgCore.findIconDefinition(homeLookup);
const userTieDefinition: svgCore.IconDefinition = svgCore.findIconDefinition(userTieLookup);
const graduationDefinition: svgCore.IconDefinition =
svgCore.findIconDefinition(graduationCapLookup);
const userClockDefinition: svgCore.IconDefinition = svgCore.findIconDefinition(userClockLookUp);
const addressCardDefinition: svgCore.IconDefinition =
svgCore.findIconDefinition(addressCardLookUp);
export let currentLanguage: CurrentLanguage = 'it';
const menu: Record<MenuEntry, LanguagePair> = {
home: { it: 'Home', en: 'Home' },
job: { it: 'Esperienze', en: 'Experiences' },
school: { it: 'Formazione', en: 'Training' },
blog: { it: 'Blog', en: 'Blog' },
portfolio: { it: 'Portfolio', en: 'Portfolio' }
};
</script>
<div class="container">
<ul>
<li>
<a class="menu-element" href="#top">
<i>
<FontAwesomeIcon icon={homeIconDefinition} />
</i>
<span>{menu.home[currentLanguage]}</span></a
>
</li>
<li>
<a class="menu-element" href="#jobs"
><i>
<FontAwesomeIcon icon={userTieDefinition} />
</i><span>{menu.job[currentLanguage]}</span></a
>
</li>
<li>
<a class="menu-element" href="#training"
><i>
<FontAwesomeIcon icon={graduationDefinition} />
</i><span>{menu.school[currentLanguage]}</span></a
>
</li>
<li>
<a class="menu-element" href="#portfolio"
><i>
<FontAwesomeIcon icon={userClockDefinition} />
</i><span>{menu.portfolio[currentLanguage]}</span></a
>
</li>
<!-- <li>
<a class="menu-element" href="/blog"
><i>
<FontAwesomeIcon icon={addressCardDefinition} />
</i><span>{menu.blog[currentLanguage]}</span></a
>
</li> -->
</ul>
</div>
<style lang="scss">
@import '../../app.scss';
$menu-size: 1004px;
a {
padding: 0;
margin: 0;
display: flex;
justify-content: center;
align-items: center;
font-size: larger;
min-width: 50px;
width: 100%;
height: 50px;
i {
margin-right: 10%;
}
}
a:hover,
a:active {
background-color: $default-active-color;
}
ul {
display: flex;
width: 100%;
height: 100%;
list-style-type: none;
padding: 0;
margin: 0;
margin: auto;
border-radius: $default-border-radius;
}
.container {
border-radius: $default-border-radius;
width: 100%;
border-bottom: solid $border-hover-color 1px;
}
ul li {
background-color: $basecolor2;
flex: 1;
}
li:first-of-type {
background-color: $basecolor2;
border-top-left-radius: $default-border-radius;
border-bottom-left-radius: $default-border-radius;
a:hover,
a:active {
border-top-left-radius: $default-border-radius;
border-bottom-left-radius: $default-border-radius;
}
}
li:last-of-type {
border-top-right-radius: $default-border-radius;
border-bottom-right-radius: $default-border-radius;
a:hover,
a:active {
border-top-right-radius: $default-border-radius;
border-bottom-right-radius: $default-border-radius;
}
}
</style>

View File

@@ -0,0 +1,206 @@
<script lang="ts">
import { FontAwesomeIcon } from '@fortawesome/svelte-fontawesome';
import * as svgIcons from '@fortawesome/free-solid-svg-icons';
import * as svgCore from '@fortawesome/fontawesome-svg-core';
import type { CurrentLanguage, LanguagePair, MenuEntry } from '$lib/types';
export let currentLanguage: CurrentLanguage = 'it';
svgCore.library.add(svgIcons.faBars);
svgCore.library.add(svgIcons.faHome);
svgCore.library.add(svgIcons.faUserTie);
svgCore.library.add(svgIcons.faGraduationCap);
svgCore.library.add(svgIcons.faUserClock);
svgCore.library.add(svgIcons.faAddressCard);
svgCore.library.add(svgIcons.faBars);
svgCore.library.add(svgIcons.faX);
svgCore.library.add(svgIcons.faGlobeEurope);
const barsLookup: svgCore.IconLookup = { prefix: 'fas', iconName: 'bars' };
const globeLookup: svgCore.IconLookup = { prefix: 'fas', iconName: 'globe-europe' };
const homeLookup: svgCore.IconLookup = { prefix: 'fas', iconName: 'home' };
const userTieLookup: svgCore.IconLookup = { prefix: 'fas', iconName: 'user-tie' };
const graduationCapLookup: svgCore.IconLookup = { prefix: 'fas', iconName: 'graduation-cap' };
const userClockLookUp: svgCore.IconLookup = { prefix: 'fas', iconName: 'user-clock' };
const addressCardLookUp: svgCore.IconLookup = { prefix: 'fas', iconName: 'address-card' };
const xLookUp: svgCore.IconLookup = { prefix: 'fas', iconName: 'x' };
const homeIconDefinition: svgCore.IconDefinition = svgCore.findIconDefinition(homeLookup);
const userTieDefinition: svgCore.IconDefinition = svgCore.findIconDefinition(userTieLookup);
const graduationDefinition: svgCore.IconDefinition =
svgCore.findIconDefinition(graduationCapLookup);
const userClockDefinition: svgCore.IconDefinition = svgCore.findIconDefinition(userClockLookUp);
const addressCardDefinition: svgCore.IconDefinition =
svgCore.findIconDefinition(addressCardLookUp);
const barsDefinition: svgCore.IconDefinition = svgCore.findIconDefinition(barsLookup);
const xDefinition: svgCore.IconDefinition = svgCore.findIconDefinition(xLookUp);
const globeDefinition: svgCore.IconDefinition = svgCore.findIconDefinition(globeLookup);
const menu: Record<MenuEntry, LanguagePair> = {
home: { it: 'Home', en: 'Home' },
job: { it: 'Esperienze', en: 'Experiences' },
school: { it: 'Formazione', en: 'Training' },
blog: { it: 'Blog', en: 'Blog' },
portfolio: { it: 'Portfolio', en: 'Portfolio' }
};
const menuButton: Record<number, LanguagePair> = {
1: { it: 'Apri il menu', en: 'Open menu' },
0: { it: 'Chiudi il menu', en: 'Close menu' }
};
let menuContainer: Element;
let menuOpen = false;
function setOpen() {
menuOpen = !menuOpen;
const animation = menuContainer.animate([{ height: '0px' }, { height: '240px' }], {
duration: 100,
fill: 'both'
});
if (menuOpen) animation.play();
else animation.reverse();
}
</script>
<div class="menu-container">
<div class="header {menuOpen ? 'borderclass' : ''}">
<button on:click={setOpen} tabindex="0" title={menuButton[Number(menuOpen)][currentLanguage]}>
<i>
{#if !menuOpen}<FontAwesomeIcon icon={barsDefinition} />
{:else}
<FontAwesomeIcon icon={xDefinition} />
{/if}
</i>
</button>
<div class="title">
<h1>Gianmarco Pettinato</h1>
<h2>Software developer</h2>
</div>
</div>
<ul class="wrapper" bind:this={menuContainer}>
<li>
<a on:click={setOpen} class="menu-element" href="#top">
<i>
<FontAwesomeIcon icon={homeIconDefinition} />
</i>
<span>{menu.home[currentLanguage]}</span></a
>
</li>
<li>
<a on:click={setOpen} class="menu-element" href="#jobs"
><i>
<FontAwesomeIcon icon={userTieDefinition} />
</i><span>{menu.job[currentLanguage]}</span></a
>
</li>
<li>
<a on:click={setOpen} class="menu-element" href="#training"
><i>
<FontAwesomeIcon icon={graduationDefinition} />
</i><span>{menu.school[currentLanguage]}</span></a
>
</li>
<li>
<a on:click={setOpen} class="menu-element" href="#portfolio"
><i>
<FontAwesomeIcon icon={userClockDefinition} />
</i><span>{menu.portfolio[currentLanguage]}</span></a
>
</li>
<!-- <li>
<a on:click={setOpen} class="menu-element" href="/blog"
><i>
<FontAwesomeIcon icon={addressCardDefinition} />
</i><span>{menu.blog[currentLanguage]}</span></a
>
</li> -->
</ul>
</div>
<style lang="scss">
@import '../../app.scss';
.borderclass {
border-bottom: solid $border-hover-color 2px;
border-radius: $default-border-radius;
}
.header {
display: flex;
justify-content: space-evenly;
align-items: center;
button {
border: none;
background: none;
margin-left: 3rem;
height: 50px;
width: 50px;
i {
text-align: center;
height: 50px;
width: 50px;
border: none;
font-size: 30px;
background: none;
}
}
.title {
justify-content: center;
text-align: right;
margin-left: auto;
margin-right: 3rem;
h1,
h2 {
margin-top: 0.5px;
margin-bottom: 0.5rem;
margin-left: 2.5rem;
@media (min-width: 450px) {
margin-left: unset;
}
}
}
}
.menu-container {
margin: 0;
padding: 0;
margin: auto;
}
ul {
list-style-type: none;
overflow: hidden;
margin: 0;
padding: 0;
margin: auto;
}
a {
display: flex;
justify-content: space-evenly;
align-items: center;
background-color: $basecolor2;
font-size: 20px;
height: 60px;
border-bottom: solid $border-hover-color 2px;
border-radius: 0px 0px $default-border-radius $default-border-radius;
i {
text-align: center;
height: 50px;
width: 50px;
border: none;
font-size: 30px;
background: none;
margin-left: 3rem;
}
span {
justify-content: center;
text-align: right;
margin-left: auto;
margin-right: 3rem;
}
}
a:hover {
background-color: $default-active-color;
}
.wrapper {
height: 0px;
border-radius: 0px 0px $default-border-radius $default-border-radius;
}
</style>

View File

@@ -25,7 +25,7 @@
.inside { .inside {
width: 70px; width: 70px;
height: 70px; height: 70px;
// background-color: white; // background-color:$basecolor2;
border-radius: 50%; border-radius: 50%;
text-align: center; text-align: center;
vertical-align: middle; vertical-align: middle;

View File

@@ -1,37 +1,36 @@
<script lang="ts"> <script lang="ts">
import MarkdownIt from 'markdown-it'; import MarkdownIt from 'markdown-it';
import data from '../model/training.json';
import type { Job } from '../model/job';
import type { CurrentLanguage } from '$lib/types';
const md = new MarkdownIt({ const md = new MarkdownIt({
html: true, html: true,
xhtmlOut: true, xhtmlOut: true,
typographer: true typographer: true
}); });
import data from '../model/training.json'; export let currentLanguage: CurrentLanguage = 'it';
import type { Schema } from 'src/model/job'; const training: Job[] = data as Job[];
export let currentLanguage = 'it';
const training: Schema[] = data as Schema[];
</script> </script>
<div class="training"> <div>
{#each training as school} {#each training as school}
<div class="element"> <div class="element">
<img src={school.images[0]} alt="school logo" /> <img src={school.images[0]} alt="school logo" />
<div> <div>
<h3>{school.title[currentLanguage]}</h3> <h3>{school.title[currentLanguage]}</h3>
<p>{school.content[currentLanguage]}</p> <p>{school.content[currentLanguage]}</p>
<p>{school.year.start} - {school.year.end}</p> <p>{school.year.start} {#if school.year.end} - {school.year.end}{/if}</p>
</div> </div>
</div> </div>
{/each} {/each}
</div> </div>
<style lang="scss"> <style lang="scss">
.training { @import '../../app.scss';
padding: 10px;
}
@import '../app.scss';
.element { .element {
border-radius: $default-border-radius; border-radius: $default-border-radius;
background-color: white; background-color: $basecolor2;
padding: 45px; padding: 45px;
display: flex; display: flex;
flex-direction: column; flex-direction: column;

View File

@@ -5,31 +5,26 @@
* and run json-schema-to-typescript to regenerate this file. * and run json-schema-to-typescript to regenerate this file.
*/ */
export interface Schema { export interface Job {
id?: string; id?: string;
year: { year: {
start: string; start: string;
end: string; end: string;
[k: string]: unknown;
}; };
title: { title: {
en: string; en: string;
it: string; it: string;
[k: string]: unknown;
}; };
content: { content: {
en: string; en: string;
it: string; it: string;
[k: string]: unknown;
}; };
collaborators: { collaborators: {
name: string; name: string;
surname: string; surname: string;
ref: string; ref: string;
[k: string]: unknown;
}[]; }[];
languages: string[]; languages: string[];
tecnologies: string[]; technologies: string[];
images: string[]; images: string[];
[k: string]: unknown;
} }

179
src/lib/model/jobs.json Normal file
View File

@@ -0,0 +1,179 @@
[
{
"year": {
"start": "2024-09-23",
"end": ""
},
"title": {
"en": "Corley Cloud",
"it": "Corley Cloud"
},
"content": {
"en": "In September 2024, I joined Corley Cloud, a company focused on building scalable and resilient cloud-native solutions.\nMy role involves designing and developing **serverless architectures** and **event-driven applications** using **AWS** services such as Lambda, API Gateway, DynamoDB, and Step Functions.\nThe main technologies I use are **Node.js** and **Python**.\nI contribute to the definition of **DevOps pipelines**, infrastructure as code with **Terraform** and **AWS SAM**, and best practices for CI/CD in cloud environments.",
"it": "Nel settembre 2024 ho iniziato a lavorare in Corley Cloud, un'azienda specializzata nella creazione di soluzioni cloud-native scalabili e resilienti.\nIl mio ruolo prevede la progettazione e lo sviluppo di **architetture serverless** e **applicazioni event-driven** utilizzando servizi **AWS** come Lambda, API Gateway, DynamoDB e Step Functions.\nLe tecnologie principali che utilizzo sono **Node.js** e **Python**.\nContribuisco alla definizione delle **pipeline DevOps**, dellinfrastruttura come codice con **Terraform** e **AWS SAM**, e delle best practice per CI/CD in ambienti cloud."
},
"collaborators": [],
"languages": [
"TypeScript",
"Python",
"Node.js",
"yaml",
"json",
"bash"
],
"technologies": [
"AWS Lambda",
"API Gateway",
"DynamoDB",
"Step Functions",
"Terraform",
"AWS SAM",
"GitHub Actions"
],
"images": [
"corley.png"
]
},
{
"year": {
"start": "2022-01-03",
"end": "2024-09-06"
},
"title": {
"en": "ALTEN italy",
"it": "ALTEN italia"
},
"content": {
"en": "At the end of 2021, while I was trying to advertise my business, I received several job offers, including one from Alten Italy.\nSo, since January 3, 2022, I have been employed at Alten Italy, in the Bologna office, as an **IT consultant**.\nThere are two aspects to keep in mind when working in consulting: the client and the consulting company, both of which require attention and different tasks.\nFor the client, I perform the duties of a **full stack cloud developer in AWS** and some **Scrum Master** responsibilities.\nRegarding Alten, I have written and conducted courses on **git**, **docker**, and **CI/CD** systems. I have been involved in the personnel selection process.",
"it": "Alla fine del 2021, mentre stavo cercando di fare pubblicità per la mia attività, ho ricevuto diverse offerte di lavoro, tra cui Alten Italia.\nQuindi, dal 3 gennaio 2022 sono impiegato in Alten Italia, nella sede di Bologna, come **consulente informatico**.\nCi sono due lati da tenere a mente quando si lavora in consulenza, il cliente e lazienda di consulenza, entrambe le realtà richiedono attenzione e mansioni diverse.\nPer il cliente mi svolgo le mansioni da **full stack cloud developer in AWS** e alcune delle mansioni dello **Scrum Master**.\nPer quanto riguarda Alten, ho scritto e tenuto dei corsi per **git**, **docker** e sistemi di **CI/CD**. Ho fatto parte del processo di selezione del personale."
},
"collaborators": [],
"languages": [
"Php",
"bash",
"yaml",
"json",
"Javascript",
"TypeScript",
"Python"
],
"technologies": [
"Vue.js",
"Node.js",
"Laravel",
"Docker",
"AWS"
],
"images": [
"/ALTEN.webp"
]
},
{
"year": {
"start": "2021-01-10",
"end": "2021-12-31"
},
"title": {
"en": "Jatus.tech my start-up",
"it": "La mia start-up Jatus.tech"
},
"content": {
"en": "During 2021, I worked to launch my own startup based on my app idea. The app focused on smartphone-based shopping within a supermarket, utilizing a network of **Bluetooth** sensors for user tracking and enabling user triangulation. The entire application infrastructure was built on **AWS** cloud services.\nThroughout this period, I took on various roles and performed different tasks. I established a working infrastructure with a **Git** server and **SonarQube** for automated code quality verification. Additionally, I gained experience in managing virtual machines for development and staging environments to test applications in a production-like setting.\nI developed **CI/CD** solutions for the product using custom-built **Docker** images. Lastly, I designed and developed the app using **TypeScript** and **Java**. TypeScript was used for the backend and certain parts of the application, while Java was employed for the app's native components, including transmitting **Bluetooth** signals for tracking purposes.",
"it": "Durante il 2021, ho avviato una mia attività indipendente basata su un'idea di app. L'app si focalizzava sulla spesa all'interno di un supermercato tramite smartphone, utilizzando una rete di sensori **Bluetooth** per il tracciamento degli utenti. L'intera infrastruttura dell'app era basata sui servizi cloud di **AWS**.\nDurante questo periodo, ho svolto diversi ruoli e mansioni. Ho creato un'infrastruttura di lavoro con un server **Git** e **SonarQube** per la verifica automatica della qualità del codice. Inoltre, ho imparato a gestire macchine virtuali per lo sviluppo e la fase di test in un ambiente simile a quello di produzione.\nHo sviluppato soluzioni di **CI/CD** per il prodotto utilizzando immagini **Docker** create appositamente. Infine, ho progettato e sviluppato l'applicazione utilizzando **TypeScript** e **Java**. Ho utilizzato TypeScript per il backend e alcune parti dell'applicazione, mentre Java è stato utilizzato per le funzionalità native dell'app, come l'invio dei segnali **Bluetooth** per il tracciamento."
},
"collaborators": [],
"languages": [
"TypeScript",
"bash",
"Docker-file",
"yaml",
"json"
],
"technologies": [
"Vue.js",
"Node.js",
"Nuxt",
"Docker",
"GitLab",
"Nativescript"
],
"images": [
"/logo-jatus-tech.webp"
]
},
{
"year": {
"start": "2020-9-21",
"end": "2020-11-21"
},
"title": {
"en": "Intership in Athesys",
"it": "Tirocinio in Athesys"
},
"content": {
"en": "I've chosen to work in Athesis to end my bachelor degree course. The project was about developing a middleware to put in communication two applications between **NATed** networks based on **OAuth2.0**. This middleware assures the connection is authorized. This software mainly approved the connection of devices that detected the presence of a face mask and the body temperature in the range",
"it": "Per la tesi di laurea, ho scelto di fare il tirocinio in Athesys. Il progetto prevedeva lo sviluppo di un middleware per mettere in comunicazione, in maniera sicura, due applicazioni tra reti **NAT** basato sui protocolli autorizzativi di **OAuth2.0**.\n Dato il periodo, dove la seconda ondata della pandemia era alle porte, era necessario avere un sistema sicuro per la comuncazione tra dispositivi di controllo dell'ingresso e il \"back-end\", come tablet con termoscanner e software per il riconoscimento della mascherina."
},
"collaborators": [],
"languages": [
"TypeScript",
"HTML",
"CSS"
],
"technologies": [
"Vue.js",
"Node.js",
"Nuxt",
"Docker"
],
"images": [
"/logo-athesys.webp"
]
},
{
"year": {
"start": "2016-08-13",
"end": "2017-02-13"
},
"title": {
"en": "Developer in Alternative Studio",
"it": "Sviluppatore in Alternative Studio"
},
"content": {
"en": "I've projected and developed a Telegram bot with direct communication to management software for the dog squad Italian civil defence to enable communication between HQ and agent on the ground",
"it": "Progettazione e sviluppo di un Bot Telegram con comunicazione diretta al gestionale per la sezione cinofila della Protezione Civile"
},
"collaborators": [],
"languages": [
"PHP"
],
"technologies": [
"Telegram",
"Composer",
"Docker"
],
"images": [
"/alternative-studio.webp"
]
},
{
"year": {
"start": "2012-06-05",
"end": "2012-07-05"
},
"title": {
"en": "ICT office's assistant",
"it": "Assistente dell'ufficio ICT "
},
"content": {
"en": "I applied to this position, in Saxon Hill Academy, through the European project Leonardo which provided accommodation for the stay, an English course and a workplace mainly for practices the language skill. In Saxon Hill Academy, my responsibilities were:\n - Maintenance of administration's computers.\n - Maintenance of students' computers.\n - Make the sensorial room usable.",
"it": "Ho avuto l'opportunità di lavorare in questo ambiente grazie al progetto europeo Leonardo. Questo progetto di 4 settimane si occupava di fornire agli studenti tutto il necessario tra vitto e alloggio, prevedeva, inoltre, un corso di inglese e un luogo di lavoro dove fare principalmente pratica con la lingua. In questo contesto sono stato assegnato a Saxon Hill Academy dove ho svolto le seguenti mansioni:\n - Manutenzione dei computer della segreteria\n - Manutenzione dei computer degli studenti \n - Rendere operativa la \"sensiorial room\""
},
"collaborators": [],
"languages": [],
"technologies": [],
"images": [
"/saxonhilllogo.webp"
]
}
]

11
src/lib/model/logo.ts Normal file
View File

@@ -0,0 +1,11 @@
/* tslint:disable */
/**
* This file was automatically generated by json-schema-to-typescript.
* DO NOT MODIFY IT BY HAND. Instead, modify the source JSONSchema file,
* and run json-schema-to-typescript to regenerate this file.
*/
export interface Logo {
img: string;
name: string;
}

8
src/lib/model/logos.json Normal file
View File

@@ -0,0 +1,8 @@
[
{
"img": "ts-logo-128.svg",
"name": "TypeScript"
},
{ "img": "cplusplus", "name": "C++" },
{ "img": "rust-logo.svg", "name": "Rust" }
]

View File

@@ -0,0 +1,356 @@
[
{
"year": {
"start": "2021-10-01",
"end": "2021-10-19"
},
"title": {
"en": "This web site",
"it": "Questo sito web"
},
"content": {
"en": "I created this web page to collect and present all my experiences. I'm not a web designer. However, I can build web pages because I have good knowledge of HTML and CSS. I made this page using TypeScript and Svelte. To manage the content, I've created a simple system to load content from a couple of JSON files that define where to put the information.",
"it": "Ho creato questo sito web per raccogliere e raccontare le mie esperienze. Come si può facilmente intuire non sono un web designer, ma ho comunque buone conoscenze nell'uso di HTML e CSS. Ho realizzato questa pagina web in TypeScript e Svelte, per la gestione dei contenuti ho ideato un semplice sistema che controlla i dati presenti in un paio di file JSON che definiscono i contenuti della pagina e delle sezioni."
},
"collaborators": [],
"languages": [
"TypeScript",
"JSON-schema"
],
"technologies": [
"Svelte",
"Node.js"
],
"images": [
"/webpage.webp"
]
},
{
"year": {
"start": "2021-09-15",
"end": "2021-09-28"
},
"title": {
"en": "Greenpass server validator",
"it": "Greenpass server validatore"
},
"content": {
"en": "I've created a server in TypeScript with Express.js endpoints that can read the raw data from a Green pass Qrcode and establish if it is valid with the Italian regulations. I [released the software](https://git.jatus.tech/Jatus/dgcserververifier) under AGPLv3 as requested from the DCC utils library.",
"it": "Ho creato un server in TypeScript e express che leggendo i dati *raw* del Qr code del green pass può determinarne la sua validità, ho [rilasciato il software](https://git.jatus.tech/Jatus/dgcserververifier) in licenza AGPLv3 come previsto dalla librearia DCC utils del Ministero della Salute italiano."
},
"collaborators": [],
"languages": [
"TypeScript"
],
"technologies": [
"Node.js"
],
"images": [
"./DGCServerVerifier.webp"
]
},
{
"year": {
"start": "2021-04-01",
"end": "2021-05-02"
},
"title": {
"en": "Keyboard",
"it": "Tastiera"
},
"content": {
"en": "I spend a lot of time at my desk writing on the PC with not the best posture. This kind of behaviour was going to take a toll on my well-being, so I decided to start looking for a split design keyboard.\n The first keyboard that I found was the [Ergodox-EZ](https://ergodox-ez.com), but the steep price of more than 300 euros put me off. Then I found the subreddit [r/ErgoMechBoards](https://www.reddit.com/r/ErgoMechKeyboards) and saw a lot of different concepts, the one that stuck with me was the [lily58](https://github.com/kata0510/Lily58).\n So, I ordered all the pieces from various online stores. I took the kit from the [Keyhive](https://keyhive.xyz) shop for the base parts, like PCB and guide for the switches, bought the switches from [CandyKeys](https://candykeys.com) and a cheap keycap set from amazon.\n When all the pieces showed up at my place, I soldered all the components and assembled the keyboard. To add some flare, I printed with my 3d printer a custom case that I found on Thingiverse.\n In the future, I'd like to add a system to tilt the keyboard to fix the pronation issue.",
"it": "Io passo molto tempo al PC e spesso non ho una corretta postura. Sperando di mitigare il problema, ho cercato delle tastiere ergonomiche come quelle con il design *split*.\n Il primo risultato su google era [Ergodox-EZ](https://ergodox-ez.com), ma il prezzo di più 300 euro ha fatto desistere. Successivamente, tramite il *subreddit* [r/ErgoMechBoards](https://www.reddit.com/r/ErgoMechKeyboards), ho visto diversi modelli DIY, quello che ha stuzicato il mio interesse è stato [lily58](https://github.com/kata0510/Lily58).\n Quindi, ho ordinato il PCB e le parti base della tastiera da [Keyhive](https://keyhive.xyz) e da [CandyKeys](https://candykeys.com) gli switch, per quanto riguarda i keycaps ho scelto un set da poco su da Amazon.\n Arrivati tutti i pezzi, con pazienza e dedizione ho saldato tutti i componenti e assemblato la tastiera. Per aggiungere un tocco personale, ho stampato con la mia stampante 3d la scocca trovata su Thingverse.\n Come miglioramenti futuri, mi piacerebbe aggiungere un sistema per angolare la tastiera e risolvere il problema di pronazione dei polsi."
},
"collaborators": [],
"languages": [
"C"
],
"technologies": [
"QMK"
],
"images": [
"/custom-keyboard.webp"
]
},
{
"year": {
"start": "2021-09-15",
"end": "2021-09-30"
},
"title": {
"en": "3D printer, to print all my ideas",
"it": "Stampante 3D per stampare le mie idee."
},
"content": {
"en": "I'm a tech enthusiast and, I like to overcome challenges made for the maker type of people. To organize the 3d printer area, I followed a few of the many bits of advice from the 3d printing *community*. Like, build the furniture to hold the printer from two IKEA's Lack stack one upon the other and joined with some 3d printed parts. Another upgrade was to add a Raspberry pi 4 with a camera module and OctoPrint software to remote manage the printer whenever.",
"it": "Sono un appassionato di tecnologia e mi piace anche affrontare sfide tipiche dei *maker*. Per organizzare meglio gli spazi ho seguito gli innumerovili consigli della *community* sul costruire un mobile a partire da due mobili ikea \"Lack\" e di unirli con due pezzi stampati. Un'altra miglioria che ho effettuato è sul sistema di controllo della stampante stessa aggiungendo un raspberry pi 4 con webcam e munito del software octoprint che mi permette di controllarne lo stato da remoto."
},
"collaborators": [],
"languages": [
"bash",
"python"
],
"technologies": [
"raspberry"
],
"images": [
"/3dprinter.webp"
]
},
{
"year": {
"start": "2021-09-15",
"end": "2021-09-30"
},
"title": {
"en": "Unraid Server",
"it": "Unraid Server"
},
"content": {
"en": "To manage all my software and data, I built a home server with Unraid server. I based the system on the Ryzen platform with an R9 3900X CPU, two 2TB disks for work data and software and, 4 disks 4TB for family storage.",
"it": "Per gestire il mio software e i miei dati, ho costruito un server usando la distrubuzione Unraid. Il server è basato su una piattaforma ryzen con R9 3900X, due dischi da 2TB per i dati di lavoro e 4 dischi da 4TB, in configurazione RAID10, per lo spazio della mia famiglia."
},
"collaborators": [],
"languages": [
"YAML"
],
"technologies": [
"Docker",
"Unraid",
"GNU/Linux"
],
"images": [
"./unraid.webp"
]
},
{
"year": {
"start": "2019-04-15",
"end": ""
},
"title": {
"en": "Workstation",
"it": "Postazione di lavoro"
},
"content": {
"en": "My workstation is build upon my custom desk made on request and can accommodate my PC and laptop, I use both of them to work and develop my projects. The monitors are an 34\" 21:9 with a resoluztion of 3440x1440 and a 27\" 16:9 with a resolution of 2560x1440. ",
"it": "La mia postazione di lavoro parte dalla scrivania che è stata fatta su misura e può accomodare il mio computer fisso e il mio portatile, entrambe macchine che uso per lavorare e dedicarmi ai miei progetti. I monitor sono un 21:9 da 34\" con risoluzione 3440x1440 e un 16:9 da 27\" in verticale da 2560x1440."
},
"collaborators": [],
"languages": [],
"technologies": [],
"images": [
"/workstation.webp"
]
},
{
"year": {
"start": "2019-11-17",
"end": "2020-05-18"
},
"title": {
"en": "Software Engineering Project",
"it": "Progetto di Ingegneria del Software"
},
"content": {
"en": "While in university, I worked on a project for the software engineering course. The group decided to develop the project Etherless, a FAAS based on Etherium and AWS lambda. The system worked like this, a user writes a function and uploads it to the service that assigns a cost of execution. Then, when a user wants to execute the function, must issue the request and pay the execution through the Ethereum network. We released all the software in MIT licence here [Tenners Unipd](https://github.com/TennersUnipd).",
"it": "Per il corso di ingegneria del software sono stato assegnato ad un gruppo di colleghi di corso universitario per sviluppare uno dei progetti proposti. Scegliemmo Etherless ovvero un **FAAS** usando la piattaforma AWS lambda per l'esecuzione delle funzioni. Gli utenti possono scrivere e pubblicare funzioni sul servizio, determinandone il costo di esecuzione. Quindi, altri utenti possono richiedere l'esecuzione, pagando il corrispettivo compenso, attraverso la rete Ethereum. Abbiamo rilasciato il software in licenza MIT [Tenners Unipd](https://github.com/TennersUnipd)"
},
"collaborators": [
{
"name": "Gezim",
"surname": "Cikaqi",
"ref": "https://www.linkedin.com/in/gezimcikaqi/"
},
{
"name": "Gabriel",
"surname": "Ciulei",
"ref": "https://www.linkedin.com/in/gabriel-ciulei/"
},
{
"name": "Simone",
"surname": "Franconetti",
"ref": "https://www.linkedin.com/in/simone-franconetti-2b48b4147/"
},
{
"name": "Giovanni",
"surname": "Incalza",
"ref": "https://www.linkedin.com/in/giovanni-incalza/"
},
{
"name": "Nicola",
"surname": "Salvadore",
"ref": "https://www.linkedin.com/in/nicola-salvadore-02b015210/"
},
{
"name": "Paola",
"surname": "Trevisan",
"ref": "https://www.linkedin.com/in/paola-trevisan-166891113/"
}
],
"languages": [
"TypeScript",
"Solidity",
"YAML"
],
"technologies": [
"Node.js",
"AWS Lambda",
"Docker",
"GitHub Action",
"Ethereum"
],
"images": [
"./tenners.webp"
]
},
{
"year": {
"start": "2019-11-27",
"end": "2019-12-15"
},
"title": {
"en": "Latex-multicompiler",
"it": "Latex-multicompiler"
},
"content": {
"en": "I developed a GitHub Action to compile Latex documents from a git repository. I did this to produce the PDFs as artefacts and to practice the **CI/CD** practices. I released the project with an MIT license [here](https://github.com/Jatus93/Latex-multicompiler).",
"it": "Ho sviluppato una GitHub Action per compilare i documenti Latex contenuti in un repository specifico. Questa GitHub Action crea come artefatti dei PDF partendo dal sorgente Latex.\n Questo progetto mi ha permesso di esercitarmi nelle pratiche di **CI/CD**. Ho rilasciato il tutto con licenza MIT [qui](https://github.com/Jatus93/Latex-multicompiler)."
},
"collaborators": [],
"languages": [
"bash"
],
"technologies": [
"Docker",
"GitHub Action"
],
"images": [
"./LatexMulticompiler.webp"
]
},
{
"year": {
"start": "2019-12-18",
"end": "2020-05-08"
},
"title": {
"en": "Spell checker, aspell GitHub Action",
"it": "Controllo ortografico, aspell GitHub Action"
},
"content": {
"en": "I developed a GitHub Action to perform a spell check on PDF documents from a git repository, the software transform the PDF file to a plain txt and checks the spelling of words using aspell. I released the project with an LGPL-2.1 license [here](https://github.com/Jatus93/spellCheck).",
"it": "Ho sviluppato una GitHub Action per effettuare il controllo ortografico. Il software trasforma i PDF in file di testo e verifica che le parole siano scritte correttamente usando Aspell. Ho rilasciato il software su licenza LGPL-2.1 [qui](https://github.com/Jatus93/spellCheck)"
},
"collaborators": [],
"languages": [
"bash"
],
"technologies": [
"Docker",
"GitHub Action"
],
"images": [
"/spellCheck.webp"
]
},
{
"year": {
"start": "2019-04-14",
"end": "2019-06-10"
},
"title": {
"en": "Project for object oriented programming course",
"it": "Progetto per il corso di programmazione ad oggetti"
},
"content": {
"en": "I delevoped a IoT object container for the object oriented programming course with the possiblity to edit the devices' configuration. <a rel=\"external\" href=\"/QContainer.pdf\">I wrote a report about it (italian)</a> and [released the software](https://github.com/Jatus93/QONTAINER) in LGPL-3.0 License ",
"it": "Per il corso di programmazione ad oggetti ho fatto un container di dispositivi iot con la possibilità di configurare i dispositivi. Per maggiori infomrmazioni <a rel=\"external\" href=\"/QContainer.pdf\">ho scritto una relazione al riguardo</a> e [rilasciato il software](https://github.com/Jatus93/QONTAINER) sotto licenza LGPL-3.0"
},
"collaborators": [],
"languages": [
"C++"
],
"technologies": [
"Qt"
],
"images": [
"/QContainer.webp"
]
},
{
"year": {
"start": "2018-12-03",
"end": "2019-02-13"
},
"title": {
"en": "Tech web",
"it": "Tecnologie Web"
},
"content": {
"en": "For the tech web course, my colleagues and I develop a portfolio website for an artist where the user could upload and manage all their images and also included a blog with a comments section.",
"it": "Per il corso di tecnologie web io e i miei colleghi abbiamo sviluppato un sito web vetrina per artisti con un sistema per la gestione dei contenuti."
},
"collaborators": [
{
"name": "Giuseppe Vito",
"surname": "Bitetti",
"ref": "https://www.linkedin.com/in/giuseppe-vito-bitetti-587751200"
},
{
"name": "Enrico",
"surname": "Buratto",
"ref": "https://www.linkedin.com/in/enrico-buratto-04104b151"
},
{
"name": "Mariano",
"surname": "Sciacco",
"ref": "https://www.linkedin.com/in/marianosciacco/"
}
],
"languages": [
"PHP",
"SQL"
],
"technologies": [
"Apache",
"MariaDB"
],
"images": [
"/techweb.webp"
]
},
{
"year": {
"start": "2018-05-16",
"end": "2018-05-22"
},
"title": {
"en": "ANTRL parser Swl",
"it": "ANTRL parser Swl"
},
"content": {
"en": "For the course about Automata and Formal, my colleague and I developed a translator from a made-up language SWL to a more common C++. For this project, the professors required the use of \"antlr\" a framework used to recognise a regular expression and apply logic for every rule. For more information https://swl.debug.ovh/ (italian)",
"it": "Per il corso di Automi e linguaggi formali, il mio collega ed io sviluppammo un traduttore da un linguaggio inventato, SWL, a uno più comune C++. Per questo compito i professori richiesero l'uso di un framework chiamato \"ANTRL\" che è in grado di riconoscere le epressioni regolari che gli vengono proposte e di applicare delle logiche al riguardo. Per maggiori info https://swl.debug.ovh/"
},
"collaborators": [
{
"name": "Mariano",
"surname": "Sciacco",
"ref": "https://www.linkedin.com/in/marianosciacco/"
}
],
"languages": [
"C++",
"SWL",
"ANTLR grammar"
],
"technologies": [
"ANTLR"
],
"images": [
"./SWL.webp"
]
}
]

View File

@@ -18,7 +18,8 @@
"required": [ "required": [
"start", "start",
"end" "end"
] ],
"additionalProperties": false
}, },
"title": { "title": {
"type": "object", "type": "object",
@@ -33,7 +34,8 @@
"required": [ "required": [
"en", "en",
"it" "it"
] ],
"additionalProperties": false
}, },
"content": { "content": {
"type": "object", "type": "object",
@@ -48,7 +50,8 @@
"required": [ "required": [
"en", "en",
"it" "it"
] ],
"additionalProperties": false
}, },
"collaborators": { "collaborators": {
"type": "array", "type": "array",
@@ -69,7 +72,8 @@
"name", "name",
"surname", "surname",
"ref" "ref"
] ],
"additionalProperties": false
} }
}, },
"languages": { "languages": {
@@ -78,7 +82,7 @@
"type": "string" "type": "string"
} }
}, },
"tecnologies": { "technologies": {
"type": "array", "type": "array",
"items": { "items": {
"type": "string" "type": "string"
@@ -97,7 +101,8 @@
"content", "content",
"collaborators", "collaborators",
"languages", "languages",
"tecnologies", "technologies",
"images" "images"
] ],
"additionalProperties": false
} }

View File

@@ -0,0 +1,17 @@
{
"$schema": "http://json-schema.org/draft-04/schema#",
"type": "object",
"properties": {
"img": {
"type": "string"
},
"name": {
"type": "string"
}
},
"required": [
"img",
"name"
],
"additionalProperties": false
}

View File

@@ -0,0 +1,62 @@
[
{
"year": {
"start": "2024"
},
"title": {
"en": "AWS Certified Developer Associate",
"it": "AWS Certified Developer Associate"
},
"content": {
"en": " AWS Certified Developer Associate Skills in developing and managing applications on AWS.",
"it": " AWS Certified Developer Associate Competenze nello sviluppo e nella gestione di applicazioni su AWS."
},
"collaborators": [],
"technologies": [
"AWS"
],
"images": [
"AWS_DEV.png"
]
},
{
"year": {
"start": "2016",
"end": "2020"
},
"title": {
"en": "Bachelor's degree in Computer Science (EQF 6): ",
"it": "Laurea triennale in Scienze Informatiche (EQF 6)"
},
"content": {
"en": "Computer Science, Università degli Studi di Padova",
"it": "Corso triennale in Informatica all'Università degli Studi di Padova"
},
"collaborators": [],
"languages": [],
"technologies": [],
"images": [
"unipd-universita-di-padova.webp"
]
},
{
"year": {
"start": "2007",
"end": "2013"
},
"title": {
"en": "High School diploma, Liceo Scientifico Tecnologico (EQF 4): ",
"it": "Diploma di maturità di Liceo Scientifico Tecnologico (EQF 4)"
},
"content": {
"en": "The scientific and technological high school I.T.I.S. Severi di Padova where instead of Latin, there were more physics, chemistry and basic programming lessons.",
"it": "Corso di Liceo Scientifico Tecnologico all'istituto I.T.I.S. Severi di Padova, dove al posto del Latino i corsi puntavano di più su fisica, chimica e dei corsi introduttivi alla programmazione"
},
"collaborators": [],
"languages": [],
"technologies": [],
"images": [
"logoSeveri.webp"
]
}
]

5
src/lib/types.ts Normal file
View File

@@ -0,0 +1,5 @@
export type CurrentLanguage = 'it' | 'en';
export type MenuEntry = 'home' | 'job' | 'school' | 'blog' | 'portfolio';
export type LanguagePair = {
[key in CurrentLanguage]: string;
};

View File

@@ -1,121 +0,0 @@
[
{
"year": {
"start": "2022-01-03",
"end": ""
},
"title": {"en":"ALTEN italy","it":"ALTEN italia"},
"content": {
"en":"At the end of 2021, while I was trying to publicize my activity, I received many jobs offers.\n Alten Italy offered a position as a software developer consultant for their clients.\n So, from the 3rd of January, I'm working for Aten Italy in the Bologna's division.\n In this period, I'm working with Laravel, Vuejs, Nodejs and AWS environments.",
"it":"Alla fine del 2021, mentre stavo cercando di fare pubblicità per la mia attività, ho ricevuto diverse offerte di lavoro, tra cui Alten Italia.\n Quindi, dal 3 gennaio 2022 sono impiegato in Alten Italia, nella sede di Bologna, come consulente informatico.\n Attualmente di occupo di sviluppo software con laravel, vuejs e nodejs in ambienti AWS."
},
"collaborators": [],
"languages": [
"Php",
"bash",
"yaml",
"json",
"Javascript",
"TypeScript",
"Python"
],
"tecnologies": [
"Vue.js",
"Node.js",
"Laravel",
"Docker",
"AWS"
],
"images":["/ALTEN.webp"]
},
{
"year": {
"start": "2021-01-10",
"end": "2021-12-31"
},
"title": {"en":"Jatus.tech my start-up","it":"La mia start-up Jatus.tech"},
"content": {
"en":"In 2021, I worked to open a start-up with an app idea.\n To do so, I learned a lot of different skills, including how to set up a server with all my services running in **Docker**, set up a **GitLab** server, **design and build** an application infrastructure, and set up a private registry for **npm** and **docker images**.\n Furthermore, I configured all the **automation pipelines** to streamline the software distribution in virtualized environments and build the application **proof of concept** to demo to potential customers.",
"it":"Nel corso del 2021 ho lavorato, per avviare una attività indipendente che si basa su una mia idea di servizio. Per far ciò, durante questo periodo ho imparato a creare un'infrastruttura di lavoro, su un server **GNU\/Linux** dove centralizzare le risorse con **GitLab** in container **Docker**.\n Per semplificare la distribuzione di elementi di sviluppo ho integrato un *repository* privato di pacchetti **npm** e immagini **Docker**. Oltre alle mansioni da sistemista e devops ho progettato e scritto il **Proof of concept** del mio servizio per dimostrarlo a potenziali clienti"
"en":"In 2021, I worked to open a start-up with an app idea.\nTo do so, I acquired skills in design and developing a software solution for the problem. I learnt how to set up a **CI/CD** pipeline with **Docker** and **Gitlab** and took confidence in **serverless** technologies like AWS.",
"it":"Nel corso del 2021 ho lavorato per avviare una mia attività indipendente, basata su unidea per una app che ritenevo, e ritengo, fattibile. In questo periodo ho dovuto ricoprire diversi ruoli per portar avanti questiniziativa. Di conseguenza ho imparato a svolgere le mansioni di analista e architetto, **devops** e sviluppo. \n In particolare, ho acquisito dimestichezza con i sistemi di **CI/CD** basati su **Docker** e nelluso di tecnologie **serverless**."
},
"collaborators": [],
"languages": [
"TypeScript",
"bash",
"Docker-file",
"yaml",
"json"
],
"tecnologies": [
"Vue.js",
"Node.js",
"Nuxt",
"Docker",
"GitLab",
"Nativescript"
],
"images":["/logo-jatus-tech.webp"]
},
{
"year": {
"start": "2020-9-21",
"end": "2020-11-21"
},
"title": {"en":"Intership in Athesys","it":"Tirocinio in Athesys"},
"content": {
"en":"I've chosen to work in Athesis to end my bachelor degree course. The project was about developing a middleware to put in communication two applications between **NATed** networks based on **OAuth2.0**. This middleware assures the connection is authorized. This software mainly approved the connection of devices that detected the presence of a face mask and the body temperature in the range",
"it":"Per la tesi di laurea, ho scelto di fare il tirocinio in Athesys. Il progetto prevedeva lo sviluppo di un middleware per mettere in comunicazione, in maniera sicura, due applicazioni tra reti **NAT** basato sui protocolli autorizzativi di **OAuth2.0**.\n Dato il periodo, dove la seconda ondata della pandemia era alle porte, era necessario avere un sistema sicuro per la comuncazione tra dispositivi di controllo dell'ingresso e il \"back-end\", come tablet con termoscanner e software per il riconoscimento della mascherina."
},
"collaborators": [],
"languages": [
"TypeScript",
"HTML",
"CSS"
],
"tecnologies": [
"Vue.js",
"Node.js",
"Nuxt",
"Docker"
],
"images":["/logo-athesys.webp"]
},
{
"year": {
"start": "2016-08-13",
"end": "2017-02-13"
},
"title": {"en":"Developer in Alternative Studio","it":"Sviluppatore in Alternative Studio"},
"content": {
"en":"I've projected and developed a Telegram bot with direct communication to management software for the dog squad Italian civil defence to enable communication between HQ and agent on the ground",
"it":"Progettazione e sviluppo di un Bot Telegram con comunicazione diretta al gestionale per la sezione cinofila della Protezione Civile"
},
"collaborators": [],
"languages": [
"PHP"
],
"tecnologies": [
"Telegram",
"Composer",
"Docker"
],
"images":["/alternative-studio.webp"]
},
{
"year": {
"start": "2012-06-05",
"end": "2012-07-05"
},
"title": {"en":"ICT office's assistant","it":"Assistente dell'ufficio ICT "},
"content": {
"en":"I applied to this position, in Saxon Hill Academy, through the European project Leonardo which provided accommodation for the stay, an English course and a workplace mainly for practices the language skill. In Saxon Hill Academy, my responsibilities were:\n - Maintenance of administration's computers.\n - Maintenance of students' computers.\n - Make the sensorial room usable.",
"it":"Ho avuto l'opportunità di lavorare in questo ambiente grazie al progetto europeo Leonardo. Questo progetto di 4 settimane si occupava di fornire agli studenti tutto il necessario tra vitto e alloggio, prevedeva, inoltre, un corso di inglese e un luogo di lavoro dove fare principalmente pratica con la lingua. In questo contesto sono stato assegnato a Saxon Hill Academy dove ho svolto le seguenti mansioni:\n - Manutenzione dei computer della segreteria\n - Manutenzione dei computer degli studenti \n - Rendere operativa la \"sensiorial room\""
},
"collaborators": [],
"languages": [],
"tecnologies": [],
"images":["/saxonhilllogo.webp"]
}
]

View File

@@ -1,179 +0,0 @@
[
{
"year": {
"start": "2021-10-01",
"end": "2021-10-19"
},
"title": {"en":"This web site","it":"Questo sito web"},
"content": {
"en":"I created this web page to collect and present all my experiences. I'm not a web designer. However, I can build web pages because I have good knowledge of HTML and CSS. I made this page using TypeScript and Svelte. To manage the content, I've created a simple system to load content from a couple of JSON files that define where to put the information.",
"it":"Ho creato questo sito web per raccogliere e raccontare le mie esperienze. Come si può facilmente intuire non sono un web designer, ma ho comunque buone conoscenze nell'uso di HTML e CSS. Ho realizzato questa pagina web in TypeScript e Svelte, per la gestione dei contenuti ho ideato un semplice sistema che controlla i dati presenti in un paio di file JSON che definiscono i contenuti della pagina e delle sezioni."
},
"collaborators": [],
"languages": [
"TypeScript",
"JSON-schema"
],
"tecnologies": [
"Svelte",
"Node.js"
],
"images":["/webpage.webp"]
},
{
"year":{
"start":"2021-09-15",
"end":"2021-09-28"},
"title":{"en":"Greenpass server validator","it":"Greenpass server validatore"},
"content":{
"en":"I've created a server in TypeScript with Express.js endpoints that can read the raw data from a Green pass Qrcode and establish if it is valid with the Italian regulations. I [released the software](https://git.jatus.tech/Jatus/dgcserververifier) under AGPLv3 as requested from the DCC utils library.",
"it":"Ho creato un server in TypeScript e express che leggendo i dati *raw* del Qr code del green pass può determinarne la sua validità, ho [rilasciato il software](https://git.jatus.tech/Jatus/dgcserververifier) in licenza AGPLv3 come previsto dalla librearia DCC utils del Ministero della Salute italiano."},
"collaborators":[],
"languages":["TypeScript"],
"tecnologies":["Node.js"],
"images":["./DGCServerVerifier.webp"]
},
{
"year": {
"start": "2021-04-01",
"end": "2021-05-02"
},
"title": {"en":"Keyboard","it":"Tastiera"},
"content": {
"en":"I spend a lot of time at my desk writing on the PC with not the best posture. This kind of behaviour was going to take a toll on my well-being, so I decided to start looking for a split design keyboard.\n The first keyboard that I found was the [Ergodox-EZ](https://ergodox-ez.com), but the steep price of more than 300 euros put me off. Then I found the subreddit [r/ErgoMechBoards](https://www.reddit.com/r/ErgoMechKeyboards) and saw a lot of different concepts, the one that stuck with me was the [lily58](https://github.com/kata0510/Lily58).\n So, I ordered all the pieces from various online stores. I took the kit from the [Keyhive](https://keyhive.xyz) shop for the base parts, like PCB and guide for the switches, bought the switches from [CandyKeys](https://candykeys.com) and a cheap keycap set from amazon.\n When all the pieces showed up at my place, I soldered all the components and assembled the keyboard. To add some flare, I printed with my 3d printer a custom case that I found on Thingiverse.\n In the future, I'd like to add a system to tilt the keyboard to fix the pronation issue.",
"it":"Io passo molto tempo al PC e spesso non ho una corretta postura. Sperando di mitigare il problema, iniziai a cercare delle tastiere ergonomiche come quelle con il design *split*.\n La prima che trovai fu [Ergodox-EZ](https://ergodox-ez.com), ma il prezzo di più 300 euro mi fece desistere. Successivamente trovai il *subreddit* [r/ErgoMechBoards](https://www.reddit.com/r/ErgoMechKeyboards) e vidi molti modelli diversi, quello che mi piacque di più fu [lily58](https://github.com/kata0510/Lily58).\n Quindi, ordinai i pezzi da diversi negozi online. Presi da [Keyhive](https://keyhive.xyz) le parti base come il PCB e la guida per i tasti e da [CandyKeys](https://candykeys.com) gli switch, per quanto riguarda i keycaps li presi da Amazon ordinando dal meno caro.\n Quando tutti i pezzi arrivarono, con pazienza e dedizione saldai tutti i componenti e assemblai la tastiera. Per aggiungere un tocco personale, stampai con la mia stampante 3d la scocca che trovai su Thingverse.\n Come miglioramenti futuri, mi piacerebbe aggiungere un sistema per angolare la tastiera e risolvere il problema di pronazione dei polsi."
},
"collaborators": [],
"languages": [
"C"
],
"tecnologies": [
"QMK"
],
"images":["/custom-keyboard.webp"]
},
{
"year":{
"start":"2021-09-15",
"end":"2021-09-30"},
"title":{"en":"3D printer, to print all my ideas","it":"Stampante 3D per stampare le mie idee."},
"content":{
"en":"I'm a tech enthusiast and, I like to overcome challenges made for the maker type of people. To organize the 3d printer area, I followed a few of the many bits of advice from the 3d printing *community*. Like, build the furniture to hold the printer from two IKEA's Lack stack one upon the other and joined with some 3d printed parts. Another upgrade was to add a Raspberry pi 4 with a camera module and OctoPrint software to remote manage the printer whenever.",
"it":"Sono un appassionato di tecnologia e mi piace anche affrontare sfide tipiche dei *maker*. Per organizzare meglio gli spazi ho seguito gli innumerovili consigli della *community* sul costruire un mobile a partire da due mobili ikea \"Lack\" e di unirli con due pezzi stampati. Un'altra miglioria che ho effettuato è sul sistema di controllo della stampante stessa aggiungendo un raspberry pi 4 con webcam e munito del software octoprint che mi permette di controllarne lo stato da remoto."
},
"collaborators":[],
"languages":["bash","python"],
"tecnologies":["raspberry"],
"images":["/3dprinter.webp"]
},{
"year":{
"start":"2021-09-15",
"end":"2021-09-30"},
"title":{"en":"Unraid Server","it":"Unraid Server"},
"content":{
"en":"To manage all my software and data, I built a home server with Unraid server. I based the system on the Ryzen platform with an R9 3900X CPU, two 2TB disks for work data and software and, 4 disks 4TB for family storage.",
"it":"Per gestire il mio software e i miei dati, ho costruito un server usando la distrubuzione Unraid. Il server è basato su una piattaforma ryzen con R9 3900X, due dischi da 2TB per i dati di lavoro e 4 dischi da 4TB, in configurazione RAID10, per lo spazio della mia famiglia."
},
"collaborators":[],
"languages":["YAML"],
"tecnologies":["Docker","Unraid","GNU/Linux"],
"images":["./unraid.webp"]
},
{
"year":{
"start":"2019-04-15",
"end":""},
"title":{"en":"Workstation","it":"Postazione di lavoro"},
"content":{
"en":"My workstation is build upon my custom desk made on request and can accommodate my PC and laptop, I use both of them to work and develop my projects. The monitors are an 34\" 21:9 with a resoluztion of 3440x1440 and a 27\" 16:9 with a resolution of 2560x1440. ",
"it":"La mia postazione di lavoro parte dalla scrivania che è stata fatta su misura e può accomodare il mio computer fisso e il mio portatile, entrambe macchine che uso per lavorare e dedicarmi ai miei progetti. I monitor sono un 21:9 da 34\" con risoluzione 3440x1440 e un 16:9 da 27\" in verticale da 2560x1440."
},
"collaborators":[],
"languages":[],
"tecnologies":[],
"images":["/workstation.webp"]
},
{
"year":{
"start":"2019-11-17",
"end":"2020-05-18"},
"title":{"en":"Software Engineering Project","it":"Progetto di Ingegneria del Software"},
"content":{
"en":"While in university, I worked on a project for the software engineering course. The group decided to develop the project Etherless, a FAAS based on Etherium and AWS lambda. The system worked like this, a user writes a function and uploads it to the service that assigns a cost of execution. Then, when a user wants to execute the function, must issue the request and pay the execution through the Ethereum network. We released all the software in MIT licence here [Tenners Unipd](https://github.com/TennersUnipd).",
"it":"Per il corso di ingegneria del software sono stato assegnato ad un gruppo di colleghi di corso universitario per sviluppare uno dei progetti proposti. Scegliemmo Etherless ovvero un **FAAS** usando la piattaforma AWS lambda per l'esecuzione delle funzioni. Gli utenti possono scrivere e pubblicare funzioni sul servizio, determinandone il costo di esecuzione. Quindi, altri utenti possono richiedere l'esecuzione, pagando il corrispettivo compenso, attraverso la rete Ethereum. Abbiamo rilasciato il software in licenza MIT [Tenners Unipd](https://github.com/TennersUnipd)"
},
"collaborators":[{"name":"Gezim","surname":"Cikaqi","ref":"https://www.linkedin.com/in/gezimcikaqi/"},{"name":"Gabriel","surname":"Ciulei","ref":"https://www.linkedin.com/in/gabriel-ciulei/"},{"name":"Simone","surname":"Franconetti","ref":"https://www.linkedin.com/in/simone-franconetti-2b48b4147/"},{"name":"Giovanni","surname":"Incalza","ref":"https://www.linkedin.com/in/giovanni-incalza/"},{"name":"Nicola","surname":"Salvadore","ref":"https://www.linkedin.com/in/nicola-salvadore-02b015210/"},{"name":"Paola","surname":"Trevisan","ref":"https://www.linkedin.com/in/paola-trevisan-166891113/"}],
"languages":["TypeScript","Solidity","YAML"],
"tecnologies":["Node.js","AWS Lambda","Docker","GitHub Action","Ethereum"],
"images":["./tenners.webp"]
},
{
"year":{
"start":"2019-11-27",
"end":"2019-12-15"},
"title":{"en":"Latex-multicompiler","it":"Latex-multicompiler"},
"content":{
"en":"I developed a GitHub Action to compile Latex documents from a git repository. I did this to produce the PDFs as artefacts and to practice the **CI/CD** practices. I released the project with an MIT license [here](https://github.com/Jatus93/Latex-multicompiler).",
"it":"Ho sviluppato una GitHub Action per compilare i documenti Latex contenuti in un repository specifico. Questa GitHub Action crea come artefatti dei PDF partendo dal sorgente Latex.\n Questo progetto mi ha permesso di esercitarmi nelle pratiche di **CI/CD**. Ho rilasciato il tutto con licenza MIT [qui](https://github.com/Jatus93/Latex-multicompiler)."
},
"collaborators":[],
"languages":["bash"],
"tecnologies":["Docker","GitHub Action"],
"images":["./LatexMulticompiler.webp"]
},
{
"year":{
"start":"2019-12-18",
"end":"2020-05-08"},
"title":{"en":"Spell checker, aspell GitHub Action","it":"Controllo ortografico, aspell GitHub Action"},
"content":{
"en":"I developed a GitHub Action to perform a spell check on PDF documents from a git repository, the software transform the PDF file to a plain txt and checks the spelling of words using aspell. I released the project with an LGPL-2.1 license [here](https://github.com/Jatus93/spellCheck).",
"it":"Ho sviluppato una GitHub Action per effettuare il controllo ortografico. Il software trasforma i PDF in file di testo e verifica che le parole siano scritte correttamente usando Aspell. Ho rilasciato il software su licenza LGPL-2.1 [qui](https://github.com/Jatus93/spellCheck)"
},
"collaborators":[],
"languages":["bash"],
"tecnologies":["Docker","GitHub Action"],
"images":["/spellCheck.webp"]
},
{
"year":{
"start":"2019-04-14",
"end":"2019-06-10"},
"title":{"en":"Project for object oriented programming course","it":"Progetto per il corso di programmazione ad oggetti"},
"content":{
"en":"I delevoped a IoT object container for the object oriented programming course with the possiblity to edit the devices' configuration. <a rel=\"external\" href=\"/QContainer.pdf\">I wrote a report about it (italian)</a> and [released the software](https://github.com/Jatus93/QONTAINER) in LGPL-3.0 License ",
"it":"Per il corso di programmazione ad oggetti ho fatto un container di dispositivi iot con la possibilità di configurare i dispositivi. Per maggiori infomrmazioni <a rel=\"external\" href=\"/QContainer.pdf\">ho scritto una relazione al riguardo</a> e [rilasciato il software](https://github.com/Jatus93/QONTAINER) sotto licenza LGPL-3.0"
},
"collaborators":[],
"languages":["C++"],
"tecnologies":["Qt"],
"images":["/QContainer.webp"]
},
{
"year":{
"start":"2018-12-03",
"end":"2019-02-13"},
"title":{"en":"Tech web","it":"Tecnologie Web"},
"content":{
"en":"For the tech web course, my colleagues and I develop a portfolio website for an artist where the user could upload and manage all their images and also included a blog with a comments section.",
"it":"Per il corso di tecnologie web io e i miei colleghi abbiamo sviluppato un sito web vetrina per artisti con un sistema per la gestione dei contenuti."},
"collaborators":[{"name":"Giuseppe Vito","surname":"Bitetti","ref":"https://www.linkedin.com/in/giuseppe-vito-bitetti-587751200"}, {"name":"Enrico","surname":"Buratto","ref":"https://www.linkedin.com/in/enrico-buratto-04104b151"},{"name":"Mariano","surname":"Sciacco","ref":"https://www.linkedin.com/in/marianosciacco/"}],
"languages":["PHP","SQL"],
"tecnologies":["Apache","MariaDB"],
"images":["/techweb.webp"]
},
{
"year":{
"start":"2018-05-16",
"end":"2018-05-22"},
"title":{"en":"ANTRL parser Swl","it":"ANTRL parser Swl"},
"content":{
"en":"For the course about Automata and Formal, my colleague and I developed a translator from a made-up language SWL to a more common C++. For this project, the professors required the use of \"antlr\" a framework used to recognise a regular expression and apply logic for every rule. For more information https://swl.debug.ovh/ (italian)",
"it":"Per il corso di Automi e linguaggi formali, il mio collega ed io sviluppammo un traduttore da un linguaggio inventato, SWL, a uno più comune C++. Per questo compito i professori richiesero l'uso di un framework chiamato \"ANTRL\" che è in grado di riconoscere le epressioni regolari che gli vengono proposte e di applicare delle logiche al riguardo. Per maggiori info https://swl.debug.ovh/"
},
"collaborators":[{"name":"Mariano","surname":"Sciacco","ref":"https://www.linkedin.com/in/marianosciacco/"}],
"languages":["C++","SWL","ANTLR grammar"],
"tecnologies":["ANTLR"],
"images":["./SWL.webp"]
}
]

View File

@@ -1,29 +0,0 @@
[
{
"year": {
"start": "2016",
"end": "2020"
},
"title": {"en":"Bachelor's degree in Computer Science (EQF 6): ","it":"Laurea triennale in Scienze Informatiche (EQF 6)"},
"content": {
"en":"Computer Science, Università degli Studi di Padova","it":"Corso triennale in Informatica all'Università degli Studi di Padova"},
"collaborators": [],
"languages": [],
"tecnologies": [],
"images":["unipd-universita-di-padova.webp"]
},
{
"year": {
"start": "2007",
"end": "2013"
},
"title": {"en":"High School diploma, Liceo Scientifico Tecnologico (EQF 4): ","it":"Diploma di maturità di Liceo Scientifico Tecnologico (EQF 4)"},
"content": {
"en":"The scientific and technological high school I.T.I.S. Severi di Padova where instead of Latin, there were more physics, chemistry and basic programming lessons.",
"it":"Corso di Liceo Scientifico Tecnologico all'istituto I.T.I.S. Severi di Padova, dove al posto del Latino i corsi puntavano di più su fisica, chimica e dei corsi introduttivi alla programmazione"},
"collaborators": [],
"languages": [],
"tecnologies": [],
"images":["logoSeveri.webp"]
}
]

2
src/routes/+layout.ts Normal file
View File

@@ -0,0 +1,2 @@
export const ssr = false;
export const prerender = true;

103
src/routes/+page.svelte Normal file
View File

@@ -0,0 +1,103 @@
<script lang="ts">
import {} from 'svelte';
import { MetaTags } from 'svelte-meta-tags';
import type { CurrentLanguage } from '$lib/types';
import AboutMe from '$lib/elements/AboutMe.svelte';
import Jobs from '$lib/elements/Jobs.svelte';
import Menu from '$lib/elements/Menu.svelte';
import Training from '$lib/elements/Training.svelte';
import Data_jobs from '$lib/model/jobs.json';
import Data_portfolio from '$lib/model/portfolio.json';
import LanguageSelector from '$lib/elements/LanguageSelector.svelte';
import type { Job } from '$lib/model/job';
let jobs: Job[] = Data_jobs as Job[];
let portfolio: Job[] = Data_portfolio as Job[];
let currentLanguage: CurrentLanguage = 'it';
let titles = {
home: {
it: 'Gianmarco Pettinato',
en: 'Gianmarco Pettinato'
},
job: { it: 'Esperienze', en: 'Experiences' },
school: { it: 'Formazione', en: 'Training' },
contacts: { it: 'Contatti', en: 'Contacts' },
portfolio: { it: 'Portfolio', en: 'Portfolio' }
};
let modalOpen: boolean = false;
</script>
<MetaTags
title="Gianmarco Pettinato"
description="This is the Gianmarco's portfolio site"
canonical="https://pettinato.eu/"
openGraph={{
url: 'https://pettinato.eu/',
title: 'Gianmarco Pettinato',
description: "This is the Gianmarco's portfolio site",
images: [],
site_name: 'Gianmarco Pettinato Portfolio'
}}
twitter={{
handle: '@jatus_93',
site: '@jatus_93',
cardType: 'summary',
title: 'Gianmarco Pettinato Portfolio',
description: "This is the Gianmarco's portfolio site",
image: 'https://pettinato.eu/profile_pic.webp',
imageAlt: 'Gianmarco Photo'
}}
/>
<main lang={currentLanguage}>
<!-- svelte-ignore a11y-invalid-attribute -->
<LanguageSelector bind:currentLanguage />
<Menu {currentLanguage} />
<div
class="default"
on:scroll={(event) => {
if (modalOpen) {
event.preventDefault();
}
console.log(event);
}}
>
<span id="home" class="anchor" />
<AboutMe {currentLanguage} />
</div>
<div class="default">
<span id="jobs" class="anchor" />
<h2>{titles.job[currentLanguage]}</h2>
<Jobs {jobs} {currentLanguage} bind:modalOpen />
</div>
<div class="default">
<span id="training" class="anchor" />
<h2>{titles.school[currentLanguage]}</h2>
<Training {currentLanguage} />
</div>
<div class="default">
<span id="portfolio" class="anchor" />
<h2>{titles.portfolio[currentLanguage]}</h2>
<Jobs jobs={portfolio} {currentLanguage} bind:modalOpen />
</div>
</main>
<style lang="scss">
@import '../app.scss';
@media (max-width: $min-tablet) {
.custom-button {
font-size: large;
}
}
.anchor {
position: absolute;
margin-top: -150px;
@media (min-width: 460px) {
margin-top: -100px;
}
@media (min-width: $min-tablet) {
margin-top: -60px;
}
}
</style>

View File

@@ -1,132 +0,0 @@
<script lang="ts">
import { MetaTags } from 'svelte-meta-tags';
import Menu from '$elem/Menu.svelte';
import Jobs from '$elem/Jobs.svelte';
let currentLanguage: string = 'it';
let isBlogContainer = true;
import Data_portfolio from '../../model/portfolio.json';
import type { Schema } from 'src/model/job';
let jobs: Schema[] = Data_portfolio as Schema[];
let title = { it: 'I miei articoli', en: 'my blog posts' };
</script>
<MetaTags
title="Gianmarco Pettinato"
description="This is the Gianmarco's portfolio site"
canonical="https://pettinato.eu/"
openGraph={{
url: 'https://pettinato.eu/',
title: 'Gianmarco Pettinato',
description: "This is the Gianmarco's portfolio site",
images: [
{
url: 'https://www.example.ie/og-image-01.jpg',
width: 800,
height: 600,
alt: 'Og Image Alt'
},
{
url: 'https://www.example.ie/og-image-02.jpg',
width: 900,
height: 800,
alt: 'Og Image Alt Second'
},
{ url: 'https://www.example.ie/og-image-03.jpg' },
{ url: 'https://www.example.ie/og-image-04.jpg' }
],
site_name: 'Gianmarco Pettinato Portfolio'
}}
twitter={{
handle: '@jatus_93',
site: '@jatus_93',
cardType: 'summary',
title: 'Gianmarco Pettinato Portfolio',
description: "This is the Gianmarco's portfolio site",
image: 'https://pettinato.eu/profile_pic.webp',
imageAlt: 'Gianmarco Photo'
}}
/>
<main>
<!-- svelte-ignore a11y-invalid-attribute -->
<div class="language-selector" id="language-selector">
<button
class="custom-button {currentLanguage == 'it' ? 'custom-button-active' : ''}"
on:click={() => {
currentLanguage = 'it';
}}>it</button
>
<button
class="custom-button {currentLanguage == 'en' ? 'custom-button-active' : ''}"
on:click={() => {
currentLanguage = 'en';
}}>en</button
>
</div>
<div class="menu">
<Menu {currentLanguage} />
</div>
<div id="portfolio" class="default">
<h2>{title[currentLanguage]}</h2>
<Jobs {jobs} {currentLanguage} {isBlogContainer} />
</div>
</main>
<style lang="scss">
@import '../../app.scss';
.language-selector {
right: 0;
height: 30px;
text-align: center;
text-transform: uppercase;
padding-top: 10px;
display: flex;
flex-direction: row;
justify-content: end;
position: absolute;
z-index: 999;
@media (max-width: $min-desktop) {
width: 100%;
position: unset;
padding-bottom: 10px;
background-color: $basecolor2;
}
}
.menu {
background-color: $basecolor2;
position: sticky;
position: -webkit-sticky;
top: 0px;
display: flex;
justify-content: center;
align-items: center;
padding: 10px;
border-bottom: solid #999 1px;
}
.custom-button {
border: 0;
background: none;
box-shadow: none;
border-radius: $default-border-radius;
border: solid $button-border-color 1px;
width: 40px;
cursor: pointer;
margin-right: 5px;
}
.custom-button:hover {
background-color: $text-color;
color: white;
}
.custom-button-active {
cursor: unset;
background-color: $text-color;
color: white;
}
@media (max-width: $min-tablet) {
.custom-button {
font-size: large;
}
}
</style>

View File

@@ -1,157 +0,0 @@
<script lang="ts">
import { MetaTags } from 'svelte-meta-tags';
import AboutMe from '$elem/AboutMe.svelte';
import Jobs from '$elem/Jobs.svelte';
import Menu from '$elem/Menu.svelte';
import Training from '$elem/Training.svelte';
import Data_jobs from '../model/jobs.json';
import Data_portfolio from '../model/portfolio.json';
import type { Schema } from 'src/model/job';
let jobs: Schema[] = Data_jobs as Schema[];
let portfolio: Schema[] = Data_portfolio as Schema[];
let currentLanguage: string = 'it';
let titles = {
home: {
it: 'Gianmarco Pettinato',
en: 'Gianmarco Pettinato'
},
job: { it: 'Esperienze', en: 'Experiences' },
school: { it: 'Formazione', en: 'Training' },
contacts: { it: 'Contatti', en: 'Contacts' },
portfolio: { it: 'Portfolio', en: 'Portfolio' }
};
</script>
<MetaTags
title="Gianmarco Pettinato"
description="This is the Gianmarco's portfolio site"
canonical="https://pettinato.eu/"
openGraph={{
url: 'https://pettinato.eu/',
title: 'Gianmarco Pettinato',
description: "This is the Gianmarco's portfolio site",
images: [
{
url: 'https://www.example.ie/og-image-01.jpg',
width: 800,
height: 600,
alt: 'Og Image Alt'
},
{
url: 'https://www.example.ie/og-image-02.jpg',
width: 900,
height: 800,
alt: 'Og Image Alt Second'
},
{ url: 'https://www.example.ie/og-image-03.jpg' },
{ url: 'https://www.example.ie/og-image-04.jpg' }
],
site_name: 'Gianmarco Pettinato Portfolio'
}}
twitter={{
handle: '@jatus_93',
site: '@jatus_93',
cardType: 'summary',
title: 'Gianmarco Pettinato Portfolio',
description: "This is the Gianmarco's portfolio site",
image: 'https://pettinato.eu/profile_pic.webp',
imageAlt: 'Gianmarco Photo'
}}
/>
<main>
<!-- svelte-ignore a11y-invalid-attribute -->
<div class="language-selector" id="language-selector">
<button
class="custom-button {currentLanguage == 'it' ? 'custom-button-active' : ''}"
on:click={() => {
currentLanguage = 'it';
}}>it</button
>
<button
class="custom-button {currentLanguage == 'en' ? 'custom-button-active' : ''}"
on:click={() => {
currentLanguage = 'en';
}}>en</button
>
</div>
<div class="menu">
<Menu {currentLanguage} />
</div>
<div id="home" class="default">
<h1>{titles.home[currentLanguage]}</h1>
<h2>Software developer</h2>
<AboutMe {currentLanguage} />
</div>
<div id="jobs" class="default">
<h2>{titles.job[currentLanguage]}</h2>
<Jobs {jobs} {currentLanguage} />
</div>
<div id="training" class="default">
<h2>{titles.school[currentLanguage]}</h2>
<Training {currentLanguage} />
</div>
<div id="portfolio" class="default">
<h2>{titles.portfolio[currentLanguage]}</h2>
<Jobs jobs={portfolio} {currentLanguage} />
</div>
</main>
<style lang="scss">
@import '../app.scss';
.language-selector {
right: 0;
height: 30px;
text-align: center;
text-transform: uppercase;
padding-top: 10px;
display: flex;
flex-direction: row;
justify-content: end;
position: absolute;
z-index: 999;
@media (max-width: $min-desktop) {
width: 100%;
position: unset;
padding-bottom: 10px;
background-color: $basecolor2;
}
}
.menu {
background-color: $basecolor2;
position: sticky;
position: -webkit-sticky;
top: 0px;
display: flex;
justify-content: center;
align-items: center;
padding: 10px;
border-bottom: solid #999 1px;
}
.custom-button {
border: 0;
background: none;
box-shadow: none;
border-radius: $default-border-radius;
border: solid $button-border-color 1px;
width: 40px;
cursor: pointer;
margin-right: 5px;
}
.custom-button:hover {
background-color: $text-color;
color: white;
}
.custom-button-active {
cursor: unset;
background-color: $text-color;
color: white;
}
@media (max-width: $min-tablet) {
.custom-button {
font-size: large;
}
}
</style>

BIN
static/AWS_DEV.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 56 KiB

View File

@@ -1,18 +0,0 @@
{
"year": {
"start": "2022-05-15",
"end": ""
},
"title": {
"en": "blog",
"it": "Il blog"
},
"content": {
"en": "Articolo di prova in inglese",
"it": "Articolo di prova in italiano."
},
"collaborators": [],
"languages": [],
"tecnologies": [],
"images": []
}

BIN
static/corley.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 88 KiB

BIN
static/cplusplus.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.2 KiB

After

Width:  |  Height:  |  Size: 334 KiB

17
static/qt_logo.svg Normal file
View File

@@ -0,0 +1,17 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" version="1.1" viewBox="0 0 32 32">
<path
d="m5.0909092 5.0000001h24.48052s1.428571 0 1.428571 1.4117646v18.352941l-4.090909 4.235294h-24.480519s-1.4285715 0-1.4285715-1.411765v-18.352941z"
style="opacity:.2" />
<path
d="m5.0909092 4.0000001h24.48052s1.428571 0 1.428571 1.4117646v18.352941l-4.090909 4.235294h-24.480519s-1.4285715 0-1.4285715-1.411765v-18.352941z"
style="fill:#00cc5c" />
<path
d="m 20,10 v 3 h -2 v 2 h 2 v 4.117188 C 20,21.940717 20.999201,23 22.792969,23 H 25 V 21 H 23.015625 C 22.050838,21 22,20.329735 22,18.917969 V 15 h 3 v -2 h -3 v -3 z m -7.974609,0.02148 C 8.0549478,10.021484 7,12.264706 7,16.5 c 0,4.235294 1.0363906,6.527344 5.025391,6.527344 h 1.132812 l 1.650391,2.822265 1.912109,-0.705078 -1.558594,-2.824219 C 16.646387,21.61443 17,19.323529 17,16.5 17,12.264706 15.995834,10.021484 12.025391,10.021484 Z M 12.007812,12 C 14.429818,12 15.000006,13.75699 15,16.654297 15,19.551603 14.44817,21 12.007812,21 9.5674558,21 9,19.551603 9,16.654297 9,13.75699 9.5858083,12 12.007812,12 Z"
style="opacity:.2" />
<path
d="m20 9v3h-2v2h2v4.117188c0 2.823529 0.999201 3.882812 2.792969 3.882812h2.207031v-2h-1.984375c-0.964787 0-1.015625-0.670265-1.015625-2.082031v-3.917969h3v-2h-3v-3h-2zm-7.974609 0.0214844c-3.9704432 0-5.025391 2.2432216-5.025391 6.4785156s1.0363906 6.527344 5.025391 6.527344h1.132812l1.650391 2.822265 1.912109-0.705078-1.558594-2.824219c1.484278-0.705882 1.837891-2.996783 1.837891-5.820312 0-4.235294-1.004166-6.4785156-4.974609-6.4785156zm-0.017579 1.9785156c2.422006 0 2.992194 1.75699 2.992188 4.654297 0 2.897306-0.55183 4.345703-2.992188 4.345703-2.4403562 0-3.007812-1.448397-3.007812-4.345703 0-2.897307 0.5858083-4.654297 3.007812-4.654297z"
style="fill:#ffffff" />
<path
d="m5.0917969 4-4.0917969 4.234375v1l4.0917969-4.234375h24.480469s1.427734 3.448e-4 1.427734 1.4121094v-1c0-1.4117646-1.427734-1.4121094-1.427734-1.4121094h-24.480469z"
style="fill:#ffffff;opacity:.2" />
</svg>

After

Width:  |  Height:  |  Size: 2.0 KiB

8
static/rust-logo.svg Normal file
View File

@@ -0,0 +1,8 @@
<svg height="144" width="144" xmlns="http://www.w3.org/2000/svg">
<path
d="m71.05 23.68c-26.06 0-47.27 21.22-47.27 47.27s21.22 47.27 47.27 47.27 47.27-21.22 47.27-47.27-21.22-47.27-47.27-47.27zm-.07 4.2a3.1 3.11 0 0 1 3.02 3.11 3.11 3.11 0 0 1 -6.22 0 3.11 3.11 0 0 1 3.2-3.11zm7.12 5.12a38.27 38.27 0 0 1 26.2 18.66l-3.67 8.28c-.63 1.43.02 3.11 1.44 3.75l7.06 3.13a38.27 38.27 0 0 1 .08 6.64h-3.93c-.39 0-.55.26-.55.64v1.8c0 4.24-2.39 5.17-4.49 5.4-2 .23-4.21-.84-4.49-2.06-1.18-6.63-3.14-8.04-6.24-10.49 3.85-2.44 7.85-6.05 7.85-10.87 0-5.21-3.57-8.49-6-10.1-3.42-2.25-7.2-2.7-8.22-2.7h-40.6a38.27 38.27 0 0 1 21.41-12.08l4.79 5.02c1.08 1.13 2.87 1.18 4 .09zm-44.2 23.02a3.11 3.11 0 0 1 3.02 3.11 3.11 3.11 0 0 1 -6.22 0 3.11 3.11 0 0 1 3.2-3.11zm74.15.14a3.11 3.11 0 0 1 3.02 3.11 3.11 3.11 0 0 1 -6.22 0 3.11 3.11 0 0 1 3.2-3.11zm-68.29.5h5.42v24.44h-10.94a38.27 38.27 0 0 1 -1.24-14.61l6.7-2.98c1.43-.64 2.08-2.31 1.44-3.74zm22.62.26h12.91c.67 0 4.71.77 4.71 3.8 0 2.51-3.1 3.41-5.65 3.41h-11.98zm0 17.56h9.89c.9 0 4.83.26 6.08 5.28.39 1.54 1.26 6.56 1.85 8.17.59 1.8 2.98 5.4 5.53 5.4h16.14a38.27 38.27 0 0 1 -3.54 4.1l-6.57-1.41c-1.53-.33-3.04.65-3.37 2.18l-1.56 7.28a38.27 38.27 0 0 1 -31.91-.15l-1.56-7.28c-.33-1.53-1.83-2.51-3.36-2.18l-6.43 1.38a38.27 38.27 0 0 1 -3.32-3.92h31.27c.35 0 .59-.06.59-.39v-11.06c0-.32-.24-.39-.59-.39h-9.15zm-14.43 25.33a3.11 3.11 0 0 1 3.02 3.11 3.11 3.11 0 0 1 -6.22 0 3.11 3.11 0 0 1 3.2-3.11zm46.05.14a3.11 3.11 0 0 1 3.02 3.11 3.11 3.11 0 0 1 -6.22 0 3.11 3.11 0 0 1 3.2-3.11z" />
<path
d="m115.68 70.95a44.63 44.63 0 0 1 -44.63 44.63 44.63 44.63 0 0 1 -44.63-44.63 44.63 44.63 0 0 1 44.63-44.63 44.63 44.63 0 0 1 44.63 44.63zm-.84-4.31 6.96 4.31-6.96 4.31 5.98 5.59-7.66 2.87 4.78 6.65-8.09 1.32 3.4 7.46-8.19-.29 1.88 7.98-7.98-1.88.29 8.19-7.46-3.4-1.32 8.09-6.65-4.78-2.87 7.66-5.59-5.98-4.31 6.96-4.31-6.96-5.59 5.98-2.87-7.66-6.65 4.78-1.32-8.09-7.46 3.4.29-8.19-7.98 1.88 1.88-7.98-8.19.29 3.4-7.46-8.09-1.32 4.78-6.65-7.66-2.87 5.98-5.59-6.96-4.31 6.96-4.31-5.98-5.59 7.66-2.87-4.78-6.65 8.09-1.32-3.4-7.46 8.19.29-1.88-7.98 7.98 1.88-.29-8.19 7.46 3.4 1.32-8.09 6.65 4.78 2.87-7.66 5.59 5.98 4.31-6.96 4.31 6.96 5.59-5.98 2.87 7.66 6.65-4.78 1.32 8.09 7.46-3.4-.29 8.19 7.98-1.88-1.88 7.98 8.19-.29-3.4 7.46 8.09 1.32-4.78 6.65 7.66 2.87z"
fill-rule="evenodd" stroke="#000" stroke-linecap="round" stroke-linejoin="round"
stroke-width="3" />
</svg>

After

Width:  |  Height:  |  Size: 2.4 KiB

1
static/ts-logo-128.svg Normal file
View File

@@ -0,0 +1 @@
<svg fill="none" height="128" viewBox="0 0 128 128" width="128" xmlns="http://www.w3.org/2000/svg"><rect fill="#3178c6" height="128" rx="6" width="128"/><path clip-rule="evenodd" d="m74.2622 99.468v14.026c2.2724 1.168 4.9598 2.045 8.0625 2.629 3.1027.585 6.3728.877 9.8105.877 3.3503 0 6.533-.321 9.5478-.964 3.016-.643 5.659-1.702 7.932-3.178 2.272-1.476 4.071-3.404 5.397-5.786 1.325-2.381 1.988-5.325 1.988-8.8313 0-2.5421-.379-4.7701-1.136-6.6841-.758-1.9139-1.85-3.6159-3.278-5.1062-1.427-1.4902-3.139-2.827-5.134-4.0104-1.996-1.1834-4.246-2.3011-6.752-3.353-1.8352-.7597-3.4812-1.4975-4.9378-2.2134-1.4567-.7159-2.6948-1.4464-3.7144-2.1915-1.0197-.7452-1.8063-1.5341-2.3598-2.3669-.5535-.8327-.8303-1.7751-.8303-2.827 0-.9643.2476-1.8336.7429-2.6079s1.1945-1.4391 2.0976-1.9943c.9031-.5551 2.0101-.9861 3.3211-1.2929 1.311-.3069 2.7676-.4603 4.3699-.4603 1.1658 0 2.3958.0877 3.6928.263 1.296.1753 2.6.4456 3.911.8109 1.311.3652 2.585.8254 3.824 1.3806 1.238.5552 2.381 1.198 3.43 1.9285v-13.1051c-2.127-.8182-4.45-1.4245-6.97-1.819s-5.411-.5917-8.6744-.5917c-3.3211 0-6.4674.3579-9.439 1.0738-2.9715.7159-5.5862 1.8336-7.844 3.353-2.2578 1.5195-4.0422 3.4553-5.3531 5.8075-1.311 2.3522-1.9665 5.1646-1.9665 8.4373 0 4.1785 1.2017 7.7433 3.6052 10.6945 2.4035 2.9513 6.0523 5.4496 10.9466 7.495 1.9228.7889 3.7145 1.5633 5.375 2.323 1.6606.7597 3.0954 1.5486 4.3044 2.3668s2.1628 1.7094 2.8618 2.6736c.7.9643 1.049 2.06 1.049 3.2873 0 .9062-.218 1.7462-.655 2.5202s-1.1 1.446-1.9885 2.016c-.8886.57-1.9956 1.016-3.3212 1.337-1.3255.321-2.8768.482-4.6539.482-3.0299 0-6.0305-.533-9.0021-1.6-2.9715-1.066-5.7245-2.666-8.2591-4.799zm-23.5596-34.9136h18.2974v-11.5544h-51v11.5544h18.2079v51.4456h14.4947z" fill="#fff" fill-rule="evenodd"/></svg>

After

Width:  |  Height:  |  Size: 1.7 KiB

View File

@@ -1,36 +1,25 @@
import preprocess from 'svelte-preprocess';
import adapter from '@sveltejs/adapter-static'; import adapter from '@sveltejs/adapter-static';
import { vitePreprocess } from '@sveltejs/kit/vite';
import {markdown} from 'svelte-preprocess-markdown'; import {markdown} from 'svelte-preprocess-markdown';
import path from 'path'; import preprocess from 'svelte-preprocess';
/** @type {import('@sveltejs/kit').Config} */ /** @type {import('@sveltejs/kit').Config} */
const config = { const config = {
// Consult https://github.com/sveltejs/svelte-preprocess // Consult https://kit.svelte.dev/docs/integrations#preprocessors
// for more information about preprocessors // for more information about preprocessors
preprocess: [preprocess({ preprocess: [vitePreprocess(), markdown(),preprocess({
sass: true, sass: true,
typescript: true, typescript: true,
})],
}), markdown()],
kit: { kit: {
// hydrate the <div id="svelte"> element in src/app.html
target: '#svelte',
vite:{
resolve:{
alias:{
$elem: path.resolve('src/elements'),
// $model: path.resolve('src/model')
}
}
},
hostHeader: 'X-Forwarded-Host',
adapter: adapter({ adapter: adapter({
// default options are shown // default options are shown
pages: 'build', pages: 'build',
assets: 'build', assets: 'build',
fallback: null fallback: null
}), })
} }
}; };

6
tests/test.ts Normal file
View File

@@ -0,0 +1,6 @@
import { expect, test } from '@playwright/test';
test('index page has expected h1', async ({ page }) => {
await page.goto('/');
expect(await page.textContent('h1')).toBe('Welcome to SvelteKit');
});

View File

@@ -0,0 +1,56 @@
<script lang="ts">
import { MetaTags } from 'svelte-meta-tags';
import type { CurrentLanguage } from '$lib/types';
import Data_portfolio from '$lib/model/portfolio.json';
import type { Job } from '$lib/model/job';
import Menu from '$lib/elements/MenuBig.svelte';
import Jobs from '$lib/elements/Jobs.svelte';
import LanguageSelector from '$lib/elements/LanguageSelector.svelte';
let currentLanguage: CurrentLanguage = 'it';
let isBlogContainer = true;
let jobs: Job[] = Data_portfolio as Job[];
let title = { it: 'I miei articoli', en: 'my blog posts' };
</script>
<MetaTags
title="Gianmarco Pettinato"
description="This is the Gianmarco's portfolio site"
canonical="https://pettinato.eu/"
openGraph={{
url: 'https://pettinato.eu/',
title: 'Gianmarco Pettinato',
description: "This is the Gianmarco's portfolio site",
images: [],
site_name: 'Gianmarco Pettinato Portfolio'
}}
twitter={{
handle: '@jatus_93',
site: '@jatus_93',
cardType: 'summary',
title: 'Gianmarco Pettinato Portfolio',
description: "This is the Gianmarco's portfolio site",
image: 'https://pettinato.eu/profile_pic.webp',
imageAlt: 'Gianmarco Photo'
}}
/>
<main>
<!-- svelte-ignore a11y-invalid-attribute -->
<LanguageSelector bind:currentLanguage />
<Menu {currentLanguage} />
<div id="portfolio" class="default">
<h2>{title.it}</h2>
<Jobs {jobs} {currentLanguage} {isBlogContainer} />
</div>
</main>
<style lang="scss">
@import '../../app.scss';
@media (max-width: $min-tablet) {
.custom-button {
font-size: large;
}
}
</style>

View File

@@ -1,9 +1,10 @@
<script lang="ts"> <script lang="ts">
import { MetaTags } from 'svelte-meta-tags'; import { MetaTags } from 'svelte-meta-tags';
import Menu from '$elem/Menu.svelte'; import Menu from '$lib/elements/MenuBig.svelte';
let currentLanguage: string = 'it'; let currentLanguage: CurrentLanguage = 'it';
import { page } from '$app/stores'; import { page } from '$app/stores';
console.log($page) import type { CurrentLanguage } from '$lib/types';
console.log($page);
</script> </script>
<MetaTags <MetaTags
@@ -66,7 +67,7 @@
</main> </main>
<style lang="scss"> <style lang="scss">
@import '../../app.scss'; @import '../../../app.scss';
.language-selector { .language-selector {
right: 0; right: 0;
height: 30px; height: 30px;
@@ -94,7 +95,7 @@
justify-content: center; justify-content: center;
align-items: center; align-items: center;
padding: 10px; padding: 10px;
border-bottom: solid #999 1px; border-bottom: solid $border-hover-color 1px;
} }
.custom-button { .custom-button {
@@ -109,12 +110,12 @@
} }
.custom-button:hover { .custom-button:hover {
background-color: $text-color; background-color: $text-color;
color: white; color: $basecolor2;
} }
.custom-button-active { .custom-button-active {
cursor: unset; cursor: unset;
background-color: $text-color; background-color: $text-color;
color: white; color: $basecolor2;
} }
@media (max-width: $min-tablet) { @media (max-width: $min-tablet) {
.custom-button { .custom-button {

View File

@@ -1,33 +1,17 @@
{ {
"extends": "./.svelte-kit/tsconfig.json",
"compilerOptions": { "compilerOptions": {
"moduleResolution": "node",
"module": "es2020",
"lib": ["es2020", "DOM"],
"target": "es2019",
/**
svelte-preprocess cannot figure out whether you have a value or a type, so tell TypeScript
to enforce using \`import type\` instead of \`import\` for Types.
*/
"importsNotUsedAsValues": "error",
"isolatedModules": true,
"resolveJsonModule": true,
/**
To have warnings/errors of the Svelte compiler at the correct position,
enable source maps by default.
*/
"sourceMap": true,
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true,
"baseUrl": ".",
"allowJs": true, "allowJs": true,
"checkJs": true, "checkJs": true,
"paths": { "esModuleInterop": true,
"$lib": ["src/lib"], "forceConsistentCasingInFileNames": true,
"$lib/*": ["src/lib/*"], "resolveJsonModule": true,
"$elem/*":["src/elements/*"], "skipLibCheck": true,
"$model/*":["src/model/*"] "sourceMap": true,
} "strict": true
}, }
"include": ["src/**/*.d.ts", "src/**/*.js", "src/**/*.ts", "src/**/*.svelte"] // Path aliases are handled by https://kit.svelte.dev/docs/configuration#alias
//
// If you want to overwrite includes/excludes, make sure to copy over the relevant includes/excludes
// from the referenced tsconfig.json - TypeScript does not merge them in
} }

10
vite.config.ts Normal file
View File

@@ -0,0 +1,10 @@
import { sveltekit } from '@sveltejs/kit/vite';
import type { UserConfig, defineConfig } from 'vite';
const config: UserConfig = {
plugins: [sveltekit()]
};
// config.server = { port: 80, origin: 'pettinato.eu' };
export default config;

11
vite.config.ts.js Normal file
View File

@@ -0,0 +1,11 @@
// vite.config.ts
import { sveltekit } from "@sveltejs/kit/vite";
var config = {
plugins: [sveltekit()]
};
// config.server = { port: 8800, origin: "pettinato.eu" };
var vite_config_default = config;
export {
vite_config_default as default
};
//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsidml0ZS5jb25maWcudHMiXSwKICAic291cmNlc0NvbnRlbnQiOiBbImltcG9ydCB7IHN2ZWx0ZWtpdCB9IGZyb20gJ0BzdmVsdGVqcy9raXQvdml0ZSc7XG5pbXBvcnQgdHlwZSB7IFVzZXJDb25maWcsIGRlZmluZUNvbmZpZyB9IGZyb20gJ3ZpdGUnO1xuXG5jb25zdCBjb25maWc6IFVzZXJDb25maWcgPSB7XG5cdHBsdWdpbnM6IFtzdmVsdGVraXQoKV1cbn07XG5cbmNvbmZpZy5zZXJ2ZXIgPSB7IHBvcnQ6IDgwLCBvcmlnaW46ICdwZXR0aW5hdG8uZXUnIH07XG5cbmV4cG9ydCBkZWZhdWx0IGNvbmZpZztcbiJdLAogICJtYXBwaW5ncyI6ICI7QUFBQTtBQUdBLElBQU0sU0FBcUI7QUFBQSxFQUMxQixTQUFTLENBQUM7QUFBQTtBQUdYLE9BQU8sU0FBUyxFQUFFLE1BQU0sSUFBSSxRQUFRO0FBRXBDLElBQU8sc0JBQVE7IiwKICAibmFtZXMiOiBbXQp9Cg==