Full-featured website for a Minecraft server with a community / social network vibe: news, forum, profiles, store, support tickets and a complete admin panel.
Live site Β· Setup Β· Troubleshooting Β· Changelog
- β¨ Highlights
- β¨ Features
- π§± Stack
- β Requirements
- π Quickstart
- β‘ Quick Find (Where to Change Things)
- π Access & Roles
- π§ Environment Variables
- π Scripts
- πΊοΈ SEO (Sitemap/Robots/Schema)
- π Project Stats
- πΌοΈ Uploads (Local vs Production)
- π Deploy
- π§― Troubleshooting
- π Security
- π Changelog
- Social identity:
@username+displayName(like a social app). - Dynamic content: blog/news + forum with media.
- Production-ready admin panel with roles, moderation and settings.
- SEO-ready:
sitemap.xml,robots.txt, canonical URLs and JSON-LD. - Deploy-friendly: MongoDB Atlas + NextAuth + uploads compatible with Vercel.
- π Home with server status (configurable IP/port).
- π° News/Blog (posts, views, likes).
- π¬ Forum (posts, replies, likes, views, images).
- π€ Public & private profiles (avatar, banner, activity, follows).
- π Store (products + categories).
- π« Support (tickets + chat).
- π Notifications.
- π Legal pages: terms, privacy policy, rules.
- π Dashboard with statistics + quick access.
- π₯ Users (roles, bans, verification, etc.).
- ποΈ Store/Products (CRUD).
- π« Tickets/Support.
- π¬ Forum (moderation/management).
- π° Blog/News (CRUD + image).
- π§Ύ Staff applications.
- π§ Logs.
- βοΈ Settings (includes maintenance mode).
- π Section-based permissions (OWNER).
| Layer | Technology |
|---|---|
| Frontend | Next.js 14 (App Router) + React + TypeScript |
| UI | TailwindCSS + Framer Motion |
| Auth | NextAuth (JWT) |
| Database | MongoDB Atlas + Mongoose |
| Uploads (prod) | Vercel Blob (recommended on Vercel) |
| AI (chatbot) | Groq (OpenAI-compatible API style) |
- Node.js 18.17+ (Node 20+ recommended)
- npm
- MongoDB (Atlas recommended)
- Install dependencies:
npm install- Create your
.envfile from the example:
cp .env.example .env- Generate a strong secret for NextAuth:
node -e "console.log(require('crypto').randomBytes(32).toString('base64'))"-
Fill the required
.envvalues. -
Initialize the database (seed + initial admin):
npm run init-db- Start the development server:
npm run devOpen: http://localhost:3000
For a complete setup guide (local + production), see SETUP.md.
Quick guide to find text locations fast.
| Case | Where to edit | Notes |
|---|---|---|
Text that uses t(lang, '...') |
lib/i18n.ts |
Always update both es and en to keep translations consistent. |
| Hardcoded JSX text | app/**/page.tsx or components/**/*.tsx |
If it does not use t(...), edit that file or migrate it to i18n. |
| Global SEO title/description | app/layout.tsx |
metadata.title, metadata.description, openGraph, twitter. |
| Site name in JSON-LD | app/layout.tsx |
orgJsonLd and websiteJsonLd (uses SITE_NAME if available). |
| What you want to change | File | Keys/area |
|---|---|---|
| Navbar labels (Home, Shop, Vote, etc.) | lib/i18n.ts |
nav.* |
| User menu labels (Admin, Profile, Sign out) | lib/i18n.ts |
user.* |
| Full footer text | lib/i18n.ts |
footer.* |
| Language selector labels (Spanish/English) | lib/i18n.ts |
lang.* |
| Common labels (Save, Cancel, etc.) | lib/i18n.ts |
common.* |
| Navbar component structure/icons/buttons | components/Navbar.tsx |
UI structure; labels should preferably come from i18n |
| Footer component | components/Footer.tsx |
Check for any additional hardcoded text |
| Route | File | Where text usually lives |
|---|---|---|
/ |
app/page.tsx |
Hero (<h1>), primary buttons, home blocks |
/tienda |
app/tienda/page.tsx |
Shop header, filters, product cards |
/carrito |
app/carrito/page.tsx |
Checkout, summary, states and toasts |
/vote |
app/vote/page.tsx |
vote.* in i18n + potential local labels |
/noticias |
app/noticias/page.tsx |
news.* + listing text |
/noticias/[slug] |
app/noticias/[slug]/page.tsx |
Post details, likes, errors |
/foro |
app/foro/page.tsx |
Feed, create post, filters, toasts |
/foro/[id] |
app/foro/[id]/page.tsx |
Details, replies, actions |
/soporte |
app/soporte/page.tsx |
Tickets, states, form |
/soporte/[id] |
app/soporte/[id]/page.tsx |
Ticket chat, actions |
/perfil |
app/perfil/page.tsx |
Header and summary |
/perfil/ajustes |
app/perfil/ajustes/page.tsx |
Account settings, errors/toasts |
/staff |
app/staff/page.tsx |
Staff page text and applications |
/normas |
app/normas/page.tsx |
Rules and tables |
/terminos |
app/terminos/page.tsx |
Legal |
/privacidad |
app/privacidad/page.tsx |
Legal |
/cookies |
app/cookies/page.tsx |
Legal/cookies |
/mantenimiento |
app/mantenimiento/page.tsx |
Visual message and fallback |
| Admin route | File | Main text areas |
|---|---|---|
/admin |
app/admin/page.tsx |
Dashboard, KPIs, quick actions |
| Admin side layout | app/admin/layout.tsx |
Sidebar, groups, breadcrumbs |
/admin/users |
app/admin/users/page.tsx |
User table, actions |
/admin/users/[userId] |
app/admin/users/[userId]/page.tsx |
User details |
/admin/products |
app/admin/products/page.tsx |
Product CRUD |
/admin/tickets |
app/admin/tickets/page.tsx |
Support inbox + webhook |
/admin/foro |
app/admin/foro/page.tsx |
Forum moderation |
/admin/blog |
app/admin/blog/page.tsx |
News/blog CRUD |
/admin/badges |
app/admin/badges/page.tsx |
Badge management |
/admin/coupons |
app/admin/coupons/page.tsx |
Coupons and coupon webhook |
/admin/referrals |
app/admin/referrals/page.tsx |
Referrals and rewards |
/admin/newsletter |
app/admin/newsletter/page.tsx |
Newsletter, status, schedule |
/admin/postulaciones |
app/admin/postulaciones/page.tsx |
Staff applications |
/admin/logs |
app/admin/logs/page.tsx |
Admin history + webhook |
/admin/services-status |
app/admin/services-status/page.tsx |
Service status + reports |
/admin/settings |
app/admin/settings/page.tsx |
Maintenance and settings |
/admin/permisos |
app/admin/permisos/page.tsx |
Section permissions |
/admin/partner |
app/admin/partner/page.tsx |
Partner management |
Base file: lib/i18n.ts
| Module | Key prefix |
|---|---|
| Home | home.* |
| Auth | auth.* |
| Shop | shop.* |
| Rules | rules.* |
| Staff | staff.* |
| News | news.* |
| Forum | forum.* |
| Support/Tickets | support.* |
| Profile | profile.* |
| Vote | vote.* |
| Notifications | notifications.* |
| Full admin | admin.* |
| Footer | footer.* |
| Chatbot | chatbot.* |
| Public partner | partnerPublic.* |
- First check whether the text comes from i18n (
t(lang, '...')). - If it comes from i18n, edit only
lib/i18n.tsin bothesanden. - If it is hardcoded, edit the page/component file and consider migrating it to i18n.
- Verify the same route in both languages using the selector (
LanguageSwitcher). - If you change admin labels, validate both desktop and mobile (
app/admin/layout.tsx).
Find potentially hardcoded text in admin:
rg "lang === 'es'|\?\s*'[^']{3,}'\s*:\s*'[^']{3,}'|toast\.(error|success|warn)\([^\)]*'Error'" app/adminFind possible non-i18n text across pages:
rg "'[^']{4,}'|\"[^\"]{4,}\"" app --glob "**/*.tsx"If rg is not installed, use grep -R as an alternative.
- Login:
/auth/login - Admin:
/admin
| Role | Access |
|---|---|
OWNER |
Full access + section-based permissions |
ADMIN |
Admin access (can be limited by section) |
STAFF |
Admin access (currently full behavior) |
USER |
Public access + own profile |
The initial admin user is created with npm run init-db using ADMIN_EMAIL / ADMIN_PASSWORD.
Full reference available in .env.example.
| Variable | Required | Purpose |
|---|---|---|
MONGODB_URI |
β | MongoDB connection |
NEXTAUTH_URL |
β | Base URL (local: http://localhost:3000) |
NEXTAUTH_SECRET |
β | NextAuth secret |
| Variable | Purpose |
|---|---|
ADMIN_EMAIL |
Initial admin email (seed) |
ADMIN_PASSWORD |
Initial admin password (seed) |
SITE_NAME |
Website name |
SITE_URL |
Website URL |
GOOGLE_SITE_VERIFICATION |
Google Search Console HTML tag content |
BING_SITE_VERIFICATION |
Bing Webmaster Tools HTML tag content |
MINECRAFT_SERVER_IP |
Server IP/host for status |
MINECRAFT_SERVER_PORT |
Server port for status |
NEXT_PUBLIC_STAFF_APPLICATIONS_OPEN |
Open/close staff applications |
BLOB_READ_WRITE_TOKEN |
Vercel Blob uploads (production) |
GROQ_API_KEY |
Chatbot API key (Groq) |
GROQ_MODEL |
Chatbot model (e.g. llama-3.1-8b-instant) |
CLOUDINARY_URL (or 3 vars) |
Alternative uploads (optional) |
| Variable | Purpose |
|---|---|
NEXT_PUBLIC_MINECRAFT_SERVER_IP |
Displayed server IP on Home |
NEXT_PUBLIC_DISCORD_URL |
Footer link |
NEXT_PUBLIC_TIKTOK_URL |
Footer link |
NEXT_PUBLIC_YOUTUBE_URL |
Footer link |
| Script | Description |
|---|---|
npm run dev |
Start development server |
npm run build |
Production build |
npm start |
Run production build |
npm run lint |
Run linter |
npm run init-db |
Seed DB + create initial admin |
npm run stats |
Print project stats (files/dirs/LOC) |
node scripts/check-db.jsnode scripts/clean-db.jsnode scripts/reset-admin-password.jsnode scripts/set-owner.js --email your@email.com --tags OWNER,FOUNDERnode scripts/fix-tickets-index.js
- Local/Dev: Files are written to
public/uploads/.... - Production (Vercel): Filesystem is ephemeral β use Vercel Blob (
BLOB_READ_WRITE_TOKENrequired).
Upload helper supports providers in this order (based on configuration):
- Cloudinary (if configured)
- Vercel Blob (if token is present)
- Local filesystem (dev only)
BLOB_READ_WRITE_TOKEN=Option A (1 variable):
CLOUDINARY_URL=cloudinary://API_KEY:API_SECRET@CLOUD_NAMEOption B (3 variables):
CLOUDINARY_CLOUD_NAME=
CLOUDINARY_API_KEY=
CLOUDINARY_API_SECRET=Recommended: Vercel
- Configure environment variables in your hosting provider (same as
.env). - MongoDB Atlas: verify credentials and Network Access (IP allowlist).
- Set
NEXTAUTH_URLto your real domain. - If using uploads on Vercel β configure
BLOB_READ_WRITE_TOKEN.
This project ships with:
GET /sitemap.xml(includes static routes + dynamic blog/forum URLs when DB is available)GET /robots.txt- Canonical URLs (
metadataBase+ per-section canonical) - JSON-LD:
Organization,WebSite, plusNewsArticleandDiscussionForumPostingon dynamic pages.
Recommended for production:
- Set
SITE_URL=https://www.999wrldnetwork.es - Verify ownership in Google Search Console and submit your sitemap.
Generated by npm run stats.
| Metric | Value |
|---|---|
| Total files | 278 |
| Total directories | 203 |
| Text files counted | 267 |
| Total lines (text) | 40,381 |
| Non-empty lines (text) | 35,576 |
Top file types (by non-empty lines):
| Ext | Files | Lines | Non-empty |
|---|---|---|---|
| .tsx | 95 | 20,820 | 18,985 |
| .ts | 143 | 15,680 | 13,573 |
| .js | 9 | 1,193 | 981 |
| .md | 8 | 1,173 | 789 |
| (noext) | 3 | 644 | 522 |
| .mjs | 2 | 389 | 319 |
| .css | 1 | 145 | 117 |
| .example | 1 | 126 | 104 |
| .env | 1 | 115 | 94 |
| .json | 4 | 96 | 92 |
- Check
MONGODB_URI,NEXTAUTH_URL,NEXTAUTH_SECRET - Run
npm run init-db - Clear cache:
rm -rf .nextand restart
- Verify Atlas username/password
- Verify IP allowlist in Atlas
Additional documentation:
SETUP.mdTROUBLESHOOTING.md
- Do NOT upload
.envto the repository. - If a secret leaks, rotate credentials immediately.
- Vulnerability reporting: see SECURITY.md.
Made by KayXDev with β€οΈ