> ## Documentation Index
> Fetch the complete documentation index at: https://devperez08-platform-list-anime-54.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Configuration

> Complete guide to configuring your EpiNeko instance

## Environment Variables

EpiNeko requires specific environment variables to function properly. All configuration is stored in `.env.local` at the root of your project.

<Warning>
  Never commit your `.env.local` file to version control. It should already be included in `.gitignore`.
</Warning>

### Required Variables

<CodeGroup>
  ```bash .env.local theme={null}
  # Supabase Configuration
  NEXT_PUBLIC_SUPABASE_URL=your_supabase_project_url
  NEXT_PUBLIC_SUPABASE_ANON_KEY=your_supabase_anon_key
  ```

  ```bash Example Values theme={null}
  # Supabase Configuration
  NEXT_PUBLIC_SUPABASE_URL=https://xyzcompany.supabase.co
  NEXT_PUBLIC_SUPABASE_ANON_KEY=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
  ```
</CodeGroup>

<Steps>
  <Step title="Get Supabase URL">
    1. Go to [app.supabase.com](https://app.supabase.com)
    2. Select your project
    3. Navigate to Settings > API
    4. Copy the "Project URL"
  </Step>

  <Step title="Get Anon Key">
    1. In the same API settings page
    2. Copy the "anon public" key
    3. This key is safe to use in the browser
  </Step>

  <Step title="Create .env.local">
    Create the file in your project root and paste both values
  </Step>

  <Step title="Restart Development Server">
    Changes to environment variables require a server restart
  </Step>
</Steps>

<Note>
  The `NEXT_PUBLIC_` prefix makes these variables available to the browser. This is required for client-side Supabase operations.
</Note>

### Optional Variables

Add these for enhanced functionality:

```bash .env.local theme={null}
# Analytics (optional)
NEXT_PUBLIC_GA_MEASUREMENT_ID=G-XXXXXXXXXX

# Jikan API Configuration (optional - uses defaults)
NEXT_PUBLIC_JIKAN_API_URL=https://api.jikan.moe/v4

# Development
NODE_ENV=development
```

## Next.js Configuration

The `next.config.ts` file controls Next.js behavior and optimization settings.

### Current Configuration

<CodeGroup>
  ```typescript next.config.ts theme={null}
  import type { NextConfig } from "next";

  const nextConfig: NextConfig = {
    images: {
      remotePatterns: [
        {
          protocol: 'https',
          hostname: 'cdn.myanimelist.net',
          port: '',
          pathname: '/**',
        },
      ],
    },
  };

  export default nextConfig;
  ```
</CodeGroup>

### Image Optimization

EpiNeko loads anime images from MyAnimeList CDN. The configuration allows Next.js Image component to optimize these external images:

<Accordion title="Why configure remote patterns?">
  Next.js requires explicit configuration for external image domains to prevent abuse and ensure security. Without this configuration, images from MyAnimeList won't load.
</Accordion>

### Adding Additional Image Sources

If you want to allow images from other sources:

```typescript next.config.ts theme={null}
const nextConfig: NextConfig = {
  images: {
    remotePatterns: [
      {
        protocol: 'https',
        hostname: 'cdn.myanimelist.net',
        port: '',
        pathname: '/**',
      },
      {
        protocol: 'https',
        hostname: 'your-custom-cdn.com',
        port: '',
        pathname: '/images/**',
      },
    ],
  },
};
```

### Other Useful Next.js Options

<AccordionGroup>
  <Accordion title="TypeScript Strict Mode" icon="code">
    Enable strict TypeScript checking:

    ```typescript theme={null}
    const nextConfig: NextConfig = {
      typescript: {
        ignoreBuildErrors: false, // Fail build on TS errors
      },
    }
    ```
  </Accordion>

  <Accordion title="React Strict Mode" icon="react">
    Enable React strict mode for development:

    ```typescript theme={null}
    const nextConfig: NextConfig = {
      reactStrictMode: true,
    }
    ```
  </Accordion>

  <Accordion title="Redirects & Rewrites" icon="arrow-right">
    Configure URL redirects:

    ```typescript theme={null}
    const nextConfig: NextConfig = {
      async redirects() {
        return [
          {
            source: '/home',
            destination: '/',
            permanent: true,
          },
        ]
      },
    }
    ```
  </Accordion>

  <Accordion title="Environment Variables" icon="key">
    Make server-side env vars available:

    ```typescript theme={null}
    const nextConfig: NextConfig = {
      env: {
        CUSTOM_KEY: process.env.CUSTOM_KEY,
      },
    }
    ```
  </Accordion>
</AccordionGroup>

## Supabase Configuration

### Client Configuration

The Supabase clients are configured in the utility files with error handling:

<CodeGroup>
  ```typescript src/utils/supabase/client.ts theme={null}
  import { createBrowserClient } from '@supabase/ssr'

  export function createClient() {
    const supabaseUrl = process.env.NEXT_PUBLIC_SUPABASE_URL;
    const supabaseKey = process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY;

    if (!supabaseUrl || !supabaseKey) {
      throw new Error('Missing Supabase environment variables: NEXT_PUBLIC_SUPABASE_URL or NEXT_PUBLIC_SUPABASE_ANON_KEY');
    }

    return createBrowserClient(
      supabaseUrl,
      supabaseKey
    )
  }
  ```

  ```typescript src/utils/supabase/server.ts theme={null}
  import { createServerClient } from '@supabase/ssr'
  import { cookies } from 'next/headers'

  export async function createClient() {
    const cookieStore = await cookies()

    const supabaseUrl = process.env.NEXT_PUBLIC_SUPABASE_URL;
    const supabaseKey = process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY;

    if (!supabaseUrl || !supabaseKey) {
      throw new Error('Missing Supabase environment variables');
    }

    return createServerClient(
      supabaseUrl,
      supabaseKey,
      {
        cookies: {
          getAll() {
            return cookieStore.getAll()
          },
          setAll(cookiesToSet) {
            try {
              cookiesToSet.forEach(({ name, value, options }) =>
                cookieStore.set(name, value, options)
              )
            } catch {
              // Server Component limitation - handled by middleware
            }
          },
        },
      }
    )
  }
  ```
</CodeGroup>

### Advanced Supabase Options

Customize the Supabase client with additional options:

```typescript theme={null}
return createBrowserClient(
  supabaseUrl,
  supabaseKey,
  {
    auth: {
      persistSession: true,
      autoRefreshToken: true,
      detectSessionInUrl: true,
    },
    db: {
      schema: 'public',
    },
    global: {
      headers: {
        'X-Custom-Header': 'value',
      },
    },
  }
)
```

## Database Configuration

### Row Level Security (RLS)

EpiNeko uses RLS to protect user data. The policies are configured in the migration file:

<CodeGroup>
  ```sql Profiles RLS theme={null}
  -- Enable RLS
  alter table public.profiles enable row level security;

  -- Anyone can view profiles
  create policy "Public profiles are viewable by everyone." 
    on public.profiles
    for select 
    using (true);

  -- Users can only insert their own profile
  create policy "Users can insert their own profile." 
    on public.profiles
    for insert 
    with check (auth.uid() = id);

  -- Users can only update their own profile
  create policy "Users can update own profile." 
    on public.profiles
    for update 
    using (auth.uid() = id);
  ```

  ```sql User Library RLS theme={null}
  -- Enable RLS
  alter table public.user_library enable row level security;

  -- Users can only view their own library
  create policy "Users can view their own library items." 
    on public.user_library
    for select 
    using (auth.uid() = user_id);

  -- Users can only insert to their own library
  create policy "Users can insert their own library items." 
    on public.user_library
    for insert 
    with check (auth.uid() = user_id);

  -- Users can only update their own library
  create policy "Users can update their own library items." 
    on public.user_library
    for update 
    using (auth.uid() = user_id);

  -- Users can only delete from their own library
  create policy "Users can delete their own library items." 
    on public.user_library
    for delete 
    using (auth.uid() = user_id);
  ```
</CodeGroup>

<Tip>
  RLS policies are enforced at the database level, providing an additional security layer beyond application logic.
</Tip>

### Database Indexes

For better performance, consider adding indexes:

```sql theme={null}
-- Index on username for faster lookups
create index profiles_username_idx on public.profiles(username);

-- Index on user_id for library queries
create index user_library_user_id_idx on public.user_library(user_id);

-- Index on anime_id for duplicate checks
create index user_library_anime_id_idx on public.user_library(anime_id_jikan);

-- Composite index for status filtering
create index user_library_user_status_idx on public.user_library(user_id, status);
```

## Styling Configuration

### Tailwind CSS

EpiNeko uses Tailwind CSS v4 with custom configuration. The configuration is minimal by design:

```typescript tailwind.config.ts theme={null}
import type { Config } from 'tailwindcss'

const config: Config = {
  content: [
    './src/pages/**/*.{js,ts,jsx,tsx,mdx}',
    './src/components/**/*.{js,ts,jsx,tsx,mdx}',
    './src/app/**/*.{js,ts,jsx,tsx,mdx}',
  ],
  theme: {
    extend: {},
  },
  plugins: [],
}

export default config
```

### DaisyUI Configuration

DaisyUI provides pre-built components. Configure themes in `tailwind.config.ts`:

```typescript theme={null}
import daisyui from 'daisyui'

const config: Config = {
  // ... other config
  plugins: [daisyui],
  daisyui: {
    themes: [
      'light',
      'dark',
      'cupcake',
      {
        epineko: {
          'primary': '#570df8',
          'secondary': '#f000b8',
          'accent': '#37cdbe',
          'neutral': '#3d4451',
          'base-100': '#ffffff',
        },
      },
    ],
    darkTheme: 'dark',
    base: true,
    styled: true,
    utils: true,
  },
}
```

## TypeScript Configuration

EpiNeko uses TypeScript with strict mode enabled:

```json tsconfig.json theme={null}
{
  "compilerOptions": {
    "target": "ES2017",
    "lib": ["dom", "dom.iterable", "esnext"],
    "allowJs": true,
    "skipLibCheck": true,
    "strict": true,
    "noEmit": true,
    "esModuleInterop": true,
    "module": "esnext",
    "moduleResolution": "bundler",
    "resolveJsonModule": true,
    "isolatedModules": true,
    "jsx": "preserve",
    "incremental": true,
    "plugins": [
      {
        "name": "next"
      }
    ],
    "paths": {
      "@/*": ["./src/*"]
    }
  },
  "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
  "exclude": ["node_modules"]
}
```

<Note>
  The `@/*` path alias allows you to import from `src/` using `@/` instead of relative paths.
</Note>

## Middleware Configuration

The middleware configuration controls which routes are protected:

```typescript src/middleware.ts theme={null}
export const config = {
  matcher: [
    /*
     * Match all request paths except:
     * - _next/static (static files)
     * - _next/image (image optimization)
     * - favicon.ico
     * - image files (svg, png, jpg, etc.)
     */
    '/((?!_next/static|_next/image|favicon.ico|.*\\.(?:svg|png|jpg|jpeg|gif|webp)$).*)',
  ],
}
```

### Customizing Protected Routes

To add route-specific logic:

```typescript src/middleware.ts theme={null}
import { type NextRequest } from 'next/server'
import { updateSession } from '@/utils/supabase/middleware'

export async function middleware(request: NextRequest) {
  const response = await updateSession(request)
  
  // Add custom logic for specific routes
  if (request.nextUrl.pathname.startsWith('/admin')) {
    const supabase = createServerClient(/* ... */)
    const { data: { user } } = await supabase.auth.getUser()
    
    if (!user?.user_metadata?.is_admin) {
      return NextResponse.redirect(new URL('/', request.url))
    }
  }
  
  return response
}
```

## Production Configuration

### Environment Variables for Production

When deploying, ensure these variables are set:

```bash Production .env theme={null}
NEXT_PUBLIC_SUPABASE_URL=your_production_url
NEXT_PUBLIC_SUPABASE_ANON_KEY=your_production_key
NODE_ENV=production
```

### Build Optimization

Optimize your production build:

```typescript next.config.ts theme={null}
const nextConfig: NextConfig = {
  // Minify output
  swcMinify: true,
  
  // Enable compression
  compress: true,
  
  // Optimize images
  images: {
    formats: ['image/avif', 'image/webp'],
    minimumCacheTTL: 60,
  },
  
  // Configure headers
  async headers() {
    return [
      {
        source: '/:path*',
        headers: [
          {
            key: 'X-DNS-Prefetch-Control',
            value: 'on'
          },
          {
            key: 'Strict-Transport-Security',
            value: 'max-age=63072000; includeSubDomains'
          },
        ],
      },
    ]
  },
}
```

### Vercel Deployment

EpiNeko is optimized for Vercel deployment:

<Steps>
  <Step title="Connect Repository">
    Import your Git repository in Vercel dashboard
  </Step>

  <Step title="Configure Environment Variables">
    Add your Supabase credentials in the Vercel project settings
  </Step>

  <Step title="Deploy">
    Vercel automatically detects Next.js and deploys
  </Step>
</Steps>

<Tip>
  Vercel automatically sets `NODE_ENV=production` and enables optimizations.
</Tip>

## Troubleshooting

<AccordionGroup>
  <Accordion title="Environment variables not loading" icon="exclamation-triangle">
    **Solution:**

    1. Ensure `.env.local` is in the project root
    2. Restart the development server
    3. Check for typos in variable names
    4. Verify the `NEXT_PUBLIC_` prefix for client-side variables
  </Accordion>

  <Accordion title="Images not loading" icon="image">
    **Solution:**

    1. Verify `next.config.ts` includes the CDN hostname
    2. Check that the hostname matches exactly (no trailing slash)
    3. Restart the dev server after config changes
  </Accordion>

  <Accordion title="Database connection issues" icon="database">
    **Solution:**

    1. Verify Supabase project is active
    2. Check API keys are correct
    3. Ensure RLS policies are properly configured
    4. Check Supabase service status
  </Accordion>

  <Accordion title="TypeScript errors" icon="code">
    **Solution:**

    1. Run `npm install` to ensure all types are installed
    2. Delete `.next` folder and rebuild
    3. Check `tsconfig.json` paths configuration
  </Accordion>
</AccordionGroup>
