Saleor Store
우리 컬렉션을 쇼핑하세요
신뢰받는 TrustClub 네트워크 기반 지역 광고·판매·서비스 중개, 직접 구매자와 대화
Classifieds para sa bayan mo, naka-ranggo ayon sa pinagkakatiwalaan na ng TrustClub network mo. Magbenta, magparenta o mag-alok ng serbisyo — tapos usap kayo mismo ng buyer.
커머스TypeScript · CSSGitHub @TrustClubHQ온라인운영자 미확인
써 보셨어요? 한 번만 눌러 주세요. 로그인은 필요 없어요.
아직 감지된 업데이트가 없습니다. GitHub 릴리스가 나오면 여기에 보입니다.
개인 계정의 공개 저장소 소유자는 GitHub로 로그인해 운영자를 확인하고 소개를 직접 관리할 수 있습니다. 관리자 승인은 필요하지 않습니다.
로그인한 뒤 확인 파일을 만들어 이 저장소의 기본 브랜치에 30분 안에 커밋해 주세요. 다른 브랜치나 포크의 파일은 인정하지 않습니다. 파일을 올린 뒤 아래에서 확인하면 관리자 승인 없이 관리할 수 있습니다. 자격을 유지하려면 파일을 남겨 두세요.
로그인이 필요하면 로그인 화면으로 이동합니다. 로그인 후 이곳으로 돌아와 원하는 확인 버튼을 다시 눌러 주세요.
프로젝트 폴더에서 /nomorevibe verify를 실행하면 소유권을 확인하고 소개를 직접 관리할 수 있습니다.
1분 만에 확인하기README 전체를 불러오는 중입니다. 아래는 저장된 발췌입니다.
A trust-ranked classifieds marketplace for Philippine province users, built on
TrustClub.
Members post things for sale, things for rent, and services they offer. Other
members browse them ranked by their own trust path to the poster, filtered
by category-specific attributes, price and location. There is exactly one call
to action on a listing: contact the seller.
KantoList deliberately does not handle payment, escrow, delivery or messaging.
Its job is discovery and trust signalling; the transaction happens between two
people who now have a reason to trust each other.README 전문 보기 ↗A trust-ranked classifieds marketplace for Philippine province users, built on TrustClub.
Members post things for sale, things for rent, and services they offer. Other members browse them ranked by their own trust path to the poster, filtered by category-specific attributes, price and location. There is exactly one call to action on a listing: contact the seller.
KantoList deliberately does not handle payment, escrow, delivery or messaging. Its job is discovery and trust signalling; the transaction happens between two people who now have a reason to trust each other.
Kanto is the family; KantoList is the goods market. KantoRooms,
KantoServices, KantoFarm and KantoJobs are planned beside it, sharing one
account, one login and one trust lookup. The market switcher in the header is
already wired for them.
cp .env.example .env # fill in DATABASE_URL and AUTH_SECRET at minimum
npm install
npx prisma migrate dev # applies migrations and seeds
npm run dev
Without TrustClub credentials the OIDC login cannot run. For local work set
ALLOW_DEV_LOGIN=true and the sign-in page offers the seeded accounts —
juan.santos has a pre-warmed trust cache, so trust ranking is visible
immediately.
| Command | What it does |
|---|---|
npm run dev | Dev server |
npm run build | prisma generate → migrate deploy → next build |
npm test | Jest unit tests |
npm run lint / npm run typecheck | ESLint / tsc --noEmit |
npm run seed | Re-seed for development (destructive — see below) |
npm run seed:reference | Categories and municipalities only; additive, safe against production |
npm run seed:demo | 77 realistic demo listings across 24 accounts; idempotent, adds only |
| Path | What lives there |
|---|---|
src/lib/trustclub.ts | Trust-chain lookups, cached, with a batched per-viewer call |
src/lib/trustclub-oidc.ts | The OIDC device-authorization wire protocol |
src/lib/search.ts | Search, filtering and the trust ranking pipeline |
src/lib/attributes.ts | The category-attribute engine |
src/lib/listing.ts | Listing rules: codes, slugs, expiry, price units |
src/components/ui.tsx | The signwriter primitives |
src/app/api/* | Route handlers |
Trust points are directed: TrustClub answers "how strongly does A's network vouch for B", not "how trusted is B". There is no global score, so ranking is per viewer and cannot be precomputed into an index column.
searchListings therefore: narrows hard in SQL → takes a bounded candidate
window ordered by recency → resolves trust for that window only, batched and
budgeted → sorts and paginates. The tradeoff: a listing outside the
candidate window cannot be lifted by trust however strong it is. The window is
several pages deep, so this only bites on very broad searches.
Three states are kept distinct everywhere, and a failed lookup is never rendered as a zero:
| State | Meaning | Shown as |
|---|---|---|
| a number | the viewer's network vouches for the poster | green badge, 320 TP · via @juan |
0 | the graph has no path between them | grey "No trust path" |
null | the lookup failed or was never made | grey "Trust unknown" |
The badge reuses TruRate's indirect_trust_incoming / outgoing symbols and
its formatTrustPoints abbreviations, so the number means the same thing to a
member who uses both products.
A leaf category carries an attributeSchema — a JSON array of attribute
definitions. It drives the posting form, the filter rail and the detail table,
and is validated on write. Adding a filter is a seed edit, not a deploy.
{ "key": "displacement_cc", "label": "Engine size", "type": "int",
"unit": "cc", "min": 25, "max": 2000, "filter": "range",
"buckets": [{ "label": "125–155", "min": 125, "max": 155 }] }
Production runs prisma migrate deploy, which applies migration files, not
the live schema. A schema edit without a matching migration means the deployed
client references a column the database never got. Always:
npx prisma migrate dev --name <change_name>
npx prisma migrate diff --from-schema-datasource prisma/schema.prisma \
--to-schema-datamodel prisma/schema.prisma # must print "No difference detected."
Seeding is destructive and refuses to run against a non-localhost
DATABASE_URL unless ALLOW_DESTRUCTIVE_SEED=1 is set.
Filipino vernacular signage — hand-painted jeepney lettering, sari-sari store price boards. Flat enamel fills and hard black outlines survive a cheap LCD in daylight, which is where province users actually shop, better than gradients and soft shadows do.
Cream #FFF4D6 ground, enamel red #C6362B, chrome yellow #F2B01E, jeepney
green #1F6B4A for trust. Square corners; one depth device (4px 4px 0
offset); Anton for display and Barlow Condensed for labels. Yellow carries
black text only. Tokens live in src/app/globals.css; compose
src/components/ui.tsx rather than re-typing the rules.
See docs/DEPLOY.md. In short: create the Postgres first
(the build runs prisma migrate deploy), set DATABASE_URL and AUTH_SECRET,
import the repo in Vercel, then seed the category tree.
phoneVerifiedAt exists and gates the
larger posting allowance, but nothing sets it yet.expiresAt is set and filtered on, but nothing flips
ACTIVE to EXPIRED on a schedule.en/tl layer yet./terms and /privacy carry visible placeholders pending legal review.