# To AI Agent: Implement Server-Hosted Android APK Download Button and Automated Build Deployment Pipeline

## 1. Context & Feature Objective
We are adding a native Android app distribution workflow directly from our self-hosted server backend. Instead of relying purely on app stores, users visiting the web version from an Android device must be able to download the official compiled `.apk` file directly.

**Objective:** 1. **Backend Asset Exposure:** Configure a secure, static file directory on the Node.js/Express server to host the production `.apk` binary.
2. **Build Pipeline Link Automation:** Create a post-build deployment shell script. Every time a new production Android APK is generated (`release`), the script must automatically rename and copy it to the backend's public distribution folder under a persistent file pointer name (`yotrip-latest.apk`).
3. **Frontend Action Button:** Add an interactive "Tải ứng dụng Android" action row with a download icon inside both the Member and Guest profile menu sheets.

---

## 2. Technical Architecture & Implementation Steps

[Android Build Output] ➔ [deploy-apk.sh Script] ➔ [Backend public/downloads/yotrip-latest.apk]
▲
[Frontend UI Button] ➔ ➔ ➔ [Triggers HTTP GET Request] ➔ ➔ ➔ ➔ ➔ ┛

### Step 1: Configure Backend Static Asset Folder
Locate the core server setup file (e.g., `server.ts`, `app.ts`, or `index.js`). Ensure a dedicated folder path named `public/downloads` is created and mapped to express static file serving handlers:

```typescript
import express from 'express';
import path from 'path';

const app = express();

// Ensure the directory exists: public/downloads/
const downloadsDir = path.join(__dirname, '../public/downloads');

/* ✅ BACKEND STATIC MIDDLEWARE REGISTRATION
   This exposes the file at: [https://yourdomain.com/downloads/yotrip-latest.apk](https://yourdomain.com/downloads/yotrip-latest.apk)
*/
app.use('/downloads', express.static(downloadsDir, {
  setHeaders: (res) => {
    // Force browser engines to download the file directly instead of trying to parse it
    res.set('Content-Type', 'application/vnd.android.package-archive');
    res.set('Content-Disposition', 'attachment; filename="yotrip-latest.apk"');
  }
}));

### Step 2: Automate APK Release Mapping Link (Post-Build Script)
Create an automation script file named scripts/deploy-apk.sh in the root environment. This script runs instantly after your Android compiler output is generated (e.g., via Gradle ./gradlew assembleRelease or Capacitor/Cordova build actions):

#!/bin/bash

# Define relative path coordinates
ANDROID_OUTPUT_PATH="./android/app/build/outputs/apk/release/app-release.apk"
BACKEND_TARGET_DIR="./backend/public/downloads"
TARGET_FILE_NAME="yotrip-latest.apk"

echo "🚀 Starting automated post-build Android deployment pipeline..."

# 1. Verify compiler target exists
if [ -f "$ANDROID_OUTPUT_PATH" ]; then
    # 2. Ensure target storage folder structure is active
    mkdir -p "$BACKEND_TARGET_DIR"

    # 3. Copy and force overwrite the old production bundle with the updated version
    cp -f "$ANDROID_OUTPUT_PATH" "$BACKEND_TARGET_DIR/$TARGET_FILE_NAME"
    
    echo "✅ Success! New build copied safely to $BACKEND_TARGET_DIR/$TARGET_FILE_NAME"
    echo "🔗 Direct Download Link Active: /downloads/$TARGET_FILE_NAME"
else
    echo "❌ Critical Error: Android build output artifact not found at $ANDROID_OUTPUT_PATH"
    exit 1
fi

Add "build:android": "cd android && ./gradlew assembleRelease && cd .. && sh scripts/deploy-apk.sh" inside package.json scripts matrix for unified execution hooks.

### Step 3: Add Download Trigger into Frontend UI (MapProfileDropdown.tsx)
Locate the unified dropdown menu component created in the previous layout consolidation phase. Inject the direct-download operational action rows:

// Define the static destination asset link helper
const APK_DOWNLOAD_URL = `${process.env.REACT_APP_API_BASE_URL || ''}/downloads/yotrip-latest.apk`;

/* --- INSIDE AUTHENTICATED MEMBER STACK SECTION --- */
<div className="flex flex-col space-y-1">
  {/* Existing Dashboard, Profile, Create Tour rows... */}
  
  {/* NEW: ANDROID APK DIRECT DOWNLOAD BUTTON */}
  <a 
    href={APK_DOWNLOAD_URL} 
    download="yotrip.apk"
    className="flex items-center gap-3 w-full px-4 py-3 hover:bg-slate-800 rounded-lg text-left text-xs text-slate-200 transition-colors"
  >
    <svg xmlns="[http://www.w3.org/2000/svg](http://www.w3.org/2000/svg)" className="w-4 h-4 text-green-400 shrink-0" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={2}>
      <path strokeLinecap="round" strokeLinejoin="round" d="M4 16v1a3 3 0 003 3h10a3 3 0 003-3v1m-4-4l-4 4m0 0l-4-4m4 4V4" />
    </svg>
    <span>Tải ứng dụng Android (APK)</span>
  </a>
</div>

/* --- INSIDE ANONYMOUS GUEST STACK SECTION --- */
<div className="flex flex-col space-y-1">
  {/* Existing Guest language/theme configurations... */}
  
  <div className="h-[1px] bg-slate-800 my-1 mx-2" />
  
  {/* NEW: GUEST STATE ANDROID APK DOWNLOAD BUTTON */}
  <a 
    href={APK_DOWNLOAD_URL}
    download="yotrip.apk"
    className="flex items-center gap-3 w-full px-4 py-3 hover:bg-slate-800 rounded-lg text-left text-xs text-slate-200 transition-colors"
  >
    <svg xmlns="[http://www.w3.org/2000/svg](http://www.w3.org/2000/svg)" className="w-4 h-4 text-green-400 shrink-0" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={2}>
      <path strokeLinecap="round" strokeLinejoin="round" d="M12 18h.01M8 21h8a2 2 0 002-2V5a2 2 0 00-2-2H8a2 2 0 00-2 2v14a2 2 0 002 2z" />
    </svg>
    <span>Cài đặt bản Android (.APK)</span>
  </a>
  
  {/* Existing Register/Login Button row below... */}
</div>

## 3. Verification & Acceptance Criteria for AI Agent
    [ ] Deployment Script Validation: Run the build sequence script. Confirm that backend/public/downloads/yotrip-latest.apk updates its file modification timestamp matching the compiler execution timing logs.
    [ ] Direct Download Header Safety: Trigger a request to GET /downloads/yotrip-latest.apk. The network tab response must show content-type: application/vnd.android.package-archive to guarantee mobile devices instantly trigger package installation workflows.
    [ ] UI Integrity Test: Open the drop menu layout panel on a mobile simulator frame. Confirm that clicking the text icon row acts as a standard link target that downloads the binary file smoothly without breaking route navigation states.