Skills · Where & for how long
Skills, by the work they come from.
These are the technologies I’ve used in my professional, freelance and personal work, placed on a timeline of when I used them. Every entry links to the work it came from: the case study, or my CV where there isn’t one.
Over time
– PresentFrontend
Interfaces, styling & 3DJavaScript
5 years
The language of my React and Node.js work at INTRALOT, KIMATICA / POCITYF and Malus Garden, and of my CGWorks work, from a framework-free museum tour to a React and Three.js configurator.
INTRALOTCV (opens in a new tab) – Present
React and Node.js on the operator platform
ES modules and JSX, in the apps and the API
The energy-community app, with Next.js and Express
CGWorksCV (opens in a new tab) –
Vanilla JavaScript for the museum tour, and in the Eberus configurator
React
5 years
My main interface library: the operator platform’s core applications at INTRALOT, the Malus Garden shop and admin, the energy-community app at KIMATICA / POCITYF, and a 3D configurator at CGWorks.
INTRALOTCV (opens in a new tab) – Present
Building and extending the operator platform’s core applications
The shop and the admin, two React 19 apps
The energy-community app’s interface, through Next.js
CGWorksCV (opens in a new tab) –
Fixed bugs in the Eberus 3D configurator
Redux
3 years
State management in the React applications I build and extend at INTRALOT.
INTRALOTCV (opens in a new tab) – Present
State in the platform’s React applications
Tailwind CSS
2 years 2 months
Utility-first styling for the energy-community app at KIMATICA / POCITYF and both Malus Garden apps.
Styled the shop and the admin
Styled the Next.js interface, alongside Sass
Next.js
1 year 10 months
The framework behind the energy-community app at KIMATICA / POCITYF, whose interface and navigation I also redesigned.
Built the energy-community app’s frontend
Sass
1 year 10 months
Styling for the energy-community app at KIMATICA / POCITYF.
Styled the Next.js interface, alongside Tailwind CSS
Accessibility
4 months
Accessibility for the Malus Garden shop and admin, with a published statement of partial WCAG 2.2 AA conformance.
Keyboard checks of the browse-to-checkout flow
i18next
4 months
Translation, with react-i18next, for the bilingual Malus Garden shop and admin.
Greek and English in both apps
React Router
4 months
Client-side routing for the two React apps at Malus Garden.
Routing in the shop and the admin
SEO
4 months
Search and sharing metadata for the Malus Garden shop.
JSON-LD structured data, a sitemap and Open Graph tags
TanStack Query
4 months
Server data, fetched and cached with React Query 5, in the Malus Garden shop and admin.
Data fetching and caching in both apps
Three.js
3 months
3D rendering in the browser for my CGWorks work, on a virtual museum tour and a 3D configurator.
CGWorksCV (opens in a new tab) –
Configured a Matterport-based museum tour and fixed bugs in the Eberus 3D configurator
Backend & Data
APIs, databases & paymentsSQL
5 years
Querying data to debug production issues at INTRALOT, the energy-community app’s database at KIMATICA / POCITYF, hand-written queries and migrations for Malus Garden, and fixes in the Eberus configurator at CGWorks.
INTRALOTCV (opens in a new tab) – Present
Debugging production issues, and scripts that run with a release
Hand-written queries and migrations
Queries against the energy-community app’s PostgreSQL database
CGWorksCV (opens in a new tab) –
Bug fixes in the Eberus 3D configurator
JWT
4 years 9 months
Token-based authentication at INTRALOT, KIMATICA / POCITYF and Malus Garden, where the admin also has bcrypt-hashed passwords and rate-limited login.
INTRALOTCV (opens in a new tab) – Present
Authentication on the operator platform
Admin sessions in httpOnly cookies
Alongside the ecosystem-wide SSO service
Node.js
4 years 9 months
My server-side runtime: the service behind INTRALOT’s platform applications, the energy-community app’s APIs, and the Malus Garden API.
INTRALOT – Present
The service orchestrating the platform’s microservices, and the shipping-document refactor
The shop’s REST API, with Express
Express REST APIs for the energy-community app
Objection.js
4 years 9 months
The ORM in INTRALOT’s Node.js services, and between the KIMATICA / POCITYF services and PostgreSQL.
INTRALOTCV (opens in a new tab) – Present
Data access on the operator platform
Data access for the energy-community app
hapi
3 years
A Node.js framework for services on INTRALOT’s operator platform.
INTRALOTCV (opens in a new tab) – Present
Node.js services on the operator platform
Knex
3 years
SQL query building on INTRALOT’s operator platform; Objection.js builds on it.
INTRALOTCV (opens in a new tab) – Present
Query building in the platform’s Node.js services
MySQL
3 years
A database on INTRALOT’s operator platform.
INTRALOTCV (opens in a new tab) – Present
Data on the operator platform
OAuth 2.0
3 years
Authorization on INTRALOT’s operator platform, and the client-credentials flow the Malus Garden API uses to call BoxNow.
INTRALOTCV (opens in a new tab) – Present
Authorization on the operator platform
Client credentials for the BoxNow API
Shipping APIs
3 years
Carrier integrations at INTRALOT, and BoxNow parcel lockers for the Malus Garden shop.
INTRALOTCV (opens in a new tab) – Present
UPS, USPS and SpeedEx carriers, in the ordering workflows
BoxNow parcel lockers: the map widget at checkout, and a worker that sends parcels, with retries
Express
2 years 2 months
The web framework for the REST APIs at KIMATICA / POCITYF and Malus Garden.
The REST API for the shop and the admin
REST APIs for the energy-community app
PostgreSQL
2 years 2 months
The database for the energy-community app and the Malus Garden shop, where an order is marked paid in the same transaction that deducts its stock.
Transactions, row locks and advisory locks, with additive migrations
The energy-community app’s database
SSO integration
1 year 10 months
Single sign-on for the energy-community app at KIMATICA / POCITYF.
Sign-in through an SSO service shared across the whole ecosystem, with JWT
Content Security Policy
4 months
A CSP for the Malus Garden apps, alongside helmet’s other security headers.
Set for the shop and the admin
Stripe
4 months
Payments for the Malus Garden shop: an order is marked paid only when Stripe’s signed webhook arrives, and refunds carry an idempotency key so a retry can’t refund twice.
Checkout Sessions, signed webhooks and refunds
winston
4 months
Logging for the Malus Garden API, with personal data masked.
API logs, rotated daily
zod
4 months
Request validation for the Malus Garden API.
Validates every API request
GraphQL
3 months
Part of the Eberus 3D configurator stack I fixed bugs in at CGWorks.
CGWorksCV (opens in a new tab) –
Bug fixes in the Eberus 3D configurator
Python
3 months
The language of the UGV Nav control stack: 134 tests passing, clean under mypy --strict and ruff.
UGV Nav – Present
The rover’s control stack, in Python 3.12
Testing & Delivery
Tests, builds & releasesBamboo
3 years
The build server behind INTRALOT’s releases.
INTRALOTCV (opens in a new tab) – Present
Supported builds
Jest
3 years
Automated tests for my work at INTRALOT.
INTRALOTCV (opens in a new tab) – Present
Wrote tests, alongside browser testing
Kibana
3 years
Log search when I investigate a production issue at INTRALOT.
INTRALOTCV (opens in a new tab) – Present
Logs for debugging production issues
Kubernetes
3 years
The platform behind INTRALOT’s DEV and QA environments, which I release to.
INTRALOTCV (opens in a new tab) – Present
Releases to DEV and QA
Docker
2 years 2 months
Packaging and running the energy-community app at KIMATICA / POCITYF, and local development and database tests for Malus Garden.
The local environment, and throwaway PostgreSQL containers for database tests
Ran the app on private servers
axe-core
4 months
Automated accessibility audits of the Malus Garden shop and admin, which fail on a violation of any impact.
0 axe violations against WCAG 2.2 A/AA rules on 20 pages, in Greek and English, at desktop and phone sizes
DigitalOcean
4 months
The cloud provider behind the Malus Garden shop, where production and staging each have their own database.
Production and staging on one Ubuntu droplet
Nginx
4 months
The reverse proxy in front of the Malus Garden apps, redirecting to HTTPS and the bare domain.
Reverse proxy, with Let’s Encrypt TLS
PM2
4 months
Process management for the Malus Garden API, which the release script restarts after backing up and migrating the database.
Runs the API; the release script restarts it
React Testing Library
4 months
Component tests for the Malus Garden shop and admin.
Component tests for both apps, in jsdom
Tooling
Builds & packagesGit
3 years
Version control and pull requests at INTRALOT and for Malus Garden.
INTRALOTCV (opens in a new tab) – Present
Hotfix branches cut from release tags, merged through pull requests
GitHub, with a pull-request workflow
Bash
4 months
The scripts that deploy and look after the Malus Garden server.
Deployment and server scripts
ESLint & Prettier
4 months
Code quality checks for the Malus Garden codebase.
Linting and formatting
pnpm
4 months
Package management for the Malus Garden monorepo, whose apps share UI, hooks, API-client and utility packages.
A monorepo of the two apps and four shared packages
Vite
4 months
The build tool for the two React apps at Malus Garden.
Builds the shop and the admin