Skip to main content

Environment Variables

All environment variables are loaded from .env file in development and from Vercel dashboard in production.
See .env.example:1-2 for the environment variable template.

GEMINI_API_KEY

GEMINI_API_KEY
string
required
Google Gemini API key for AI-powered tarot reading generation.Obtain from: Google AI StudioFormat: AIza prefix followed by 35 characters (total 39 chars)Example: AIzaSyC1234567890abcdefghijklmnopqrUsed in: src/actions/index.ts:37Security: Never exposed to client. Only accessible in server actions via import.meta.env.GEMINI_API_KEY

Setting the API Key

# Create .env file in project root
GEMINI_API_KEY=your_gemini_api_key_here
Missing GEMINI_API_KEY will cause server actions to throw: "GEMINI_API_KEY no configurada"

NODE_ENV

NODE_ENV
string
default:"production"
Node.js environment mode. Automatically set by Vercel.Possible values:
  • development - Local development server
  • production - Production deployment
  • test - Testing environment (if configured)
Set automatically by:
  • bun devdevelopment
  • vercel --prodproduction
Not required: This variable is automatically managed.

Astro Configuration

Configuration is defined in astro.config.mjs.
import { defineConfig } from 'astro/config';
import vercel from '@astrojs/vercel';

export default defineConfig({
  output: 'server',
  adapter: vercel(),
});

output

output
string
default:"server"
required
Rendering mode for Astro pages.Value: "server" (SSR - Server-Side Rendering)Effect: All routes are rendered on-demand per request, enabling:
  • Dynamic content generation
  • Server actions (API endpoints)
  • Environment variable access
  • Session/cookie handling
Alternative values (not used in this project):
  • "static" - Pre-render all pages at build time
  • "hybrid" - Mix of static and server-rendered pages
Location: astro.config.mjs:7
Changing output to "static" will break server actions. AI functionality requires SSR.

adapter

adapter
function
default:"vercel()"
required
Deployment adapter for SSR.Package: @astrojs/vercel (version ^9.0.4)Purpose: Transforms Astro SSR output into Vercel serverless functionsFeatures enabled:
  • Automatic serverless function creation
  • Edge runtime support (optional)
  • Environment variable injection
  • Request/response handling
Configuration options (all optional):
adapter: vercel({
  edgeMiddleware: false,    // Use Edge Runtime
  functionPerRoute: false,  // Separate function per route
  maxDuration: 10,          // Function timeout (seconds)
})
Location: astro.config.mjs:8
The default configuration (no options) is optimal for this project.

Package.json Scripts

{
  "scripts": {
    "dev": "astro dev",
    "build": "astro build",
    "preview": "astro preview",
    "astro": "astro"
  }
}

dev

npm run dev
script
Command: astro devPurpose: Start local development server with hot reloadServer: http://localhost:4321Features:
  • Auto-restart on code changes
  • Source maps for debugging
  • Fast HMR (Hot Module Replacement)
  • Environment variable loading from .env
Usage:
bun dev
# or
npm run dev
Port override:
bun dev -- --port 3000

build

npm run build
script
Command: astro buildPurpose: Create production-ready buildOutput directory: dist/Build steps:
  1. Compile TypeScript
  2. Bundle CSS and JavaScript
  3. Optimize images
  4. Generate serverless function handlers
  5. Create static asset manifest
Usage:
bun build
# or
npm run build
Vercel: This command runs automatically during deployment

preview

npm run preview
script
Command: astro previewPurpose: Preview production build locallyRequires: bun build must be run firstServer: http://localhost:4321Usage:
bun build
bun preview
Use case: Test production build before deploying

astro

npm run astro
script
Command: astroPurpose: Direct access to Astro CLIUsage:
bun astro --help
bun astro add tailwind
bun astro check

Dependencies

{
  "dependencies": {
    "@astrojs/vercel": "^9.0.4",
    "@google/genai": "^1.42.0",
    "astro": "^5.17.1"
  },
  "trustedDependencies": [
    "protobufjs"
  ]
}

@astrojs/vercel

@astrojs/vercel
package
default:"^9.0.4"
Purpose: Vercel deployment adapter for Astro SSRFeatures:
  • Serverless function generation
  • Edge runtime support
  • Image optimization
Documentation: Astro Vercel Adapter

@google/genai

@google/genai
package
default:"^1.42.0"
Purpose: Google Gemini API client for Node.jsUsed for: AI-powered tarot reading generationModels used:
  • gemini-2.5-flash
  • gemini-2.0-flash
  • gemini-2.0-flash-lite
Documentation: Google AI SDK

astro

astro
package
default:"^5.17.1"
Purpose: Core Astro frameworkFeatures used:
  • Server-Side Rendering (SSR)
  • Server Actions
  • TypeScript support
  • Zod schema validation
Documentation: Astro Docs

trustedDependencies

trustedDependencies
array
Purpose: Allow post-install scripts for specific packagesContains: ["protobufjs"]Reason: @google/genai depends on protobufjs, which requires post-install script to compile protocol buffersSecurity: Only listed packages can run post-install scripts
Do not add untrusted packages to trustedDependencies. Post-install scripts can execute arbitrary code.

Usage Limit Configuration

Usage limits are enforced client-side via localStorage.

Configuration Constants

const LIMIT = 5;
const WINDOW_MS = 24 * 60 * 60 * 1000; // 24 hours
const STORAGE_KEY = 'tarot_usage';

LIMIT

LIMIT
number
default:"5"
Purpose: Maximum consultations per user per dayDefault: 5Enforcement: Client-side (localStorage)Bypass: Users can clear localStorage to reset limitLocation: src/components/TarotForm.astro:177Modify:
const LIMIT = 10; // Allow 10 consultations per day

WINDOW_MS

WINDOW_MS
number
default:"86400000"
Purpose: Time window for usage limit (milliseconds)Default: 24 * 60 * 60 * 1000 (24 hours)Reset behavior: Counter resets 24 hours after first useLocation: src/components/TarotForm.astro:178Examples:
const WINDOW_MS = 12 * 60 * 60 * 1000; // 12 hours
const WINDOW_MS = 7 * 24 * 60 * 60 * 1000; // 7 days

STORAGE_KEY

STORAGE_KEY
string
default:"tarot_usage"
Purpose: localStorage key for usage trackingDefault: "tarot_usage"Data structure:
{
  "count": 3,
  "firstUse": 1709481600000
}
Location: src/components/TarotForm.astro:179
Usage limits are not server-enforced. They serve as a gentle UX boundary for a recreational app.

Usage Tracking Logic

function getUsage(): { count: number; firstUse: number } {
  try {
    const raw = localStorage.getItem(STORAGE_KEY);
    if (raw) return JSON.parse(raw);
  } catch {}
  return { count: 0, firstUse: Date.now() };
}

function incrementUsage(): void {
  const usage = getUsage();
  const now = Date.now();
  const reset = now - usage.firstUse >= WINDOW_MS;
  localStorage.setItem(STORAGE_KEY, JSON.stringify({
    count: reset ? 1 : usage.count + 1,
    firstUse: reset ? now : usage.firstUse,
  }));
}

function getRemainingReadings(): number {
  const usage = getUsage();
  if (Date.now() - usage.firstUse >= WINDOW_MS) return LIMIT;
  return Math.max(0, LIMIT - usage.count);
}
See src/components/TarotForm.astro:181-203 for the complete usage tracking implementation.

Advanced Configuration

Custom Vercel Configuration

Create vercel.json for advanced settings (optional):
{
  "buildCommand": "bun build",
  "devCommand": "bun dev",
  "installCommand": "bun install",
  "framework": "astro",
  "outputDirectory": "dist",
  "regions": ["iad1"],
  "functions": {
    "src/pages/**/*.astro": {
      "maxDuration": 10,
      "memory": 1024
    }
  },
  "headers": [
    {
      "source": "/cards/(.*)",
      "headers": [
        {
          "key": "Cache-Control",
          "value": "public, max-age=31536000, immutable"
        }
      ]
    }
  ]
}
vercel.json is optional. Vercel auto-detects Astro projects and applies optimal defaults.

TypeScript Configuration

Astro automatically generates tsconfig.json. No manual configuration needed.
{
  "extends": "astro/tsconfigs/strict"
}

Configuration Validation

Run these checks to ensure proper configuration:
# Check environment variables
echo $GEMINI_API_KEY

# Validate Astro config
bun astro check

# Test build
bun build

# Test server actions locally
bun dev
# Submit a test consultation
All configuration is validated at build time. Missing required values will fail the build.

Build docs developers (and LLMs) love