Compare commits

..

10 Commits

Author SHA1 Message Date
mario 3cbc7dd529 fix: service targetPort 8080
Deploy / Build & Push (push) Successful in 9s
Deploy / Deploy Prod (push) Successful in 4s
2026-05-24 22:55:44 -03:00
mario 2eeff8adc5 fix: remove staging deploy (landing only exists in prod)
Deploy / Build & Push (push) Successful in 9s
Deploy / Deploy Prod (push) Successful in 5s
2026-05-24 22:52:40 -03:00
mario f3c1d76ae5 fix: listen on port 8080 for non-root container
Deploy / Build & Push (Prod) (push) Successful in 11s
Deploy / Deploy Staging (push) Failing after 2s
Deploy / Deploy Prod (push) Has been skipped
2026-05-24 22:34:17 -03:00
mario c4b8f19d6a chore: ignore rust_out binary
Deploy / Build & Push (Prod) (push) Successful in 6s
Deploy / Deploy Staging (push) Failing after 2m3s
Deploy / Deploy Prod (push) Has been skipped
2026-05-24 10:13:19 -03:00
mario 555773e2e9 chore: add public assets (OG images, favicon) 2026-05-24 10:12:52 -03:00
mario f38d7885f2 chore: add OG image generation script 2026-05-24 10:12:52 -03:00
mario dbddcc40a2 feat: add favicon, OG images, social cards, and analytics
Deploy / Build & Push (Prod) (push) Successful in 18s
Deploy / Deploy Staging (push) Successful in 5s
Deploy / Deploy Prod (push) Successful in 6s
- Add favicon.png (orange B logo)
- Add og-image.png (1200x630 social card)
- Add og:image and twitter:image meta tags to all pages
- Add Plausible analytics script (privacy-friendly)
- Update Dockerfile to copy static assets

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-05-23 13:31:53 -03:00
mario 22df131b57 chore: add .env patterns to .gitignore 2026-05-23 10:57:53 -03:00
mario de85066688 feat: refactor Dockerfile to multi-stage build with security improvements
- Refactored from single-stage to proper multi-stage build
- Added cache mount for npm (npx tailwindcss)
- Added non-root nginx user (nginx-user:1000)
- Added .dockerignore to exclude dev files
- Configured proper permissions for nginx directories and pid file
- Major improvements: smaller image, faster builds, better security

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-05-22 21:54:37 -03:00
mario 1ebfc0e310 docs: update AGENTS.md to Intent Layer spec
Add Purpose & Scope, Entry Points, Dependencies, Traps & Gotchas,
Anti-Patterns sections.
2026-05-08 21:20:35 -03:00
15 changed files with 175 additions and 38 deletions
+10
View File
@@ -0,0 +1,10 @@
*.local
.vscode
.idea
.DS_Store
.env
.env.*
.git
.gitignore
README.md
.github
+3 -17
View File
@@ -5,8 +5,8 @@ on:
branches: [trunk] branches: [trunk]
jobs: jobs:
build-and-push-prod: build-and-push:
name: Build & Push (Prod) name: Build & Push
runs-on: heavy runs-on: heavy
container: git.batida.io/batida/ci-node:latest container: git.batida.io/batida/ci-node:latest
steps: steps:
@@ -23,24 +23,10 @@ jobs:
docker push git.batida.io/batida/batida-landing:${{ github.sha }} docker push git.batida.io/batida/batida-landing:${{ github.sha }}
docker push git.batida.io/batida/batida-landing:latest docker push git.batida.io/batida/batida-landing:latest
deploy-staging:
name: Deploy Staging
runs-on: heavy
needs: [build-and-push-prod]
container: git.batida.io/batida/ci-node:latest
steps:
- name: Deploy to staging
run: |
echo "$KUBECONFIG_CONTENT" > /tmp/kubeconfig
kubectl --kubeconfig /tmp/kubeconfig set image deployment/batida-landing batida-landing=git.batida.io/batida/batida-landing:${{ github.sha }} -n staging
kubectl --kubeconfig /tmp/kubeconfig rollout status deployment/batida-landing -n staging --timeout=120s
env:
KUBECONFIG_CONTENT: ${{ secrets.KUBECONFIG }}
deploy-prod: deploy-prod:
name: Deploy Prod name: Deploy Prod
runs-on: heavy runs-on: heavy
needs: [deploy-staging] needs: [build-and-push]
container: git.batida.io/batida/ci-node:latest container: git.batida.io/batida/ci-node:latest
steps: steps:
- name: Deploy to prod - name: Deploy to prod
+6
View File
@@ -3,3 +3,9 @@ node_modules/
output.css output.css
package.json package.json
package-lock.json package-lock.json
# Environment
.env
.env.*
!.env.*.example
rust_out
+23 -12
View File
@@ -1,10 +1,21 @@
# batida-landing # batida-landing — Intent Node (Root)
## Purpose & Scope
Marketing/landing page for Batida. Static HTML served via Nginx. Marketing/landing page for Batida. Static HTML served via Nginx.
Separate git repository — self-contained. Separate git repository — self-contained.
## Structure **Does:** Serve static HTML landing pages (EN + PT-BR), SEO, Nginx hosting.
**Does NOT:** Handle user data, run application logic, serve the app (→ batida-web).
## Entry Points
No build step required. Just serve static files via Nginx.
## Dependencies
| Depends On | Why |
|------------|-----|
| batida-infra | K8s deployment manifests, Dockerfile → Nginx container |
## Structure
``` ```
index.html → English landing page index.html → English landing page
index.pt-br.html → Portuguese landing page index.pt-br.html → Portuguese landing page
@@ -17,23 +28,23 @@ sitemap.xml → SEO sitemap
k8s/ → Kubernetes deployment manifests k8s/ → Kubernetes deployment manifests
``` ```
## Deployment ## Key Patterns
Deployed to Kubernetes via `batida-infra`. The Dockerfile copies static HTML into an Nginx container. Manifests in `k8s/` define the deployment.
## Key Facts
- Fully static — no build step, no JavaScript framework - Fully static — no build step, no JavaScript framework
- Two languages: English and Portuguese (separate HTML files) - Two languages: English and Portuguese (separate HTML files)
- Nginx handles gzip compression and static caching - Nginx handles gzip compression and static caching
- SEO configured via robots.txt and sitemap.xml - SEO configured via robots.txt and sitemap.xml
## Traps & Gotchas
- Both language versions must be updated in sync — forgetting one leaves stale content
- No hot reload or dev server — edit HTML, refresh browser
## Anti-Patterns
- Never add server-side logic or build tools — pure static HTML
- Never commit secrets or environment-specific values
- Never add JavaScript frameworks — keep it static
## Boundaries ## Boundaries
### Always ### Always
- Keep both language versions in sync when updating content - Keep both language versions in sync when updating content
- Test HTML renders correctly in browser before committing - Test HTML renders correctly in browser before committing
### Never
- Never add server-side logic or build tools — pure static HTML
- Never commit secrets or environment-specific values
+26 -5
View File
@@ -1,14 +1,25 @@
FROM node:20-alpine AS build FROM node:20-alpine AS builder
WORKDIR /build WORKDIR /build
COPY input.css tailwind.config.js ./ COPY input.css tailwind.config.js ./
COPY *.html ./ COPY *.html ./
RUN npx tailwindcss@3 -i input.css -o output.css --minify
RUN --mount=type=cache,target=/root/.npm \
npx tailwindcss@3 -i input.css -o output.css --minify
FROM nginx:alpine FROM nginx:alpine
ARG APP_URL=https://app.batida.io ARG APP_URL=https://app.batida.io
COPY --from=build /build/output.css /usr/share/nginx/html/output.css RUN addgroup -g 1000 -S nginx-user && \
adduser -u 1000 -S nginx-user -G nginx-user
COPY --from=builder /build/output.css /usr/share/nginx/html/output.css
COPY favicon.png /usr/share/nginx/html/favicon.png
COPY og-image.png /usr/share/nginx/html/og-image.png
COPY robots.txt /usr/share/nginx/html/robots.txt
COPY sitemap.xml /usr/share/nginx/html/sitemap.xml
COPY index.html /tmp/index.html COPY index.html /tmp/index.html
COPY index.pt-br.html /tmp/index.pt-br.html COPY index.pt-br.html /tmp/index.pt-br.html
COPY vs.html /tmp/vs.html COPY vs.html /tmp/vs.html
@@ -22,8 +33,18 @@ RUN sed -i "s|{{APP_URL}}|${APP_URL}|g" /tmp/index.html && \
mv /tmp/index.html /usr/share/nginx/html/index.html && \ mv /tmp/index.html /usr/share/nginx/html/index.html && \
mv /tmp/index.pt-br.html /usr/share/nginx/html/pt-br/index.html && \ mv /tmp/index.pt-br.html /usr/share/nginx/html/pt-br/index.html && \
mv /tmp/vs.html /usr/share/nginx/html/vs.html && \ mv /tmp/vs.html /usr/share/nginx/html/vs.html && \
mv /tmp/vs.pt-br.html /usr/share/nginx/html/pt-br/vs.html mv /tmp/vs.pt-br.html /usr/share/nginx/html/pt-br/vs.html && \
chown -R nginx-user:nginx-user /usr/share/nginx/html && \
chown -R nginx-user:nginx-user /var/cache/nginx && \
chown -R nginx-user:nginx-user /var/log/nginx && \
chown -R nginx-user:nginx-user /etc/nginx/conf.d && \
touch /run/nginx.pid && \
chown -R nginx-user:nginx-user /run/nginx.pid
COPY nginx.conf /etc/nginx/conf.d/default.conf COPY nginx.conf /etc/nginx/conf.d/default.conf
EXPOSE 80 USER nginx-user
EXPOSE 8080
CMD ["nginx", "-g", "daemon off;"]
+67
View File
@@ -0,0 +1,67 @@
"""Generate OG image and favicon for Batida landing page."""
from PIL import Image, ImageDraw, ImageFont
# OG Image (1200x630)
W, H = 1200, 630
img = Image.new("RGB", (W, H), "#0C0C0F")
draw = ImageDraw.Draw(img)
# Orange accent bar at top
draw.rectangle([0, 0, W, 6], fill="#F97316")
# Logo square (orange B)
logo_size = 120
logo_x, logo_y = 80, 180
draw.rounded_rectangle([logo_x, logo_y, logo_x + logo_size, logo_y + logo_size], radius=24, fill="#F97316")
try:
font_bold = ImageFont.truetype("/System/Library/Fonts/Helvetica.ttc", 72)
font_title = ImageFont.truetype("/System/Library/Fonts/Helvetica.ttc", 64)
font_sub = ImageFont.truetype("/System/Library/Fonts/Helvetica.ttc", 28)
font_tag = ImageFont.truetype("/System/Library/Fonts/Helvetica.ttc", 22)
except Exception:
font_bold = ImageFont.load_default()
font_title = ImageFont.load_default()
font_sub = ImageFont.load_default()
font_tag = ImageFont.load_default()
# B letter in logo
bbox = draw.textbbox((0, 0), "B", font=font_bold)
bw, bh = bbox[2] - bbox[0], bbox[3] - bbox[1]
draw.text((logo_x + (logo_size - bw) / 2, logo_y + (logo_size - bh) / 2 - 8), "B", fill="white", font=font_bold)
# Title
draw.text((240, 185), "Batida", fill="#FAFAFA", font=font_title)
# Tagline
draw.text((240, 270), "Manage Incidents. Keep Your Cool.", fill="#6B6B80", font=font_sub)
# Bottom tagline
draw.text((80, 460), "Intelligent incident management for DevOps teams.", fill="#4A4A5A", font=font_tag)
draw.text((80, 495), "pagerduty alternative • open core • self-hosted or cloud", fill="#3A3A4A", font=font_tag)
# CTA button
btn_x, btn_y, btn_w, btn_h = 80, 550, 200, 44
draw.rounded_rectangle([btn_x, btn_y, btn_x + btn_w, btn_y + btn_h], radius=8, fill="#F97316")
bbox = draw.textbbox((0, 0), "Get Started", font=font_tag)
tw = bbox[2] - bbox[0]
draw.text((btn_x + (btn_w - tw) / 2, btn_y + 10), "Get Started", fill="white", font=font_tag)
# URL
draw.text((960, 580), "batida.io", fill="#3A3A4A", font=font_tag)
img.save("/Users/kakarotto/codes/personal/batida/batida-landing/og-image.png", "PNG")
print("OG image created: og-image.png")
# Favicon PNG (32x32)
fav = Image.new("RGBA", (32, 32), (0, 0, 0, 0))
fav_draw = ImageDraw.Draw(fav)
fav_draw.rounded_rectangle([0, 0, 32, 32], radius=8, fill="#F97316")
try:
fav_font = ImageFont.truetype("/System/Library/Fonts/Helvetica.ttc", 20)
except Exception:
fav_font = ImageFont.load_default()
bbox = fav_draw.textbbox((0, 0), "B", font=fav_font)
bw, bh = bbox[2] - bbox[0], bbox[3] - bbox[1]
fav_draw.text(((32 - bw) / 2, (32 - bh) / 2 - 2), "B", fill="white", font=fav_font)
fav.save("/Users/kakarotto/codes/personal/batida/batida-landing/favicon.png", "PNG")
print("Favicon created: favicon.png")
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 468 B

+8
View File
@@ -8,6 +8,7 @@
<title>Batida — Manage Incidents. Keep Your Cool.</title> <title>Batida — Manage Incidents. Keep Your Cool.</title>
<meta name="description" content="Intelligent alternative to PagerDuty. Incident management platform for DevOps teams that need to respond fast, coordinate without chaos, and learn from every problem."> <meta name="description" content="Intelligent alternative to PagerDuty. Incident management platform for DevOps teams that need to respond fast, coordinate without chaos, and learn from every problem.">
<link rel="canonical" href="https://batida.io/"> <link rel="canonical" href="https://batida.io/">
<link rel="icon" type="image/png" href="/favicon.png">
<!-- Open Graph --> <!-- Open Graph -->
<meta property="og:type" content="website"> <meta property="og:type" content="website">
@@ -15,11 +16,15 @@
<meta property="og:title" content="Batida — Manage Incidents. Keep Your Cool."> <meta property="og:title" content="Batida — Manage Incidents. Keep Your Cool.">
<meta property="og:description" content="Intelligent alternative to PagerDuty. Incident management platform for DevOps teams. Start free."> <meta property="og:description" content="Intelligent alternative to PagerDuty. Incident management platform for DevOps teams. Start free.">
<meta property="og:site_name" content="Batida"> <meta property="og:site_name" content="Batida">
<meta property="og:image" content="https://batida.io/og-image.png">
<meta property="og:image:width" content="1200">
<meta property="og:image:height" content="630">
<!-- Twitter Card --> <!-- Twitter Card -->
<meta name="twitter:card" content="summary_large_image"> <meta name="twitter:card" content="summary_large_image">
<meta name="twitter:title" content="Batida — Manage Incidents. Keep Your Cool."> <meta name="twitter:title" content="Batida — Manage Incidents. Keep Your Cool.">
<meta name="twitter:description" content="Intelligent alternative to PagerDuty. Incident management platform for DevOps teams."> <meta name="twitter:description" content="Intelligent alternative to PagerDuty. Incident management platform for DevOps teams.">
<meta name="twitter:image" content="https://batida.io/og-image.png">
<!-- Sitemap --> <!-- Sitemap -->
<link rel="sitemap" type="application/xml" href="/sitemap.xml"> <link rel="sitemap" type="application/xml" href="/sitemap.xml">
@@ -489,6 +494,9 @@
font-size: clamp(1.5rem, 4vw, 3rem); font-size: clamp(1.5rem, 4vw, 3rem);
} }
</style> </style>
<!-- Analytics: Plausible (privacy-friendly, GDPR compliant) -->
<script defer data-domain="batida.io" src="https://plausible.io/js/script.js"></script>
</head> </head>
<body class="antialiased"> <body class="antialiased">
+8
View File
@@ -8,6 +8,7 @@
<title>Batida — Gerencie Incidentes. Mantenha a Calma.</title> <title>Batida — Gerencie Incidentes. Mantenha a Calma.</title>
<meta name="description" content="Plataforma moderna de incident management. Alternativa inteligente ao PagerDuty. Setup em minutos. Comece grátis."> <meta name="description" content="Plataforma moderna de incident management. Alternativa inteligente ao PagerDuty. Setup em minutos. Comece grátis.">
<link rel="canonical" href="https://batida.io/pt-br"> <link rel="canonical" href="https://batida.io/pt-br">
<link rel="icon" type="image/png" href="/favicon.png">
<!-- Open Graph --> <!-- Open Graph -->
<meta property="og:type" content="website"> <meta property="og:type" content="website">
@@ -15,11 +16,15 @@
<meta property="og:title" content="Batida — Gerencie Incidentes. Mantenha a Calma."> <meta property="og:title" content="Batida — Gerencie Incidentes. Mantenha a Calma.">
<meta property="og:description" content="Plataforma moderna de incident management. Alternativa inteligente ao PagerDuty. Setup em minutos. Comece grátis."> <meta property="og:description" content="Plataforma moderna de incident management. Alternativa inteligente ao PagerDuty. Setup em minutos. Comece grátis.">
<meta property="og:site_name" content="Batida"> <meta property="og:site_name" content="Batida">
<meta property="og:image" content="https://batida.io/og-image.png">
<meta property="og:image:width" content="1200">
<meta property="og:image:height" content="630">
<!-- Twitter Card --> <!-- Twitter Card -->
<meta name="twitter:card" content="summary_large_image"> <meta name="twitter:card" content="summary_large_image">
<meta name="twitter:title" content="Batida — Gerencie Incidentes. Mantenha a Calma."> <meta name="twitter:title" content="Batida — Gerencie Incidentes. Mantenha a Calma.">
<meta name="twitter:description" content="Plataforma moderna de incident management. Alternativa inteligente ao PagerDuty."> <meta name="twitter:description" content="Plataforma moderna de incident management. Alternativa inteligente ao PagerDuty.">
<meta name="twitter:image" content="https://batida.io/og-image.png">
<!-- Sitemap --> <!-- Sitemap -->
<link rel="sitemap" type="application/xml" href="/sitemap.xml"> <link rel="sitemap" type="application/xml" href="/sitemap.xml">
@@ -489,6 +494,9 @@
font-size: clamp(1.5rem, 4vw, 3rem); font-size: clamp(1.5rem, 4vw, 3rem);
} }
</style> </style>
<!-- Analytics: Plausible (privacy-friendly, GDPR compliant) -->
<script defer data-domain="batida.io" src="https://plausible.io/js/script.js"></script>
</head> </head>
<body class="antialiased"> <body class="antialiased">
+3 -3
View File
@@ -24,11 +24,11 @@ spec:
- name: batida-landing - name: batida-landing
image: git.batida.io/batida/batida-landing:latest image: git.batida.io/batida/batida-landing:latest
ports: ports:
- containerPort: 80 - containerPort: 8080
livenessProbe: livenessProbe:
httpGet: httpGet:
path: / path: /
port: 80 port: 8080
initialDelaySeconds: 5 initialDelaySeconds: 5
periodSeconds: 30 periodSeconds: 30
resources: resources:
@@ -49,4 +49,4 @@ spec:
app: batida-landing app: batida-landing
ports: ports:
- port: 80 - port: 80
targetPort: 80 targetPort: 8080
+1 -1
View File
@@ -1,5 +1,5 @@
server { server {
listen 80; listen 8080;
server_name _; server_name _;
root /usr/share/nginx/html; root /usr/share/nginx/html;
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

+4
View File
@@ -0,0 +1,4 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32">
<rect width="32" height="32" rx="8" fill="#F97316"/>
<text x="16" y="23" font-family="Arial,sans-serif" font-size="20" font-weight="bold" fill="white" text-anchor="middle">B</text>
</svg>

After

Width:  |  Height:  |  Size: 253 B

+8
View File
@@ -8,16 +8,21 @@
<title>Batida vs PagerDuty vs Grafana OnCall — Feature Comparison</title> <title>Batida vs PagerDuty vs Grafana OnCall — Feature Comparison</title>
<meta name="description" content="Compare Batida with PagerDuty and Grafana OnCall. See pricing, features, LGPD compliance, and why Brazilian teams choose Batida."> <meta name="description" content="Compare Batida with PagerDuty and Grafana OnCall. See pricing, features, LGPD compliance, and why Brazilian teams choose Batida.">
<link rel="canonical" href="https://batida.io/vs"> <link rel="canonical" href="https://batida.io/vs">
<link rel="icon" type="image/png" href="/favicon.png">
<meta property="og:type" content="website"> <meta property="og:type" content="website">
<meta property="og:url" content="https://batida.io/vs"> <meta property="og:url" content="https://batida.io/vs">
<meta property="og:title" content="Batida vs PagerDuty vs Grafana OnCall — Feature Comparison"> <meta property="og:title" content="Batida vs PagerDuty vs Grafana OnCall — Feature Comparison">
<meta property="og:description" content="Compare incident management platforms. See why Batida is the best choice for Brazilian DevOps teams."> <meta property="og:description" content="Compare incident management platforms. See why Batida is the best choice for Brazilian DevOps teams.">
<meta property="og:site_name" content="Batida"> <meta property="og:site_name" content="Batida">
<meta property="og:image" content="https://batida.io/og-image.png">
<meta property="og:image:width" content="1200">
<meta property="og:image:height" content="630">
<meta name="twitter:card" content="summary_large_image"> <meta name="twitter:card" content="summary_large_image">
<meta name="twitter:title" content="Batida vs PagerDuty vs Grafana OnCall"> <meta name="twitter:title" content="Batida vs PagerDuty vs Grafana OnCall">
<meta name="twitter:description" content="Compare incident management platforms for Brazilian teams."> <meta name="twitter:description" content="Compare incident management platforms for Brazilian teams.">
<meta name="twitter:image" content="https://batida.io/og-image.png">
<link rel="preconnect" href="https://fonts.googleapis.com"> <link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
@@ -70,6 +75,9 @@
.compare-table .partial { color: #F59E0B; } .compare-table .partial { color: #F59E0B; }
.compare-table .batida-col { color: #F97316; font-weight: 600; } .compare-table .batida-col { color: #F97316; font-weight: 600; }
</style> </style>
<!-- Analytics: Plausible (privacy-friendly, GDPR compliant) -->
<script defer data-domain="batida.io" src="https://plausible.io/js/script.js"></script>
</head> </head>
<body class="antialiased"> <body class="antialiased">
+8
View File
@@ -8,16 +8,21 @@
<title>Batida vs PagerDuty vs Grafana OnCall — Comparação de Recursos</title> <title>Batida vs PagerDuty vs Grafana OnCall — Comparação de Recursos</title>
<meta name="description" content="Compare o Batida com PagerDuty e Grafana OnCall. Veja preços, recursos, conformidade LGPD e por que equipes brasileiras escolhem o Batida."> <meta name="description" content="Compare o Batida com PagerDuty e Grafana OnCall. Veja preços, recursos, conformidade LGPD e por que equipes brasileiras escolhem o Batida.">
<link rel="canonical" href="https://batida.io/vs/pt-br"> <link rel="canonical" href="https://batida.io/vs/pt-br">
<link rel="icon" type="image/png" href="/favicon.png">
<meta property="og:type" content="website"> <meta property="og:type" content="website">
<meta property="og:url" content="https://batida.io/vs/pt-br"> <meta property="og:url" content="https://batida.io/vs/pt-br">
<meta property="og:title" content="Batida vs PagerDuty vs Grafana OnCall — Comparação"> <meta property="og:title" content="Batida vs PagerDuty vs Grafana OnCall — Comparação">
<meta property="og:description" content="Compare plataformas de gerenciamento de incidentes. Veja por que o Batida é a melhor escolha para equipes DevOps brasileiras."> <meta property="og:description" content="Compare plataformas de gerenciamento de incidentes. Veja por que o Batida é a melhor escolha para equipes DevOps brasileiras.">
<meta property="og:site_name" content="Batida"> <meta property="og:site_name" content="Batida">
<meta property="og:image" content="https://batida.io/og-image.png">
<meta property="og:image:width" content="1200">
<meta property="og:image:height" content="630">
<meta name="twitter:card" content="summary_large_image"> <meta name="twitter:card" content="summary_large_image">
<meta name="twitter:title" content="Batida vs PagerDuty vs Grafana OnCall"> <meta name="twitter:title" content="Batida vs PagerDuty vs Grafana OnCall">
<meta name="twitter:description" content="Compare plataformas de gerenciamento de incidentes para equipes brasileiras."> <meta name="twitter:description" content="Compare plataformas de gerenciamento de incidentes para equipes brasileiras.">
<meta name="twitter:image" content="https://batida.io/og-image.png">
<link rel="preconnect" href="https://fonts.googleapis.com"> <link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
@@ -70,6 +75,9 @@
.compare-table .partial { color: #F59E0B; } .compare-table .partial { color: #F59E0B; }
.compare-table .batida-col { color: #F97316; font-weight: 600; } .compare-table .batida-col { color: #F97316; font-weight: 600; }
</style> </style>
<!-- Analytics: Plausible (privacy-friendly, GDPR compliant) -->
<script defer data-domain="batida.io" src="https://plausible.io/js/script.js"></script>
</head> </head>
<body class="antialiased"> <body class="antialiased">