429 lines
9.2 KiB
Markdown
429 lines
9.2 KiB
Markdown
# SaveInMed Website
|
|
|
|
## Status (pronto x faltando)
|
|
|
|
**Pronto**
|
|
- Conteúdo descrito neste documento.
|
|
|
|
**Faltando**
|
|
- Confirmar no código o estado real das funcionalidades e atualizar esta seção conforme necessário.
|
|
|
|
---
|
|
|
|
|
|
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
|