1
📐 Arquitetura do Frontend
Stack simples com Jinja2, HTMX e Tailwind CSS.
app/
├── templates/
│ ├── base.html # Layout base
│ ├── components/
│ │ ├── navbar.html
│ │ ├── chat_message.html
│ │ └── source_card.html
│ ├── pages/
│ │ ├── home.html
│ │ ├── notebook.html
│ │ └── chat.html
│ └── partials/ # Fragments HTMX
│ ├── message_list.html
│ └── source_list.html
├── static/
│ ├── css/
│ │ └── styles.css # Tailwind compilado
│ └── js/
│ └── app.js # JavaScript minimo
2
🎨 Template Base
Layout compartilhado por todas as paginas.
<!-- templates/base.html -->
<!DOCTYPE html>
<html lang="pt-BR" class="dark">
<head>
<meta charset="UTF-8">
<title>{% block title %}NotebookLMX{% endblock %}</title>
<script src="https://cdn.tailwindcss.com"></script>
<script src="https://unpkg.com/htmx.org@1.9.10"></script>
</head>
<body class="bg-gray-900 text-white min-h-screen">
{% include "components/navbar.html" %}
<main class="max-w-6xl mx-auto px-4 py-8">
{% block content %}{% endblock %}
</main>
{% block scripts %}{% endblock %}
</body>
</html>
3
💬 Interface de Chat
Componente de chat com HTMX para atualizacoes em tempo real.
<!-- templates/pages/chat.html -->
{% extends "base.html" %}
{% block content %}
<div class="flex flex-col h-[calc(100vh-200px)]">
<!-- Mensagens -->
<div id="messages" class="flex-1 overflow-y-auto space-y-4 p-4">
{% for msg in messages %}
{% include "components/chat_message.html" %}
{% endfor %}
</div>
<!-- Input -->
<form hx-post="/api/notebooks/{{ notebook.id }}/chat"
hx-target="#messages"
hx-swap="beforeend"
class="p-4 border-t border-gray-700">
<div class="flex space-x-4">
<input type="text" name="message"
class="flex-1 bg-gray-800 rounded-lg px-4 py-2"
placeholder="Digite sua mensagem...">
<button type="submit" class="bg-amber-600 px-6 py-2 rounded-lg">
Enviar
</button>
</div>
</form>
</div>
{% endblock %}
4
📤 Upload de Fontes
Componente para upload de PDFs e arquivos de texto.
<!-- Componente de upload com drag-and-drop -->
<div id="upload-zone"
class="border-2 border-dashed border-gray-600 rounded-xl p-8
hover:border-amber-500 transition-colors"
hx-post="/api/notebooks/{{ notebook.id }}/sources"
hx-encoding="multipart/form-data"
hx-target="#source-list"
hx-swap="beforeend">
<input type="file" name="file" accept=".pdf,.txt,.md"
class="hidden" id="file-input">
<div class="text-center">
<p class="text-gray-400">Arraste arquivos aqui ou</p>
<label for="file-input" class="text-amber-400 cursor-pointer">
clique para selecionar
</label>
</div>
</div>
<!-- Lista de fontes -->
<div id="source-list" class="mt-6 space-y-3">
{% for source in sources %}
{% include "components/source_card.html" %}
{% endfor %}
</div>
5
🎯 Selecao de Persona
Interface para escolher o estilo de resposta da IA.
<!-- Seletor de persona -->
<div class="flex space-x-2 mb-4">
{% for persona in personas %}
<button type="button"
class="persona-btn px-4 py-2 rounded-lg
{% if persona.id == current_persona %}
bg-amber-600 text-white
{% else %}
bg-gray-700 text-gray-300
{% endif %}"
hx-post="/api/notebooks/{{ notebook.id }}/persona"
hx-vals='{"persona": "{{ persona.id }}"}'
hx-swap="none">
{{ persona.icon }} {{ persona.name }}
</button>
{% endfor %}
</div>
<!-- Personas disponiveis -->
<!-- 🎓 Academico - Tom formal, citacoes -->
<!-- 💼 Profissional - Direto, objetivo -->
<!-- 🎨 Criativo - Analogias, exemplos -->
6
📊 Dashboard de Metricas
Visualizacao de uso e custos para transparencia.
<!-- Dashboard de metricas GIPM -->
<div class="grid grid-cols-4 gap-4 mb-8">
<div class="bg-gray-800 rounded-xl p-4">
<p class="text-gray-400 text-sm">Mensagens</p>
<p class="text-2xl font-bold text-white">{{ stats.total_messages }}</p>
</div>
<div class="bg-gray-800 rounded-xl p-4">
<p class="text-gray-400 text-sm">Tokens Usados</p>
<p class="text-2xl font-bold text-white">{{ stats.total_tokens | format_number }}</p>
</div>
<div class="bg-gray-800 rounded-xl p-4">
<p class="text-gray-400 text-sm">Custo Total</p>
<p class="text-2xl font-bold text-amber-400">${{ stats.total_cost | round(4) }}</p>
</div>
<div class="bg-gray-800 rounded-xl p-4">
<p class="text-gray-400 text-sm">Artefatos</p>
<p class="text-2xl font-bold text-white">{{ stats.total_artifacts }}</p>
</div>
</div>
📝 Resumo do Modulo
✓Jinja2 - Templates server-side
✓HTMX - Interatividade sem SPA
✓Tailwind - Estilizacao rapida
✓Metricas - Transparencia para o usuario