Ichitux f8d8a3832c
Build & Push Docker Images / test-backend (push) Successful in 35s
Build & Push Docker Images / test-frontend (push) Successful in 32s
Build & Push Docker Images / deploy (push) Successful in 6s
Build & Push Docker Images / build-backend (push) Successful in 17s
Build & Push Docker Images / build-frontend (push) Successful in 16s
Merge pull request 'fix: improve OCR CIP extraction to filter common TSI card text' (#10) from fix/ocr-barcode-extraction into main
Reviewed-on: #10
2026-07-06 13:23:11 +00:00
2026-06-29 13:50:27 +02:00
2026-07-01 16:44:48 +02:00
2026-07-01 15:54:10 +02:00
2026-06-26 16:59:20 +02:00
2026-06-29 11:29:40 +02:00
2026-06-29 13:50:27 +02:00
2026-06-29 11:29:40 +02:00
2026-04-01 01:18:21 +02:00
2026-06-26 16:59:20 +02:00
2026-04-01 01:18:21 +02:00
2026-06-29 13:02:16 +02:00
2026-05-19 18:27:16 +02:00

💊 FarmaFinder

A web application to search for medicines from the official Spanish CIMA database and find which pharmacies sell them.

Features

Web App (Desktop/PWA)

  • 🔍 Real-time medicine search from CIMA API (Agencia Española de Medicamentos)
  • 💾 Redis caching for improved performance
  • 📍 View pharmacies that sell a specific medicine
  • 💰 See prices and stock availability
  • 📱 Responsive design for mobile and desktop
  • ⚙️ Admin Panel - Manage pharmacies and link medicines
    • 🔐 Secure authentication - Login required to access admin features
    • Add, edit, and delete pharmacies
    • Search medicines from CIMA database
    • Link medicines to pharmacies with prices and stock

Mobile App (React Native)

  • 📱 Native iOS/Android experience with Expo
  • 🔍 Medicine search with real-time results
  • 🗺️ Interactive map with pharmacy markers
  • 📷 Barcode scanner for quick medicine lookup
  • 🔔 Push notifications for availability alerts
  • 🔐 Biometric authentication (Face ID / Touch ID)
  • 💾 Offline cache for favorite medicines

🛠️ Tech Stack

Backend

  • Runtime: Node.js + Express
  • Database: SQLite (for pharmacies and relationships)
  • Cache: Redis
  • External API: CIMA (Centro de Información online de Medicamentos de la AEMPS)

Frontend (Web/PWA)

  • Framework: React + Vite
  • Mobile wrapper: Capacitor (for hybrid mobile builds)

Frontend (Mobile - React Native)

  • Framework: Expo SDK 57 + React Native
  • Navigation: Expo Router v4
  • State: Zustand
  • HTTP: Axios + TanStack Query
  • Maps: react-native-maps
  • Camera: expo-camera (barcode scanning)
  • Auth: expo-local-authentication (biometrics)
  • Notifications: expo-notifications
  • Build: EAS Build

📋 Prerequisites

  • Node.js (v18 or higher)
  • npm or yarn
  • Redis server (v6.0 or higher)

Runs the full stack (backend, frontend, Redis) with a single command.

Prerequisites: Docker and Docker Compose v2.

# Copy and configure environment (optional — defaults work for local dev)
cp backend/.env.example backend/.env
# Edit backend/.env to set SESSION_SECRET and any other vars

docker compose up --build

App available at http://localhost:3000.

First run — create an admin user:

docker compose exec backend node create-admin.js
# Default: admin / admin123 — change after first login

Seed sample pharmacies:

docker compose exec backend node seed.js

Stop:

docker compose down

Database is persisted in a named Docker volume (backend_data). To wipe it:

docker compose down -v

🚀 Manual Setup Instructions

1. Install Redis

On Ubuntu/Debian:

sudo apt-get update
sudo apt-get install redis-server
sudo systemctl start redis-server
sudo systemctl enable redis-server

On macOS (using Homebrew):

brew install redis
brew services start redis

On Windows: Download and install from: https://redis.io/download

Using Docker:

docker run -d -p 6379:6379 redis:alpine

Verify Redis is running:

redis-cli ping
# Should respond with: PONG

2. Install Application Dependencies

Install backend dependencies:

cd backend
npm install

Install frontend dependencies:

cd ../frontend
npm install

3. Configure Environment (Optional)

Create a .env file in the backend directory if you need custom Redis settings:

REDIS_HOST=localhost
REDIS_PORT=6379
REDIS_PASSWORD=
SESSION_SECRET=your-secret-key-here

4. Initialize Database

Seed the database with sample pharmacies:

cd backend
npm run seed

Create admin user:

npm run create-admin

This creates a default admin user with:

  • Username: admin
  • Password: admin123

⚠️ Important: Change the default password after first login!

You can customize credentials using environment variables:

ADMIN_USERNAME=myadmin ADMIN_PASSWORD=mypassword npm run create-admin

5. Running the Application

Start Redis (if not running):

redis-server

Start the backend server:

cd backend
npm start

The backend will run on http://localhost:3001

Start the frontend development server:

cd frontend
npm run dev

The frontend will run on http://localhost:3000

Open your browser and navigate to http://localhost:3000

🎯 How to Use

  1. Type the name of a medicine in the search bar
  2. The app will search the CIMA database in real-time
  3. Click on a medicine to see which pharmacies have it
  4. View prices and stock availability

Admin Panel

  1. Click the "⚙️ Admin Panel" button
  2. Login with your credentials (default: admin / admin123)
  3. Pharmacies Tab: Add, edit, or delete pharmacies
  4. Medicines Tab: Search medicines from the CIMA database
  5. Link Medicine Tab: Associate medicines with pharmacies and set prices/stock

📁 Project Structure

FarmaFinder/
├── docker-compose.yml         # Full stack: backend + frontend + Redis
├── backend/
│   ├── Dockerfile
│   ├── server.js              # Express server and API routes
│   ├── cima-service.js        # CIMA API integration with Redis cache
│   ├── redis-client.js        # Redis connection configuration
│   ├── seed.js                # Database seeding script
│   ├── create-admin.js        # Admin user creation script
│   ├── .env.example           # Environment variable template
│   └── package.json
├── frontend/                  # React + Vite (Desktop/PWA)
│   ├── Dockerfile
│   ├── nginx.conf             # Nginx config (Docker): serves SPA + proxies /api
│   ├── src/
│   │   ├── components/        # React components
│   │   │   ├── admin/        # Admin panel components
│   │   │   ├── PharmacyMap.jsx  # Leaflet map (OpenStreetMap)
│   │   │   └── ...
│   │   ├── views/            # View components (Public/Admin)
│   │   ├── App.jsx           # Main app component
│   │   └── main.jsx          # Entry point
│   ├── index.html
│   └── package.json
├── frontend-mobile/           # Expo + React Native (iOS/Android)
│   ├── app/
│   │   ├── _layout.tsx        # Root layout with providers
│   │   ├── (tabs)/            # Bottom tab navigation
│   │   │   ├── index.tsx      # Home (medicine search)
│   │   │   ├── map.tsx        # Pharmacy map
│   │   │   └── profile.tsx    # User profile
│   │   ├── medicine/[id].tsx  # Medicine detail
│   │   ├── pharmacy/[id].tsx  # Pharmacy detail
│   │   ├── auth/              # Login/Register screens
│   │   └── scanner.tsx        # Barcode scanner
│   ├── components/            # Reusable UI components
│   ├── services/              # API and business logic
│   ├── store/                 # Zustand state management
│   ├── hooks/                 # Custom React hooks
│   ├── constants/             # Theme and config
│   ├── types/                 # TypeScript types
│   ├── eas.json               # EAS Build configuration
│   └── package.json
├── android/                   # Capacitor Android project
├── ios/                       # Capacitor iOS project
└── README.md

🔌 API Endpoints

Public API

  • GET /api/medicines/search?q=<query> - Search medicines from CIMA API (cached in Redis)
  • GET /api/medicines/:nregistro - Get medicine details from CIMA
  • GET /api/medicines/:nregistro/pharmacies - Get pharmacies selling a medicine
  • GET /api/pharmacies - Get all pharmacies

Authentication API

  • POST /api/auth/login - Login (requires username and password)
  • POST /api/auth/logout - Logout
  • GET /api/auth/check - Check authentication status

Admin API (All require authentication)

  • POST /api/admin/pharmacies - Add a new pharmacy
  • PUT /api/admin/pharmacies/:id - Update a pharmacy
  • DELETE /api/admin/pharmacies/:id - Delete a pharmacy
  • GET /api/admin/medicines?q=<query> - Search medicines from CIMA (for admin)
  • GET /api/admin/pharmacies/:id/medicines - Get medicines linked to a pharmacy
  • POST /api/admin/pharmacy-medicines - Link medicine to pharmacy
  • PUT /api/admin/pharmacy-medicines/:id - Update price/stock
  • DELETE /api/admin/pharmacy-medicines/:id - Remove medicine from pharmacy

💾 Database Schema

SQLite Tables

pharmacies

  • id: Integer (Primary Key)
  • name: Text (Pharmacy name)
  • address: Text (Full address)
  • phone: Text (Contact phone)
  • latitude: Real (GPS coordinate)
  • longitude: Real (GPS coordinate)

pharmacy_medicines

  • id: Integer (Primary Key)
  • pharmacy_id: Integer (Foreign Key → pharmacies.id)
  • medicine_nregistro: Text (CIMA medicine registration number)
  • medicine_name: Text (Cached medicine name)
  • price: Real (Price in EUR)
  • stock: Integer (Available units)

users

  • id: Integer (Primary Key)
  • username: Text (Unique)
  • password_hash: Text (Bcrypt hashed)
  • created_at: DateTime

Redis Cache Structure

  • medicines:search:{query} - Search results (TTL: 1 hour)
  • medicine:{nregistro} - Medicine details (TTL: 24 hours)

🔧 Architecture Changes

Migration from Local Database to CIMA API

The application now uses the CIMA (Centro de Información online de Medicamentos) API as the source of truth for medicine data, with Redis caching for performance:

Benefits:

  • Always up-to-date medicine information
  • Official data from Spanish health authorities
  • Reduced database maintenance
  • Fast responses thanks to Redis cache
  • Fallback to stale cache if API is down

Changes:

  • Medicines are no longer stored locally in SQLite
  • Medicine searches query the CIMA API
  • Results are cached in Redis for performance
  • pharmacy_medicines now uses medicine_nregistro (CIMA registration number) instead of local medicine_id

📱 Mobile App Setup (React Native)

Prerequisites

  • Node.js (v18 or higher)
  • npm or yarn
  • Expo CLI: npm install -g expo-cli
  • EAS CLI: npm install -g eas-cli
  • iOS: Xcode (Mac only) + CocoaPods
  • Android: Android Studio + Android SDK

Quick Start

# Install all dependencies (backend + web + mobile)
npm run install:all

# Start mobile development server
npm run dev:mobile

# Scan QR code with Expo Go app (iOS/Android)

Development Build

For native features (camera, biometrics, notifications), use a development build:

# Install EAS CLI
npm install -g eas-cli

# Login to Expo
eas login

# Create development build
eas build --profile development --platform ios
eas build --profile development --platform android

Project Structure

frontend-mobile/
├── app/                    # Expo Router screens
│   ├── (tabs)/             # Bottom tab navigation
│   ├── auth/               # Login/Register
│   ├── medicine/           # Medicine detail
│   ├── pharmacy/           # Pharmacy detail
│   └── scanner.tsx         # Barcode scanner
├── components/             # Reusable UI components
├── services/               # API and business logic
├── store/                  # Zustand state management
├── hooks/                  # Custom React hooks
├── constants/              # Theme and config
└── types/                  # TypeScript types

Native Features

Feature Implementation
Barcode Scanner expo-camera with CameraView
Push Notifications expo-notifications
Biometrics expo-local-authentication
Maps react-native-maps
Secure Storage expo-secure-store

EAS Build Profiles

Profile Platform Build Type Use Case
development iOS Simulator Local testing on Mac
development Android APK Local testing on device
preview Android APK Internal testing & sharing
production Android AAB Google Play Store submission

Note: iOS builds require Apple Developer account ($99/year) and are configured separately.

Environment Configuration

The mobile app uses the same backend API as the web app. Configure the API URL in:

// frontend-mobile/constants/config.ts
const ENV = {
  development: {
    API_BASE_URL: 'http://localhost:3001/api',
  },
  production: {
    API_BASE_URL: 'https://your-production-api.com/api',
  },
};

🚀 Production Deployment (Mobile)

Distribution Flow

Development → EAS Build → App Store / Google Play → User Device

The mobile app is a native application that runs directly on the device. No Docker or server needed - users download it from the app stores.

Step 1: Setup Expo Account

# Install EAS CLI
npm install -g eas-cli

# Create account at https://expo.dev

# Login
eas login

Step 2: Initialize EAS Project

cd frontend-mobile
eas init

This generates a projectId - add it to app.json:

"extra": {
  "eas": {
    "projectId": "your-project-id"
  }
}

Step 3: Configure Credentials

Android (Google Play):

  1. Create developer account ($25 one-time fee)
  2. Create project in Google Cloud Console
  3. Enable Play Developer API
  4. Download google-service-account.json
  5. Place in frontend-mobile/ directory

iOS (App Store):

  1. Join Apple Developer Program ($99/year)
  2. Create App ID in Apple Developer portal
  3. Generate certificates and provisioning profiles
  4. Update eas.json with your credentials

Step 4: Build for Production

# Android (Google Play)
eas build --profile production --platform android

# iOS (App Store)
eas build --profile production --platform ios

Step 5: Submit to Stores

# Submit to Google Play
eas submit --profile production --platform android

# Submit to App Store
eas submit --profile production --platform ios

OTA Updates (Without App Store Review)

Push updates directly to users without going through store review:

# Install expo-updates
npx expo install expo-updates

# Send update
eas update --branch production --message "Fix: improved search"

Useful Commands

Command Description
eas build:list View previous builds
eas build:cancel <id> Cancel a build
eas submit:list View previous submissions
eas update Send OTA update

🐛 Troubleshooting

Redis Connection Issues

If you see "Redis Client Error":

# Check if Redis is running
redis-cli ping

# Start Redis if needed
redis-server

CIMA API Timeout

If medicine searches are slow or failing:

  • Check your internet connection
  • The CIMA API may be temporarily unavailable
  • The app will use cached data if available

Database Issues

Reset the database:

cd backend
rm database.sqlite
npm run seed
npm run create-admin

📝 Development

Backend

Start with auto-reload:

cd backend
npm run dev

Frontend (Web/PWA)

Start development server:

cd frontend
npm run dev

Frontend (Mobile - React Native)

Install all dependencies:

npm run install:all

Start Expo dev server:

npm run dev:mobile

Start for specific platform:

npm run dev:mobile:android   # Android emulator
npm run dev:mobile:ios       # iOS simulator

Build with EAS:

npm run build:mobile         # Production build

Submit to stores:

npm run submit:android       # Google Play
npm run submit:ios           # App Store

Clear Redis cache

redis-cli FLUSHALL

🌐 External Resources

📄 License

ISC

S
Description
No description provided
Readme 14 MiB
Languages
JavaScript 39.8%
Python 32.6%
TypeScript 16.9%
CSS 8.5%
HTML 1.8%
Other 0.3%