saveinmed/website/README.md
2026-01-01 15:20:48 -03:00

418 lines
9 KiB
Markdown

# SaveInMed Website
Site institucional do SaveInMed, desenvolvido com Fresh (Deno framework).
## 🎯 Propósito
Este é o site institucional e de marketing do SaveInMed, responsável por:
- Apresentar a plataforma para novos usuários
- Landing pages de produtos e serviços
- Captura de leads
- Informações sobre a empresa
- Blog e conteúdo educacional
- SEO otimizado para aquisição orgânica
## 🚀 Tecnologias
- **Fresh v2** - Framework web moderno para Deno
- **Deno 2** - Runtime JavaScript/TypeScript seguro
- **Preact** - Biblioteca UI leve (3KB)
- **Tailwind CSS** - Framework CSS utility-first
- **Islands Architecture** - Hidratação parcial para performance máxima
## 📋 Funcionalidades
### Landing Pages
- Página inicial institucional
- Páginas de produtos
- Casos de uso
- Preços e planos
### Captura de Leads
- Formulários de contato
- Newsletter signup
- Demonstração agendada
- Download de materiais
### Conteúdo
- Blog posts
- Artigos educacionais
- FAQ
- Documentação pública
### SEO
- Meta tags otimizadas
- Open Graph
- Schema.org markup
- Sitemap XML
- robots.txt
## 🏗️ Arquitetura (Fresh Islands)
```
website/
├── routes/ # Rotas baseadas em arquivo
│ ├── index.tsx # Página inicial
│ ├── about.tsx # Sobre nós
│ ├── contact.tsx # Contato
│ ├── blog/
│ │ ├── index.tsx # Lista de posts
│ │ └── [slug].tsx # Post individual
│ └── api/ # API routes
│ └── newsletter.ts # Endpoint de newsletter
├── islands/ # Componentes interativos (client-side)
│ ├── FlowTicker.tsx # Ticker animado
│ ├── LeadForm.tsx # Formulário de captura
│ └── ContactForm.tsx # Formulário de contato
├── components/ # Componentes estáticos (SSR)
│ ├── Header.tsx
│ ├── Footer.tsx
│ └── Hero.tsx
├── static/ # Arquivos estáticos
│ ├── styles.css
│ ├── logo.svg
│ └── images/
├── fresh.config.ts # Configuração do Fresh
├── deno.json # Configuração do Deno
└── README.md
```
## 🔧 Configuração
### Variáveis de Ambiente
Crie um arquivo `.env` na raiz do projeto:
```bash
# API Backend
API_URL=https://api.saveinmed.com
# Email (para formulários)
SMTP_HOST=smtp.gmail.com
SMTP_PORT=587
SMTP_USER=noreply@saveinmed.com
SMTP_PASSWORD=your-password
# Analytics
GOOGLE_ANALYTICS_ID=G-XXXXXXXXXX
# Ambiente
DENO_ENV=development
```
### Pré-requisitos
- Deno 2.0 ou superior
## 🏃 Execução Local
```bash
# Executar em modo desenvolvimento
deno task dev
# Site estará disponível em http://localhost:8000
```
## 🏗️ Build e Produção
```bash
# Build para produção
deno task build
# Executar build de produção
deno task start
# Preview
deno task preview
```
## 🎨 Islands Architecture
Fresh utiliza a arquitetura de "islands" para hidratação parcial:
### Componentes Estáticos (SSR)
Renderizados no servidor, sem JavaScript no cliente:
```tsx
// components/Hero.tsx
export function Hero() {
return (
<section class="bg-gradient-to-r from-blue-600 to-purple-600 text-white py-20">
<h1 class="text-5xl font-bold">SaveInMed</h1>
<p class="text-xl mt-4">Marketplace B2B Farmacêutico</p>
</section>
);
}
```
### Islands (Interativos)
Componentes que precisam de JavaScript no cliente:
```tsx
// islands/LeadForm.tsx
import { useState } from "preact/hooks";
export default function LeadForm() {
const [email, setEmail] = useState("");
const handleSubmit = async (e: Event) => {
e.preventDefault();
await fetch("/api/newsletter", {
method: "POST",
body: JSON.stringify({ email }),
});
};
return (
<form onSubmit={handleSubmit}>
<input
type="email"
value={email}
onInput={(e) => setEmail(e.currentTarget.value)}
placeholder="Seu email"
/>
<button type="submit">Inscrever</button>
</form>
);
}
```
## 🛣️ Roteamento
Fresh usa roteamento baseado em arquivos:
```
routes/
├── index.tsx → /
├── about.tsx → /about
├── contact.tsx → /contact
├── blog/
│ ├── index.tsx → /blog
│ └── [slug].tsx → /blog/:slug
└── api/
└── newsletter.ts → /api/newsletter
```
## 📡 API Routes
```typescript
// routes/api/newsletter.ts
import { Handlers } from "$fresh/server.ts";
export const handler: Handlers = {
async POST(req) {
const { email } = await req.json();
// Salvar email no banco de dados
await saveToNewsletter(email);
return new Response(JSON.stringify({ success: true }), {
headers: { "Content-Type": "application/json" },
});
},
};
```
## 🎨 Estilização
O projeto usa Tailwind CSS com configuração customizada:
```typescript
// tailwind.config.ts
export default {
theme: {
extend: {
colors: {
primary: '#3b82f6',
secondary: '#8b5cf6',
},
},
},
};
```
## 🔍 SEO
### Meta Tags
```tsx
export default function BlogPost({ data }) {
return (
<>
<Head>
<title>{data.title} | SaveInMed Blog</title>
<meta name="description" content={data.excerpt} />
<meta property="og:title" content={data.title} />
<meta property="og:description" content={data.excerpt} />
<meta property="og:image" content={data.image} />
</Head>
<article>{/* ... */}</article>
</>
);
}
```
### Sitemap
```typescript
// routes/sitemap.xml.ts
export const handler: Handlers = {
GET() {
const sitemap = `<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
<url>
<loc>https://saveinmed.com/</loc>
<priority>1.0</priority>
</url>
</urlset>`;
return new Response(sitemap, {
headers: { "Content-Type": "application/xml" },
});
},
};
```
## ⚡ Performance
Fresh é otimizado para performance máxima:
- **Zero JavaScript por padrão**: Apenas islands têm JS
- **Edge rendering**: Deploy em edge para latência mínima
- **Streaming SSR**: Renderização progressiva
- **Automatic code splitting**: Por rota e island
- **Preact**: Apenas 3KB de runtime
### Lighthouse Score Esperado
- Performance: 95-100
- Accessibility: 95-100
- Best Practices: 95-100
- SEO: 95-100
## 🚀 Deploy
### Deno Deploy (Recomendado)
```bash
# Instalar deployctl
deno install -Arf https://deno.land/x/deploy/deployctl.ts
# Deploy
deployctl deploy --project=saveinmed-website
```
### Docker
```bash
# Build
docker build -t saveinmed-website:latest .
# Run
docker run -p 8000:8000 saveinmed-website:latest
```
### Outras Plataformas
- **Cloudflare Pages**: Suporte para Deno
- **Netlify**: Via Deno runtime
- **Vercel**: Via Deno runtime
## 📧 Formulários de Contato
```tsx
// islands/ContactForm.tsx
export default function ContactForm() {
const handleSubmit = async (e: Event) => {
e.preventDefault();
const formData = new FormData(e.target as HTMLFormElement);
await fetch("/api/contact", {
method: "POST",
body: JSON.stringify(Object.fromEntries(formData)),
});
alert("Mensagem enviada!");
};
return (
<form onSubmit={handleSubmit}>
<input name="name" placeholder="Nome" required />
<input name="email" type="email" placeholder="Email" required />
<textarea name="message" placeholder="Mensagem" required />
<button type="submit">Enviar</button>
</form>
);
}
```
## 🧪 Testes
```bash
# Executar testes
deno test
# Com coverage
deno test --coverage=coverage
# Gerar relatório de coverage
deno coverage coverage --lcov > coverage.lcov
```
> Para matriz completa (com/sem banco e Playwright), veja: [docs/TESTES.md](../docs/TESTES.md)
## 📊 Analytics
Integração com Google Analytics:
```tsx
// components/Analytics.tsx
export function Analytics() {
return (
<script
async
src={`https://www.googletagmanager.com/gtag/js?id=${GA_ID}`}
/>
);
}
```
## 🔗 Integração com Outros Componentes
- **Backend APIs**: Links para signup e login
- **SaveInMed Frontend**: Redirecionamento após captura de lead
- **Blog**: Pode ser hospedado separadamente ou integrado
## 📝 Conteúdo
### Estrutura de Blog Post
```typescript
interface BlogPost {
slug: string;
title: string;
excerpt: string;
content: string;
author: string;
publishedAt: Date;
tags: string[];
image: string;
}
```
## 🌐 Internacionalização (i18n)
```typescript
// lib/i18n.ts
const translations = {
pt: {
hero: {
title: "Marketplace B2B Farmacêutico",
cta: "Começar Agora",
},
},
en: {
hero: {
title: "B2B Pharmaceutical Marketplace",
cta: "Get Started",
},
},
};
```
## 📝 Licença
MIT