Skip to content

Getting Started with WellChina

This guide walks you through setting up the WellChina development environment from scratch.

Prerequisites

ToolVersionNotes
Node.js20+LTS recommended
npm10+Ships with Node.js 20
PostgreSQL15+Local instance or managed (Supabase/Neon)
Git2.xAny recent version

Optional but recommended:

  • Prisma Studio — visual database browser (included via npm run db:studio)
  • VS Code with Tailwind CSS IntelliSense and Prisma extensions

Quick Start

bash
# 1. Clone the repository
git clone https://github.com/Phinease/WellChina.git
cd WellChina

# 2. Install dependencies
npm install

# 3. Set up environment variables
cp .env.example .env
# Edit .env with your database connection string (see "Environment Variables" below)

# 4. Generate Prisma client
npm run db:generate

# 5. Push schema to database (creates all tables)
npm run db:push

# 6. Seed the database
npx tsx prisma/seed.ts

# 7. Seed hospital images (optional)
npx tsx scripts/seed-hospital-images.ts

# 8. Start the dev server
npm run dev

Open http://localhost:3000 to see the site.

Environment Variables

Copy .env.example to .env and fill in the values:

env
# Required — Supabase PostgreSQL connection string (Pooler session mode, port 5432)
DATABASE_URL="postgresql://postgres.[project-ref]:[password]@aws-0-[region].pooler.supabase.com:5432/postgres"

# Public site URL — used by SEO (hreflang) and admin links in emails
NEXT_PUBLIC_SITE_URL="https://wellchina.top"

# Optional — Resend email service (contact form notifications)
# Full email infra setup: docs/dns-email-migration-plan.md
RESEND_API_KEY=""
ADMIN_EMAIL=""
FROM_EMAIL="WellChina <no-reply@wellchina.top>"

# Optional — Exchange rate API (currency conversion, not yet implemented)
EXCHANGE_RATE_API_KEY=""

Database Setup

This project uses Supabase PostgreSQL as the database. Copy the Pooler connection string (session mode, port 5432) from your Supabase project dashboard and set it as DATABASE_URL.

NPM Scripts

CommandDescription
npm run devStart Next.js dev server (port 3000)
npm run buildProduction build
npm startRun production build
npm run lintRun ESLint on src/
npm run formatFormat code with Prettier
npm run format:checkCheck formatting without changes
npm run db:generateGenerate Prisma client from schema
npm run db:migrateCreate and apply migrations (interactive)
npm run db:pushPush schema to database (non-interactive)
npm run db:studioOpen Prisma Studio (database GUI on port 5555)

Database

Schema Overview

The database has 12 models organized around medical tourism data:

Core entities:

  • cities — 13 Chinese cities with expat population, accessibility, transportation info
  • hospitals — 101 hospitals with English service level, JCI accreditation, Fudan rankings, payment methods
  • procedures — 50 medical procedures with pricing (CNY range + US comparison)
  • procedure_categories — 12 categories (Dental, Eye Care, Health Checkup, Fertility, Cancer Care, Orthopedics, Cardiac, TCM, Cosmetic, Neurosurgery, Organ Transplant, Bariatric)
  • specialties — 10 medical specialties
  • insurances — 5 international insurance providers (Cigna, Bupa, AXA, Allianz, Now Health)
  • guides — 4 healthcare guides (visa, payment, booking, insurance)
  • contact_inquiries — Contact form submissions

Junction tables:

  • hospital_procedures — Links hospitals to procedures with hospital-specific pricing
  • hospital_specialties — Links hospitals to specialties (with is_strength flag)
  • hospital_insurances — Links hospitals to insurances (with direct_billing flag)

See prisma/schema.prisma for the full schema definition.

Running Migrations

bash
# Development: push schema changes directly (no migration files)
npm run db:push

# Production: create a named migration
npm run db:migrate

Seeding

The seed script (prisma/seed.ts) populates the database with sample data:

bash
npx tsx prisma/seed.ts

This creates 13 cities, 101 hospitals, 12 procedure categories, 50 procedures, 10 specialties, 5 insurance providers, 4 guides, and all relationship links.

To add hospital thumbnail images:

bash
npx tsx scripts/seed-hospital-images.ts

Project Structure

wellchina/
├── prisma/
│   ├── schema.prisma           # Database schema (12 models)
│   ├── seed.ts                 # Seed orchestrator
│   ├── seed/                   # Modular seed data files
│   │   ├── seed-cities.ts      # 13 cities
│   │   ├── seed-hospitals.ts   # 101 hospitals
│   │   ├── seed-procedures.ts  # 12 categories + 50 procedures
│   │   ├── seed-specialties.ts # 10 specialties
│   │   ├── seed-insurances.ts  # 5 insurance providers
│   │   ├── seed-guides.ts      # 4 guides
│   │   └── seed-relations.ts   # Junction table seeding
│   └── migrations/             # Migration history
├── src/
│   ├── app/                    # Next.js App Router
│   │   ├── page.tsx            # Homepage (hero + popular procedures + featured cities)
│   │   ├── hospitals/          # Hospital listing + detail pages
│   │   ├── procedures/         # Category browsing + procedure detail
│   │   ├── cities/             # City listing + detail pages
│   │   ├── guides/             # Healthcare guide articles
│   │   ├── pricing/            # Price overview with comparison charts
│   │   ├── compare/            # Hospital comparison tool (up to 3)
│   │   ├── search/             # Search results page
│   │   ├── contact/            # Contact inquiry form
│   │   ├── about/              # About page
│   │   ├── admin/              # Admin panel (login + dashboard)
│   │   │   ├── login/          # Admin authentication
│   │   │   └── (dashboard)/    # Hospital/procedure/insurance/contact management
│   │   └── api/
│   │       ├── contact/        # POST /api/contact
│   │       ├── search/         # GET /api/search?q=
│   │       └── admin/          # Admin CRUD endpoints (auth-protected)
│   ├── components/
│   │   ├── layout/             # Navbar, Footer
│   │   ├── ui/                 # AnimatedSection, Badge, Button, Card, FilterBar, etc.
│   │   ├── compare/            # CompareBar, CompareButton, CompareProvider
│   │   └── guides/             # GuideContent (Markdown renderer)
│   ├── lib/
│   │   ├── prisma.ts           # Prisma client singleton
│   │   ├── email.ts            # Resend email integration
│   │   ├── admin-auth.ts       # Cookie-based admin auth
│   │   └── supabase.ts         # Supabase client (configured, not actively used)
│   ├── i18n/
│   │   └── request.ts          # next-intl locale config
│   └── types/                  # TypeScript type definitions
├── messages/
│   └── en.json                 # English UI strings (next-intl)
├── scripts/
│   ├── seed-hospital-images.ts # Unsplash image URL seeder
│   └── seed-supabase.mjs       # Legacy Supabase REST seeder
├── public/                     # Static assets
├── docs/                       # Project documentation
└── .github/workflows/ci.yml    # GitHub Actions CI pipeline

Key Files

  • next.config.ts — Next.js config with next-intl plugin and Unsplash image domain
  • prisma.config.ts — Prisma engine configuration
  • tsconfig.json — TypeScript config with @/* path alias for src/
  • postcss.config.mjs — PostCSS with Tailwind CSS v4 plugin
  • src/middleware.ts — Protects /admin/* and /api/admin/* routes with cookie-based auth

Tech Stack

LayerTechnology
FrameworkNext.js 15.3 (App Router)
UIReact 19 + Tailwind CSS 4
AnimationFramer Motion
IconsLucide React
DatabasePostgreSQL
ORMPrisma 6
i18nnext-intl (English only for MVP)
EmailResend
ValidationZod
LintingESLint 9 + Prettier

Deployment

Production Build

bash
npm run build
npm start
  1. Connect the GitHub repo to Vercel.
  2. Set environment variables in the Vercel dashboard (DATABASE_URL, RESEND_API_KEY, ADMIN_EMAIL, FROM_EMAIL).
  3. Vercel auto-detects Next.js and builds on push.

Database for Production

Use a managed PostgreSQL provider:

  • Supabase — free tier available, but may be blocked by the GFW in mainland China
  • Neon — serverless PostgreSQL, free tier available

After connecting your production database:

bash
# Apply schema
DATABASE_URL="your-production-url" npx prisma db push

# Seed data
DATABASE_URL="your-production-url" npx tsx prisma/seed.ts

GFW Considerations

If deploying or developing from mainland China:

  • Supabase dashboard and API endpoints may be inaccessible without a VPN
  • npm registry can be slow — consider using a mirror: npm config set registry https://registry.npmmirror.com
  • GitHub may have intermittent connectivity — use SSH keys and consider a proxy

CI/CD

GitHub Actions is configured in .github/workflows/ci.yml. It runs on pushes to main/develop and PRs to main.

Pipeline stages:

  1. Lint & Type Check — installs deps, generates Prisma client, runs tsc --noEmit and npm run lint
  2. Build — runs npm run build against a CI database (DATABASE_URL set in workflow env)

Troubleshooting

prisma generate fails

Make sure DATABASE_URL is set in .env. Prisma needs it even for client generation in some configurations.

Database connection refused

  • Verify PostgreSQL is running: pg_isready
  • Check your DATABASE_URL credentials and port
  • For Supabase: ensure you're using the direct connection string (not the pooler) for migrations

Build errors with next build

  • Run npm run db:generate first — the Prisma client must be generated before building
  • Ensure DATABASE_URL points to an accessible database (Next.js fetches data at build time for static pages)

Images not loading

Hospital images are loaded from images.unsplash.com. This domain is allowed in next.config.ts. If you see broken images:

  • Check if hospital image URLs have been seeded: npx tsx scripts/seed-hospital-images.ts
  • Verify Unsplash is accessible from your network

Slow npm install in China

bash
npm config set registry https://registry.npmmirror.com

Email notifications not sending

  • RESEND_API_KEY must be set in .env
  • The contact form still saves to the database even without email configured
  • Check server logs for Resend API errors

WellChina 内部文档 · 基于 VitePress