docs: implement Antigravity global rules

This commit is contained in:
2026-04-03 21:11:05 +00:00
parent bcbc5b851e
commit bd9592eb73
4 changed files with 126 additions and 102 deletions

22
.agent/rules/GEMINI.md Normal file
View File

@@ -0,0 +1,22 @@
---
trigger: always_on
---
# GEMINI.md - Antigravity Kit (Auto-Generated)
## TIER 0: UNIVERSAL RULES (Always Active)
### 🌍 Global User Rules (MANDATORY)
1. **Idioma**: Conversar e desenvolver sempre em **Português do Brasil**.
2. **Automação Terminais**: Executar comandos de terminal, leitura de arquivos e edições de forma automática. Comandos de desenvolvimento (build, install, lint, git, etc.) são sempre 'SafeToAutoRun'.
3. **Memória & Monitoramento**: Após cada evolução ou atualização no app, é OBRIGATÓRIO:
- Atualizar a memória do app em '/root/Antigravity_Memory/knowledge/{AppName}.md'.
- Atualizar o status e credenciais no 'app.py' do Cronos Dashboard.
- Realizar 'git commit', 'git push' e executar o 'update.sh' do Cronos para deploy automático.
### 🌐 Language Handling
---

View File

@@ -1,5 +1,6 @@
# Estágio de Build # Estágio de Build
FROM node:20-alpine as build-stage FROM bitnami/node:22 as build-stage
RUN apt-get update && apt-get upgrade -y && apt-get clean && rm -rf /var/lib/apt/lists/*
WORKDIR /app WORKDIR /app
COPY package*.json ./ COPY package*.json ./
RUN npm install --frozen-lockfile || npm install RUN npm install --frozen-lockfile || npm install
@@ -7,7 +8,8 @@ COPY . .
RUN npm run build RUN npm run build
# Estágio de Produção # Estágio de Produção
FROM nginx:stable-alpine as production-stage FROM nginxinc/nginx-unprivileged:alpine as production-stage
RUN apk update && apk upgrade --no-cache
COPY --from=build-stage /app/dist /usr/share/nginx/html COPY --from=build-stage /app/dist /usr/share/nginx/html
EXPOSE 80 EXPOSE 8080
CMD ["nginx", "-g", "daemon off;"] CMD ["nginx", "-g", "daemon off;"]

View File

@@ -1,68 +1,68 @@
import React, { useState } from 'react'; import React, { useState } from 'react';
import { KeyIcon, SaveIcon } from './Icons'; import { KeyIcon, SaveIcon } from './Icons';
interface ApiKeySetupProps { interface ApiKeySetupProps {
onKeySave: (key: string) => void; onKeySave: (key: string) => void;
} }
export const ApiKeySetup: React.FC<ApiKeySetupProps> = ({ onKeySave }) => { export const ApiKeySetup: React.FC<ApiKeySetupProps> = ({ onKeySave }) => {
const [localApiKey, setLocalApiKey] = useState(''); const [localApiKey, setLocalApiKey] = useState('');
const handleSave = () => { const handleSave = () => {
if (localApiKey.trim()) { if (localApiKey.trim()) {
onKeySave(localApiKey.trim()); onKeySave(localApiKey.trim());
} }
}; };
return ( return (
<div className="max-w-md mx-auto animate-fade-in pt-10"> <div className="max-w-md mx-auto animate-fade-in pt-10">
<div className="bg-white/70 dark:bg-slate-800/60 backdrop-blur-md border border-white/20 dark:border-slate-700/50 shadow-xl p-6 sm:p-8 rounded-2xl relative overflow-hidden group"> <div className="bg-white/70 dark:bg-slate-800/60 backdrop-blur-md border border-white/20 dark:border-slate-700/50 shadow-xl p-6 sm:p-8 rounded-2xl relative overflow-hidden group">
<div className="absolute inset-0 bg-gradient-to-br from-blue-500/10 to-purple-500/10 opacity-0 group-hover:opacity-100 transition-opacity duration-500"></div> <div className="absolute inset-0 bg-gradient-to-br from-blue-500/10 to-purple-500/10 opacity-0 group-hover:opacity-100 transition-opacity duration-500"></div>
<div className="relative z-10"> <div className="relative z-10">
<h2 className="text-2xl font-display font-bold text-center mb-3 text-slate-800 dark:text-white"> <h2 className="text-2xl font-display font-bold text-center mb-3 text-slate-800 dark:text-white">
Configurar Chave de API Configurar Chave de API
</h2> </h2>
<p className="text-sm text-slate-500 dark:text-slate-400 text-center mb-8"> <p className="text-sm text-slate-500 dark:text-slate-400 text-center mb-8">
Para começar, insira sua chave de API do Google Gemini. Ela será mantida segura no seu navegador. Para começar, insira sua chave de API do Google Gemini. Ela será mantida segura no seu navegador.
</p> </p>
<div className="space-y-5"> <div className="space-y-5">
<div> <div>
<label htmlFor="api-key-setup" className="block text-sm font-medium text-slate-700 dark:text-slate-300 mb-2"> <label htmlFor="api-key-setup" className="block text-sm font-medium text-slate-700 dark:text-slate-300 mb-2">
Sua Chave de API Sua Chave de API
</label> </label>
<div className="relative group/input"> <div className="relative group/input">
<div className="pointer-events-none absolute inset-y-0 left-0 flex items-center pl-3"> <div className="pointer-events-none absolute inset-y-0 left-0 flex items-center pl-3">
<KeyIcon className="h-5 w-5 text-slate-400 group-focus-within/input:text-blue-500 transition-colors" /> <KeyIcon className="h-5 w-5 text-slate-400 group-focus-within/input:text-blue-500 transition-colors" />
</div> </div>
<input <input
type="password" type="password"
id="api-key-setup" id="api-key-setup"
className="block w-full rounded-xl border-slate-300 dark:border-slate-600 bg-white/50 dark:bg-slate-700/50 py-3 pl-10 pr-3 text-slate-900 dark:text-slate-100 shadow-sm focus:border-blue-500 focus:ring-blue-500 sm:text-sm backdrop-blur-sm transition-all" className="block w-full rounded-xl border-slate-300 dark:border-slate-600 bg-white/50 dark:bg-slate-700/50 py-3 pl-10 pr-3 text-slate-900 dark:text-slate-100 shadow-sm focus:border-blue-500 focus:ring-blue-500 sm:text-sm backdrop-blur-sm transition-all"
placeholder="Cole sua chave aqui" placeholder="Cole sua chave aqui"
value={localApiKey} value={localApiKey}
onChange={(e) => setLocalApiKey(e.target.value)} onChange={(e) => setLocalApiKey(e.target.value)}
onKeyDown={(e) => e.key === 'Enter' && handleSave()} onKeyDown={(e) => e.key === 'Enter' && handleSave()}
autoComplete="off" autoComplete="off"
/> />
</div> </div>
<p className="mt-3 text-xs text-center text-slate-500 dark:text-slate-400"> <p className="mt-3 text-xs text-center text-slate-500 dark:text-slate-400">
Não tem uma chave? <a href="https://aistudio.google.com/app/apikey" target="_blank" rel="noopener noreferrer" className="font-semibold text-blue-600 hover:text-blue-700 dark:text-blue-400 dark:hover:text-blue-300 hover:underline">Obtenha no Google AI Studio</a>. Não tem uma chave? <a href="https://aistudio.google.com/app/apikey" target="_blank" rel="noopener noreferrer" className="font-semibold text-blue-600 hover:text-blue-700 dark:text-blue-400 dark:hover:text-blue-300 hover:underline">Obtenha no Google AI Studio</a>.
</p> </p>
</div> </div>
<button <button
onClick={handleSave} onClick={handleSave}
disabled={!localApiKey.trim()} disabled={!localApiKey.trim()}
className="w-full flex justify-center items-center gap-2 bg-gradient-to-r from-blue-600 to-indigo-600 hover:from-blue-700 hover:to-indigo-700 text-white font-bold py-3.5 px-4 rounded-xl shadow-lg hover:shadow-blue-500/30 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 disabled:opacity-50 disabled:cursor-not-allowed transition-all duration-300 transform active:scale-[0.98]" className="w-full flex justify-center items-center gap-2 bg-gradient-to-r from-blue-600 to-indigo-600 hover:from-blue-700 hover:to-indigo-700 text-white font-bold py-3.5 px-4 rounded-xl shadow-lg hover:shadow-blue-500/30 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 disabled:opacity-50 disabled:cursor-not-allowed transition-all duration-300 transform active:scale-[0.98]"
> >
<SaveIcon className="h-5 w-5" /> <SaveIcon className="h-5 w-5" />
<span>Salvar e Continuar</span> <span>Salvar e Continuar</span>
</button> </button>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
); );
}; };

View File

@@ -1,31 +1,31 @@
@tailwind base; @tailwind base;
@tailwind components; @tailwind components;
@tailwind utilities; @tailwind utilities;
@layer base { @layer base {
body { body {
@apply bg-slate-100 dark:bg-slate-900 text-slate-900 dark:text-slate-100 transition-colors duration-300 font-sans; @apply bg-slate-100 dark:bg-slate-900 text-slate-900 dark:text-slate-100 transition-colors duration-300 font-sans;
background: linear-gradient(135deg, #f8fafc 0%, #e2e8f0 100%); background: linear-gradient(135deg, #f8fafc 0%, #e2e8f0 100%);
} }
.dark body { .dark body {
background: linear-gradient(135deg, #0f172a 0%, #1e293b 100%); background: linear-gradient(135deg, #0f172a 0%, #1e293b 100%);
} }
} }
@layer components { @layer components {
.glass-panel { .glass-panel {
@apply bg-white/70 dark:bg-slate-800/60 backdrop-blur-md border border-white/20 dark:border-slate-700/50 shadow-xl; @apply bg-white/70 dark:bg-slate-800/60 backdrop-blur-md border border-white/20 dark:border-slate-700/50 shadow-xl;
} }
.glass-card { .glass-card {
@apply bg-white/50 dark:bg-slate-800/40 backdrop-blur-sm border border-white/30 dark:border-slate-700/30 hover:bg-white/60 dark:hover:bg-slate-800/50 transition-all duration-300; @apply bg-white/50 dark:bg-slate-800/40 backdrop-blur-sm border border-white/30 dark:border-slate-700/30 hover:bg-white/60 dark:hover:bg-slate-800/50 transition-all duration-300;
} }
} }
@keyframes fade-in { @keyframes fade-in {
from { opacity: 0; transform: translateY(10px); } from { opacity: 0; transform: translateY(10px); }
to { opacity: 1; transform: translateY(0); } to { opacity: 1; transform: translateY(0); }
} }
.animate-fade-in { .animate-fade-in {
animation: fade-in 0.5s ease-out forwards; animation: fade-in 0.5s ease-out forwards;
} }