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)
TL;DR: If you just want to skip the 5 months — it's available as a developer boilerplate for $59 → grab it on Gumroad. Keep reading for the full technical breakdown.
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.
Who is this for?
Does any of these sound like you?
- You want to launch an online store without spending months building auth, payments, admin, and DevOps from scratch
- You're a freelancer who wants a solid, battle-tested client project starter
- You're learning Spring Boot + Angular and want to study a real production codebase, not another tutorial
- You want to rebrand and resell — the brand name lives in environment config, not hardcoded everywhere
If that's you, this is built exactly for you → $59 on Gumroad
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)
- Direct email support — if you hit a wall getting it running, I'll help you through it personally
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.
Get it
Five months of architecture decisions, debugging, and production fixes — packaged so you can skip straight to building your actual product.
Test the full checkout flow first at kicknoir.vercel.app before you buy. Questions? Drop them in the comments — happy to answer anything technical.













