Language / Idioma: English · Español
Full-stack code snippet manager built with Spring Boot and Angular.
SnippetVault is a code snippet manager. Users can store, organize, search and share code snippets with syntax highlighting. It includes JWT authentication, public and private snippets, tags, collections and a community view that lists public snippets from other users.
- Register and log in with stateless JWT authentication.
- Create, edit, delete and search snippets, with live syntax highlighting.
- Organize snippets with tags and collections.
- Make a snippet public and share it through a unique link.
- Explore public snippets from other users and save your own copy.
- Personal settings: light/dark/system theme, high contrast, accent colour and font size.
- Bilingual interface (English/Spanish) with instant switching.
- Profile with avatar upload, password change and account preferences.
- Export snippets and collections to a file or a ZIP archive.
Backend
- Java 21, Spring Boot 4
- Spring Security with JWT (stateless authentication), BCrypt password hashing
- Spring Data JPA (Hibernate), Specifications for filtering
- PostgreSQL, Maven
Frontend
- Angular 21 (standalone components, signals, zoneless change detection)
- PrimeNG, PrimeFlex, PrimeIcons
- highlight.js (syntax highlighting), JSZip (export)
Tooling
- Docker / Docker Compose (PostgreSQL and SonarQube)
- SonarQube with JaCoCo and Vitest coverage (code-quality analysis)
- GitHub Actions (continuous integration)
- Java 21
- Node.js 20+
- Docker and Docker Compose
Copy the example environment file and set your local values. A single .env
holds the variables used by both Compose files:
cp .env.example .env| Variable | Used by |
|---|---|
POSTGRES_PASSWORD |
development database (docker-compose.yml) |
SONARQUBE_DB_PASSWORD |
SonarQube database (docker-compose.yml) |
SNIPPETVAULT_DB_PASSWORD |
production database and the backend |
SNIPPETVAULT_JWT_SECRET |
backend JWT signing secret (at least 32 characters) |
When running the backend with Maven, the database password and JWT secret are
read from those environment variables. Alternatively you can create
backend/src/main/resources/application-local.properties (gitignored) with:
spring.datasource.password=your_local_password
app.jwt.secret=your_local_jwt_secretdocker compose up -d postgresPostgreSQL is exposed on port 5432. To also run SonarQube locally:
docker compose up -d sonarqube-db sonarqubeSonarQube is then available on port 9000.
cd backend
./mvnw spring-boot:runThe REST API is served at http://localhost:8080/api.
cd frontend
npm install
npm startThe application is served at http://localhost:4200.
The whole stack can be built and run with Docker. The frontend is served by
nginx, which also proxies /api to the backend, so the browser talks to a
single origin:
docker compose -f docker-compose.prod.yml up -d --buildThe application is then available at http://localhost:8080.
The backend is analysed through Maven, with JaCoCo providing coverage:
cd backend
./mvnw clean verify sonar:sonar \
-Dsonar.host.url=http://localhost:9000 \
-Dsonar.projectKey=snippetvault-backend \
-Dsonar.token=your_tokenThe frontend is analysed with the SonarScanner, with Vitest producing the
coverage report, using frontend/sonar-project.properties:
cd frontend
npm test
npx sonarqube-scannerGitHub Actions builds and tests both modules on every push and pull request:
the backend runs ./mvnw verify against a PostgreSQL service, and the frontend
runs the unit tests and a production build.
The frontend stores the JWT in localStorage and sends it as a bearer token.
This keeps the SPA self-contained and is a common pattern, but the token is
readable by JavaScript, so the API must stay free of XSS. The deployed frontend
is served with security headers (including a Content-Security-Policy) as defence
in depth.
snippetvault/
├── backend/ # Spring Boot API (Maven)
│ └── pom.xml # build + SonarQube/JaCoCo configuration
├── frontend/ # Angular application
│ └── sonar-project.properties
├── docker-compose.yml # local PostgreSQL + SonarQube
├── docker-compose.prod.yml # production stack (db + backend + nginx)
├── .env.example
└── README.md