Runam
Food, groceries, gas refills and parcels from the gate — Runam runners handle errands inside Games Village, Abuja.
Restoran, toy və tədbirlər üçün gitaristdən tar ifaçısına qədər musiqiçiləri tapın, musiqi alətlərini günlük kirayələyin, səs studiyası seçin.
Translation pending
CommerceTypeScript · PythonGitHub @ayyub1nnatOnlineOwner unconfirmed
Have you tried it? One tap is enough. No sign-in needed.
No updates detected yet. GitHub releases will appear here.
Owners of public repositories under a personal GitHub account can sign in to verify ownership and manage the introduction themselves. No administrator approval is needed.
Sign in, generate a verification file, and commit it to this repository’s default branch within 30 minutes. Files on other branches or forks do not count. Then check the file below to manage the project without administrator approval. Keep the file to retain your access.
If needed, you will go to sign-in. After signing in, return here and press your chosen verification button again.
Run /nomorevibe verify in your project folder to verify ownership and manage the introduction yourself.
Verify in one minuteAsk about other verification options
The maker's introduction consists of the line above. Read the repository README for more details. Repository README ↗
Loading the full README.
Read the full README ↗Küçə, həvəskar və professional musiqiçilərin elan yerləşdirdiyi, canlı musiqi axtaran restoranların onları tapıb birbaşa əlaqə saxladığı platforma.
Stack: Next.js 15 (App Router) · MongoDB (Mongoose) · Tailwind · JWT sessiya (httpOnly cookie)
1. MongoDB Atlas (pulsuz baza) — cloud.mongodb.com
musiqichi bazasına (Atlas admin deyil); şifrə — Autogenerate Secure Password (uzun, təsadüfi)151.243.169.44/32). 0.0.0.0/0 qoymayın — bazaya bütün internetdən qoşulma cəhdi açıq qalır. Vercel-də IP sabit deyil: orada məcburən 0.0.0.0/0 lazımdırsa, güclü şifrə və məhdud istifadəçi şərtdir<password> yerinə şifrəni yazın, .net/-dən sonra musiqichi əlavə edin:
mongodb+srv://ad:[email protected]/musiqichi?retryWrites=true&w=majority2. GitHub — github.com → New repository → ad: musiqichi-az, Private → uploading an existing file linkinə basın → açılmış qovluğun içindəki bütün fayl və qovluqları sürüşdürüb atın → Commit changes
3. Vercel — vercel.com → Add New → Project → musiqichi-az reposunu Import edin → Environment Variables bölməsinə bunları yazın:
| Ad | Dəyər |
|---|---|
MONGODB_URI | 1-ci addımdakı link |
JWT_SECRET | istənilən uzun mətn (ən azı 32 simvol) |
OTP_SECRET | başqa uzun mətn |
TEST_MODE | yalnız test üçün true (production-da ayrıca ALLOW_TEST_MODE_IN_PRODUCTION=yes olmadan işləmir) |
ADMIN_PHONES | öz nömrəniz, məs. +994501234567 |
→ Deploy
4. Fayllar üçün Blob — Vercel-də layihə → Storage → Create → Blob → layihəyə qoşun (Connect). Sonra Deployments → sonuncu deploy → ⋯ → Redeploy.
5. Yoxlama — musiqichi-az-xxxx.vercel.app linkini açın. Test rejimində OTP kodu SMS əvəzinə ekranda sarı qutuda görünür, boost ödənişi test səhifəsi ilə təsdiqlənir.
Domen: Vercel → layihə → Settings → Domains → musiqichi.az əlavə edin və göstərilən DNS qeydlərini domen panelinizə yazın.
Real istifadəyə açmazdan əvvəl: SMS provayderini qoşun (SMS_PROVIDER=http, SMS_HTTP_URL, SMS_HTTP_TOKEN), bank ödənişini qoşun, sonra TEST_MODE dəyişənini silib Redeploy edin. Təhlükəsizlik üçün production-da test rejimi TEST_MODE=true olsa belə avtomatik sönülüdür; sayt başlayanda loqda xəbərdarlıq yazılır.
cp .env.example .env # JWT_SECRET, OTP_SECRET dəyişin
npm install
npm run dev # http://localhost:3000 (MongoDB lazımdır)
npm test # rotasiya, OTP, nömrə və reytinq testləri
Öz VPS-də Docker ilə: docker compose up -d --build (fayllar UPLOAD_DIR volume-da saxlanılır).
| Funksiya | Harada |
|---|---|
| Qeydiyyat: ad, soyad, nömrə + SMS OTP | app/qeydiyyat, app/api/auth/*, lib/otp.ts |
| Bioqrafiya: şəkil, doğum tarixi (yaş), şəhər, sənət (kateqoriya + “Digər”), əlavə alətlər, janr, səviyyə, təcrübə, qiymət, tədbir növləri, avadanlıq, uyğun günlər, sosial şəbəkələr | app/panel/ProfileEditor.tsx, lib/profile.ts, lib/catalog.ts |
| Ən yaxşı 1 mahnı + 1 video (fayl və ya YouTube linki) | app/panel/MediaUploader.tsx, app/api/upload, lib/storage.ts |
| Elanın dərci (natamam profil dərc olunmur) | app/api/profile/publish |
| Restoran rəyləri (hesabsız, nömrə OTP ilə təsdiqlənir; 1 nömrə = 1 rəy) | components/ReviewForm.tsx, app/api/reviews/* |
| Reytinq cədvəli + profildə yer (#N) | app/reytinq, lib/rating.ts, lib/queries.ts |
| Boost: 1 gün 2.99 · 7 gün 5.99 · 30 gün 19.99 AZN | app/panel/boost, app/api/boost/checkout, lib/boost.ts |
| Ana səhifədə boost rotasiyası | lib/rotation.ts, lib/boost.ts → getFeaturedIds |
| Nömrəni göstər / WhatsApp (botlardan qorunur, kliklər sayılır) | components/ContactButton.tsx |
SMS əvəzinə istifadəçi saytda göstərilən 6 rəqəmli kodu öz WhatsApp-ından biznes nömrəsinə göndərir. WhatsApp göndərənin nömrəsini özü təsdiqlədiyi üçün SMS lazım olmur.
Axın: nömrə yazılır → /api/auth/wa/start kod və wa.me linki qaytarır → istifadəçi "WhatsApp-da göndər" basır → Meta mesajı /api/whatsapp/webhook-a göndərir → göndərən nömrə + kod uyğun gəlirsə təsdiq olunur → brauzer /api/auth/wa/status-u 2 saniyədən bir yoxlayır və avtomatik davam edir.
Təhlükəsizlik: webhook-un hər sorğusu WHATSAPP_APP_SECRET ilə imza yoxlamasından keçir; WHATSAPP_APP_SECRET yoxdursa webhook heç nə qəbul etmir.
Qurulma (Meta tərəfi):
https://<domen>/api/whatsapp/webhook, Verify token — WHATSAPP_VERIFY_TOKEN-ə yazdığınız söz → Verify and save → messages sahəsinə abunə olun.WHATSAPP_APP_SECRET-ə yazın.WHATSAPP_NUMBER, WHATSAPP_VERIFY_TOKEN, WHATSAPP_APP_SECRET dəyişənlərini əlavə edib Redeploy edin./admin)İlk admin: saytda adi qeydiyyatdan keçin, sonra nömrənizi .env → ADMIN_PHONES siyahısına yazın və serveri yenidən başladın. Digər adminləri paneldən “Admin et” düyməsi ilə təyin etmək olar. Admin olmayanlar üçün /admin 404 qaytarır.
| Bölmə | Nə edir |
|---|---|
| İcmal | Qeydiyyat, aktiv elan, aktiv boost, bloklanmış sayı; bu gün / 7 gün / 30 gün gəlir; 15 dəq-dən çox “gözləyir” qalan ödənişlər üçün xəbərdarlıq; son 7 günün ≤2 ulduzlu rəyləri |
| Musiqiçilər | Ad/nömrə ilə axtarış, statusa görə filtr; elanı gizlət, blokla/blokdan çıxar, pulsuz boost ver, boostu ləğv et, admin et, hesabı sil (fayllar və rəylər də silinir, ödənişlər qalır) |
| Rəylər | Hamısı / ≤2 ulduz / gizlədilmiş; gizlət və bərpa et (reytinq dərhal yenidən hesablanır); bir nömrədən 3-dən çox rəy yazılıbsa qırmızı işarə |
| Ödənişlər | Statusa görə filtr; bankda pul çıxıb, amma callback çatmayıbsa — bankın əməliyyat nömrəsi ilə “Əl ilə təsdiqlə” |
| Jurnal | Hər admin əməliyyatı: kim, nə vaxt, kimə, hansı səbəblə |
Bloklama, gizlətmə və silmə səbəbsiz edilmir — səbəb jurnala yazılır. Bloklanmış istifadəçi daxil ola bilmir, açıq sessiyası varsa da heç nəyi dəyişə bilmir.
FEATURED_SLOTS).Parametrlər: lib/rotation.ts → WINDOW_MINUTES, FEATURED_SLOTS.
Restoranlar 1–5 ulduz verir. Sıralama Bayes ortalaması ilə aparılır (lib/rating.ts): 1 rəyi 5.0 olan musiqiçi 40 rəyi 4.8 olanı keçmir. Cədvələ ən azı 3 rəyi olanlar düşür. Restoranın nömrəsi heç yerdə göstərilmir.
Admin panelin (/admin) yuxarısındakı “Sayt hazırlığı” bloku nəyin qalmadığını göstərir.
WHATSAPP_NUMBER, WHATSAPP_VERIFY_TOKEN, WHATSAPP_APP_SECRET. Və ya SMS: SMS_PROVIDER=http + lib/sms.ts.TEST_MODE dəyişənini silin. Real rejimdə təsdiq qurulmayıbsa sayt kodu ekranda göstərmir, aydın xəta verir.PAYMENT_PROVIDER:
manual (real rejimdə defolt): /odenis/gozle səhifəsi sifariş kodu (MQ-XXXXXX) və WhatsApp düyməsi göstərir; pul gələndə /admin/odenisler → “Əl ilə təsdiqlə”. PAYMENT_WHATSAPP, PAYMENT_INSTRUCTIONS.free: açılış dövrü üçün pulsuz boost (eyni anda 1 aktiv).gateway: bank müqaviləsi olanda lib/payments.ts adapterini tamamlayın. Callback: /api/payments/callback.VIDEO_UPLOADS=true./qaydalar, /mexfilik hazırdır; CONTACT_EMAIL istəyə bağlı.APP_URL=https://musiqichi.az; /sitemap.xml avtomatikdir; domen dəyişəndə public/robots.txt-dəki Sitemap linkini yeniləyin.app/
page.tsx ana səhifə (önə çıxanlar, son elanlar, top 5)
musiqiciler/ axtarış + filtrlər
musiqici/[id]/ profil: mahnı, video, bio, rəylər, əlaqə
reytinq/ reytinq cədvəli
qeydiyyat/ giris/ OTP ilə qeydiyyat və giriş
panel/ profil redaktəsi, media, dərc, boost
odenis/test/ test ödəniş səhifəsi (yalnız dev)
api/ auth, profile, upload, media, reviews, boost, payments, featured
lib/ modellər, OTP, sessiya, rotasiya, ödəniş, reytinq, kataloq
tests/core.test.ts saf məntiq testləri
Server hər 5 dəqiqədən bir GitHub-u yoxlayır; main-də yeni commit varsa, özü çəkib saytı yenidən qurur (scripts/auto-deploy.sh).
cd /opt/musiqichi && git pull -q && chmod +x scripts/auto-deploy.sh && (crontab -l 2>/dev/null | grep -v auto-deploy; echo "*/5 * * * * /opt/musiqichi/scripts/auto-deploy.sh >> /var/log/musiqichi-deploy.log 2>&1") | crontab -
Jurnal: tail -20 /var/log/musiqichi-deploy.log. Söndürmək: crontab -l | grep -v auto-deploy | crontab -.
/aletler). İngiliscə /en/..., rusca /ru/... — eyni səhifələr, middleware.ts rewrite edir.mq_lang cookie-sində yadda qalır; /az/... Azərbaycancaya qaytarır. Admin panel yalnız Azərbaycancadır.const t = await getT() (lib/i18n-server.ts), client komponentlərdə const t = useT() (components/I18n.tsx). Açar — Azərbaycanca mətnin özüdür: t("Daxil ol").lib/i18n/en.json və lib/i18n/ru.json. Yeni mətn əlavə edəndə hər iki fayla da yazın; tərcümə yoxdursa, Azərbaycanca göstərilir.import Link from "@/components/I18n" — dil prefiksini özü əlavə edir.SMTP qurulanda qeydiyyat, şifrə bərpası və restoran rəyləri WhatsApp əvəzinə e-poçt kodu ilə təsdiqlənir (lib/otp-channel.ts). Pulsuz variant — Brevo (gündə 300 məktub):
SMTP_HOST=smtp-relay.brevo.com
SMTP_PORT=587
SMTP_USER=<Brevo SMTP login>
SMTP_PASS=<Brevo SMTP key>
MAIL_FROM=musiqichi.az <[email protected]>
BREVO_API_KEY=<Brevo API key> yazın — məktub HTTPS (443) ilə Brevo API-dən gedir; SMTP_* lazım deyil.OTP_CHANNEL=email | whatsapp | sms.