Ecommerce Template
Next.js·React 등으로 만든 최신 전자상거래 템플릿
개인 계정의 공개 저장소 소유자는 GitHub로 로그인해 운영자를 확인하고 소개를 직접 관리할 수 있습니다. 관리자 승인은 필요하지 않습니다.
로그인한 뒤 확인 파일을 만들어 이 저장소의 기본 브랜치에 30분 안에 커밋해 주세요. 다른 브랜치나 포크의 파일은 인정하지 않습니다. 파일을 올린 뒤 아래에서 확인하면 관리자 승인 없이 관리할 수 있습니다. 자격을 유지하려면 파일을 남겨 두세요.
로그인이 필요하면 로그인 화면으로 이동합니다. 로그인 후 이곳으로 돌아와 원하는 확인 버튼을 다시 눌러 주세요.
프로젝트 폴더에서 /nomorevibe verify를 실행하면 소유권을 확인하고 소개를 직접 관리할 수 있습니다.
1분 만에 확인하기README 전체를 불러오는 중입니다. 아래는 저장된 발췌입니다.
An offline-first product catalog — built once in Kotlin, shipped to Android, iOS & Web. ⬇️ Download the Android APK · Releases · Architecture · Build & runREADME 전문 보기 ↗
⬇️ Download the Android APK · Releases · Architecture · Build & run
Kaleido starts from the classic "Product Catalog" brief — list the Fake Store API
products, open a detail screen — and takes it as far as the data allows: one Compose
Multiplatform codebase, a real offline-first data layer, and a set of features the
API's price / rating fields quietly make possible (value scoring, side‑by‑side
compare, category analytics), wrapped in a quick‑commerce UI that runs identically on
a phone, a tablet and a desktop browser.
| Platform | Entry point | Status |
|---|---|---|
| Android | composeApp/src/androidMain → MainActivity | ✅ Download APK · minSdk 24 |
| iOS | iosApp/ (SwiftUI shell) + KaleidoKit.framework | ✅ framework builds — open iosApp/iosApp.xcodeproj in Xcode |
| Web | composeApp/src/wasmJsMain (Kotlin/Wasm + Skia) | ✅ prebuilt in web/ — deploy to Vercel |
The APK is a debug build signed with the standard Android debug key. Enable Install unknown apps for your browser or file manager to sideload it.
| 🔌 Offline‑first | The last good catalog is persisted locally and shown instantly on a cold start. A failed refresh keeps the cached data on screen and flips a visible "showing your saved copy" banner instead of erroring. |
| 🛒 Wishlist · Cart · Compare | Favourite anything, adjust cart quantities, compare 2–3 products side by side. All on‑device — survives process death and airplane mode, no account, no backend. |
| ⚡ Quick‑commerce UI | ADD button on every card that morphs into an inline − qty + stepper; a sticky View cart bar; a 2‑row category tile grid; "Deals of the day" rail; pull‑to‑refresh; an "Added to cart · VIEW CART" snackbar; a sort bottom sheet; grid items animate on reorder and press. |
| 💎 Deal Score & "For You" | An explainable 0–100 value metric per product — rewards a good rating (shrunk toward the mean when reviews are thin) and punishes a high price. Drives the badges, the default sort, and a diverse per‑category "For You" rail. |
| 📊 Category insights | Average price & rating, price ranges, a rating histogram and a per‑category "best value" — charts drawn in Compose. |
| 📐 Responsive scaling | A cross‑platform sdp / ssp system (see below) so every dimension and font size scales cleanly from a small phone to a desktop browser. |
MVVM · unidirectional state · clean‑ish layering. Every screen exposes a single
StateFlow<XxxUiState> from a multiplatform ViewModel and renders it with
collectAsStateWithLifecycle. The domain layer is plain Kotlin — no Compose, no Ktor,
no platform types — and is where the interesting logic lives, which is why it's the part
that's unit‑tested.
flowchart LR
subgraph UI["ui · Compose Multiplatform"]
S[Screens] --> VM[ViewModels]
end
subgraph DOMAIN["domain · pure Kotlin"]
M[Models + Engines<br/>DealScore · CatalogEngine · InsightsEngine]
R[[CatalogRepository]]
end
subgraph DATA["data"]
IMPL[CatalogRepositoryImpl<br/>cache-then-network]
API[FakeStoreApi<br/>Ktor 3]
CACHE[CatalogCache + ShelfStore]
KV[(KeyValueStore<br/>SharedPreferences / NSUserDefaults / localStorage)]
end
VM --> M
VM --> R
IMPL -. implements .-> R
IMPL --> API
IMPL --> CACHE
CACHE --> KV
composeApp/src/commonMain/kotlin/com/kaleido/app/
├─ domain/ pure Kotlin — no Compose / Ktor / platform types
│ ├─ Product.kt model + dealScore() + synthetic MRP/discount
│ ├─ Catalog.kt CatalogEngine: filter / sort / "for you"
│ ├─ Insights.kt InsightsEngine: category aggregates, histograms
│ ├─ Cart.kt CartSummary totals
│ └─ CatalogRepository.kt interface + DataStatus
│
├─ data/
│ ├─ remote/ Ktor client + hand-rolled JSON mapping for the Fake Store API
│ ├─ local/ KeyValueStore (interface) + CatalogCache + ShelfStore
│ └─ CatalogRepositoryImpl.kt cache-then-network, status tracking
│
├─ di/ Koin modules (expect/actual platformModule per target)
│
└─ ui/
├─ theme/ Kaleido colour system + commerce tokens + Scale.kt (sdp/ssp)
├─ components/ ProductCard, AddButton, RatingChip, PriceRow, charts, states
├─ catalog/ detail/ store/ compare/ insights/ screen + ViewModel per feature
└─ nav/ string route table
Dependency rule: ui → domain ← data. domain depends on nothing platform‑specific.
DI is Koin, with an expect val platformModule supplying the HTTP engine
(OkHttp / Darwin / JS) and the key‑value store per platform.
The Android‑only com.intuit.sdp / com.intuit.ssp
libraries are XML‑dimen resources — they don't exist for iOS or Web.
ui/theme/Scale.kt
reimplements the idea for Compose Multiplatform:
12.sdp / 13.ssp read like the sdp/ssp API but resolve identically
on phone, tablet and desktop web.On wide screens the primary content column is also centred and width‑capped, like every real store's web layout.
| Area | Choice |
|---|---|
| Language | Kotlin 2.4.10 · coroutines / Flow |
| UI | Compose Multiplatform 1.11 (Material 3) · Navigation Compose |
| Networking | Ktor 3 client · kotlinx.serialization JSON‑tree parsing |
| DI | Koin 4 |
| Images | Coil 3 (multiplatform, Ktor fetcher) |
| Persistence | platform key‑value stores behind one interface |
| Build | Gradle 9 · AGP 9 · version catalog |
| Tests | kotlin-test · kotlinx-coroutines-test · Turbine · Ktor MockEngine |
# Android — APK or straight onto a device / emulator
./gradlew :composeApp:assembleDebug
./gradlew :composeApp:installDebug
# Web — static bundle in composeApp/build/dist/wasmJs/productionExecutable
./gradlew :composeApp:wasmJsBrowserDistribution
./gradlew :composeApp:wasmJsBrowserDevelopmentRun # live dev server on :8080
# iOS — build the shared framework, then open the Xcode project
./gradlew :composeApp:linkDebugFrameworkIosSimulatorArm64
open iosApp/iosApp.xcodeproj # pick a simulator and Run
# Tests — domain, repository, stores, DI graph (32 tests)
./gradlew :composeApp:testDebugUnitTest
The Fake Store API needs no key.
NSAppTransportSecurityis relaxed in the iOSInfo.plistbecause the API is plain HTTP‑friendly.
The Kotlin/Wasm build is committed prebuilt to web/, so Vercel serves it
with no build step.
Live demo: add your
*.vercel.appURL here after the first deploy
chinmay-tayade/Kaleido)vercel.json — Output Directory web, no build command,
.wasm MIME + cache headers already set. Just click Deploy.main redeploys.Refresh the bundle after changing app code:
./scripts/build-web.sh # rebuilds web/ from source
git commit -am "rebuild web" && git push
The Build web bundle GitHub Action (.github/workflows/web.yml)
also does this automatically whenever composeApp/src/** changes.
commonTest covers the parts that carry logic:
DealScoreTest — monotonicity (cheaper ⇒ higher, better‑rated ⇒ higher, more reviews ⇒ higher) and boundsCatalogEngineTest — search, category filter, every sort mode, "For You" diversityCartAndInsightsTest — cart totals & smart‑basket savings, category aggregates, histogram coverageCatalogRepositoryTest — warm‑start emits cache before any network call; refresh success ⇒ Live; refresh failure keeps cache ⇒ Offline (Ktor MockEngine)ProductPricingTest — synthetic MRP / discount % is deterministic, in range, and always above the sale priceShelfStoreTest — wishlist / cart / compare persistence round‑tripsDiGraphTest — every Koin definition resolves@Serializable is avoided in shared code — the kotlinx.serialization compiler
plugin currently crashes on the Kotlin/Wasm target, so DTOs are mapped by hand from the
JSON tree and navigation uses string routes. Small cost, keeps Web alive.iosArm64 + iosSimulatorArm64) — Compose Multiplatform
no longer publishes iosX64.web/ + vercel.json)Built with Compose Multiplatform · Report an issue