Skip to content

Commit 09dcabd

Browse files
committed
feat: ✨ include seo, ico, manifest and finish project
1 parent 9525cee commit 09dcabd

File tree

13 files changed

+179
-39
lines changed

13 files changed

+179
-39
lines changed

README.md

Lines changed: 105 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -3,60 +3,133 @@
33
![Capa](/src/assets/capa.jpeg)
44
</center>
55

6-
# 🚀 SaaS Template - Full Stack Boilerplate
7-
8-
Este projeto é um **template SaaS completo**, desenvolvido com foco em escalabilidade, modularidade e facilidade de personalização. Ele fornece uma estrutura robusta para aplicações SaaS que exigem autenticação, cobrança recorrente, entrega de produtos digitais e funcionalidades essenciais como rotas protegidas, WebHooks, APIs RESTful e muito mais.
9-
10-
---
6+
## 🧩 Template MicroSaaS
7+
Este projeto foi desenvolvido durante um minicurso da Rocketseat com o objetivo de me aprofundar no modelo de aplicações SaaS (Software as a Service). A proposta foi criar um template funcional com os principais recursos que caracterizam esse tipo de sistema — incluindo autenticação, integração com gateways de pagamento, tratamento de webhooks e armazenamento de dados.
118

129
<center>
1310

1411
![Gateway de pagamento Stripe](/src/assets/arch.jpeg)
12+
Diagrama de pagamento
1513
</center>
1614

17-
---
15+
### 🚀 Tecnologias Utilizadas
16+
* Next.js
17+
* TypeScript
18+
* Tailwind CSS
19+
* Auth.js (Google OAuth2)
20+
* Stripe & Mercado Pago
21+
* Firebase Firestore
22+
* Vercel (deploy)
23+
* Resend (e-mail)
24+
25+
### 🔧 Instalação e Execução
26+
Para rodar o projeto localmente, siga os passos abaixo:
27+
28+
1. Clone o repositório
29+
```
30+
git clone https://github.com/esbnet/template-saas.git
31+
```
1832

19-
## 🧱 Stack Tecnológica
33+
2. Instale as dependências
34+
```
35+
npm install
36+
# ou
37+
yarn install
38+
```
2039

21-
- **Next.js** (App Router) — SSR/SSG híbrido com excelente performance.
22-
- **TypeScript** — Tipagem estática para maior confiabilidade.
23-
- **Auth.js** — Autenticação segura e flexível (OAuth, credentials, etc).
24-
- **Stripe & Mercado Pago** — Integração completa com gateways de pagamento.
25-
- **Firebase - Cloud Firestore** — Armazenamento de dados em tempo real.
26-
- **Tailwind CSS + ShadCN/UI** — UI moderna, responsiva e baseada em componentes.
27-
- **Zod** — Validação de dados robusta e typesafe.
28-
- **React Query/TanStack Query** — Gerenciamento de cache e requisições assíncronas.
40+
3. Configure as variáveis de ambiente
41+
Para cada recurso, configure as variáveis de ambiente correspondentes no arquivo .env.local. Altamente recomendado a consulta [documentação oficial](https://nextjs.org/docs/basic-features/environment-variables#exposing-environment-variables-to-the-browser) do Next e dos demais frameworks e APIs.
42+
Crie um arquivo .env.local na raiz do projeto com as seguintes variáveis (exemplo):
43+
```
44+
# Auth.js
45+
AUTH_SECRET=
46+
47+
# Google
48+
AUTH_GOOGLE_ID=
49+
AUTH_GOOGLE_SECRET=
50+
51+
# Firebase
52+
FIREBASE_PROJECT_ID=
53+
FIREBASE_PRIVATE_KEY=
54+
FIREBASE_CLIENT_EMAIL=
55+
56+
# meio de pagamento - stripe
57+
STRIPE_SECRET_KEY=
58+
NEXT_PUBLIC_STRIPE_PUBLIC_KEY=
59+
STRIPE_PRODUCT_PRICE_ID=
60+
STRIPE_SUBSCRIPTION_PRICE_ID=
61+
STRIPE_WEBHOOK_SECRET=
62+
63+
# Mercado Pago
64+
MERCADO_PAGO_PUBLIC_KEY=
65+
MERCADO_PAGO_ACCESS_TOKEN=
66+
MERCADO_PAGO_WEBHOOK_SECRET=
67+
MERCADO_PAGO_WEB_HOOK_SECRET_PROD=
68+
69+
# Resend
70+
RESEND_API_KEY=
71+
```
72+
4. Execute o projeto em modo de desenvolvimento
73+
```
74+
npm run dev
75+
# ou
76+
yarn dev
77+
```
78+
A aplicação estará disponível em: http://localhost:3000
2979

30-
---
80+
### 🔐 Autenticação
81+
A autenticação foi implementada com Auth.js, utilizando login via Google (OAuth2). As credenciais são armazenadas com segurança e utilizadas para proteger rotas específicas da aplicação.
3182

32-
## 🔐 Autenticação com Auth.js
83+
### 💳 Integração com Gateways de Pagamento
84+
#### Stripe
85+
A integração com o Stripe foi realizada da seguinte forma:
3386

34-
Implementação com suporte a:
87+
* Instalação da biblioteca oficial do Stripe;
88+
* Configuração de produtos e preços na plataforma;
89+
* Ajuste de variáveis no .env.local;
90+
* Criação de um hook para facilitar chamadas de funções do Stripe;
91+
* Desenvolvimento de uma API para execução das ações e disparo de eventos;
92+
* Implementação dos webhooks, que tratam respostas do Stripe e atualizam o Firestore com informações como confirmação ou cancelamento de assinaturas.
3593

36-
- **OAuth (Google, GitHub, etc)**
37-
- **JWT** ou **session-based auth**
38-
- **Proteção de rotas** no client e server (middleware `auth()` no server side e `useSession()` no client side)
39-
- **Roles e permissions** (admin, user, etc)
94+
#### Mercado Pago
95+
Além do Stripe, foi integrada também a solução do Mercado Pago, incluindo:
96+
* Criação de contas e configuração inicial;
97+
Implementação dos webhooks;
98+
* Criação de hook e rotas internas para comunicação com a API;
99+
* Testes de pagamento para validar a operação completa.
40100

41-
```ts
42-
// Exemplo de proteção SSR
43-
export const getServerSideProps = withAuth(async (ctx) => {
44-
const session = await getSession(ctx);
45-
if (!session) return { redirect: { destination: '/login', permanent: false } };
46-
return { props: { user: session.user } };
47-
});
48-
```
49-
##
101+
## ☁️ Deploy e Recursos Adicionais
102+
Para a finalização do projeto, foram adicionados os seguintes recursos:
103+
104+
* Deploy na Vercel
105+
* Favicon e imagem OpenGraph (1200x630)
106+
* Arquivo de manifesto (PWA-ready)
107+
* Envio automático de e-mail de boas-vindas com Resend
108+
* Melhoria de SEO com meta tags otimizadas
109+
110+
## 📦 Estrutura Pronta para Evoluir
111+
Com tudo isso implementado, o template está pronto para servir como base sólida no desenvolvimento de produtos SaaS. Ele já conta com autenticação, integrações com meios de pagamento, deploy otimizado e estrutura escalável — perfeito para acelerar o início de novos projetos.
112+
113+
---
114+
115+
<center>
50116

51117
## 📨 Contato
52118
📫 Email: (mailto:[email protected])
53119
🌐 Site [Edmilson Soares](https://esbnet-port.vercel.app/)
54120

55121

56122

57-
<center>
58123

59124
## 🙏 Agradecimentos
125+
126+
André Elias - https://www.linkedin.com/in/andr%C3%A9-elias/
127+
Rocketseat - https://rocketseat.com.br 🚀
128+
129+
130+
</br >
131+
</br >
132+
60133
Sinte-se a vontade para fazer uma doação via [BuyMeACoffee](https://www.buymeacoffee.com/esbdev)
61134
![Capa](/src/assets/bmc_qr.png)
62135

env.example

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
# Auth.js
2+
AUTH_SECRET=
3+
4+
# Google
5+
AUTH_GOOGLE_ID=
6+
AUTH_GOOGLE_SECRET=
7+
8+
# Firebase
9+
FIREBASE_PROJECT_ID=
10+
FIREBASE_PRIVATE_KEY=
11+
FIREBASE_CLIENT_EMAIL=
12+
13+
# meio de pagamento - stripe
14+
STRIPE_SECRET_KEY=
15+
NEXT_PUBLIC_STRIPE_PUBLIC_KEY=
16+
STRIPE_PRODUCT_PRICE_ID=
17+
STRIPE_SUBSCRIPTION_PRICE_ID=
18+
STRIPE_WEBHOOK_SECRET=
19+
20+
# Mercado Pago
21+
MERCADO_PAGO_PUBLIC_KEY=
22+
MERCADO_PAGO_ACCESS_TOKEN=
23+
MERCADO_PAGO_WEBHOOK_SECRET=
24+
MERCADO_PAGO_WEB_HOOK_SECRET_PROD=

public/images/homescreen48.jpeg

133 KB
Loading

src/app/(project)/dashboard/page.tsx

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,13 @@
11
import { handleAuth } from '@/app/actions/handle-auth';
22
import { auth } from '@/app/lib/auth';
3+
import type { Metadata } from 'next';
34
import Link from 'next/link';
45
import { redirect } from 'next/navigation';
56

7+
export const metadata: Metadata = {
8+
title: 'Dashboard',
9+
};
10+
611
export default async function Dashboard() {
712
const session = await auth();
813

@@ -28,8 +33,7 @@ export default async function Dashboard() {
2833
href="/payment"
2934
className="bg-yellow-400 hover:bg-yellow-500 shadow-md px-6 py-3 rounded-lg font-semibold text-gray-900 transition duration-300 ease-in-out"
3035
>
31-
{' '}
32-
Pagamentos
36+
Assinar Serviço
3337
</Link>
3438
</div>
3539

src/app/(project)/layout.tsx

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,9 @@
11
import Header from '@/app/components/header';
2+
import type { Metadata } from 'next';
3+
4+
export const metadata: Metadata = {
5+
title: 'Pagamentos',
6+
};
27

38
export default function DashboardLayout({
49
children,

src/app/(project)/login/page.tsx

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,15 @@
1-
'use client';
2-
31
import { handleAuth } from '@/app/actions/handle-auth';
2+
import { auth } from '@/app/lib/auth';
3+
import { redirect } from 'next/navigation';
44
import { FcGoogle } from 'react-icons/fc';
55

6-
export default function Login() {
6+
export default async function Login() {
7+
const session = await auth();
8+
9+
if (session) {
10+
return redirect('/dashboard');
11+
}
12+
713
return (
814
<div className="flex flex-col justify-center items-center gap-6 p-4 h-full">
915
<h1 className="font-[font-family:var(--font-geist-sans)] text-3xl">

src/app/_favicon.ico

25.3 KB
Binary file not shown.

src/app/api/mercado-pago/create-checkout/route.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ export async function POST(req: NextRequest) {
1414
external_reference: testId,
1515
metadata: {
1616
testId, // convertida para snake_case
17+
userEmail,
1718
},
1819
...(userEmail && { payer: { email: userEmail } }), // importante para pontuação mp
1920
items: [

src/app/favicon.ico

108 KB
Binary file not shown.

src/app/layout.tsx

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,11 @@ const geistMono = Geist_Mono({
1616
});
1717

1818
export const metadata: Metadata = {
19-
title: 'Make Money',
20-
description: 'Compartilhe sua vida com quem você ama',
19+
title: {
20+
default: 'Make Money',
21+
template: '%s | MM',
22+
},
23+
description: 'A simply saas template.',
2124
};
2225

2326
export default function RootLayout({

0 commit comments

Comments
 (0)