I spent 5 months building a production Spring Boot 4 + Angular 19 e-commerce boilerplate — so you don't have to
I'm a self-taught developer from Sri Lanka. No bootcamp, no CS degree — just months of building, breaking things, and figuring it out.
Over the last 5 months I built KICKNOIR — a complete, production-ready full-stack e-commerce boilerplate. Not a tutorial project. Not a mockup. A real app, live in production, battle-tested, with real Stripe payments going through it.
🔴 Live demo: kicknoir.vercel.app
(Test card: 4242 4242 4242 4242 · any future date · any CVC)
I'm now selling it as a developer boilerplate for $59 on Gumroad. Here's exactly what's in it and why I built it the way I did.
The Stack
Backend: Java 22 + Spring Boot 4 + Spring Security + JWT
Frontend: Angular 19 (Standalone Components) + TailwindCSS 4
Database: PostgreSQL 17 on Neon
Payments: Stripe Hosted Checkout + Webhooks
DevOps: Docker Compose + GitHub Actions CI/CD
Deploy: Render (backend) + Vercel (frontend)
What's actually included
This isn't just source code dropped in a ZIP. Every layer is documented and wired up end-to-end:
- JWT Authentication + RBAC — register, login, token refresh, two roles (ADMIN / CUSTOMER), enforced on both Spring Security and Angular route guards
-
Stripe Hosted Checkout — real payments, not mocked. Webhook-driven order confirmation, inventory reduction, and cart clearing on
payment_intent.succeeded - Full Admin Panel — dashboard with live stats, product CRUD via modal, order status pipeline (PENDING → CONFIRMED → SHIPPED → DELIVERED), customer list
- Product Catalog — search by name, filter by brand and price range, pagination, dedicated product detail pages
- Shopping Cart — powered by Angular Signals, reactive, real-time badge updates, no extra state library needed
- Inventory Management — stock tracking per product, automatic reduction on successful payment, low-stock and out-of-stock status
-
Docker Compose — one command spins up PostgreSQL + Spring Boot + Angular together.
seed.sqlloads 10 sample products and a default admin account automatically -
CI/CD pipelines — GitHub Actions workflows for both repos, auto-deploy to Render and Vercel on push to
main
A problem I had to solve properly: Stripe + async payment state
One of the hardest parts was making the order lifecycle bulletproof.
The naive approach — confirming an order the moment the user hits "pay" — breaks when a user closes their browser mid-checkout, or when a network request fails after Stripe processes the payment but before your backend receives the response.
The correct approach is webhooks. Here's the core of how I handled it in Spring Boot:
@PostMapping("/stripe")
public ResponseEntity<String> handleWebhook(
@RequestBody String payload,
@RequestHeader("Stripe-Signature") String sigHeader
) {
Event event = Webhook.constructEvent(payload, sigHeader, webhookSecret);
if ("payment_intent.succeeded".equals(event.getType())) {
PaymentIntent intent = (PaymentIntent) event.getDataObjectDeserializer()
.getObject().orElseThrow();
// Idempotency check — ignore duplicate events
if (paymentRepository.existsByStripePaymentIntentId(intent.getId())) {
return ResponseEntity.ok("Already processed");
}
orderService.confirmOrder(intent.getId());
inventoryService.reduceStock(intent.getId());
cartService.clearCartForOrder(intent.getId());
}
return ResponseEntity.ok("Received");
}
Key decisions here:
- Idempotency check — Stripe can send the same webhook event more than once. Without the duplicate check, you'd reduce inventory twice.
- Event-driven confirmation — the order only confirms when Stripe tells you the payment succeeded, not when the user clicks a button.
-
Webhook signature validation —
Webhook.constructEvent()verifies the request is genuinely from Stripe, not a spoofed POST.
The frontend state problem: Angular Signals for the cart
The cart was another area where I made a deliberate architectural decision. Most tutorials reach for NgRx or a BehaviorSubject for reactive cart state. I used Angular Signals instead — built into Angular 19, zero extra dependencies.
// cart.service.ts
export class CartService {
private cartItems = signal<CartItem[]>([]);
readonly itemCount = computed(() =>
this.cartItems().reduce((sum, item) => sum + item.quantity, 0)
);
addToCart(item: CartItem) {
this.cartItems.update(items => {
const existing = items.find(i => i.productId === item.productId);
if (existing) {
return items.map(i =>
i.productId === item.productId
? { ...i, quantity: i.quantity + 1 }
: i
);
}
return [...items, item];
});
}
}
The navbar badge reads itemCount directly — it updates instantly, no subscription management, no memory leaks to worry about.
Docker: full stack in one command
One of the things I'm most happy with is the Docker setup. A lot of projects ship a docker-compose.yml that's half-working or requires you to manually set up the database. This one works out of the box:
git clone https://github.com/BuddheemaRyan/KICKNOIR_Backend
git clone https://github.com/BuddheemaRyan/KICKNOIR-frontend
cd KICKNOIR_Backend
# Add your env vars to docker-compose.yml (see DOCKER.md)
docker-compose up --build
That's it. PostgreSQL starts, seed data loads automatically, Spring Boot connects, Angular builds and serves via Nginx. Visit http://localhost:4200.
The Dockerfiles use multi-stage builds — Alpine-based JRE for the backend, Nginx for the Angular frontend — so image sizes stay minimal.
What you get for $59
- Full source code — frontend and backend repos
- All Docker, CI/CD, and deployment configs
-
application-example.yml— clean environment variable reference -
DOCKER.md— step-by-step local setup guide - Full API endpoint documentation
- Database schema (auto-managed by Hibernate — no manual migrations)
- Support: installation help, environment setup, deployment guidance
The codebase is modular. Adding a new product category, a new payment currency, or a new admin module doesn't require fighting the architecture — it's built to be extended.
Who is this for?
- A developer who wants to launch an online store without building auth, payments, admin, and DevOps from scratch
- A freelancer who wants a solid client project starter
- Someone learning Spring Boot + Angular who wants to study a production codebase instead of a tutorial
- A developer who wants to rebrand and resell — the brand name lives in environment config, not hardcoded everywhere
Get it
Live demo at kicknoir.vercel.app — test the full checkout flow before you buy.
Questions? Drop them in the comments — happy to answer anything technical.
Top comments (0)