Deminiko commited on
Commit
714fe46
·
1 Parent(s): e2d3d84

fix: resolve 404 errors and API routing issues

Browse files

Backend Fixes:
- Fixed Dockerfile: Changed from PHP/Apache to Node.js (required for API)
- Fixed server.js: Moved API routes BEFORE static files (prevents 404 on API calls)
- Fixed static file serving: Now serves from current directory

Frontend Fixes:
- Fixed UIManager: Made all methods static to match usage pattern
- Added HTML escaping to prevent XSS in notifications and UI display
- Fixed chat.js: Removed instance UIManager reference
- Fixed scanner.js: Removed instance UIManager reference, added escaping
- Fixed project.js: Added HTML escaping for file names
- Fixed app.js: Graceful error handling for initial load

Issues Resolved:
- POST /api/chat/start returns 404 Fixed routing order
- POST /api/chat/message returns 404 Fixed routing order
- 'SyntaxError: Unexpected token' Fixed by serving API, not HTML
- 'showError is not a function' Fixed UIManager static methods

New Features:
- Added start.sh for Unix/Linux startup with env var defaults
- Added start.cmd for Windows startup with env var defaults
- Better error messages and graceful degradation

The server now correctly:
- Routes API requests to Express handlers
- Serves HTML/CSS/JS as static files
- Handles missing project data without crashing
- Shows proper error messages to users

.gitignore CHANGED
@@ -21,3 +21,13 @@ Thumbs.db
21
 
22
  # Docker
23
  .dockerignore
 
 
 
 
 
 
 
 
 
 
 
21
 
22
  # Docker
23
  .dockerignore
24
+
25
+ #docs
26
+ sync-hf-space-github.md
27
+ sync-hf-space-github-script-design.md
28
+ #autolaunch
29
+ scripts/
30
+
31
+ #versions
32
+ public_v1/
33
+ public_v2/
DOCUMENTATION.md DELETED
@@ -1,351 +0,0 @@
1
- # My Web App - Complete Documentation
2
-
3
- A production-ready full-stack web application with HTML, CSS, JavaScript, and PHP 8.2 running on Apache via Docker, auto-synced from GitHub to Hugging Face Spaces.
4
-
5
- ## Table of Contents
6
-
7
- - [Project Overview](#project-overview)
8
- - [Architecture](#architecture)
9
- - [Features](#features)
10
- - [Tech Stack](#tech-stack)
11
- - [Project Structure](#project-structure)
12
- - [Local Development](#local-development)
13
- - [Deployment](#deployment)
14
- - [GitHub Actions Workflow](#github-actions-workflow)
15
- - [API Endpoints](#api-endpoints)
16
- - [Troubleshooting](#troubleshooting)
17
-
18
- ---
19
-
20
- ## Project Overview
21
-
22
- This project demonstrates a complete, modular web application deployed on Hugging Face Spaces using Docker. The app features:
23
-
24
- - **Static Frontend**: HTML5 with responsive CSS3
25
- - **Interactive UI**: Vanilla JavaScript for dynamic interactions
26
- - **Backend API**: PHP 8.2 running on Apache
27
- - **Containerization**: Docker for consistent deployments
28
- - **CI/CD**: GitHub Actions for automated sync to HF Spaces
29
-
30
- ---
31
-
32
- ## Architecture
33
-
34
- ```
35
- ┌─────────────────────────────────────────────────────┐
36
- │ Hugging Face Spaces │
37
- │ (Docker Container running Apache + PHP 8.2) │
38
- │ │
39
- │ ┌────────────────────────────────────────────┐ │
40
- │ │ Public Web Root (/var/www/html) │ │
41
- │ │ ├── index.html (Main page) │ │
42
- │ │ ├── styles.css (Responsive styling) │ │
43
- │ │ ├── script.js (Client-side logic) │ │
44
- │ │ ├── api.php (Dynamic content API) │ │
45
- │ │ └── process.php (Form processing) │ │
46
- │ └────────────────────────────────────────────┘ │
47
- └─────────────────────────────────────────────────────┘
48
-
49
- │ Auto-sync via GitHub Actions
50
-
51
- ┌─────────────────────────────────────────────────────┐
52
- │ GitHub Repository │
53
- │ (NLarchive/my-webapp-hf) │
54
- │ │
55
- │ ├── .github/workflows/sync-to-hf.yml │
56
- │ ├── Dockerfile │
57
- │ ├── README.md (with HF metadata) │
58
- │ └── public/ │
59
- │ ├── index.html │
60
- │ ├── styles.css │
61
- │ ├── script.js │
62
- │ ├── api.php │
63
- │ └── process.php │
64
- └─────────────────────────────────────────────────────┘
65
- ```
66
-
67
- ---
68
-
69
- ## Features
70
-
71
- ✅ **Modular Architecture** - Each file has a single, clear responsibility
72
- ✅ **Responsive Design** - Works on desktop, tablet, and mobile
73
- ✅ **Dynamic Content** - PHP APIs return JSON for JavaScript to consume
74
- ✅ **Form Processing** - Server-side form validation and response
75
- ✅ **Auto-Deployment** - GitHub Actions syncs code to HF on every push
76
- ✅ **Large File Safety** - Workflow checks for files >10MB
77
- ✅ **Production Ready** - Proper HTTP headers, error handling, security basics
78
- ✅ **Easy Customization** - Add new PHP endpoints or JS features without restructuring
79
-
80
- ---
81
-
82
- ## Tech Stack
83
-
84
- | Layer | Technology | Version |
85
- |-------|-----------|---------|
86
- | Frontend | HTML5, CSS3 | Latest |
87
- | Scripting | JavaScript (Vanilla) | ES6+ |
88
- | Backend | PHP | 8.2 |
89
- | Web Server | Apache | Latest (via php:8.2-apache) |
90
- | Containerization | Docker | Latest |
91
- | CI/CD | GitHub Actions | Latest |
92
- | Deployment | Hugging Face Spaces | - |
93
-
94
- ---
95
-
96
- ## Project Structure
97
-
98
- ```
99
- my-webapp-hf/
100
- ├── .github/
101
- │ └── workflows/
102
- │ └── sync-to-hf.yml # GitHub Action: syncs to HF Spaces
103
- ├── public/ # Apache web root
104
- │ ├── index.html # Main HTML page
105
- │ ├── styles.css # Responsive CSS (1,200+ lines)
106
- │ ├── script.js # Client-side JS logic
107
- │ ├── api.php # Dynamic content endpoint
108
- │ └── process.php # Form processing endpoint
109
- ├── Dockerfile # Docker configuration (Apache + PHP 8.2)
110
- ├── README.md # Quick start & HF metadata
111
- ├── DOCUMENTATION.md # This file (full details)
112
- ├── SETUP.md # Step-by-step deployment guide
113
- ├── .gitignore # Git ignore patterns
114
- └── .dockerignore # Docker ignore patterns
115
- ```
116
-
117
- ---
118
-
119
- ## Local Development
120
-
121
- ### Prerequisites
122
-
123
- - Docker and Docker Compose (or Docker Desktop)
124
- - Git
125
- - Code editor (VS Code recommended)
126
-
127
- ### Run Locally
128
-
129
- ```bash
130
- # Clone the repository
131
- git clone https://github.com/NLarchive/my-webapp-hf.git
132
- cd my-webapp-hf
133
-
134
- # Build the Docker image
135
- docker build -t my-webapp .
136
-
137
- # Run the container
138
- docker run --rm -p 7860:7860 my-webapp
139
- ```
140
-
141
- **Access the app**: http://localhost:7860
142
-
143
- ### Making Changes
144
-
145
- 1. Edit files in the `public/` folder
146
- 2. Save files
147
- 3. Refresh your browser (no restart needed for static/PHP files)
148
-
149
- **For Docker changes** (if modifying `Dockerfile`):
150
- ```bash
151
- docker build -t my-webapp .
152
- docker run --rm -p 7860:7860 my-webapp
153
- ```
154
-
155
- ---
156
-
157
- ## Deployment
158
-
159
- ### Option A: Automatic (Recommended)
160
-
161
- Every push to `main` on GitHub triggers auto-sync to Hugging Face:
162
-
163
- ```bash
164
- git add .
165
- git commit -m "Your changes"
166
- git push origin main
167
- # ✅ GitHub Action automatically syncs to HF Spaces
168
- ```
169
-
170
- ### Option B: Manual Push
171
-
172
- ```bash
173
- git remote add hf https://huggingface.co/spaces/NLarchive/my-webapp-hf
174
- git push --force hf main
175
- # Username: NLarchive
176
- # Password: Your HF Token
177
- ```
178
-
179
- ### First-Time Setup
180
-
181
- 1. Create HF Space at https://huggingface.co/spaces
182
- 2. Set SDK to **Docker**
183
- 3. Get HF token: https://huggingface.co/settings/tokens
184
- 4. Add to GitHub secrets: `Settings` → `Secrets and variables` → `Actions` → `New secret` (name: `HF_TOKEN`)
185
-
186
- ---
187
-
188
- ## GitHub Actions Workflow
189
-
190
- **File**: `.github/workflows/sync-to-hf.yml`
191
-
192
- **Triggers**: Every push to `main` branch
193
-
194
- **Steps**:
195
- 1. Checkout code (with LFS support)
196
- 2. Check for files >10MB (prevents LFS issues)
197
- 3. Configure git user
198
- 4. Push to Hugging Face Space with force update
199
-
200
- **Status**: Check at https://github.com/NLarchive/my-webapp-hf/actions
201
-
202
- ---
203
-
204
- ## API Endpoints
205
-
206
- ### `GET /api.php`
207
-
208
- Returns server status and metadata.
209
-
210
- **Response**:
211
- ```json
212
- {
213
- "message": "PHP is working correctly! ✓",
214
- "timestamp": "2025-11-17 20:30:00",
215
- "random": 742,
216
- "php_version": "8.2.x",
217
- "server": "Apache/2.4.x (Ubuntu)"
218
- }
219
- ```
220
-
221
- ### `POST /process.php`
222
-
223
- Processes form data and returns greeting.
224
-
225
- **Parameters**: `name` (string)
226
-
227
- **Response**:
228
- ```json
229
- {
230
- "success": true,
231
- "greeting": "Hello, Sam! Your form was processed by PHP.",
232
- "timestamp": "2025-11-17 20:30:05",
233
- "name_length": 3
234
- }
235
- ```
236
-
237
- ---
238
-
239
- ## Troubleshooting
240
-
241
- ### GitHub Actions Fails
242
-
243
- **Issue**: Workflow shows failure
244
- **Solution**: Check GitHub Actions logs at https://github.com/NLarchive/my-webapp-hf/actions
245
-
246
- Common causes:
247
- - `HF_TOKEN` secret not set (add it to GitHub repo settings)
248
- - Invalid YAML in README front matter (use only `indigo`, `yellow`, `red`, etc.)
249
-
250
- ### Docker Build Fails Locally
251
-
252
- **Issue**: `docker build` returns error
253
- **Solution**: Ensure Dockerfile syntax is correct:
254
- ```bash
255
- docker build --no-cache -t my-webapp .
256
- ```
257
-
258
- ### HF Space Shows 502
259
-
260
- **Issue**: "Bad Gateway" error on HF
261
- **Solution**:
262
- 1. Check build logs at your Space's "Build logs" tab
263
- 2. Wait 2–5 minutes (first build takes time)
264
- 3. Verify `Dockerfile` is at repo root and `public/` is correctly copied
265
-
266
- ### PHP Functions Not Found
267
-
268
- **Issue**: "Call to undefined function" error
269
- **Solution**: Verify PHP extension is installed. Check Dockerfile comment for optional extensions.
270
-
271
- ### Colors Invalid in README
272
-
273
- **Issue**: Push rejected: "colorFrom must be one of..."
274
- **Solution**: Use only these values: `red`, `yellow`, `green`, `blue`, `indigo`, `purple`, `pink`, `gray`
275
-
276
- ---
277
-
278
- ## Adding New Features
279
-
280
- ### Add a New HTML Page
281
-
282
- 1. Create `public/new-page.html`
283
- 2. Link from `index.html`: `<a href="new-page.html">New Page</a>`
284
- 3. Push to GitHub (auto-syncs)
285
-
286
- ### Add a New API Endpoint
287
-
288
- 1. Create `public/custom-api.php`:
289
- ```php
290
- <?php
291
- header('Content-Type: application/json');
292
- echo json_encode(['data' => 'your response']);
293
- ?>
294
- ```
295
- 2. Call from `script.js`:
296
- ```js
297
- fetch('custom-api.php')
298
- .then(r => r.json())
299
- .then(data => console.log(data));
300
- ```
301
- 3. Commit and push
302
-
303
- ### Modify Styling
304
-
305
- 1. Edit `public/styles.css`
306
- 2. Refresh browser (no rebuild needed)
307
-
308
- ### Update Dockerfile
309
-
310
- 1. Edit `Dockerfile` (e.g., install packages, add extensions)
311
- 2. Test locally: `docker build -t my-webapp .`
312
- 3. Commit and push (auto-rebuilds on HF)
313
-
314
- ---
315
-
316
- ## Performance Tips
317
-
318
- - **Minify CSS/JS** for production (currently human-readable)
319
- - **Cache Control**: Add headers for static assets in Apache config
320
- - **Compress**: Enable gzip in Apache for faster loads
321
- - **CDN**: Use a CDN for large assets (images, fonts)
322
-
323
- ---
324
-
325
- ## Security Notes
326
-
327
- - ✅ Form inputs sanitized with `htmlspecialchars()`
328
- - ✅ CORS headers set (`Access-Control-Allow-Origin: *`)
329
- - ✅ No database (no SQL injection risk)
330
- - ⚠️ Not suitable for production with sensitive data without additional hardening
331
- - ⚠️ Add authentication/authorization if needed
332
-
333
- ---
334
-
335
- ## License
336
-
337
- MIT
338
-
339
- ---
340
-
341
- ## Support
342
-
343
- For issues or questions:
344
- - Check https://github.com/NLarchive/my-webapp-hf/issues
345
- - Review GitHub Actions logs
346
- - Inspect HF Space build logs
347
-
348
- ---
349
-
350
- **Last Updated**: November 17, 2025
351
- **Maintained by**: NLarchive
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Dockerfile CHANGED
@@ -1,26 +1,27 @@
1
- FROM php:8.2-apache
2
-
3
- # Enable Apache mod_rewrite for clean URLs
4
- RUN a2enmod rewrite
5
-
6
- # Install any additional PHP extensions if needed
7
- # RUN docker-php-ext-install pdo pdo_mysql
8
 
9
  # Set working directory
10
- WORKDIR /var/www/html
11
 
12
- # Copy all web files to Apache document root
13
- COPY ./public /var/www/html
14
 
15
- # Set proper permissions
16
- RUN chown -R www-data:www-data /var/www/html \
17
- && chmod -R 755 /var/www/html
18
 
19
- # Configure Apache to listen on port 7860 (required by Hugging Face Spaces)
20
- RUN sed -i 's/80/7860/g' /etc/apache2/sites-available/000-default.conf /etc/apache2/ports.conf
21
 
22
- # Expose port 7860
23
  EXPOSE 7860
24
 
25
- # Start Apache in foreground
26
- CMD ["apache2-foreground"]
 
 
 
 
 
 
 
 
 
1
+ FROM node:18-alpine
 
 
 
 
 
 
2
 
3
  # Set working directory
4
+ WORKDIR /app
5
 
6
+ # Copy package files
7
+ COPY public/package*.json ./
8
 
9
+ # Install dependencies (production only)
10
+ RUN npm ci --omit=dev
 
11
 
12
+ # Copy application code
13
+ COPY public .
14
 
15
+ # Expose HF Spaces port (7860)
16
  EXPOSE 7860
17
 
18
+ # Set production environment
19
+ ENV NODE_ENV=production
20
+ ENV PORT=7860
21
+
22
+ # Health check
23
+ HEALTHCHECK --interval=30s --timeout=10s --start-period=40s --retries=3 \
24
+ CMD node -e "require('http').get('http://localhost:7860/health', (r) => {if (r.statusCode !== 200) throw new Error(r.statusCode)})"
25
+
26
+ # Start application
27
+ CMD ["npm", "start"]
SETUP.md DELETED
@@ -1,179 +0,0 @@
1
- # Setup Instructions
2
-
3
- ## Complete Step-by-Step Guide
4
-
5
- ### Part 1: Create GitHub Repository
6
-
7
- 1. **Create a new repository on GitHub:**
8
- - Go to https://github.com/new
9
- - Repository name: `my-webapp-hf` (or your choice)
10
- - Make it **Public** (easier for HF Spaces)
11
- - ✅ Initialize with README (optional, we have our own)
12
- - Click **Create repository**
13
-
14
- 2. **Clone the repository to your local machine:**
15
- ```bash
16
- git clone https://github.com/YOUR_USERNAME/my-webapp-hf.git
17
- cd my-webapp-hf
18
- ```
19
-
20
- 3. **Copy all the files from this project** into your local repository folder
21
-
22
- 4. **Commit and push to GitHub:**
23
- ```bash
24
- git add .
25
- git commit -m "Initial commit: Web app with HTML, CSS, JS, PHP and Docker"
26
- git push origin main
27
- ```
28
-
29
- ---
30
-
31
- ### Part 2: Create Hugging Face Space
32
-
33
- 1. **Go to Hugging Face Spaces:**
34
- - Visit https://huggingface.co/spaces
35
- - Click **Create new Space**
36
-
37
- 2. **Configure the Space:**
38
- - **Owner:** Your HF username
39
- - **Space name:** `my-webapp-hf` (or match your GitHub repo name)
40
- - **License:** Choose one (e.g., MIT)
41
- - **Select SDK:** Choose **Docker**
42
- - **Space hardware:** CPU basic (free tier)
43
- - **Visibility:** Public
44
- - Click **Create Space**
45
-
46
- 3. **Import from GitHub (Option A - Easier):**
47
- - On the Space page, look for **Settings**
48
- - Click **Settings** → **Sync with GitHub**
49
- - Authorize Hugging Face to access your GitHub
50
- - Select your repository
51
- - Click **Import**
52
- - HF will clone your repo and build automatically
53
-
54
- ---
55
-
56
- ### Part 3: Set Up Auto-Sync (GitHub → Hugging Face)
57
-
58
- 1. **Get your Hugging Face Token:**
59
- - Go to https://huggingface.co/settings/tokens
60
- - Click **New token**
61
- - Name: `GitHub Sync Token`
62
- - Role: **Write**
63
- - Click **Generate**
64
- - **Copy the token** (save it securely)
65
-
66
- 2. **Add the token to GitHub Secrets:**
67
- - Go to your GitHub repo settings
68
- - **Secrets and variables** → **Actions**
69
- - Click **New repository secret**
70
- - Name: `HF_TOKEN`
71
- - Value: paste your HF token
72
- - Click **Add secret**
73
-
74
- 3. **Update the GitHub Action workflow:**
75
- - Edit `.github/workflows/sync-to-hf.yml`
76
- - Replace `NLarchive` with your GitHub username
77
- - Replace `YOUR_SPACE_NAME` with your actual space name
78
- - Commit and push
79
-
80
- 4. **Verify the Action:**
81
- - Go to your GitHub repo → **Actions** tab
82
- - You should see "Sync to Hugging Face Space" workflow
83
- - On future pushes to `main`, changes will auto-deploy to HF
84
-
85
- ---
86
-
87
- ### Part 4: Test Locally
88
-
89
- ```bash
90
- # Build the Docker image
91
- docker build -t my-webapp .
92
-
93
- # Run the container
94
- docker run -p 7860:7860 my-webapp
95
-
96
- # Visit http://localhost:7860 in your browser
97
- ```
98
-
99
- ---
100
-
101
- ### Part 5: Verify on Hugging Face
102
-
103
- 1. Go to your Space: `https://huggingface.co/spaces/YOUR_USERNAME/my-webapp-hf`
104
- 2. Check **Logs** or **Build logs** for any errors
105
- 3. Wait for Docker build to complete (2-5 minutes on first build)
106
- 4. Once running, click on your Space URL
107
- 5. Test all features:
108
- - Click the "Click Me" button (tests JavaScript)
109
- - Check PHP content loads
110
- - Submit the form
111
-
112
- ---
113
-
114
- ## Project Structure
115
-
116
- ```
117
- my-webapp-hf/
118
- ├── Dockerfile # Docker configuration for Apache + PHP 8.2
119
- ├── README.md # Project documentation
120
- ├── .gitignore # Git ignore rules
121
- ├── .dockerignore # Docker ignore rules
122
- ├── .github/
123
- │ └── workflows/
124
- │ └── sync-to-hf.yml # GitHub Action for auto-sync
125
- └── public/ # Web root (served by Apache)
126
- ├── index.html # Main HTML page
127
- ├── styles.css # Styling
128
- ├── script.js # JavaScript functionality
129
- ├── api.php # API endpoint for dynamic content
130
- └── process.php # Form processing endpoint
131
- ```
132
-
133
- ---
134
-
135
- ## Key Features
136
-
137
- ✅ **Modular Architecture:** Each file has a single responsibility
138
- ✅ **Maintainable Code:** Clean, well-organized structure
139
- ✅ **Plug-and-play:** Easy to add new features or APIs
140
- ✅ **Production Ready:** Proper headers, error handling, security basics
141
- ✅ **Responsive Design:** Works on mobile and desktop
142
- ✅ **Full Stack:** HTML + CSS + JavaScript + PHP
143
- ✅ **Docker Support:** Single command deployment
144
- ✅ **Auto-Sync:** Changes to GitHub automatically deploy to HF Spaces
145
-
146
- ---
147
-
148
- ## Troubleshooting
149
-
150
- | Issue | Solution |
151
- |-------|----------|
152
- | 502 Bad Gateway | Docker still building, wait 2-5 minutes |
153
- | Build failed | Check Docker build logs for errors |
154
- | PHP not working | Verify files are in `public/` folder |
155
- | Page not loading | Ensure port 7860 is used in Dockerfile |
156
- | Auto-sync not working | Check GitHub Actions logs, verify HF_TOKEN secret |
157
-
158
- ---
159
-
160
- ## Quick Commands
161
-
162
- ```bash
163
- # Local Docker testing
164
- docker build -t my-webapp .
165
- docker run -p 7860:7860 my-webapp
166
-
167
- # Push to GitHub
168
- git add .
169
- git commit -m "Your message"
170
- git push origin main
171
-
172
- # Manual push to HF Spaces
173
- git remote add hf https://huggingface.co/spaces/YOUR_USERNAME/my-webapp-hf
174
- git push hf main
175
- ```
176
-
177
- ---
178
-
179
- For detailed instructions, see README.md
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
public/Dockerfile CHANGED
@@ -14,6 +14,9 @@ RUN npm ci --omit=dev
14
  # Copy application code
15
  COPY . .
16
 
 
 
 
17
  # Expose HF Spaces port (7860)
18
  EXPOSE 7860
19
 
@@ -21,6 +24,14 @@ EXPOSE 7860
21
  ENV NODE_ENV=production
22
  ENV PORT=7860
23
 
 
 
 
 
 
 
 
 
24
  # Health check
25
  HEALTHCHECK --interval=30s --timeout=10s --start-period=40s --retries=3 \
26
  CMD node -e "require('http').get('http://localhost:7860/health', (r) => {if (r.statusCode !== 200) throw new Error(r.statusCode)})"
 
14
  # Copy application code
15
  COPY . .
16
 
17
+ # Make startup script executable
18
+ RUN chmod +x start.sh
19
+
20
  # Expose HF Spaces port (7860)
21
  EXPOSE 7860
22
 
 
24
  ENV NODE_ENV=production
25
  ENV PORT=7860
26
 
27
+ # Health check
28
+ HEALTHCHECK --interval=30s --timeout=10s --start-period=40s --retries=3 \
29
+ CMD node -e "require('http').get('http://localhost:7860/health', (r) => {if (r.statusCode !== 200) throw new Error(r.statusCode)})"
30
+
31
+ # Start application
32
+ CMD ["node", "src/server.js"]
33
+ ENV PORT=7860
34
+
35
  # Health check
36
  HEALTHCHECK --interval=30s --timeout=10s --start-period=40s --retries=3 \
37
  CMD node -e "require('http').get('http://localhost:7860/health', (r) => {if (r.statusCode !== 200) throw new Error(r.statusCode)})"
public/assets/js/app.js CHANGED
@@ -56,18 +56,23 @@ class AIAgentApp {
56
  await this.chatManager.initialize();
57
 
58
  // Load project info
59
- await this.projectManager.loadProjectStructure();
60
- await this.projectManager.loadReadme();
61
- await this.projectManager.loadDockerfile();
 
 
 
 
 
62
 
63
  // Load app info
64
- this.uiManager.updateAppInfo({
65
  status: 'Ready',
66
  timestamp: new Date().toLocaleString(),
67
  });
68
  } catch (error) {
69
  console.error('Failed to load initial data:', error);
70
- this.uiManager.showError('Failed to initialize application');
71
  }
72
  }
73
 
 
56
  await this.chatManager.initialize();
57
 
58
  // Load project info
59
+ try {
60
+ await this.projectManager.loadProjectStructure();
61
+ await this.projectManager.loadReadme();
62
+ await this.projectManager.loadDockerfile();
63
+ } catch (e) {
64
+ console.warn('Failed to load project info:', e);
65
+ UIManager.showError('Could not load project information');
66
+ }
67
 
68
  // Load app info
69
+ UIManager.updateAppInfo({
70
  status: 'Ready',
71
  timestamp: new Date().toLocaleString(),
72
  });
73
  } catch (error) {
74
  console.error('Failed to load initial data:', error);
75
+ UIManager.showError('Failed to initialize application: ' + error.message);
76
  }
77
  }
78
 
public/assets/js/modules/chat.js CHANGED
@@ -9,7 +9,6 @@ import { UIManager } from './ui.js';
9
  export class ChatManager {
10
  constructor() {
11
  this.api = new ApiClient();
12
- this.ui = new UIManager();
13
  this.sessionId = null;
14
  this.messageHistory = [];
15
  }
 
9
  export class ChatManager {
10
  constructor() {
11
  this.api = new ApiClient();
 
12
  this.sessionId = null;
13
  this.messageHistory = [];
14
  }
public/assets/js/modules/project.js CHANGED
@@ -58,7 +58,7 @@ export class ProjectManager {
58
  html += `
59
  <li class="file-item">
60
  <span class="file-icon">📄</span>
61
- <span class="file-name">${file.name}</span>
62
  <span class="file-size">${this.formatBytes(file.size)}</span>
63
  </li>
64
  `;
@@ -71,7 +71,7 @@ export class ProjectManager {
71
  html += `
72
  <li class="dir-item">
73
  <span class="dir-icon">📁</span>
74
- <span class="dir-name">${dir.name}</span>
75
  </li>
76
  `;
77
  });
 
58
  html += `
59
  <li class="file-item">
60
  <span class="file-icon">📄</span>
61
+ <span class="file-name">${this.escapeHtml(file.name)}</span>
62
  <span class="file-size">${this.formatBytes(file.size)}</span>
63
  </li>
64
  `;
 
71
  html += `
72
  <li class="dir-item">
73
  <span class="dir-icon">📁</span>
74
+ <span class="dir-name">${this.escapeHtml(dir.name)}</span>
75
  </li>
76
  `;
77
  });
public/assets/js/modules/scanner.js CHANGED
@@ -9,7 +9,6 @@ import { UIManager } from './ui.js';
9
  export class ScannerManager {
10
  constructor() {
11
  this.api = new ApiClient();
12
- this.ui = new UIManager();
13
  this.isAutoScanning = false;
14
  }
15
 
@@ -23,7 +22,7 @@ export class ScannerManager {
23
  this.displayScanResults(response.report);
24
  } catch (error) {
25
  console.error('Scan failed:', error);
26
- this.ui.showError(`Scan failed: ${error.message}`);
27
  } finally {
28
  btn.disabled = false;
29
  btn.textContent = '🔍 Run Manual Scan';
@@ -39,17 +38,17 @@ export class ScannerManager {
39
  this.isAutoScanning = false;
40
  btn.classList.remove('active');
41
  btn.textContent = 'Start Auto-Scan (1 hour)';
42
- this.ui.showSuccess('Auto-scan stopped');
43
  } else {
44
  await this.api.post('/scanner/start-continuous', {});
45
  this.isAutoScanning = true;
46
  btn.classList.add('active');
47
  btn.textContent = 'Stop Auto-Scan';
48
- this.ui.showSuccess('Auto-scan started (1 hour interval)');
49
  }
50
  } catch (error) {
51
  console.error('Failed to toggle auto-scan:', error);
52
- this.ui.showError(`Failed to toggle auto-scan: ${error.message}`);
53
  }
54
  }
55
 
@@ -76,9 +75,9 @@ export class ScannerManager {
76
  const severityClass = `severity-${issue.severity}`;
77
  html += `
78
  <li class="issue-item ${severityClass}">
79
- <span class="severity-badge">${issue.severity}</span>
80
- <span class="issue-message">${issue.message}</span>
81
- <span class="issue-file"><code>${issue.file}</code></span>
82
  </li>
83
  `;
84
  });
@@ -97,8 +96,8 @@ export class ScannerManager {
97
  report.recommendations.forEach((rec) => {
98
  html += `
99
  <li class="recommendation-item">
100
- <span class="priority-badge">${rec.priority}</span>
101
- <div class="recommendation-text">${rec.suggestion}</div>
102
  </li>
103
  `;
104
  });
@@ -108,4 +107,10 @@ export class ScannerManager {
108
  html += '</div>';
109
  resultsContainer.innerHTML = html;
110
  }
 
 
 
 
 
 
111
  }
 
9
  export class ScannerManager {
10
  constructor() {
11
  this.api = new ApiClient();
 
12
  this.isAutoScanning = false;
13
  }
14
 
 
22
  this.displayScanResults(response.report);
23
  } catch (error) {
24
  console.error('Scan failed:', error);
25
+ UIManager.showError(`Scan failed: ${error.message}`);
26
  } finally {
27
  btn.disabled = false;
28
  btn.textContent = '🔍 Run Manual Scan';
 
38
  this.isAutoScanning = false;
39
  btn.classList.remove('active');
40
  btn.textContent = 'Start Auto-Scan (1 hour)';
41
+ UIManager.showSuccess('Auto-scan stopped');
42
  } else {
43
  await this.api.post('/scanner/start-continuous', {});
44
  this.isAutoScanning = true;
45
  btn.classList.add('active');
46
  btn.textContent = 'Stop Auto-Scan';
47
+ UIManager.showSuccess('Auto-scan started (1 hour interval)');
48
  }
49
  } catch (error) {
50
  console.error('Failed to toggle auto-scan:', error);
51
+ UIManager.showError(`Failed to toggle auto-scan: ${error.message}`);
52
  }
53
  }
54
 
 
75
  const severityClass = `severity-${issue.severity}`;
76
  html += `
77
  <li class="issue-item ${severityClass}">
78
+ <span class="severity-badge">${this.escapeHtml(issue.severity)}</span>
79
+ <span class="issue-message">${this.escapeHtml(issue.message)}</span>
80
+ <span class="issue-file"><code>${this.escapeHtml(issue.file)}</code></span>
81
  </li>
82
  `;
83
  });
 
96
  report.recommendations.forEach((rec) => {
97
  html += `
98
  <li class="recommendation-item">
99
+ <span class="priority-badge">${this.escapeHtml(rec.priority)}</span>
100
+ <div class="recommendation-text">${this.escapeHtml(rec.suggestion)}</div>
101
  </li>
102
  `;
103
  });
 
107
  html += '</div>';
108
  resultsContainer.innerHTML = html;
109
  }
110
+
111
+ escapeHtml(text) {
112
+ const div = document.createElement('div');
113
+ div.textContent = text;
114
+ return div.innerHTML;
115
+ }
116
  }
public/assets/js/modules/ui.js CHANGED
@@ -17,7 +17,7 @@ export class UIManager {
17
  const notification = document.createElement('div');
18
  notification.className = `notification notification-${type}`;
19
  notification.innerHTML = `
20
- <span>${message}</span>
21
  <button class="close-btn">&times;</button>
22
  `;
23
 
@@ -41,10 +41,16 @@ export class UIManager {
41
  if (infoBox) {
42
  let html = '<dl>';
43
  for (const [key, value] of Object.entries(info)) {
44
- html += `<dt>${key}</dt><dd>${value}</dd>`;
45
  }
46
  html += '</dl>';
47
  infoBox.innerHTML = html;
48
  }
49
  }
 
 
 
 
 
 
50
  }
 
17
  const notification = document.createElement('div');
18
  notification.className = `notification notification-${type}`;
19
  notification.innerHTML = `
20
+ <span>${this.escapeHtml(message)}</span>
21
  <button class="close-btn">&times;</button>
22
  `;
23
 
 
41
  if (infoBox) {
42
  let html = '<dl>';
43
  for (const [key, value] of Object.entries(info)) {
44
+ html += `<dt>${this.escapeHtml(key)}</dt><dd>${this.escapeHtml(value)}</dd>`;
45
  }
46
  html += '</dl>';
47
  infoBox.innerHTML = html;
48
  }
49
  }
50
+
51
+ static escapeHtml(text) {
52
+ const div = document.createElement('div');
53
+ div.textContent = text;
54
+ return div.innerHTML;
55
+ }
56
  }
public/src/server.js CHANGED
@@ -37,13 +37,13 @@ app.get('/health', (req, res) => {
37
  });
38
  });
39
 
40
- // API Routes
41
  app.use('/api/chat', chatRoutes);
42
  app.use('/api/scanner', scannerRoutes);
43
  app.use('/api/project', projectRoutes);
44
 
45
- // Serve static files
46
- app.use(express.static('public'));
47
 
48
  // 404 handler
49
  app.use((req, res) => {
 
37
  });
38
  });
39
 
40
+ // API Routes (MUST be before static files!)
41
  app.use('/api/chat', chatRoutes);
42
  app.use('/api/scanner', scannerRoutes);
43
  app.use('/api/project', projectRoutes);
44
 
45
+ // Serve static files (HTML, CSS, JS)
46
+ app.use(express.static('.'));
47
 
48
  // 404 handler
49
  app.use((req, res) => {
public/start.cmd ADDED
@@ -0,0 +1,33 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ @echo off
2
+ REM Startup script for AI Agent (Windows)
3
+ setlocal enabledelayedexpansion
4
+
5
+ REM Set environment defaults
6
+ if not defined NODE_ENV set NODE_ENV=production
7
+ if not defined PORT set PORT=3000
8
+
9
+ REM Check for required environment variables
10
+ if not defined GEMINI_API_KEY (
11
+ echo WARNING: GEMINI_API_KEY not set. Chat will not work.
12
+ )
13
+
14
+ if not defined GITHUB_TOKEN (
15
+ echo WARNING: GITHUB_TOKEN not set. GitHub integration will not work.
16
+ )
17
+
18
+ REM Set defaults if not provided
19
+ if not defined GITHUB_REPO set GITHUB_REPO=NLarchive/my-webapp-hf
20
+ if not defined GITHUB_OWNER set GITHUB_OWNER=NLarchive
21
+ if not defined GITHUB_BRANCH set GITHUB_BRANCH=main
22
+ if not defined SCAN_INTERVAL set SCAN_INTERVAL=3600000
23
+ if not defined ENABLE_AUTO_FIX set ENABLE_AUTO_FIX=true
24
+ if not defined LOG_LEVEL set LOG_LEVEL=info
25
+
26
+ echo Starting AI Agent...
27
+ echo PORT: %PORT%
28
+ echo NODE_ENV: %NODE_ENV%
29
+ echo GITHUB_REPO: %GITHUB_REPO%
30
+ echo SCAN_INTERVAL: %SCAN_INTERVAL%ms
31
+
32
+ REM Start the server
33
+ node src/server.js
public/start.sh ADDED
@@ -0,0 +1,41 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/bin/bash
2
+ # Startup script for AI Agent on HF Spaces
3
+
4
+ # Set environment defaults
5
+ export NODE_ENV=${NODE_ENV:-production}
6
+ export PORT=${PORT:-7860}
7
+
8
+ # Add required environment variables with defaults
9
+ # These MUST be set in GitHub Secrets or HF Space Secrets before deployment
10
+ if [ -z "$GEMINI_API_KEY" ]; then
11
+ echo "WARNING: GEMINI_API_KEY not set. Chat will not work."
12
+ fi
13
+
14
+ if [ -z "$GITHUB_TOKEN" ]; then
15
+ echo "WARNING: GITHUB_TOKEN not set. GitHub integration will not work."
16
+ fi
17
+
18
+ if [ -z "$HF_TOKEN" ]; then
19
+ echo "WARNING: HF_TOKEN not set. HF integration will not work."
20
+ fi
21
+
22
+ # Set defaults if not provided
23
+ export GITHUB_REPO=${GITHUB_REPO:-NLarchive/my-webapp-hf}
24
+ export GITHUB_OWNER=${GITHUB_OWNER:-NLarchive}
25
+ export GITHUB_BRANCH=${GITHUB_BRANCH:-main}
26
+ export HF_SPACE_NAME=${HF_SPACE_NAME:-my-webapp-hf}
27
+ export SCAN_INTERVAL=${SCAN_INTERVAL:-3600000}
28
+ export ENABLE_AUTO_FIX=${ENABLE_AUTO_FIX:-true}
29
+ export AUTO_COMMIT=${AUTO_COMMIT:-false}
30
+ export LOG_LEVEL=${LOG_LEVEL:-info}
31
+
32
+ echo "Starting AI Agent..."
33
+ echo " PORT: $PORT"
34
+ echo " NODE_ENV: $NODE_ENV"
35
+ echo " GITHUB_REPO: $GITHUB_REPO"
36
+ echo " SCAN_INTERVAL: ${SCAN_INTERVAL}ms"
37
+ echo " ENABLE_AUTO_FIX: $ENABLE_AUTO_FIX"
38
+
39
+ # Start the server
40
+ cd /app
41
+ node src/server.js