RestartCrew

AI Engineering Guidelines

This repository is developed collaboratively by humans and AI coding agents.

These guidelines ensure:


1. AI Role and Responsibilities

You are acting as a senior software engineer.

Your responsibilities:

Before implementing anything:

  1. Understand — read existing code and architecture
  2. Identify — list all files that will be affected
  3. Propose — outline your approach before writing code
  4. Implement — write clean, tested code
  5. Verify — run through the self-review checklist (Section 21)

2. Proactive Agent Behavior

This project is developed by vibecoders — developers who focus on product vision and user experience, but may not always specify every technical detail. The AI agent must compensate by being proactively professional.

When instructions are incomplete

The agent must independently apply best practices, even when not explicitly asked:

When instructions are ambiguous

  1. Make reasonable assumptions based on existing patterns in the codebase.
  2. Document assumptions — add a brief comment in the PR or code explaining what was assumed.
  3. Choose the more secure option — when in doubt, be more restrictive rather than permissive.
  4. Follow established patterns — look at how similar features are implemented in the codebase and mirror that approach.

What the agent should always do (without being asked)

Area Default behavior
Security Add auth checks, RLS policies, input validation
Error handling Wrap async operations, show user-friendly messages, log details
Types Create TypeScript interfaces for all data structures
Testing Add tests for new service functions and utilities
Documentation Update docs when adding features or changing architecture
Performance Use pagination, selective queries, proper indexes
Accessibility Use semantic HTML, add aria labels, ensure keyboard navigation

When to ask for clarification

Only ask when:

Do NOT ask when:


3. System Architecture Overview

User → Frontend (Next.js App Router) → Supabase Client → PostgreSQL Database
                                     → Supabase Edge Functions (business logic)
                                     → Supabase Auth (authentication)
                                     → Supabase Storage (file uploads)

Core components

Layer Technology Responsibility
Frontend Next.js (App Router) + TypeScript + Tailwind CSS UI rendering, SSR/SSG, user interaction, API calls
Auth Supabase Auth User sessions, JWT tokens, OAuth providers
API Supabase Client + Edge Functions Data access, business logic, secure operations
Database PostgreSQL via Supabase Schema, RLS policies, migrations
Hosting GitHub Pages (static export) Static site deployment via GitHub Actions, automatic HTTPS

4. Architecture Principles

Separation of concerns

Layer Does Does NOT
Frontend Renders UI, handles interaction, calls APIs Contain business logic, validate data authoritatively, access DB directly
Edge Functions Business logic, secret handling, complex queries Render UI, manage state
Database Schema integrity, RLS enforcement, data validation Contain application logic in stored procedures (unless justified)

Critical rules


5. Repository Structure

repo/
├── AGENTS.md                    # This file — AI agent guidelines
├── README.md                    # Project overview and setup
├── ARCHITECTURE.md              # Detailed architecture docs
│
├── src/
│   ├── components/              # Reusable UI components
│   ├── pages/                   # Page-level components / routes
│   ├── services/                # API service layer (Supabase calls)
│   ├── lib/                     # Shared utilities, Supabase client init
│   ├── types/                   # TypeScript type definitions
│   └── utils/                   # Pure helper functions
│
├── public/                      # Static assets (served to users)
│
├── supabase/
│   ├── migrations/              # Numbered SQL migration files
│   ├── functions/               # Edge Functions
│   └── seed/                    # Seed data for development
│
├── tests/                       # All test files
│   ├── services/                # Service layer tests
│   ├── functions/               # Edge Function tests
│   └── utils/                   # Utility function tests
│
├── docs/                        # Feature documentation
│
├── dev/                         # Internal developer notes (NOT served to frontend)
│   ├── strategy/                # Product strategy, roadmap, priorities
│   └── notes/                   # Technical research, architecture decisions
│
├── .env.example                 # Template for environment variables
└── .github/
    └── workflows/               # CI/CD pipeline definitions

Rules


6. Supabase Client Usage

Client initialization

Create one Supabase client instance in src/lib/supabase.ts:

import { createClient } from '@supabase/supabase-js'
import type { Database } from '../types/database.types'

export const supabase = createClient<Database>(
  process.env.NEXT_PUBLIC_SUPABASE_URL!,
  process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!
)

Key rules

Calling patterns

// ✅ Frontend: uses anon key + user JWT (via RLS)
const { data, error } = await supabase
  .from('todos')
  .select('*')
  .eq('user_id', user.id)

// ✅ Edge Function: uses service_role for admin operations
const supabaseAdmin = createClient(
  Deno.env.get('SUPABASE_URL')!,
  Deno.env.get('SUPABASE_SERVICE_ROLE_KEY')!
)

7. Database Guidelines

Schema rules

id          UUID PRIMARY KEY DEFAULT gen_random_uuid(),
created_at  TIMESTAMPTZ NOT NULL DEFAULT now(),
updated_at  TIMESTAMPTZ NOT NULL DEFAULT now()

Migration rules

Naming conventions

Element Convention Example
Tables snake_case, plural user_profiles
Columns snake_case first_name
Indexes idx_{table}_{column} idx_todos_user_id
Constraints {table}_{type}_{column} todos_fk_user_id
Migrations NNN_description.sql 003_add_user_roles.sql

8. Row Level Security (RLS)

All tables must have RLS enabled. No exceptions.

Rules

Standard policy patterns

-- Enable RLS
ALTER TABLE todos ENABLE ROW LEVEL SECURITY;

-- Users can only see their own data
CREATE POLICY "Users can view own todos"
  ON todos FOR SELECT
  USING (user_id = auth.uid());

-- Users can only insert their own data
CREATE POLICY "Users can create own todos"
  ON todos FOR INSERT
  WITH CHECK (user_id = auth.uid());

-- Users can only update their own data
CREATE POLICY "Users can update own todos"
  ON todos FOR UPDATE
  USING (user_id = auth.uid())
  WITH CHECK (user_id = auth.uid());

-- Users can only delete their own data
CREATE POLICY "Users can delete own todos"
  ON todos FOR DELETE
  USING (user_id = auth.uid());

Common mistakes to avoid


9. Edge Functions

When to use

Structure

supabase/functions/
├── my-function/
│   └── index.ts         # Entry point
├── shared/              # Shared utilities across functions
│   └── cors.ts

Standard patterns

import { serve } from 'https://deno.land/std@0.168.0/http/server.ts'
import { createClient } from 'https://esm.sh/@supabase/supabase-js@2'

serve(async (req) => {
  // CORS handling
  if (req.method === 'OPTIONS') {
    return new Response('ok', { headers: corsHeaders })
  }

  try {
    // Auth verification
    const authHeader = req.headers.get('Authorization')
    if (!authHeader) throw new Error('Missing authorization')

    // Create authenticated client
    const supabase = createClient(
      Deno.env.get('SUPABASE_URL')!,
      Deno.env.get('SUPABASE_ANON_KEY')!,
      { global: { headers: { Authorization: authHeader } } }
    )

    // Business logic here
    const { data, error } = await supabase.from('table').select('*')
    if (error) throw error

    return new Response(JSON.stringify(data), {
      headers: { ...corsHeaders, 'Content-Type': 'application/json' }
    })
  } catch (err) {
    return new Response(JSON.stringify({ error: err.message }), {
      status: 400,
      headers: { ...corsHeaders, 'Content-Type': 'application/json' }
    })
  }
})

10. Frontend Development Rules

Responsibilities

Rules


11. Error Handling and Logging

Frontend

// ✅ Always handle Supabase errors explicitly
const { data, error } = await supabase.from('todos').select('*')
if (error) {
  console.error('Failed to fetch todos:', error.message)
  // Show user-friendly message — never expose raw error details
  showToast('Could not load your todos. Please try again.')
  return
}

Edge Functions

// ✅ Structured error handling with appropriate status codes
try {
  // ... logic
} catch (err) {
  console.error('Edge function error:', {
    function: 'process-payment',
    error: err.message,
    timestamp: new Date().toISOString()
  })

  return new Response(
    JSON.stringify({ error: 'An unexpected error occurred' }),
    { status: 500 }
  )
}

Rules


12. Code Style and Standards

Language

Naming conventions

Element Convention Example
Variables, functions camelCase getUserProfile
Components PascalCase TodoListItem
Files kebab-case todo-list-item.tsx
Types/Interfaces PascalCase UserProfile
Constants SCREAMING_SNAKE MAX_RETRY_COUNT
Database columns snake_case created_at

Function design

// ✅ Early return pattern
async function getUser(id: string): Promise<User | null> {
  if (!id) return null

  const { data, error } = await supabase
    .from('users')
    .select('*')
    .eq('id', id)
    .single()

  if (error) {
    console.error('getUser failed:', error.message)
    return null
  }

  return data
}

13. Dependency Policy

Before adding any dependency:

  1. Check — does the functionality already exist in the codebase?
  2. Prefer built-in — use native APIs, Supabase features, or Deno std lib first.
  3. Evaluate — is the package well-maintained? Small bundle size? Few dependencies?
  4. Document — add a comment explaining why the dependency was added.

Avoid


14. Security Rules

Secrets management

Authentication

Input validation


15. Environment Variables

Required variables

# .env.example — commit this file (without values)
NEXT_PUBLIC_SUPABASE_URL=             # Supabase project URL
NEXT_PUBLIC_SUPABASE_ANON_KEY=        # Supabase anon/public key (safe for frontend)

# Edge Functions only (never in frontend)
SUPABASE_SERVICE_ROLE_KEY=            # Admin key — server-side only
SUPABASE_DB_URL=                      # Direct DB connection (if needed)

Rules


16. Performance Guidelines

Frontend

Database

// ✅ Efficient: single query with join
const { data } = await supabase
  .from('todos')
  .select('*, category:categories(name)')
  .eq('user_id', user.id)
  .range(0, 19)  // Paginate: first 20 items

// ❌ Inefficient: N+1 queries
const { data: todos } = await supabase.from('todos').select('*')
for (const todo of todos) {
  const { data: category } = await supabase
    .from('categories')
    .select('name')
    .eq('id', todo.category_id)  // One query per todo!
}

17. Git Workflow

Branch strategy

Branch Purpose Rules
main Production Never push directly. Deploy via merge only.
dev Development integration PRs from feature branches.
feature/* Individual features Branch from dev, PR back to dev.
fix/* Bug fixes Branch from dev or main (hotfix).

Commit messages

Use conventional commits:

feat: add user profile page
fix: correct RLS policy for shared todos
chore: update Supabase client to v2.39
docs: add Edge Function deployment guide

Pull request rules


18. Testing Requirements

What to test

Structure

tests/
├── services/          # Service layer tests
├── functions/         # Edge Function tests
├── utils/             # Utility function tests
└── setup.ts           # Test configuration and helpers

Rules


19. Documentation

Required documentation

Rules


20. AI Agent Development Workflow

When implementing a feature, follow this sequence:

Step 1 — Understand

Step 2 — Plan

Step 3 — Implement

Step 4 — Verify


21. Self-Review Checklist

Before committing code, verify every item:

Architecture

Security

Code quality

Database

Testing

Documentation


22. Long-Term Maintainability

This repository should remain:

Prefer clarity over cleverness. If a junior developer can’t understand it, simplify it.