Raí Santos commited on
Commit
87bbdf3
·
1 Parent(s): 65f788b

Optimized for Hugging Face Spaces

Browse files
Dockerfile CHANGED
@@ -1,68 +1,48 @@
1
- # Multi-stage build for optimized production image
2
- # Stage 1: Build dependencies and download media
3
- FROM node:18-alpine AS builder
4
-
5
- # Install curl for downloading (if needed)
6
- RUN apk add --no-cache curl
7
 
 
8
  WORKDIR /app
9
 
10
- # Copy package files
11
- COPY package*.json ./
12
-
13
- # Install ALL dependencies (including devDependencies for scripts)
14
- RUN npm ci && npm cache clean --force
15
-
16
- # Copy application files and scripts
17
- COPY . .
18
-
19
- # Download videos and audio files (with error handling)
20
- RUN npm run download || echo "Warning: Video download failed, will use CDN fallback"
21
-
22
- # Build production assets
23
- RUN npm run build || echo "Build step skipped"
24
-
25
- # Stage 2: Production image
26
- FROM node:18-alpine AS production
27
-
28
- WORKDIR /app
29
 
30
  # Copy package files
31
  COPY package*.json ./
32
 
33
- # Install ONLY production dependencies
34
- RUN npm ci --only=production && npm cache clean --force
35
-
36
- # Create non-root user for security FIRST
37
- RUN addgroup -g 1001 -S nodejs && \
38
- adduser -S nodejs -u 1001 -G nodejs
39
 
40
- # Copy entrypoint script as root and make executable
41
- COPY docker-entrypoint.sh /usr/local/bin/docker-entrypoint.sh
42
- RUN chmod +x /usr/local/bin/docker-entrypoint.sh
 
43
 
44
- # Copy built application from builder
45
- COPY --from=builder /app/public ./public
46
- COPY --from=builder /app/dist ./dist
47
- COPY --from=builder /app/server.js ./server.js
48
- COPY --from=builder /app/scripts ./scripts
49
 
50
- # Change ownership of app directory to nodejs user
51
- RUN chown -R nodejs:nodejs /app
 
 
52
 
53
- # Switch to non-root user
54
  USER nodejs
55
 
 
 
 
 
56
  # Expose port
57
  EXPOSE 7860
58
 
59
- # Set environment variables
60
- ENV NODE_ENV=production
61
- ENV PORT=7860
62
-
63
  # Health check
64
- HEALTHCHECK --interval=30s --timeout=3s --start-period=10s --retries=3 \
65
- CMD node -e "require('http').get('http://localhost:7860/', (res) => { process.exit(res.statusCode === 200 ? 0 : 1) })"
 
 
 
66
 
67
- # Start the application using entrypoint script
68
- ENTRYPOINT ["/usr/local/bin/docker-entrypoint.sh"]
 
1
+ # Optimized Dockerfile for Hugging Face Spaces
2
+ FROM node:18-alpine
 
 
 
 
3
 
4
+ # Set working directory
5
  WORKDIR /app
6
 
7
+ # Install only what's needed
8
+ RUN apk add --no-cache curl tini
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9
 
10
  # Copy package files
11
  COPY package*.json ./
12
 
13
+ # Install dependencies (production only for smaller image)
14
+ RUN npm ci --only=production --quiet && \
15
+ npm cache clean --force
 
 
 
16
 
17
+ # Copy application code
18
+ COPY public ./public
19
+ COPY server.js ./
20
+ COPY scripts ./scripts
21
 
22
+ # Create directories for media (will be populated at runtime if needed)
23
+ RUN mkdir -p public/videos public/songs && \
24
+ chmod -R 755 public
 
 
25
 
26
+ # Non-root user for security
27
+ RUN addgroup -g 1001 -S nodejs && \
28
+ adduser -S nodejs -u 1001 -G nodejs && \
29
+ chown -R nodejs:nodejs /app
30
 
 
31
  USER nodejs
32
 
33
+ # Environment variables
34
+ ENV NODE_ENV=production \
35
+ PORT=7860
36
+
37
  # Expose port
38
  EXPOSE 7860
39
 
 
 
 
 
40
  # Health check
41
+ HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
42
+ CMD node -e "require('http').get('http://localhost:7860/', (r) => process.exit(r.statusCode === 200 ? 0 : 1))"
43
+
44
+ # Use tini to properly handle signals
45
+ ENTRYPOINT ["/sbin/tini", "--"]
46
 
47
+ # Start server
48
+ CMD ["node", "server.js"]
README.md CHANGED
@@ -89,60 +89,31 @@ Seguindo o plano à risca, você pode esperar:
89
 
90
  Lembre-se: você é mais forte do que imagina! Cada dia é uma vitória, cada escolha é um passo em direção à sua melhor versão.
91
 
92
- ## 🐳 Executando com Docker
93
 
94
- ### Opção 1: Docker Compose (Recomendado)
95
 
96
- ```bash
97
- # Clone o repositório
98
- git clone <seu-repositorio>
99
- cd k
100
-
101
- # Construa e inicie o container
102
- docker-compose up -d
103
 
104
- # Acesse em: http://localhost:7860
105
- ```
 
 
 
 
106
 
107
- ### Opção 2: Docker Build Manual
108
 
109
  ```bash
110
  # Build da imagem
111
  docker build -t fitness-app .
112
 
113
  # Execute o container
114
- docker run -d \
115
- --name fitness-app \
116
- -p 7860:7860 \
117
- --restart unless-stopped \
118
- fitness-app
119
 
120
  # Acesse em: http://localhost:7860
121
  ```
122
 
123
- ### Comandos Úteis
124
-
125
- ```bash
126
- # Ver logs
127
- docker-compose logs -f fitness-app
128
-
129
- # Parar o container
130
- docker-compose down
131
-
132
- # Reconstruir após alterações
133
- docker-compose up -d --build
134
-
135
- # Ver status de saúde
136
- docker ps
137
- ```
138
-
139
- ### Recursos do Container
140
-
141
- - **CPU**: 1 core (limite), 0.5 core (reservado)
142
- - **Memória**: 512MB (limite), 256MB (reservado)
143
- - **Porta**: 7860
144
- - **Health Check**: A cada 30s
145
-
146
  ## 💻 Desenvolvimento Local
147
 
148
  ### Pré-requisitos
@@ -170,9 +141,8 @@ npm start
170
 
171
  - `npm start` - Inicia o servidor de produção
172
  - `npm run dev` - Modo desenvolvimento com nodemon
173
- - `npm run build` - Build de produção otimizado
174
- - `npm run download` - Baixa vídeos e áudios do Hugging Face
175
- - `npm run analyze` - Analisa o bundle
176
 
177
  ## 📊 Performance
178
 
 
89
 
90
  Lembre-se: você é mais forte do que imagina! Cada dia é uma vitória, cada escolha é um passo em direção à sua melhor versão.
91
 
92
+ ## 🚀 Deploy no Hugging Face Spaces
93
 
94
+ Este app está otimizado para rodar perfeitamente no Hugging Face Spaces!
95
 
96
+ ### Como fazer deploy:
 
 
 
 
 
 
97
 
98
+ 1. **Fork ou clone** este repositório
99
+ 2. **Vá para Hugging Face Spaces**: https://huggingface.co/spaces
100
+ 3. **Crie um novo Space** com Docker SDK
101
+ 4. **Envie os arquivos** ou conecte ao seu repositório GitHub
102
+ 5. **Aguarde o build** (leva cerca de 2-3 minutos)
103
+ 6. **Pronto!** Seu app estará disponível em `https://huggingface.co/spaces/SEU_USERNAME/SEU_SPACE`
104
 
105
+ ### 🐳 Executando Localmente com Docker
106
 
107
  ```bash
108
  # Build da imagem
109
  docker build -t fitness-app .
110
 
111
  # Execute o container
112
+ docker run -p 7860:7860 fitness-app
 
 
 
 
113
 
114
  # Acesse em: http://localhost:7860
115
  ```
116
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
117
  ## 💻 Desenvolvimento Local
118
 
119
  ### Pré-requisitos
 
141
 
142
  - `npm start` - Inicia o servidor de produção
143
  - `npm run dev` - Modo desenvolvimento com nodemon
144
+ - `npm run build` - Build de produção otimizado (minify + gzip)
145
+ - `npm run download` - Baixa vídeos e áudios do Hugging Face (31 MB)
 
146
 
147
  ## 📊 Performance
148
 
dist/app.min.js CHANGED
The diff for this file is too large to render. See raw diff
 
dist/app.min.js.gz CHANGED
@@ -1,3 +1,3 @@
1
  version https://git-lfs.github.com/spec/v1
2
- oid sha256:c22f9cb25078e4dd3f8af8e8e554b6a360e7afbbfda7505d43cec49d98cd065a
3
- size 21072
 
1
  version https://git-lfs.github.com/spec/v1
2
+ oid sha256:60a022e9575d6ea813d87ef7f0e383d2a557b4105e2910f21440c719c8d00ab2
3
+ size 21089
dist/build-report.json CHANGED
@@ -1,11 +1,11 @@
1
  {
2
- "buildDate": "2025-10-16T16:45:55.089Z",
3
  "files": [
4
  {
5
  "name": "JavaScript",
6
- "originalSize": 148038,
7
- "minifiedSize": 88212,
8
- "gzipSize": 21072,
9
  "minSavings": "40.4%",
10
  "gzipSavings": "85.8%"
11
  },
@@ -19,11 +19,11 @@
19
  },
20
  {
21
  "name": "HTML",
22
- "originalSize": 36502,
23
- "minifiedSize": 19874,
24
- "gzipSize": 5179,
25
- "minSavings": "45.6%",
26
- "gzipSavings": "85.8%"
27
  },
28
  {
29
  "name": "Service Worker",
@@ -35,14 +35,14 @@
35
  }
36
  ],
37
  "totals": {
38
- "originalSize": 249607,
39
- "minifiedSize": 151456,
40
- "gzipSize": 34254,
41
  "minSavings": "39.3%",
42
  "gzipSavings": "86.3%"
43
  },
44
  "performance": {
45
- "estimatedLoadTime3G": "0.36s",
46
  "estimatedLoadTime4G": "0.05s"
47
  }
48
  }
 
1
  {
2
+ "buildDate": "2025-10-16T17:00:29.398Z",
3
  "files": [
4
  {
5
  "name": "JavaScript",
6
+ "originalSize": 148275,
7
+ "minifiedSize": 88353,
8
+ "gzipSize": 21089,
9
  "minSavings": "40.4%",
10
  "gzipSavings": "85.8%"
11
  },
 
19
  },
20
  {
21
  "name": "HTML",
22
+ "originalSize": 35787,
23
+ "minifiedSize": 19425,
24
+ "gzipSize": 4974,
25
+ "minSavings": "45.7%",
26
+ "gzipSavings": "86.1%"
27
  },
28
  {
29
  "name": "Service Worker",
 
35
  }
36
  ],
37
  "totals": {
38
+ "originalSize": 249129,
39
+ "minifiedSize": 151148,
40
+ "gzipSize": 34066,
41
  "minSavings": "39.3%",
42
  "gzipSavings": "86.3%"
43
  },
44
  "performance": {
45
+ "estimatedLoadTime3G": "0.35s",
46
  "estimatedLoadTime4G": "0.05s"
47
  }
48
  }
dist/index.html CHANGED
@@ -1 +1 @@
1
- <!DOCTYPE html><html lang=pt-BR><head><meta charset=UTF-8><meta name=viewport content="width=device-width, initial-scale=1.0, maximum-scale=5.0, user-scalable=yes, viewport-fit=cover"><meta name=mobile-web-app-capable content=yes><meta name=apple-mobile-web-app-capable content=yes><meta name=apple-mobile-web-app-title content="Fitness App"><title>✨ Sua Jornada de Transformação</title><link rel=dns-prefetch href="https://fonts.googleapis.com"><link rel=dns-prefetch href="https://fonts.gstatic.com"><link rel=dns-prefetch href="https://huggingface.co"><link rel=preconnect href="https://fonts.googleapis.com"><link rel=preconnect href="https://fonts.gstatic.com" crossorigin><link rel=preconnect href="https://huggingface.co"><link rel=preconnect href="https://cdn-lfs.huggingface.co" crossorigin><link href="https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;500;600;700;800&family=Playfair+Display:wght@400;600;700&display=swap" rel=stylesheet media=print onload="this.media='all'"><noscript><link href="https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;500;600;700;800&family=Playfair+Display:wght@400;600;700&display=swap" rel=stylesheet></noscript><link rel=preload href="styles.css" as=style><link rel=stylesheet href="styles.css"><link rel=modulepreload href="app.js"><link rel=modulepreload href="lazy-video.js"><link rel=manifest href="manifest.json"><meta name=description content="Seu aplicativo de transformação pessoal completo - exercícios, nutrição e bem-estar"><meta name=keywords content="fitness, treino, nutrição, bem-estar, yoga, meditação, saúde"><meta name=theme-color content="#FF6B9D" media="(prefers-color-scheme: light)"><meta name=theme-color content="#1a1a1a" media="(prefers-color-scheme: dark)"><meta name=apple-mobile-web-app-capable content=yes><meta name=apple-mobile-web-app-status-bar-style content=black-translucent><link rel=apple-touch-icon sizes=192x192 href="icons/icon-192x192.svg"><link rel=apple-touch-icon sizes=512x512 href="icons/icon-512x512.svg"><meta name=msapplication-TileColor content="#FF6B9D"><meta name=msapplication-config content=none><link rel=icon type="image/svg+xml" href="icons/icon.svg"><link rel=preload href="app.js" as=script><link rel=modulepreload href="app.js"></head><body><div class=welcome-screen id=welcomeScreen><div class=welcome-content><div class=welcome-logo><div class=logo-heart>💖</div><h1>Bem-vinda!</h1><p>Sua jornada de transformação começa aqui</p></div><button class=btn-start-journey id=startJourney>Começar Agora ✨</button></div></div><div class=app-container id=appContainer style="display: none;"><header class=top-bar><div class=user-info style="cursor: pointer;" id=userProfileClick><div class=avatar id=userAvatar>💝</div><div class=user-text><span class=greeting id=greeting>Olá, Guerreira!</span><span class=streak>🔥 <span id=streakDays>0</span> dias seguidos</span></div></div><div class=top-actions><button class=icon-btn id=notifBtn title="Notificações"><span>🔔</span><span class=notification-badge id=notificationBadge style="display: none;">0</span></button></div></header><main class=main-view><section class="view active" id=homeView><div class=hero-section><h2 class=page-title>Sua Transformação</h2><div class=daily-progress><div class=progress-circle id=progressCircle><svg viewBox="0 0 120 120"><circle cx=60 cy=60 r=54 class=progress-bg></circle><circle cx=60 cy=60 r=54 class=progress-fill id=progressFill style="--progress: 0"></circle></svg><div class=progress-text><span class=progress-value id=progressValue>0</span>% <span class=progress-label>Hoje</span></div></div><div class=today-stats><div class=stat><span class=stat-icon>🔥</span><div><span class=stat-value id=caloriesBurned>0</span><span class=stat-label>kcal</span></div></div><div class=stat><span class=stat-icon>⏱️</span><div><span class=stat-value id=minutesActive>0</span><span class=stat-label>min</span></div></div><div class=stat><span class=stat-icon>💪</span><div><span class=stat-value id=workoutsCompleted>0</span><span class=stat-label>treinos</span></div></div></div></div></div><div class=plan-summary id=planSummary style="display: none;"><div class=plan-card><div class=plan-header><h3>🎯 Seu Plano Personalizado</h3><button class=btn-view-plan id=viewFullPlan>Ver Detalhes</button></div><div class=plan-quick-stats><div class=plan-stat><span class=plan-label>Meta</span><span class=plan-value id=planGoal>-</span></div><div class=plan-stat><span class=plan-label>Calorias/dia</span><span class=plan-value id=planCalories>-</span></div><div class=plan-stat><span class=plan-label>Treino</span><span class=plan-value id=planWorkout>-</span></div></div><div class=coach-message id=coachMessage> 💪 Continue assim! Você está no caminho certo! </div></div></div><div class=quick-actions><h3 class=section-title>Comece Agora</h3><div class=action-cards><div class=action-card data-navigate="workouts"><div class=action-icon>💪</div><h4>Treinar</h4><p>Escolha sua área</p></div><div class=action-card data-navigate="nutrition"><div class=action-icon>🥗</div><h4>Nutrição</h4><p>Acompanhe sua dieta</p></div><div class=action-card data-navigate="wellness"><div class=action-icon>🧘‍♀️</div><h4>Bem-Estar</h4><p>Massagens & Postura</p></div><div class=action-card data-navigate="progress"><div class=action-icon>📈</div><h4>Progresso</h4><p>Veja sua evolução</p></div></div></div><div class=motivation-card><div class=motivation-icon>✨</div><p class=motivation-text id=dailyMotivation>Você é capaz de coisas incríveis! Continue brilhando! 💫</p></div></section><section class=view id=workoutsView><div class=view-header><button class=btn-back data-back="home">← Voltar</button><h2 class=view-title>Escolha a Área</h2></div><div class=category-grid><div class=category-card data-category="personalized" style="background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white;"><div class=category-image>🎯</div><h3>Personalizado</h3><p>Seu treino único</p><span class=category-badge style="background: rgba(255,255,255,0.3);">14 exercícios</span></div><div class=category-card data-category="abs"><div class=category-image>🔥</div><h3>Abdômen</h3><p>Barriga definida</p><span class=category-badge>5 exercícios</span></div><div class=category-card data-category="legs"><div class=category-image>🦵</div><h3>Pernas</h3><p>Pernas torneadas</p><span class=category-badge>15 exercícios</span></div><div class=category-card data-category="glutes"><div class=category-image>🍑</div><h3>Glúteos</h3><p>Bumbum empinado</p><span class=category-badge>14 exercícios</span></div><div class=category-card data-category="arms"><div class=category-image>💪</div><h3>Braços</h3><p>Braços definidos</p><span class=category-badge>10 exercícios</span></div><div class=category-card data-category="waist"><div class=category-image>⏳</div><h3>Cintura</h3><p>Cintura fina</p><span class=category-badge>8 exercícios</span></div><div class=category-card data-category="back"><div class=category-image>🏋️‍♀️</div><h3>Costas</h3><p>Postura correta</p><span class=category-badge>9 exercícios</span></div><div class=category-card data-category="cardio"><div class=category-image>❤️</div><h3>Cardio</h3><p>Queime calorias</p><span class=category-badge>11 exercícios</span></div><div class=category-card data-category="fullbody"><div class=category-image>✨</div><h3>Corpo Todo</h3><p>Treino completo</p><span class=category-badge>20 exercícios</span></div><div class=category-card data-category="yoga"><div class=category-image>🧘‍♀️</div><h3>Yoga</h3><p>Flexibilidade e paz</p><span class=category-badge>12 posições</span></div><div class=category-card data-category="massage"><div class=category-image>💆‍♀️</div><h3>Massagem</h3><p>Relaxamento total</p><span class=category-badge>8 técnicas</span></div><div class=category-card data-category="face"><div class=category-image>😊</div><h3>Rosto</h3><p>Rejuvenescimento facial</p><span class=category-badge>4 exercícios</span></div></div></section><section class=view id=exercisesListView><div class=view-header><button class=btn-back data-back="workouts">← Voltar</button><h2 class=view-title id=categoryTitle>Exercícios</h2></div><div class=exercises-container id=exercisesList></div></section><section class=view id=workoutSessionView><div class=workout-header><button class=btn-close-workout id=closeWorkout>✕</button><div class=workout-timer id=workoutTimer>00:00</div></div><div class=workout-content><div class=exercise-display><div class=exercise-name id=currentExerciseName>Preparando...</div><div class=exercise-count id=exerciseCount>Exercício 1 de 5</div><div class=exercise-demo id=exerciseDemo><div class=demo-placeholder><video class=demo-video id=demoVideo loop muted playsinline style="display: none;"><source src="" type="video/mp4"></video><span class=demo-icon id=demoIcon>💪</span></div></div><div class=exercise-instructions><div class=reps-info id=repsInfo>3 séries × 15 repetições</div><div class=rest-info id=restInfo>Descanso: 30s entre séries</div></div><div class=series-tracker id=seriesTracker><div class="series-dot completed"></div><div class=series-dot></div><div class=series-dot></div></div></div><div class=workout-controls><button class="btn-workout-action secondary" id=skipExercise>Pular</button><button class="btn-workout-action primary" id=completeExercise>Concluir Série</button></div></div><div class=workout-progress-bar><div class=progress-bar-fill id=workoutProgressBar style="width: 0%"></div></div></section><section class=view id=wellnessView><div class=view-header><button class=btn-back data-back="home">← Voltar</button><h2 class=view-title>Bem-Estar</h2></div><div class=wellness-grid><div class=wellness-card data-wellness="face-massage"><div class=wellness-icon>💆‍♀️</div><h3>Massagem Facial</h3><p>Rejuvenesça e relaxe</p><span class=duration>10 min</span></div><div class=wellness-card data-wellness="body-massage"><div class=wellness-icon>💫</div><h3>Massagem Corporal</h3><p>Alivie tensões</p><span class=duration>15 min</span></div><div class=wellness-card data-wellness="posture"><div class=wellness-icon>🧍‍♀️</div><h3>Correção Postural</h3><p>Melhore sua postura</p><span class=duration>12 min</span></div><div class=wellness-card data-wellness="stretching"><div class=wellness-icon>🤸‍♀️</div><h3>Alongamento</h3><p>Flexibilidade total</p><span class=duration>8 min</span></div><div class=wellness-card data-wellness="breathing"><div class=wellness-icon>🌬️</div><h3>Respiração</h3><p>Acalme sua mente</p><span class=duration>5 min</span></div><div class=wellness-card data-wellness="meditation"><div class=wellness-icon>🧘‍♀️</div><h3>Meditação</h3><p>Paz interior</p><span class=duration>10 min</span></div></div></section><section class=view id=nutritionView><div class=view-header><button class=btn-back data-back="home">← Voltar</button><h2 class=view-title>Nutrição</h2></div><div class=nutrition-summary><h3>Resumo de Hoje</h3><div class=macros-display><div class=macro-item><div class="macro-circle carbs"><span id=carbsValue>0g</span></div><span class=macro-label>Carboidratos</span></div><div class=macro-item><div class="macro-circle protein"><span id=proteinValue>0g</span></div><span class=macro-label>Proteínas</span></div><div class=macro-item><div class="macro-circle fat"><span id=fatValue>0g</span></div><span class=macro-label>Gorduras</span></div></div><div class=calories-total><span class=calories-value id=totalCalories>0</span><span class=calories-label>kcal hoje</span></div></div><div class=water-tracker><h3>Hidratação 💧</h3><div class=water-glasses><div class=glass data-glass="1">💧</div><div class=glass data-glass="2">💧</div><div class=glass data-glass="3">💧</div><div class=glass data-glass="4">💧</div><div class=glass data-glass="5">💧</div><div class=glass data-glass="6">💧</div><div class=glass data-glass="7">💧</div><div class=glass data-glass="8">💧</div></div><p class=water-goal><span id=waterCount>0</span>/8 copos (2L)</p></div></section><section class=view id=progressView><div class=view-header><button class=btn-back data-back="home">← Voltar</button><h2 class=view-title>Seu Progresso</h2></div><div class=weight-tracking-section><h3>Controle de Peso ⚖️</h3><div class=weight-card><div class=weight-current><div class=weight-label>Peso Atual</div><div class=weight-value id=currentWeight>--</div><button class=btn-update-weight id=updateWeightBtn>Atualizar Peso</button></div><div class=weight-stats><div class=weight-stat><div class=weight-stat-label>Peso Inicial</div><div class=weight-stat-value id=initialWeight>--</div></div><div class="weight-stat success"><div class=weight-stat-label>Perdeu</div><div class=weight-stat-value id=weightLost>0 kg</div></div><div class=weight-stat><div class=weight-stat-label>Meta</div><div class=weight-stat-value id=goalWeight>--</div></div></div><div class=weight-progress-bar><div class=weight-progress-fill id=weightProgressFill style="width: 0%"></div></div><div class=weight-chart-mini id=weightChartMini></div></div></div><div class=weekly-activity-section><h3>Atividade Semanal 📅</h3><div class=weekly-activity-grid id=weeklyActivityGrid></div></div><div class=detailed-stats-section><h3>Estatísticas Detalhadas 📊</h3><div class=stats-grid><div class=stat-detail-card><div class=stat-detail-icon>🔥</div><div class=stat-detail-content><div class=stat-detail-number id=totalWorkouts>0</div><div class=stat-detail-label>Treinos Completos</div><div class=stat-detail-sublabel><span id=thisWeekWorkouts>0</span> esta semana </div></div></div><div class=stat-detail-card><div class=stat-detail-icon>⏱️</div><div class=stat-detail-content><div class=stat-detail-number id=totalMinutes>0</div><div class=stat-detail-label>Minutos Ativos</div><div class=stat-detail-sublabel><span id=avgMinutes>0</span> min/treino </div></div></div><div class=stat-detail-card><div class=stat-detail-icon>🔥</div><div class=stat-detail-content><div class=stat-detail-number id=totalCaloriesDetail>0</div><div class=stat-detail-label>Calorias Queimadas</div><div class=stat-detail-sublabel><span id=avgCalories>0</span> kcal/treino </div></div></div><div class=stat-detail-card><div class=stat-detail-icon>📅</div><div class=stat-detail-content><div class=stat-detail-number id=daysActiveDetail>0</div><div class=stat-detail-label>Dias Ativos</div><div class=stat-detail-sublabel> Sequência: <span id=currentStreak>0</span> dias </div></div></div><div class=stat-detail-card><div class=stat-detail-icon>💧</div><div class=stat-detail-content><div class=stat-detail-number id=totalWaterGlasses>0</div><div class=stat-detail-label>Copos de Água</div><div class=stat-detail-sublabel><span id=waterStreak>0</span> dias 8 copos </div></div></div><div class=stat-detail-card><div class=stat-detail-icon>🏆</div><div class=stat-detail-content><div class=stat-detail-number id=achievementsUnlocked>0</div><div class=stat-detail-label>Conquistas</div><div class=stat-detail-sublabel> de <span id=totalAchievements>12</span> possíveis </div></div></div></div></div><div class=activity-chart-section><h3>Atividade Semanal 📈</h3><div class=weekly-chart><div class=chart-bars id=weeklyChart></div></div></div><div class=achievements-section><h3>Conquistas 🏆</h3><div class=achievements-grid id=achievementsGrid></div></div><div class=records-section><h3>Recordes Pessoais 🌟</h3><div class=records-list><div class=record-item><div class=record-icon>🔥</div><div class=record-content><div class=record-label>Maior Sequência</div><div class=record-value id=longestStreak>0 dias</div></div></div><div class=record-item><div class=record-icon>⏱️</div><div class=record-content><div class=record-label>Treino Mais Longo</div><div class=record-value id=longestWorkout>0 min</div></div></div><div class=record-item><div class=record-icon>💪</div><div class=record-content><div class=record-label>Categoria Favorita</div><div class=record-value id=favoriteCategory>--</div></div></div><div class=record-item><div class=record-icon>📅</div><div class=record-content><div class=record-label>Membro Desde</div><div class=record-value id=memberSince>--</div></div></div></div></div></section></main><nav class=bottom-nav><button class="nav-item active" data-nav="home"><span class=nav-icon>🏠</span><span class=nav-label>Início</span></button><button class=nav-item data-nav="workouts"><span class=nav-icon>💪</span><span class=nav-label>Treinar</span></button><button class=nav-item data-nav="nutrition"><span class=nav-icon>🥗</span><span class=nav-label>Nutrição</span></button><button class=nav-item data-nav="progress"><span class=nav-icon>📊</span><span class=nav-label>Progresso</span></button></nav></div><div class=modal id=completionModal><div class="modal-content celebration"><div class=celebration-confetti>🎉</div><h2 class=modal-title>Parabéns! 🎊</h2><p class=modal-message id=completionMessage>Você completou o treino!</p><div class=workout-summary id=workoutSummary><div class=summary-stat><span class=summary-icon>⏱️</span><span class=summary-value id=summaryTime>15 min</span></div><div class=summary-stat><span class=summary-icon>🔥</span><span class=summary-value id=summaryCalories>120 kcal</span></div><div class=summary-stat><span class=summary-icon>💪</span><span class=summary-value id=summaryExercises>8 exercícios</span></div></div><div class=workout-details id=workoutDetails style="margin-top: var(--spacing-md); padding: var(--spacing-md); background: var(--bg-light); border-radius: var(--radius-md); text-align: left; font-size: 0.9rem; color: var(--text-secondary);"></div><button class=btn-modal-primary id=closeCompletionModal>Continuar ✨</button></div></div><div class=modal id=weightModal><div class=modal-content><h2 class=modal-title>Atualizar Peso ⚖️</h2><div class=weight-input-group><label for=weightInput>Seu peso atual (kg)</label><input type=number id=weightInput step="0.1" min=30 max=200 placeholder="Ex: 65.5"></div><div class=weight-input-group><label for=goalWeightInput>Seu peso meta (kg)</label><input type=number id=goalWeightInput step="0.1" min=30 max=200 placeholder="Ex: 60.0"></div><div class=modal-actions><button class=btn-modal-secondary id=cancelWeightBtn>Cancelar</button><button class=btn-modal-primary id=saveWeightBtn>Salvar 💖</button></div></div></div><div class=settings-fab id=settingsFab><button class=fab-settings id=toggleSound><span class=fab-icon id=soundIcon>🔊</span></button></div><link rel=preload href="lazy-video.js" as=script><script src="lazy-video.js" defer></script><script> // Only load performance monitor in dev mode if (location.hostname === 'localhost' || location.search.includes('debug=true')) { const script = document.createElement('script'); script.src = 'performance-monitor.js'; script.defer = true; document.head.appendChild(script); } </script><div class=modal id=planModal><div class="modal-content plan-modal-content"><button class=modal-close onclick="app.closeModal('planModal')">×</button><div id=planModalContent><h2 class=modal-title>🎯 Seu Plano Completo</h2><div class=profile-info id=profileInfo></div><div class=plan-section><h3>🍽️ Plano Nutricional</h3><div id=nutritionPlan></div></div><div class=plan-section><h3>💪 Plano de Treino</h3><div id=workoutPlan></div></div><div class=plan-section><h3>📅 Linha do Tempo</h3><div id=timelinePlan></div></div><div class=plan-section><h3>💡 Dicas Personalizadas</h3><div id=tipsPlan></div></div><button class=btn-edit-profile id=editProfile>✏️ Editar Perfil</button></div></div></div><script src="app.js" defer></script></body></html>
 
1
+ <!DOCTYPE html><html lang=pt-BR><head><meta charset=UTF-8><meta name=viewport content="width=device-width, initial-scale=1.0, maximum-scale=5.0, user-scalable=yes, viewport-fit=cover"><meta name=mobile-web-app-capable content=yes><meta name=apple-mobile-web-app-capable content=yes><meta name=apple-mobile-web-app-title content="Fitness App"><title>✨ Sua Jornada de Transformação</title><link rel=dns-prefetch href="https://fonts.googleapis.com"><link rel=dns-prefetch href="https://fonts.gstatic.com"><link rel=dns-prefetch href="https://huggingface.co"><link rel=preconnect href="https://fonts.googleapis.com"><link rel=preconnect href="https://fonts.gstatic.com" crossorigin><link rel=preconnect href="https://huggingface.co"><link rel=preconnect href="https://cdn-lfs.huggingface.co" crossorigin><link href="https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;500;600;700;800&family=Playfair+Display:wght@400;600;700&display=swap" rel=stylesheet media=print onload="this.media='all'"><noscript><link href="https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;500;600;700;800&family=Playfair+Display:wght@400;600;700&display=swap" rel=stylesheet></noscript><link rel=preload href="styles.css" as=style><link rel=stylesheet href="styles.css"><link rel=modulepreload href="app.js"><link rel=manifest href="manifest.json"><meta name=description content="Seu aplicativo de transformação pessoal completo - exercícios, nutrição e bem-estar"><meta name=keywords content="fitness, treino, nutrição, bem-estar, yoga, meditação, saúde"><meta name=theme-color content="#FF6B9D" media="(prefers-color-scheme: light)"><meta name=theme-color content="#1a1a1a" media="(prefers-color-scheme: dark)"><meta name=apple-mobile-web-app-capable content=yes><meta name=apple-mobile-web-app-status-bar-style content=black-translucent><link rel=apple-touch-icon sizes=192x192 href="icons/icon-192x192.svg"><link rel=apple-touch-icon sizes=512x512 href="icons/icon-512x512.svg"><meta name=msapplication-TileColor content="#FF6B9D"><meta name=msapplication-config content=none><link rel=icon type="image/svg+xml" href="icons/icon.svg"><link rel=preload href="app.js" as=script><link rel=modulepreload href="app.js"></head><body><div class=welcome-screen id=welcomeScreen><div class=welcome-content><div class=welcome-logo><div class=logo-heart>💖</div><h1>Bem-vinda!</h1><p>Sua jornada de transformação começa aqui</p></div><button class=btn-start-journey id=startJourney>Começar Agora ✨</button></div></div><div class=app-container id=appContainer style="display: none;"><header class=top-bar><div class=user-info style="cursor: pointer;" id=userProfileClick><div class=avatar id=userAvatar>💝</div><div class=user-text><span class=greeting id=greeting>Olá, Guerreira!</span><span class=streak>🔥 <span id=streakDays>0</span> dias seguidos</span></div></div><div class=top-actions><button class=icon-btn id=notifBtn title="Notificações"><span>🔔</span><span class=notification-badge id=notificationBadge style="display: none;">0</span></button></div></header><main class=main-view><section class="view active" id=homeView><div class=hero-section><h2 class=page-title>Sua Transformação</h2><div class=daily-progress><div class=progress-circle id=progressCircle><svg viewBox="0 0 120 120"><circle cx=60 cy=60 r=54 class=progress-bg></circle><circle cx=60 cy=60 r=54 class=progress-fill id=progressFill style="--progress: 0"></circle></svg><div class=progress-text><span class=progress-value id=progressValue>0</span>% <span class=progress-label>Hoje</span></div></div><div class=today-stats><div class=stat><span class=stat-icon>🔥</span><div><span class=stat-value id=caloriesBurned>0</span><span class=stat-label>kcal</span></div></div><div class=stat><span class=stat-icon>⏱️</span><div><span class=stat-value id=minutesActive>0</span><span class=stat-label>min</span></div></div><div class=stat><span class=stat-icon>💪</span><div><span class=stat-value id=workoutsCompleted>0</span><span class=stat-label>treinos</span></div></div></div></div></div><div class=plan-summary id=planSummary style="display: none;"><div class=plan-card><div class=plan-header><h3>🎯 Seu Plano Personalizado</h3><button class=btn-view-plan id=viewFullPlan>Ver Detalhes</button></div><div class=plan-quick-stats><div class=plan-stat><span class=plan-label>Meta</span><span class=plan-value id=planGoal>-</span></div><div class=plan-stat><span class=plan-label>Calorias/dia</span><span class=plan-value id=planCalories>-</span></div><div class=plan-stat><span class=plan-label>Treino</span><span class=plan-value id=planWorkout>-</span></div></div><div class=coach-message id=coachMessage> 💪 Continue assim! Você está no caminho certo! </div></div></div><div class=quick-actions><h3 class=section-title>Comece Agora</h3><div class=action-cards><div class=action-card data-navigate="workouts"><div class=action-icon>💪</div><h4>Treinar</h4><p>Escolha sua área</p></div><div class=action-card data-navigate="nutrition"><div class=action-icon>🥗</div><h4>Nutrição</h4><p>Acompanhe sua dieta</p></div><div class=action-card data-navigate="wellness"><div class=action-icon>🧘‍♀️</div><h4>Bem-Estar</h4><p>Massagens & Postura</p></div><div class=action-card data-navigate="progress"><div class=action-icon>📈</div><h4>Progresso</h4><p>Veja sua evolução</p></div></div></div><div class=motivation-card><div class=motivation-icon>✨</div><p class=motivation-text id=dailyMotivation>Você é capaz de coisas incríveis! Continue brilhando! 💫</p></div></section><section class=view id=workoutsView><div class=view-header><button class=btn-back data-back="home">← Voltar</button><h2 class=view-title>Escolha a Área</h2></div><div class=category-grid><div class=category-card data-category="personalized" style="background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white;"><div class=category-image>🎯</div><h3>Personalizado</h3><p>Seu treino único</p><span class=category-badge style="background: rgba(255,255,255,0.3);">14 exercícios</span></div><div class=category-card data-category="abs"><div class=category-image>🔥</div><h3>Abdômen</h3><p>Barriga definida</p><span class=category-badge>5 exercícios</span></div><div class=category-card data-category="legs"><div class=category-image>🦵</div><h3>Pernas</h3><p>Pernas torneadas</p><span class=category-badge>15 exercícios</span></div><div class=category-card data-category="glutes"><div class=category-image>🍑</div><h3>Glúteos</h3><p>Bumbum empinado</p><span class=category-badge>14 exercícios</span></div><div class=category-card data-category="arms"><div class=category-image>💪</div><h3>Braços</h3><p>Braços definidos</p><span class=category-badge>10 exercícios</span></div><div class=category-card data-category="waist"><div class=category-image>⏳</div><h3>Cintura</h3><p>Cintura fina</p><span class=category-badge>8 exercícios</span></div><div class=category-card data-category="back"><div class=category-image>🏋️‍♀️</div><h3>Costas</h3><p>Postura correta</p><span class=category-badge>9 exercícios</span></div><div class=category-card data-category="cardio"><div class=category-image>❤️</div><h3>Cardio</h3><p>Queime calorias</p><span class=category-badge>11 exercícios</span></div><div class=category-card data-category="fullbody"><div class=category-image>✨</div><h3>Corpo Todo</h3><p>Treino completo</p><span class=category-badge>20 exercícios</span></div><div class=category-card data-category="yoga"><div class=category-image>🧘‍♀️</div><h3>Yoga</h3><p>Flexibilidade e paz</p><span class=category-badge>12 posições</span></div><div class=category-card data-category="massage"><div class=category-image>💆‍♀️</div><h3>Massagem</h3><p>Relaxamento total</p><span class=category-badge>8 técnicas</span></div><div class=category-card data-category="face"><div class=category-image>😊</div><h3>Rosto</h3><p>Rejuvenescimento facial</p><span class=category-badge>4 exercícios</span></div></div></section><section class=view id=exercisesListView><div class=view-header><button class=btn-back data-back="workouts">← Voltar</button><h2 class=view-title id=categoryTitle>Exercícios</h2></div><div class=exercises-container id=exercisesList></div></section><section class=view id=workoutSessionView><div class=workout-header><button class=btn-close-workout id=closeWorkout>✕</button><div class=workout-timer id=workoutTimer>00:00</div></div><div class=workout-content><div class=exercise-display><div class=exercise-name id=currentExerciseName>Preparando...</div><div class=exercise-count id=exerciseCount>Exercício 1 de 5</div><div class=exercise-demo id=exerciseDemo><div class=demo-placeholder><video class=demo-video id=demoVideo loop muted playsinline style="display: none;"><source src="" type="video/mp4"></video><span class=demo-icon id=demoIcon>💪</span></div></div><div class=exercise-instructions><div class=reps-info id=repsInfo>3 séries × 15 repetições</div><div class=rest-info id=restInfo>Descanso: 30s entre séries</div></div><div class=series-tracker id=seriesTracker><div class="series-dot completed"></div><div class=series-dot></div><div class=series-dot></div></div></div><div class=workout-controls><button class="btn-workout-action secondary" id=skipExercise>Pular</button><button class="btn-workout-action primary" id=completeExercise>Concluir Série</button></div></div><div class=workout-progress-bar><div class=progress-bar-fill id=workoutProgressBar style="width: 0%"></div></div></section><section class=view id=wellnessView><div class=view-header><button class=btn-back data-back="home">← Voltar</button><h2 class=view-title>Bem-Estar</h2></div><div class=wellness-grid><div class=wellness-card data-wellness="face-massage"><div class=wellness-icon>💆‍♀️</div><h3>Massagem Facial</h3><p>Rejuvenesça e relaxe</p><span class=duration>10 min</span></div><div class=wellness-card data-wellness="body-massage"><div class=wellness-icon>💫</div><h3>Massagem Corporal</h3><p>Alivie tensões</p><span class=duration>15 min</span></div><div class=wellness-card data-wellness="posture"><div class=wellness-icon>🧍‍♀️</div><h3>Correção Postural</h3><p>Melhore sua postura</p><span class=duration>12 min</span></div><div class=wellness-card data-wellness="stretching"><div class=wellness-icon>🤸‍♀️</div><h3>Alongamento</h3><p>Flexibilidade total</p><span class=duration>8 min</span></div><div class=wellness-card data-wellness="breathing"><div class=wellness-icon>🌬️</div><h3>Respiração</h3><p>Acalme sua mente</p><span class=duration>5 min</span></div><div class=wellness-card data-wellness="meditation"><div class=wellness-icon>🧘‍♀️</div><h3>Medita��ão</h3><p>Paz interior</p><span class=duration>10 min</span></div></div></section><section class=view id=nutritionView><div class=view-header><button class=btn-back data-back="home">← Voltar</button><h2 class=view-title>Nutrição</h2></div><div class=nutrition-summary><h3>Resumo de Hoje</h3><div class=macros-display><div class=macro-item><div class="macro-circle carbs"><span id=carbsValue>0g</span></div><span class=macro-label>Carboidratos</span></div><div class=macro-item><div class="macro-circle protein"><span id=proteinValue>0g</span></div><span class=macro-label>Proteínas</span></div><div class=macro-item><div class="macro-circle fat"><span id=fatValue>0g</span></div><span class=macro-label>Gorduras</span></div></div><div class=calories-total><span class=calories-value id=totalCalories>0</span><span class=calories-label>kcal hoje</span></div></div><div class=water-tracker><h3>Hidratação 💧</h3><div class=water-glasses><div class=glass data-glass="1">💧</div><div class=glass data-glass="2">💧</div><div class=glass data-glass="3">💧</div><div class=glass data-glass="4">💧</div><div class=glass data-glass="5">💧</div><div class=glass data-glass="6">💧</div><div class=glass data-glass="7">💧</div><div class=glass data-glass="8">💧</div></div><p class=water-goal><span id=waterCount>0</span>/8 copos (2L)</p></div></section><section class=view id=progressView><div class=view-header><button class=btn-back data-back="home">← Voltar</button><h2 class=view-title>Seu Progresso</h2></div><div class=weight-tracking-section><h3>Controle de Peso ⚖️</h3><div class=weight-card><div class=weight-current><div class=weight-label>Peso Atual</div><div class=weight-value id=currentWeight>--</div><button class=btn-update-weight id=updateWeightBtn>Atualizar Peso</button></div><div class=weight-stats><div class=weight-stat><div class=weight-stat-label>Peso Inicial</div><div class=weight-stat-value id=initialWeight>--</div></div><div class="weight-stat success"><div class=weight-stat-label>Perdeu</div><div class=weight-stat-value id=weightLost>0 kg</div></div><div class=weight-stat><div class=weight-stat-label>Meta</div><div class=weight-stat-value id=goalWeight>--</div></div></div><div class=weight-progress-bar><div class=weight-progress-fill id=weightProgressFill style="width: 0%"></div></div><div class=weight-chart-mini id=weightChartMini></div></div></div><div class=weekly-activity-section><h3>Atividade Semanal 📅</h3><div class=weekly-activity-grid id=weeklyActivityGrid></div></div><div class=detailed-stats-section><h3>Estatísticas Detalhadas 📊</h3><div class=stats-grid><div class=stat-detail-card><div class=stat-detail-icon>🔥</div><div class=stat-detail-content><div class=stat-detail-number id=totalWorkouts>0</div><div class=stat-detail-label>Treinos Completos</div><div class=stat-detail-sublabel><span id=thisWeekWorkouts>0</span> esta semana </div></div></div><div class=stat-detail-card><div class=stat-detail-icon>⏱️</div><div class=stat-detail-content><div class=stat-detail-number id=totalMinutes>0</div><div class=stat-detail-label>Minutos Ativos</div><div class=stat-detail-sublabel><span id=avgMinutes>0</span> min/treino </div></div></div><div class=stat-detail-card><div class=stat-detail-icon>🔥</div><div class=stat-detail-content><div class=stat-detail-number id=totalCaloriesDetail>0</div><div class=stat-detail-label>Calorias Queimadas</div><div class=stat-detail-sublabel><span id=avgCalories>0</span> kcal/treino </div></div></div><div class=stat-detail-card><div class=stat-detail-icon>📅</div><div class=stat-detail-content><div class=stat-detail-number id=daysActiveDetail>0</div><div class=stat-detail-label>Dias Ativos</div><div class=stat-detail-sublabel> Sequência: <span id=currentStreak>0</span> dias </div></div></div><div class=stat-detail-card><div class=stat-detail-icon>💧</div><div class=stat-detail-content><div class=stat-detail-number id=totalWaterGlasses>0</div><div class=stat-detail-label>Copos de Água</div><div class=stat-detail-sublabel><span id=waterStreak>0</span> dias 8 copos </div></div></div><div class=stat-detail-card><div class=stat-detail-icon>🏆</div><div class=stat-detail-content><div class=stat-detail-number id=achievementsUnlocked>0</div><div class=stat-detail-label>Conquistas</div><div class=stat-detail-sublabel> de <span id=totalAchievements>12</span> possíveis </div></div></div></div></div><div class=activity-chart-section><h3>Atividade Semanal 📈</h3><div class=weekly-chart><div class=chart-bars id=weeklyChart></div></div></div><div class=achievements-section><h3>Conquistas 🏆</h3><div class=achievements-grid id=achievementsGrid></div></div><div class=records-section><h3>Recordes Pessoais 🌟</h3><div class=records-list><div class=record-item><div class=record-icon>🔥</div><div class=record-content><div class=record-label>Maior Sequência</div><div class=record-value id=longestStreak>0 dias</div></div></div><div class=record-item><div class=record-icon>⏱️</div><div class=record-content><div class=record-label>Treino Mais Longo</div><div class=record-value id=longestWorkout>0 min</div></div></div><div class=record-item><div class=record-icon>💪</div><div class=record-content><div class=record-label>Categoria Favorita</div><div class=record-value id=favoriteCategory>--</div></div></div><div class=record-item><div class=record-icon>📅</div><div class=record-content><div class=record-label>Membro Desde</div><div class=record-value id=memberSince>--</div></div></div></div></div></section></main><nav class=bottom-nav><button class="nav-item active" data-nav="home"><span class=nav-icon>🏠</span><span class=nav-label>Início</span></button><button class=nav-item data-nav="workouts"><span class=nav-icon>💪</span><span class=nav-label>Treinar</span></button><button class=nav-item data-nav="nutrition"><span class=nav-icon>🥗</span><span class=nav-label>Nutrição</span></button><button class=nav-item data-nav="progress"><span class=nav-icon>📊</span><span class=nav-label>Progresso</span></button></nav></div><div class=modal id=completionModal><div class="modal-content celebration"><div class=celebration-confetti>🎉</div><h2 class=modal-title>Parabéns! 🎊</h2><p class=modal-message id=completionMessage>Você completou o treino!</p><div class=workout-summary id=workoutSummary><div class=summary-stat><span class=summary-icon>⏱️</span><span class=summary-value id=summaryTime>15 min</span></div><div class=summary-stat><span class=summary-icon>🔥</span><span class=summary-value id=summaryCalories>120 kcal</span></div><div class=summary-stat><span class=summary-icon>💪</span><span class=summary-value id=summaryExercises>8 exercícios</span></div></div><div class=workout-details id=workoutDetails style="margin-top: var(--spacing-md); padding: var(--spacing-md); background: var(--bg-light); border-radius: var(--radius-md); text-align: left; font-size: 0.9rem; color: var(--text-secondary);"></div><button class=btn-modal-primary id=closeCompletionModal>Continuar ✨</button></div></div><div class=modal id=weightModal><div class=modal-content><h2 class=modal-title>Atualizar Peso ⚖️</h2><div class=weight-input-group><label for=weightInput>Seu peso atual (kg)</label><input type=number id=weightInput step="0.1" min=30 max=200 placeholder="Ex: 65.5"></div><div class=weight-input-group><label for=goalWeightInput>Seu peso meta (kg)</label><input type=number id=goalWeightInput step="0.1" min=30 max=200 placeholder="Ex: 60.0"></div><div class=modal-actions><button class=btn-modal-secondary id=cancelWeightBtn>Cancelar</button><button class=btn-modal-primary id=saveWeightBtn>Salvar 💖</button></div></div></div><div class=settings-fab id=settingsFab><button class=fab-settings id=toggleSound><span class=fab-icon id=soundIcon>🔊</span></button></div><div class=modal id=planModal><div class="modal-content plan-modal-content"><button class=modal-close id=closePlanModal>×</button><div id=planModalContent><h2 class=modal-title>🎯 Seu Plano Completo</h2><div class=profile-info id=profileInfo></div><div class=plan-section><h3>🍽️ Plano Nutricional</h3><div id=nutritionPlan></div></div><div class=plan-section><h3>💪 Plano de Treino</h3><div id=workoutPlan></div></div><div class=plan-section><h3>📅 Linha do Tempo</h3><div id=timelinePlan></div></div><div class=plan-section><h3>💡 Dicas Personalizadas</h3><div id=tipsPlan></div></div><button class=btn-edit-profile id=editProfile>✏️ Editar Perfil</button></div></div></div><script src="app.js" defer></script></body></html>
dist/index.html.gz CHANGED
@@ -1,3 +1,3 @@
1
  version https://git-lfs.github.com/spec/v1
2
- oid sha256:51011cc7cbfe371a5087c867dab280068cffceed67aa5013aff183dd0bf2d845
3
- size 5179
 
1
  version https://git-lfs.github.com/spec/v1
2
+ oid sha256:d74faced93f2d5c51e169d69bb28612390c47c9693eb183af626dc43936ed35b
3
+ size 4974
docker-entrypoint.sh CHANGED
@@ -2,42 +2,8 @@
2
  set -e
3
 
4
  echo "🚀 Starting Fitness App..."
5
-
6
- # Check if videos directory exists and has files
7
- if [ ! -d "/app/public/videos" ] || [ -z "$(ls -A /app/public/videos 2>/dev/null)" ]; then
8
- echo "📥 Videos directory is empty, attempting to download..."
9
- if npm run download 2>/dev/null; then
10
- echo "✅ Videos downloaded successfully!"
11
- else
12
- echo "⚠️ Video download failed, app will use CDN fallback"
13
- fi
14
- else
15
- VIDEO_COUNT=$(ls -1 /app/public/videos/*.mp4 2>/dev/null | wc -l)
16
- echo "✅ Found $VIDEO_COUNT video files"
17
- fi
18
-
19
- # Check if audio directory exists and has files
20
- if [ ! -d "/app/public/songs" ] || [ -z "$(ls -A /app/public/songs 2>/dev/null)" ]; then
21
- echo "📥 Audio directory is empty"
22
- echo "⚠️ Audio files missing, some features may not work"
23
- else
24
- AUDIO_COUNT=$(ls -1 /app/public/songs/*.{mp3,ogg} 2>/dev/null | wc -l)
25
- echo "✅ Found $AUDIO_COUNT audio files"
26
- fi
27
-
28
- # Check if dist directory exists (production build)
29
- if [ -d "/app/dist" ]; then
30
- echo "✅ Production build found"
31
- else
32
- echo "⚠️ No production build found, using development files"
33
- fi
34
-
35
- # Print environment info
36
- echo "📊 Environment: $NODE_ENV"
37
  echo "🌐 Port: ${PORT:-7860}"
38
- echo "👤 Running as: $(whoami)"
39
 
40
  # Start the application
41
- echo "🎯 Starting server..."
42
  exec node server.js
43
-
 
2
  set -e
3
 
4
  echo "🚀 Starting Fitness App..."
5
+ echo "📊 Environment: ${NODE_ENV:-production}"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6
  echo "🌐 Port: ${PORT:-7860}"
 
7
 
8
  # Start the application
 
9
  exec node server.js
 
package.json CHANGED
@@ -7,13 +7,7 @@
7
  "start": "node server.js",
8
  "dev": "nodemon server.js",
9
  "build": "node scripts/build-production.js",
10
- "build:analyze": "npm run build && npm run analyze",
11
- "minify": "node scripts/minify.js",
12
- "analyze": "node scripts/analyze-bundle.js",
13
- "optimize": "node scripts/build-production.js && node scripts/optimize-images.js",
14
- "download": "node scripts/download-videos.js",
15
- "test": "echo 'No tests specified'",
16
- "lighthouse": "lighthouse http://localhost:7860 --view --output html --output-path ./lighthouse-report.html"
17
  },
18
  "keywords": [
19
  "ketogenic",
 
7
  "start": "node server.js",
8
  "dev": "nodemon server.js",
9
  "build": "node scripts/build-production.js",
10
+ "download": "node scripts/download-videos.js"
 
 
 
 
 
 
11
  },
12
  "keywords": [
13
  "ketogenic",
public/app.js CHANGED
@@ -1558,6 +1558,12 @@ class FitnessApp {
1558
  }
1559
  }
1560
 
 
 
 
 
 
 
1561
  if (e.target.id === 'notifBtn' || e.target.closest('#notifBtn')) {
1562
  e.preventDefault();
1563
  e.stopPropagation();
 
1558
  }
1559
  }
1560
 
1561
+ if (e.target.id === 'closePlanModal' || e.target.closest('#closePlanModal')) {
1562
+ e.preventDefault();
1563
+ e.stopPropagation();
1564
+ this.closeModal('planModal');
1565
+ }
1566
+
1567
  if (e.target.id === 'notifBtn' || e.target.closest('#notifBtn')) {
1568
  e.preventDefault();
1569
  e.stopPropagation();
public/index.html CHANGED
@@ -31,7 +31,6 @@
31
 
32
  <!-- Performance: Preload critical JavaScript -->
33
  <link rel="modulepreload" href="app.js">
34
- <link rel="modulepreload" href="lazy-video.js">
35
 
36
  <!-- PWA Manifest -->
37
  <link rel="manifest" href="manifest.json">
@@ -690,27 +689,11 @@
690
  </button>
691
  </div>
692
 
693
- <!-- Performance: Critical path optimization -->
694
- <!-- Lazy video loading (high priority) -->
695
- <link rel="preload" href="lazy-video.js" as="script">
696
- <script src="lazy-video.js" defer></script>
697
-
698
- <!-- Performance monitoring (development only) -->
699
- <script>
700
- // Only load performance monitor in dev mode
701
- if (location.hostname === 'localhost' || location.search.includes('debug=true')) {
702
- const script = document.createElement('script');
703
- script.src = 'performance-monitor.js';
704
- script.defer = true;
705
- document.head.appendChild(script);
706
- }
707
- </script>
708
-
709
  <!-- Performance: Defer non-critical JavaScript -->
710
  <!-- Personal Plan Modal -->
711
  <div class="modal" id="planModal">
712
  <div class="modal-content plan-modal-content">
713
- <button class="modal-close" onclick="app.closeModal('planModal')">×</button>
714
  <div id="planModalContent">
715
  <h2 class="modal-title">🎯 Seu Plano Completo</h2>
716
 
 
31
 
32
  <!-- Performance: Preload critical JavaScript -->
33
  <link rel="modulepreload" href="app.js">
 
34
 
35
  <!-- PWA Manifest -->
36
  <link rel="manifest" href="manifest.json">
 
689
  </button>
690
  </div>
691
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
692
  <!-- Performance: Defer non-critical JavaScript -->
693
  <!-- Personal Plan Modal -->
694
  <div class="modal" id="planModal">
695
  <div class="modal-content plan-modal-content">
696
+ <button class="modal-close" id="closePlanModal">×</button>
697
  <div id="planModalContent">
698
  <h2 class="modal-title">🎯 Seu Plano Completo</h2>
699