Ecommerce Template
Next.js·React 등으로 만든 최신 전자상거래 템플릿
148개국 선불 eSIM 데이터 플랜, QR 즉시 제공, 무제한, 카드·암호화폐 결제
Prepaid travel eSIM data plans for 148+ countries. Instant QR delivery, unlimited plans, pay by card or crypto. Cheaper than roaming — and cheaper than the other eSIM apps.
커머스Python · HTMLGitHub @ekinsipahi온라인운영자 미확인
써 보셨어요? 한 번만 눌러 주세요. 로그인은 필요 없어요.
아직 감지된 업데이트가 없습니다. GitHub 릴리스가 나오면 여기에 보입니다.
개인 계정의 공개 저장소 소유자는 GitHub로 로그인해 운영자를 확인하고 소개를 직접 관리할 수 있습니다. 관리자 승인은 필요하지 않습니다.
로그인한 뒤 확인 파일을 만들어 이 저장소의 기본 브랜치에 30분 안에 커밋해 주세요. 다른 브랜치나 포크의 파일은 인정하지 않습니다. 파일을 올린 뒤 아래에서 확인하면 관리자 승인 없이 관리할 수 있습니다. 자격을 유지하려면 파일을 남겨 두세요.
로그인이 필요하면 로그인 화면으로 이동합니다. 로그인 후 이곳으로 돌아와 원하는 확인 버튼을 다시 눌러 주세요.
프로젝트 폴더에서 /nomorevibe verify를 실행하면 소유권을 확인하고 소개를 직접 관리할 수 있습니다.
1분 만에 확인하기Travel eSIM storefront. Django: catalogue, checkout, provisioning, subscriptions, coupons and programmatic SEO.
저장소 README에서 가져옴
README 전체를 불러오는 중입니다. 아래는 저장된 발췌입니다.
Connect without borders. A travel eSIM storefront: one Django project that
sells prepaid mobile data, provisions it through the Yesim partner API and
delivers the QR code instantly. Server-rendered pages for customers and search
engines, plus a JSON API for a future mobile app.
Without payment keys the site runs end to end; checkout simply reports that
payments are not configured. Without YESIM_API_TOKEN the catalogue stays emptyREADME 전문 보기 ↗Connect without borders. A travel eSIM storefront: one Django project that sells prepaid mobile data, provisions it through the Yesim partner API and delivers the QR code instantly. Server-rendered pages for customers and search engines, plus a JSON API for a future mobile app.
core/ settings, urls, middleware, sitemaps, rate limiting
apps/common shared template tags: icons, flags, money, data sizes
apps/accounts email-based user, Google sign-in, transactional email
apps/catalog Country / Region / Plan mirrored from the provider + pricing
apps/orders orders, eSIM records, checkout, fulfilment, dashboard
apps/payments Stripe Checkout, NOWPayments crypto, webhooks, cron trigger
apps/subscriptions auto-renewing unlimited plans on Stripe subscriptions
apps/coupons discount codes, redemption ledger, public coupon page
apps/support AI assistant chat (signed-in) + ticket system
apps/seo programmatic-SEO pages (price hub, payment, comparisons)
apps/providers Yesim partner API client
apps/blog travel guides
apps/api JSON API for the mobile app (JWT)
templates/ every page; static/css/app.css is the whole design system
docs/seo/ keyword map and the raw keyword list, grouped by intent
assets-src/ the original logo and film files the derivatives come from
python3 -m venv venv
./venv/bin/pip install -r requirements.txt
# .env holds every setting; it is gitignored and is also what you copy
# into Render. render.yaml lists the same variables with comments.
./venv/bin/python manage.py migrate
./venv/bin/python manage.py sync_plans # mirrors the catalogue (~90s)
./venv/bin/python manage.py seed_country_seo # unique copy for 148 destinations
./venv/bin/python manage.py seed_content # launch blog posts
./venv/bin/python manage.py createsuperuser
./venv/bin/python manage.py runserver
Without payment keys the site runs end to end; checkout simply reports that
payments are not configured. Without YESIM_API_TOKEN the catalogue stays empty.
Order in pending, applies a coupon if one was
entered, records the request fingerprint, and hands off to Stripe Checkout or
a NOWPayments invoice./webhooks/stripe/ or
/webhooks/nowpayments/ipn/, both signature-verified.payments.services.settle_payment is the single door money comes through. It
marks the order paid and, on commit, calls fulfilment. An underpaid crypto
invoice is recorded but never provisions.orders.services.fulfill_order issues the eSIM (one provider call, plan
attached) or tops up an existing one, then emails the QR code. It is
idempotent and locked, so a webhook retry, the admin action and the cron
sweeper cannot double-provision.paid with the error recorded, the
operator is emailed, and manage.py retry_orders picks it back up. The sale
is never lost.A subscription cycle takes the same path: each paid Stripe invoice creates a real
Order and runs it through fulfill_order, so revenue, margin and fulfilment
have exactly one implementation.
Wholesale arrives in EUR. apps/catalog/pricing.py converts to USD, applies a
markup with a minimum margin and a price floor, then rounds up to a .49/.99
ending.
| Variable | Default | Meaning |
|---|---|---|
EUR_USD_RATE | 1.10 | Wholesale EUR to retail USD |
PRICING_MARKUP | 1.65 | Multiplier on cost, our selling price |
PRICING_MIN_MARGIN_USD | 0.60 | Floor on absolute margin per sale |
PRICING_MIN_PRICE_USD | 1.49 | Never sell below this |
PRICING_COMPARE_MULTIPLIER | 4.0 | Cost multiplier for the struck-through list price |
SUBSCRIPTION_DISCOUNT_PCT | 15 | Standing discount for subscribing |
The struck-through figure is cost x 4, which is roughly what the big eSIM apps charge for the same wholesale supply, so the advertised percentage lands between 50 and 60 percent on most plans. It is presented as the going market rate, never as a former eSIMsterr price, because claiming a former price we never charged is misleading and, in the EU, regulated. If you change the multiplier, keep it defensible: spot-check two or three competitors first.
manage.py sync_plans --reprice-only recomputes every price and list price after
a change. A per-plan price_override_usd in the admin always wins.
| Command | What it does |
|---|---|
sync_plans | Mirror the catalogue, price it, refresh aggregates and badges |
sync_plans --reprice-only | Recompute prices from stored costs, no API call |
seed_country_seo | Unique intro, title and description for every destination |
sync_usage | Refresh data usage and status for live eSIMs |
retry_orders | Provision orders stuck in paid |
expire_coupon_holds | Release coupon seats held by abandoned checkouts |
purge_fingerprints | Enforce the IP retention window the privacy policy states |
yesim_status | Show partner balance and plan count |
yesim_status --register-webhook | Point the provider's notifications at this site |
seed_content | Create the launch blog articles |
The same jobs are reachable over HTTP for external schedulers:
/webhooks/cron/<task>/?token=$CRON_SECRET where task is sync-usage,
retry-orders, sync-plans or purge-fingerprints.
Logos, the hero film and the derived favicons live in static/img/ and
static/video/; static/img/README.md explains which file goes where and how
they were produced. Country flags are the flag-icons SVG set, vendored into
static/vendor/flags/.
Never use emoji. Emoji flags render as the bare country code on Windows, and
pictographs differ on every platform. Use {% flag country.iso2 %} and
{% icon "name" %} from apps/common/templatetags/ui.py.
Every user-facing string is wrapped for translation, but only the locales listed
in ENABLED_LANGUAGES are served. Publishing /tr/ pages full of English is
duplicate content, not localisation, so translate a locale first, then add its
code and redeploy. URLs use i18n_patterns with prefix_default_language=False,
so English stays on bare paths and adding a locale never moves an indexed URL.
./venv/bin/python manage.py makemessages -l tr -i venv
# translate locale/tr/LC_MESSAGES/django.po, then
./venv/bin/python manage.py compilemessages
# and set ENABLED_LANGUAGES=en,tr
docs/seo/keyword-map.md is the plan: every keyword family classified by intent,
the page type that serves it, title and description patterns, and explicit
anti-spam rules about what not to build. docs/seo/raw-keywords.txt is the
working list. Read the keyword map before adding pages.
All payment happens on the website. The mobile API deliberately has no
in-app purchase endpoint: POST /api/v1/checkout-url/ returns a web URL for the
app to open in the system browser. Keep it that way, or App Store review will
treat the app as selling digital goods outside their billing system.
See DEPLOY.md. Render web service plus Supabase Postgres;
render.yaml describes the cron jobs.
.env holds every credential and is gitignored. render.yaml lists the same
variable names with a comment on what each one is for, which is the reference
to fill in when deploying.db.sqlite3 is a local scratch database. Production runs on Postgres.assets-src/ holds the original artwork the derivatives in static/img/ were
made from. Large, and not needed to run the site.Published source, not open source. See LICENSE.