This guide explains how to configure and populate the projects integration with Supabase (Postgres + Auth + Storage).
src/app/types/project.tsProject interfaceProjectInput type for create/updatesrc/app/server/projects/get-all-projects.ts: Busca todos os projetos com filtrossrc/app/server/projects/get-project-by-slug.ts: Busca projeto por slugsrc/app/actions/projects/create-project.ts: Criar projetosrc/app/actions/projects/update-project.ts: Atualizar projetosrc/app/actions/projects/delete-project.ts: Deletar projeto (soft/hard delete)src/app/actions/projects/toggle-project-active.ts: Alternar status ativosrc/app/components/projects/projects-grid.tsx:
src/app/[locale]/(pages)/projetos/page.tsx:
Added translation keys in EN, PT, and ES:
Projects.stackFilter.title: “Filtrar por tecnologia”Projects.stackFilter.clear: “Limpar filtro”Projects.emptyState: “Nenhum projeto encontrado com os filtros selecionados”npm run db:seed to populate local data (optional)Create indexes that match your filter/sort queries (e.g., slug, created_at).
You can define indexes directly in the Supabase SQL migrations.
Open the Supabase Dashboard and create the necessary indexes: https://app.supabase.com
Recommended indexes for the projects table:
Run the seed to populate sample projects (optional):
npm run db:seedThe seed should:
src/app/data/projects.tsprojects tablestack array for filtersprojects record structure (Supabase){
"slug": "luminall-ai",
"title": "luminall-ai",
"description": "luminall-ai",
"badge": "luminall-ai",
"category": "ai",
"tech": ["Next.js", "OpenAI GPT-4", "TypeScript", "Supabase", "Tailwind"],
"link": "https://www.luminall.me",
"image": "/assets/images/projects/front-end/luminall-demo.png",
"imagePath": "/assets/images/projects/front-end/luminall-demo.png",
"stack": ["Next.js", "OpenAI GPT-4", "TypeScript", "Supabase", "Tailwind"],
"isActive": true,
"isFeatured": false,
"order": 0,
"createdAt": "2025-01-XX...",
"updatedAt": "2025-01-XX..."
}Note: The title, description, and badge fields are translation IDs. The component looks them up in messages/[locale].json using Projects.items.{slug}.{field}.
ProjectsGrid extracts the unique technologies from every project’s stack arraystack arraycreateProject:import { createProject } from "@/app/actions/projects/create-project";
const result = await createProject({
slug: "meu-novo-projeto",
title: "meu-novo-projeto", // Translation ID
description: "meu-novo-projeto", // Translation ID
badge: "meu-novo-projeto", // Translation ID
category: "front-end",
tech: ["React", "Next.js", "TypeScript"],
link: "https://exemplo.com",
stack: ["React", "Next.js", "TypeScript"],
isActive: true,
isFeatured: false,
order: 10,
});src/i18n/messages/[locale].json:{
"Projects": {
"items": {
"meu-novo-projeto": {
"title": "My New Project",
"description": "Project description...",
"badge": "Project badge"
}
}
}
}Projects are ordered by the order field (ascending). To reorder:
import { updateProject } from "@/app/actions/projects/update-project";
await updateProject(firestoreId, { order: 5 });stack field is populated correctly