Privacy Policy v2.2 — SkillMap
Effective date: 2026-04-30
Supersedes: v2.1 (2026-04-29)
1. Who we are
SkillMap is a personal skill tracking and career development platform. This privacy policy explains how we collect, use, and protect your personal data in compliance with the EU General Data Protection Regulation (GDPR).
This is version 2.2. It documents the Projects feature added in this release: what project data we store, how it is used, and how it interacts with public portfolios. No new third-party data sharing was introduced; this is a documentation update.
2. What data we collect
2.1 Account data (collected at registration)
- First name, last name, middle name (optional)
- Email address
- Password (transmitted only over HTTPS; never stored in plaintext. Password hashes are stored using bcrypt — see Section 5)
2.2 Profile data (optional, editable any time)
- Display name, location, current role
- Headline (short tagline)
- About text (longer markdown-formatted bio)
- Phone number
- Public email address (separate from account email)
- Website URL
- LinkedIn URL
- GitHub URL
- Availability status (open / open to offers / not looking / freelance)
- Profile photo (planned; placeholder uses initials)
These fields are stored only when you choose to fill them in.
2.3 Skill, tool, and learning data
- Skill states (learning, self-assessed, tested, certified)
- Tool usage states
- Test scores and history (per question + per attempt)
- Sub-skill progress
2.4 Certificate data
- Uploaded certificate files are processed to extract metadata, then the original file is deleted from our servers
- Stored after deletion: course name, provider, issue date, parsed text excerpt, name extracted from the certificate, verification status, confidence score, and the linked skills you assigned
2.5 Portfolio data
- Each portfolio you create stores: a unique slug, snapshot of your data at creation time, visibility settings, label, optional private note, optional password hash (bcrypt), expiry date, view count, last viewed timestamp
- Portfolios are immutable after creation: snapshot and visibility cannot be edited, only label and note. To change content, create a new portfolio.
2.6 Job analysis data
- Saved "dream job" skill requirements (skill IDs only)
- For analyses you save publicly: anonymized aggregate is stored in our postings database (see Section 3.6)
2.7 Project data (optional)
For each project you add to your profile, we store:
- Title and short description
- Status (one of: in progress, shipped, maintained, archived, learning project)
- Your role (e.g. "Backend developer") and your contribution (free-text description of what you did)
- Linked skills and tools — references to existing skill / tool IDs in your own profile
- Project URL and repository URL (optional; for example a GitHub link, a personal domain, or a public deploy URL)
- Start date, end date, and an "is currently active" flag
- Portfolio visibility flag — whether the project may be included in future public portfolios
You can add up to 50 projects per account. Projects are stored only when you choose to add them, and you can edit or delete any project at any time from the Profile → Projects tab. Deleted projects are removed from your active profile data. Projects already captured in existing portfolio snapshots remain there until those portfolios are deleted (see Section 3.7 on snapshot immutability).
Note about URLs: project URLs you provide may identify you (for example, a GitHub username embedded in a repo URL, or a personal domain). Provide only what you are comfortable making public — projects with the portfolio visibility flag enabled will appear in any portfolio you publish thereafter.
2.8 Activity data
- Timestamps of skill state changes, test attempts, certificate additions
- Login timestamps and counters (failed login attempt count, lockout state)
2.9 Consent records
- Timestamp, consent type, policy version accepted, content hash of the policy at time of acceptance, hashed IP address (see Section 5)
2.10 What we DO NOT collect
- Browsing history outside SkillMap
- Device fingerprints
- Tracking cookies
- Behavioral analytics
- Geographic location data
- Data from third-party sources
- Any data inside your job posting AI requests beyond what you submit
3. How we use your data
3.1 Account management
Your email and password are used for registration, authentication (via JWT tokens, HS256-signed), email verification, password reset, and to send transactional emails (verification, password reset, account deletion notices) via Resend.
3.2 Skill tracking
Your skill states, tool states, and test history are stored to display your personal skill map and track your learning progress over time. Profile data syncs across devices via versioned profile state.
3.3 Skill testing
When you take a skill test, the questions, your answers, and scores are recorded. Questions are fetched from our internal question bank. Answers are stored to calculate scores and avoid showing you the same question twice. No answer data is sent to third parties.
3.4 Certificate verification
When you upload a certificate (PDF or image):
- We extract text via OCR (for images) or PDF text extraction
- We parse for: course name, provider, issue date, and the certificate holder's name
- We compare the extracted name against your profile name using normalized text matching (case-insensitive, diacritics-insensitive, name order variants) and fuzzy matching (Levenshtein distance)
- Verification result and confidence score are stored
- The original certificate file is then deleted from our servers. Only the extracted metadata remains, accessible only by you
- For skill identification, we send only the extracted course name and provider to our AI service. No personal data, no name, no email, no certificate file content is sent.
3.5 Job analysis
When you paste a job posting in the Job Analyzer:
- The text is sent to our backend API, which forwards it to Mistral AI for skill extraction
- Our server holds a single shared API key for Mistral; you do not provide your own
- The request from our server contains only the job posting text and a parsing prompt — no user identification, no profile data
- Per-user rate limits apply (currently 30 analyses per day) to prevent abuse
- Mistral returns extracted skill names; we match them against our skill tree and display them on your map
Important: Do not paste personal information into the Job Analyzer. While we don't store the raw text long-term beyond a 500-character preview (Section 3.6), the text is transmitted to Mistral AI for processing. Don't paste your own CV, names, contact details, or anything you don't want sent to a third-party AI provider.
If you save the analysis as a "dream job", only matched skill IDs are stored in your profile.
3.6 Aggregated job postings database
Independent of your profile, we maintain an anonymized job postings database used for industry skill trend analytics shown to all users:
- Source 1: When you analyze and save a job posting, we store an anonymized record: company name, position title, location, seniority, salary range (if mentioned), required and nice-to-have skills, the first 500 characters of the posting text as a duplicate-detection preview, and source type "analyzer"
- Source 2: A one-time import of public job postings from LinkedIn job search results (imported on 2026-04-13, 405 records, source type "scrape"). This is a static dataset; no further automatic scraping is currently active
This database contains no link to your account. Records are not personal data; we cannot trace a saved analysis back to a specific user.
Legal basis: GDPR Art. 6(1)(f) — legitimate interest in providing skill trend analytics.
3.7 Public portfolios
You may create one or more shareable public portfolios:
- Each portfolio has a unique URL (e.g., myskillmap.app/cv/Ab12CdEfGhIj3kL4)
- It contains an immutable snapshot of your data at creation time
- It has visibility settings you choose: which sections, which identity fields, which contact details, and which skill states are visible
- It has an optional expiry date after which the URL stops working (the portfolio enters a "tombstone" state — the public link becomes invalid, but your label, note, and view stats are kept for your reference)
- It can be public, password-protected (bcrypt-hashed password), or private (link inactive)
By creating a portfolio that includes contact information (phone, email, website, LinkedIn, GitHub, availability) you are explicitly consenting to make this data publicly accessible to anyone with the URL. You are responsible for who you share the URL with.
Search engines and AI crawlers: When a portfolio is set to "Public", its URL becomes accessible not only to anyone you share the link with, but also to web crawlers — including search engines (such as Googlebot and Bingbot) and AI-related crawlers and agents (such as GPTBot, ClaudeBot, ChatGPT-User, and others). The content of a public portfolio may be indexed, cached, summarized, or otherwise processed by third-party crawlers according to their own policies. You can switch a portfolio back to private (or password-protected, or delete it) at any time, but cached and indexed copies held by third parties may persist for weeks or months and are outside our control.
Password-protected portfolios: When you set a password on a portfolio, the password is stored as a bcrypt hash on our server (never in plaintext). Password protection is access control, not end-to-end encryption: the portfolio snapshot is stored unencrypted on our server and is served after password verification. Treat password protection as a barrier against casual viewers, not as a confidentiality guarantee.
What we track per portfolio: view count and timestamp of the most recent view.
What we DO NOT track per portfolio: IP addresses of viewers, geographic location, browser fingerprints, identity of viewers. There is no per-view log.
You can delete a portfolio at any time. Deletion immediately invalidates the public URL; private metadata (label, note, view stats) is kept for your reference until you delete your account.
3.8 AI processing summary
We use AI services for two specific purposes:
- Job posting skill extraction — text is sent from our backend to Mistral AI using a server-held API key. Per-user rate limit: 30 calls per day.
- Certificate skill identification — only the extracted course name and provider are sent to AI for skill mapping. No personal data, no certificate file, no user identifiers.
AI providers used:
- Mistral AI (mistral.ai) — receives job posting text and certificate metadata. EU-based provider.
Note: Earlier policy versions mentioned Anthropic Claude. We are not currently using Claude for any feature.
3.9 Project tracking and portfolio inclusion
Projects you add to your profile are stored to display them on the Profile → Projects tab and to optionally include them in public portfolios. Inclusion is controlled in two layers:
- Per-project visibility flag — set on each project. A project with this flag off will never appear in any portfolio, regardless of portfolio settings.
- Per-portfolio visibility settings — when you create a portfolio (Section 3.7), you decide whether the Projects section appears.
When a project is shown on a public portfolio, the title, description, role, contribution, status, dates, URLs, and the labels of linked skills / tools become visible to anyone with the portfolio link, subject to that portfolio's privacy mode (private / password / public). For password-protected portfolios, this content is visible to anyone who has the link AND knows the password (see Section 3.7 for what password protection does and does not provide).
Project data is not sent to any third-party service. It is not used for analytics or for training of any AI model.
Snapshots are immutable (see Section 3.7). If you turn a project's visibility off in your Profile, or delete the project, this only affects portfolios you create afterwards. Portfolios that already captured the project in their snapshot will continue to display it until you delete those portfolios.
4. Legal basis
We process your data based on GDPR Article 6(1)(a) — your explicit consent, given at registration via two mandatory checkboxes:
- Agreement to this privacy policy
- Consent to processing personal data for account management, certificate verification, and (when you create a public portfolio) for sharing with recipients of your portfolio URL
Aggregated postings database (Section 3.6) is processed under GDPR Article 6(1)(f) — legitimate interest in providing skill trend analytics. This data contains no personal identifiers linkable to you.
We retain anonymized consent records after account deletion based on GDPR Article 6(1)(c) — legal obligation to demonstrate that valid consent was obtained.
5. Data storage and security
- Server location: Hetzner, Germany (EU jurisdiction)
- Edge / CDN: Cloudflare acts as our CDN and edge proxy in front of the application. It processes request metadata and proxied traffic as needed to provide caching, DDoS protection, and security features. Their privacy policy is at https://www.cloudflare.com/privacypolicy/ — see also Section 6.
- Passwords: hashed with bcrypt (12 rounds). Old SHA-256 hashes from earlier versions are auto-migrated to bcrypt on next login.
- Sessions: JWT access tokens (HS256, ~24-hour expiration), refresh tokens (~7-day expiration). Both are stored in your browser's localStorage.
- Token revocation: revoked JWTs are tracked server-side until their natural expiration.
- Certificate files: deleted from our servers after metadata extraction. Only metadata persists in the database.
- Portfolio passwords: stored as bcrypt hashes, never in plaintext. The portfolio snapshot itself is stored unencrypted server-side; password protection gates access but is not end-to-end encryption (see Section 3.7).
- Login protection: account locks for 15 minutes after 5 failed login attempts.
- Email tokens: single-use, 24-hour expiration, stored as SHA-256 hash (raw token only in the email).
- Rate limits: verification/reset emails (max 3 per 12 hours), quiz questions (max 30 per minute), job analyses (max 30 per day per user).
- Server access logs: Nginx logs HTTP request metadata (URL, status code, user-agent, source IP) and rotates daily; logs older than 14 days are deleted. Source IPs are typically Cloudflare proxy IPs, not raw user IPs.
- Consent records: IP address stored as SHA-256 hash (not raw IP), user ID anonymized after account deletion.
- Internal admin task tracker: logs admin actions with hashed IP addresses (SHA-256) and timestamps for security audit. Admin-only, not user data.
6. Data sharing
We do NOT sell, rent, or share your personal data with any third party for marketing or advertising purposes.
Services that process data on our behalf (sub-processors):
- Resend (resend.com) — transactional email delivery. Receives only your email address and the email body (verification link, password reset link, deletion notice). Privacy policy: https://resend.com/legal/privacy-policy
- Hetzner (hetzner.com) — server hosting in Germany. Infrastructure provider; no application-level access to your data.
- Cloudflare (cloudflare.com) — CDN and edge proxy. US-based provider, GDPR-compliant via Standard Contractual Clauses (SCCs). Cloudflare terminates TLS at the edge, sees the unencrypted HTTPS request between user and origin, may temporarily cache static assets and HTML, and logs source IP addresses at the edge for DDoS protection. Edge logs are retained according to Cloudflare's own privacy policy (see https://www.cloudflare.com/privacypolicy/).
- Mistral AI (mistral.ai) — receives job posting text and certificate course name + provider for skill extraction. Privacy policy: https://mistral.ai/terms/
We have no advertising networks, no analytics services, no tracking pixels, no social media integrations.
7. Your rights under GDPR
You have the following rights, exercisable at any time:
- Right of access (Art. 15): view all your data in your profile page, or export it
- Right to rectification (Art. 16): edit your profile fields at any time
- Right to erasure (Art. 17): delete your account from the profile page. After a 30-day grace period (during which you can cancel), all personal data is permanently deleted.
- Right to data portability (Art. 20): export your complete profile (skills, certificates, test history) as JSON
- Right to withdraw consent (Art. 7(3)): delete your account at any time, which withdraws all consent
- Right to lodge a complaint: you may file a complaint with your local data protection authority
For shared portfolios: the only way to revoke a portfolio's public access is to delete it from your portfolio dashboard. Anyone who downloaded or screenshotted the portfolio while it was live is outside our control.
8. Data retention
While your account is active, all data is retained.
When you delete your account, after the 30-day grace period:
DELETED:
- Name, email, password hash
- Profile fields (location, role, headline, about, phone, public_email, website, linkedin_url, github_url, availability)
- Skill states, tool states, certificates (metadata only — files were deleted at upload time), test history
- Saved dream job, activity log, sessions, refresh tokens
- All your portfolios (snapshots, passwords, view counts, notes)
- All your projects (titles, descriptions, roles, contributions, linked skill / tool IDs, URLs, dates, visibility flags)
RETAINED (anonymized, for legal compliance):
- Consent records with anonymized user ID (SHA-256 hash), timestamps, policy versions accepted, hashed IP. No personally identifiable information remains.
RETAINED (aggregate, anonymous, never linked to you):
- Skill popularity statistics
- Test difficulty statistics
- Job postings database (Section 3.6)
Server access logs (nginx) are deleted after 14 days regardless of account state.
9. Cookies and local storage
We use only essential storage for authentication and personalization:
- localStorage: JWT access token, refresh token, profile data cache, theme preference
- sessionStorage: transient UI state
We do NOT use: tracking cookies, analytics cookies, third-party cookies, advertising cookies, or any non-essential cookies.
Cloudflare and Hetzner may set their own technical cookies as part of their security/infrastructure features. These are not under our application's control.
10. Children
SkillMap is not directed at children under 16. We do not knowingly collect personal data from children under 16. If we learn that we have collected data from a child under 16, we will delete the account and all associated data promptly.
11. International transfers
Application data is processed and stored within the European Union (Germany).
Sub-processors that may process data outside the EU:
- Cloudflare — global CDN; encrypted traffic may transit non-EU edge nodes. Transient logs only.
- Mistral AI — based in France (EU), but their infrastructure may use non-EU regions for inference. Only job posting text and certificate metadata pass through; no personal identifiers.
- Resend — operates globally but stores email metadata in the US. Only your email address and the email body are sent.
By creating an account, you consent to these transfers under GDPR Art. 49(1)(a).
12. Changes to this policy
When we update this policy:
- We increment the version number (v1.0 → v2.0 → v2.1 → v3.0)
- We update the effective date
- The full text of every version is stored permanently in our database with a cryptographic hash
- If changes are material — including this v2.1 clarification of public portfolio visibility, crawler access, and the limits of password protection — existing users may be asked to review and accept the updated policy on their next login
- Previous versions remain accessible at
/privacy?version=v1.0 - The version and content hash that each user consented to is recorded in their consent record
v2.1 changes summary (compared to v2.0):
- Section 2.1 — clarifies password handling (transmitted over HTTPS; bcrypt hashes stored)
- Section 3.7 — explicit wording that public portfolios are reachable by search engines (such as Googlebot, Bingbot) and AI-related crawlers and agents (such as GPTBot, ClaudeBot, ChatGPT-User); content may be indexed, cached, summarized, or otherwise processed by those third parties according to their own policies; cached/indexed copies may persist after revoke
- Section 3.7 — explicit caveat that portfolio password protection is access control, not end-to-end encryption (snapshot stored unencrypted server-side)
- Section 5 — corrects the Cloudflare entry to drop the inaccurate "no application-level data" wording; replaced with a description aligned with Section 6
- Section 5 — cross-reference on portfolio password storage
- Section 6 — expands Cloudflare entry: US provider, SCCs, TLS termination at edge, edge IP logging for DDoS
- No new data collection. No change to lawful basis. No change to retention. This is a clarification of behaviours that already existed in v2.0.
v2.2 (2026-04-30)
- Section 1 — version line updated to v2.2.
- Section 2 — added §2.7 documenting Project data fields collected when a user adds a project to their profile (title, description, status, role, contribution, linked skills / tools, URLs, dates, visibility flag). Existing §2.7–§2.9 renumbered to §2.8–§2.10.
- Section 3 — added §3.9 describing project tracking and how project visibility on public portfolios is controlled by both a per-project flag and per-portfolio settings; restated immutability of snapshots in this context.
- Section 8 — added projects to the list of data deleted on account deletion (this matched existing behaviour in our deletion worker; the policy was missing the explicit mention).
- No new third-party data sharing. No change to lawful basis or retention. Documents the Projects feature shipped in this release.
13. Contact
For questions about this privacy policy or to exercise your data rights, contact us via the email associated with your SkillMap account.
Privacy Policy v2.2
Effective: 2026-04-30
SkillMap
All policy versions
- v2.2 (2026-04-30) (current)
- v2.1 (2026-04-29)
- v2.0 (2026-04-26)
- v1.0 (2026-04-13)