chore: remove devcontainer configuration and related scripts

This commit is contained in:
Peter Wood
2025-05-23 07:27:39 -04:00
parent d0486671cb
commit 802650510c
10 changed files with 52 additions and 595 deletions

View File

@@ -1,15 +0,0 @@
# GitHub Finance Devcontainer Configuration
# Generate a Personal Access Token here https://github.com/settings/tokens
# requires 'repo', 'read:org', 'admin:public_key'
GITHUB_PERSONAL_ACCESS_TOKEN=your_token_here
# PostgreSQL Configuration
POSTGRES_USER=financeuser
POSTGRES_PASSWORD=changeme
POSTGRES_DB=finance
POSTGRES_PORT=5432
# pgAdmin Configuration
PGADMIN_DEFAULT_EMAIL=peter@peterwood.dev
PGADMIN_DEFAULT_PASSWORD=admin
PGADMIN_PORT=5050

View File

@@ -1,12 +0,0 @@
FROM mcr.microsoft.com/devcontainers/typescript-node:1-20-bullseye
LABEL org.opencontainers.image.source=https://github.com/acedanger/finance
LABEL org.opencontainers.image.description="Development container for Finance application with Node.js, TypeScript, and dev tools"
# Install additional OS packages
RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \
&& apt-get -y install --no-install-recommends git-core \
&& apt-get clean -y && rm -rf /var/lib/apt/lists/*
# Install global npm packages if needed
RUN su node -c "npm install -g typescript"

View File

@@ -1,115 +0,0 @@
# Requires -Version 5.0
param(
[Parameter(Mandatory=$true)]
[string]$GitHubUsername
)
# Stop on first error
$ErrorActionPreference = "Stop"
# Configuration
$ImageName = "finance-devcontainer"
$ImageTag = "latest"
$ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
$DockerfilePath = Join-Path $ScriptDir "Dockerfile"
$EnvFile = Join-Path $ScriptDir ".env"
$FullImageName = "ghcr.io/$GitHubUsername/$ImageName`:$ImageTag"
# Function to check required tools
function Test-RequiredTools {
$tools = @("docker", "gh")
foreach ($tool in $tools) {
if (-not (Get-Command $tool -ErrorAction SilentlyContinue)) {
Write-Error "Error: $tool is required but not installed"
exit 1
}
}
}
# Function to load environment variables from .env file
function Get-EnvContent {
if (Test-Path $EnvFile) {
Write-Host "Loading environment from $EnvFile"
$envContent = Get-Content $EnvFile
foreach ($line in $envContent) {
if ($line -match '^GITHUB_PERSONAL_ACCESS_TOKEN=(.*)$') {
return $matches[1]
}
}
}
Write-Error "Error: GITHUB_PERSONAL_ACCESS_TOKEN not found in $EnvFile"
exit 1
}
# Verify prerequisites
Write-Host "=== Building Development Container ==="
Write-Host "Username: $GitHubUsername"
Write-Host "Image: $FullImageName"
Write-Host "Dockerfile: $DockerfilePath"
# Check required tools
Test-RequiredTools
# Check GitHub authentication
try {
gh auth status
} catch {
Write-Error "Error: Not authenticated with GitHub. Please run 'gh auth login' first"
exit 1
}
# Get GitHub PAT from .env file
$GitHubPAT = Get-EnvContent
if ([string]::IsNullOrEmpty($GitHubPAT)) {
Write-Error "Error: GITHUB_PERSONAL_ACCESS_TOKEN is empty"
exit 1
}
Write-Host "Using PAT: $($GitHubPAT.Substring(0, 4))... (first 4 chars)"
# Build the image
Write-Host "`n=> Building image..."
try {
docker build -t $FullImageName -f $DockerfilePath $ScriptDir
} catch {
Write-Error "Error: Docker build failed"
exit 1
}
# Log in to GitHub Container Registry
Write-Host "`n=> Logging into GitHub Container Registry..."
$GitHubPAT | docker login ghcr.io -u $GitHubUsername --password-stdin
if ($LASTEXITCODE -ne 0) {
Write-Error "Error: Failed to authenticate with GitHub Container Registry"
exit 1
}
# Push to GitHub Container Registry
Write-Host "`n=> Pushing image to GitHub Container Registry..."
docker push $FullImageName
if ($LASTEXITCODE -ne 0) {
Write-Error @"
Error: Failed to push image
Please check your GitHub PAT has the required permissions:
- read:packages
- write:packages
"@
exit 1
}
Write-Host "`n=== Success! ==="
Write-Host "The development container image has been built and pushed"
Write-Host "`nTo use this image, update your devcontainer.json with:"
Write-Host @"
{
"image": "$FullImageName"
}
"@
Write-Host "`nNext steps:"
Write-Host "1. Update .devcontainer/devcontainer.json with the image reference above"
Write-Host "2. Rebuild your development container in VS Code"
Write-Host " (Command Palette -> 'Dev Containers: Rebuild Container')"

View File

@@ -1,114 +0,0 @@
#!/usr/bin/env bash
# Exit on error. Append "|| true" if you expect an error.
set -o errexit
# Exit on error inside any functions or subshells.
set -o errtrace
# Do not allow use of undefined vars. Use ${VAR:-} to use an undefined VAR
set -o nounset
# Catch pipeline errors
set -o pipefail
# Turn on traces, useful while debugging but commented out by default
# set -o xtrace
# Configuration
readonly SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" &> /dev/null && pwd)"
readonly ENV_FILE="${SCRIPT_DIR}/.env"
readonly IMAGE_NAME="finance-devcontainer"
readonly IMAGE_TAG="latest"
# Check for required username argument
if [[ $# -lt 1 ]]; then
echo >&2 "Error: GitHub username is required"
echo >&2 "Usage: $0 <github_username>"
echo >&2 "Example: $0 acedanger"
exit 1
fi
readonly GITHUB_USERNAME="$1"
readonly DOCKERFILE_PATH="${SCRIPT_DIR}/Dockerfile"
readonly FULL_IMAGE_NAME="ghcr.io/${GITHUB_USERNAME}/${IMAGE_NAME}:${IMAGE_TAG}"
# Check for required tools
for cmd in docker gh; do
if ! command -v "${cmd}" >/dev/null 2>&1; then
echo >&2 "Error: ${cmd} is required but not installed"
exit 1
fi
done
# Load environment variables from .env file if it exists
if [[ ! -f "${ENV_FILE}" ]]; then
echo >&2 "Error: Environment file not found: ${ENV_FILE}"
exit 1
fi
echo "Loading environment from ${ENV_FILE}"
# Read the env file line by line to handle special characters correctly
while IFS= read -r line || [[ -n "${line}" ]]; do
# Skip comments and empty lines
[[ "${line}" =~ ^[[:space:]]*# ]] && continue
[[ -z "${line}" ]] && continue
# Export the variable if it's the PAT
if [[ "${line}" =~ ^GITHUB_PERSONAL_ACCESS_TOKEN= ]]; then
export "${line}"
break
fi
done < "${ENV_FILE}"
# Verify PAT is loaded
if [[ -z "${GITHUB_PERSONAL_ACCESS_TOKEN:-}" ]]; then
echo >&2 "Error: GITHUB_PERSONAL_ACCESS_TOKEN is not set in ${ENV_FILE}"
exit 1
fi
# Check GitHub authentication
if ! gh auth status >/dev/null 2>&1; then
echo >&2 "Error: Not authenticated with GitHub. Please run 'gh auth login' first"
exit 1
fi
echo "=== Building Development Container ==="
echo "Username: ${GITHUB_USERNAME}"
echo "Image: ${FULL_IMAGE_NAME}"
echo "Dockerfile: ${DOCKERFILE_PATH}"
echo "Using PAT: ${GITHUB_PERSONAL_ACCESS_TOKEN:0:4}... (first 4 chars)"
# Build the image
echo -e "\n=> Building image..."
if ! docker build -t "${FULL_IMAGE_NAME}" -f "${DOCKERFILE_PATH}" "${SCRIPT_DIR}"; then
echo >&2 "Error: Docker build failed"
exit 1
fi
# Log in to GitHub Container Registry
echo -e "\n=> Logging into GitHub Container Registry..."
if ! echo "${GITHUB_PERSONAL_ACCESS_TOKEN}" | docker login ghcr.io -u "${GITHUB_USERNAME}" --password-stdin; then
echo >&2 "Error: Failed to log in to GitHub Container Registry"
exit 1
fi
# Push to GitHub Container Registry
echo -e "\n=> Pushing image to GitHub Container Registry..."
if ! docker push "${FULL_IMAGE_NAME}"; then
echo >&2 "Error: Failed to push image"
echo >&2 "Please check your GitHub PAT has the required permissions:"
echo >&2 " - read:packages"
echo >&2 " - write:packages"
exit 1
fi
echo -e "\n=== Success! ==="
echo "The development container image has been built and pushed"
echo -e "\nTo use this image, update your devcontainer.json with:"
cat << EOF
{
"image": "${FULL_IMAGE_NAME}"
}
EOF
echo -e "\nNext steps:"
echo "1. Update .devcontainer/devcontainer.json with the image reference above"
echo "2. Rebuild your development container in VS Code"
echo " (Command Palette -> 'Dev Containers: Rebuild Container')"

View File

@@ -1,110 +0,0 @@
{
"name": "Finance App Development",
"image": "ghcr.io/acedanger/finance-devcontainer:latest",
"workspaceFolder": "/workspaces/finance",
"workspaceMount": "source=${localWorkspaceFolder},target=/workspaces/finance,type=bind,consistency=cached",
"features": {
"ghcr.io/devcontainers/features/git:1": {},
"ghcr.io/devcontainers/features/docker-in-docker:2": {},
"ghcr.io/devcontainers/features/github-cli:1": {}
},
"runArgs": ["--dns", "8.8.8.8", "--dns", "8.8.4.4", "--network=host", "--dns-search=."],
"containerEnv": {
"HOSTALIASES": "/etc/host.aliases",
"GITHUB_PERSONAL_ACCESS_TOKEN": "${localEnv:GITHUB_PERSONAL_ACCESS_TOKEN}",
"TZ": "America/New_York"
},
"customizations": {
"vscode": {
"extensions": [
"astro-build.astro-vscode",
"GitHub.copilot",
"GitHub.copilot-chat",
"ms-vscode.vscode-typescript-next",
"bradlc.vscode-tailwindcss",
"biomejs.biome",
"PKief.material-icon-theme",
"Gruntfuggly.todo-tree",
"humao.rest-client",
"chrisdias.promptboost"
],
"settings": {
"editor.formatOnSave": true,
"[typescript]": {
"editor.formatOnSave": true,
"editor.defaultFormatter": "biomejs.biome",
"editor.codeActionsOnSave": {
"source.fixAll.biome": "explicit",
"source.organizeImports.biome": "explicit"
}
},
"[javascript]": {
"editor.formatOnSave": true,
"editor.defaultFormatter": "biomejs.biome",
"editor.codeActionsOnSave": {
"source.fixAll.biome": "explicit",
"source.organizeImports.biome": "explicit"
}
},
"[astro]": {
"editor.defaultFormatter": "astro-build.astro-vscode"
},
"mcp": {
"servers": {
"github": {
"command": "docker",
"args": [
"run",
"-i",
"--rm",
"-e",
"GITHUB_PERSONAL_ACCESS_TOKEN=${env:GITHUB_PERSONAL_ACCESS_TOKEN}",
"ghcr.io/github/github-mcp-server"
],
"env": {
"GITHUB_PERSONAL_ACCESS_TOKEN": "${env:GITHUB_PERSONAL_ACCESS_TOKEN}"
}
}
}
},
"[json]": {
"editor.defaultFormatter": "biomejs.biome"
},
"[markdown]": {
"editor.defaultFormatter": "biomejs.biome"
},
"typescript.updateImportsOnFileMove.enabled": "always",
"editor.bracketPairColorization.enabled": true,
"files.exclude": {
"**/.git": true,
"**/.DS_Store": true,
"**/node_modules": true,
"**/.idea": true
},
"terminal.integrated.defaultProfile.linux": "bash",
"mcp.servers.github": {
"command": "bash",
"args": [
"-c",
"source ${containerWorkspaceFolder}/.devcontainer/library-scripts/load-env.sh && if [ -n \"${GITHUB_PERSONAL_ACCESS_TOKEN}\" ]; then docker run -i --rm -e GITHUB_PERSONAL_ACCESS_TOKEN=\"${GITHUB_PERSONAL_ACCESS_TOKEN}\" ghcr.io/github/github-mcp-server; else echo 'Error: GITHUB_PERSONAL_ACCESS_TOKEN not set' >&2; exit 1; fi"
],
"env": {}
}
}
}
},
"forwardPorts": [3000],
"postCreateCommand": "npm install && npm run check",
"remoteUser": "node",
"mounts": [
"type=bind,source=${localEnv:HOME}${localEnv:USERPROFILE}/.ssh,target=/home/node/.ssh,readonly"
],
"updateRemoteUserUID": true,
"remoteEnv": {
"GITHUB_PERSONAL_ACCESS_TOKEN": "${localEnv:GITHUB_PERSONAL_ACCESS_TOKEN}"
},
"initializeCommand": {
"load-env": "echo 'Preparing environment variables for container startup'"
},
"postStartCommand": "bash -c 'source ${containerWorkspaceFolder}/.devcontainer/library-scripts/load-env.sh && gh auth status || gh auth login'"
}

View File

@@ -1,80 +0,0 @@
#!/usr/bin/env bash
# Exit on error. Append "|| true" if you expect an error.
set -o errexit
# Exit on error inside any functions or subshells.
set -o errtrace
# Do not allow use of undefined vars. Use ${VAR:-} to use an undefined VAR
set -o nounset
# Catch the error in case mysqldump fails (but gzip succeeds) in `mysqldump |gzip`
set -o pipefail
# Try to get PAT from environment first
pat="${GITHUB_PERSONAL_ACCESS_TOKEN:-}"
# If not in environment, try to get from .env file
if [[ -z "${pat}" ]] || [[ "${#pat}" -lt 30 ]]; then
if [[ -f "${containerWorkspaceFolder}/.devcontainer/.env" ]]; then
source "${containerWorkspaceFolder}/.devcontainer/.env"
pat="${GITHUB_PERSONAL_ACCESS_TOKEN:-}"
fi
fi
# If still not set, try to get from GitHub CLI
if [[ -z "${pat}" ]] || [[ "${#pat}" -lt 30 ]]; then
if command -v gh &> /dev/null; then
if gh auth status &> /dev/null; then
pat=$(gh auth token)
if [[ -n "${pat}" ]] && [[ "${#pat}" -gt 30 ]]; then
# Export the token to environment
export GITHUB_PERSONAL_ACCESS_TOKEN="${pat}"
# Save the token to .env file if it's valid
ENV_FILE="/workspaces/finance/.devcontainer/.env"
echo "# GitHub Finance Devcontainer Configuration" > "${ENV_FILE}"
echo "GITHUB_PERSONAL_ACCESS_TOKEN=${pat}" >> "${ENV_FILE}"
chmod 600 "${ENV_FILE}"
fi
fi
fi
fi
# If still not found, try .env file
if [[ -z "${pat}" ]] || [[ "${#pat}" -lt 30 ]]; then
ENV_FILE="/workspaces/finance/.devcontainer/.env"
if [[ -f "${ENV_FILE}" ]]; then
# Try to extract PAT from .env file
env_pat=$(grep -E '^GITHUB_PERSONAL_ACCESS_TOKEN=.+' "${ENV_FILE}" | cut -d'=' -f2-)
# Clean up the extracted PAT
env_pat="${env_pat#\"}"
env_pat="${env_pat%\"}"
env_pat="${env_pat#\'}"
env_pat="${env_pat%\'}"
env_pat="${env_pat%%[[:space:]]}"
env_pat="${env_pat##[[:space:]]}"
if [[ -n "${env_pat}" ]] && [[ "${#env_pat}" -gt 30 ]]; then
pat="${env_pat}"
fi
fi
fi
# Export the PAT if valid
if [[ -n "${pat}" ]] && [[ "${#pat}" -gt 30 ]]; then
export GITHUB_PERSONAL_ACCESS_TOKEN="${pat}"
echo "GitHub Personal Access Token loaded successfully"
# Use return instead of exit when script is sourced
if [[ "${BASH_SOURCE[0]}" != "${0}" ]]; then
return 0
else
exit 0
fi
else
echo >&2 "ERROR: Could not find valid GitHub Personal Access Token"
# Use return instead of exit when script is sourced
if [[ "${BASH_SOURCE[0]}" != "${0}" ]]; then
return 1
else
exit 1
fi
fi

View File

@@ -10,28 +10,17 @@ This project is a financial transaction management application built with Astro
* **Language:** TypeScript, JavaScript (client-side scripts), HTML, CSS * **Language:** TypeScript, JavaScript (client-side scripts), HTML, CSS
* **Styling:** Plain CSS (`src/styles/global.css`) * **Styling:** Plain CSS (`src/styles/global.css`)
* **Data:** Using Astro's built-in API routes in `src/pages/api/` with persistent database storage via Prisma ORM (`src/data/db.service.ts`). * **Data:** Using Astro's built-in API routes in `src/pages/api/` with persistent database storage via Prisma ORM (`src/data/db.service.ts`).
* **Development Environment:** VS Code Dev Container using private Docker image (`ghcr.io/acedanger/finance-devcontainer:latest`) * **Development Environment:** Local development with Node.js, PostgreSQL, and standard tooling
## Development Environment ## Development Environment
* **Dev Container:** The project uses a VS Code Dev Container for consistent development environments. * **Local Development:** The project uses standard Node.js development practices.
* Container configuration in `.devcontainer/devcontainer.json` * Node.js (version 18 or higher)
* Uses a private container image hosted on GitHub Container Registry * PostgreSQL for database storage
* Image: `ghcr.io/acedanger/finance-devcontainer:latest` * Prisma ORM for database operations
* Includes all necessary development tools and extensions * TypeScript for type safety
* Configured with GitHub CLI and authentication * Biome.js for code formatting and linting
* Features Docker-in-Docker support for additional container needs * Husky for Git hooks and code quality enforcement
* **Container Features:**
* Node.js and npm pre-installed
* Git and GitHub CLI configured
* TypeScript support
* VS Code extensions pre-configured
* Docker-in-Docker capability
* Automatic GitHub authentication
* **Authentication:**
* Requires GitHub Personal Access Token for private container access
* Token should be configured in `.devcontainer/.env`
* GitHub CLI authentication handled in post-start command
## Current State & Key Features ## Current State & Key Features
@@ -60,10 +49,6 @@ This project is a financial transaction management application built with Astro
## File Structure Overview ## File Structure Overview
* `.devcontainer/`: Development container configuration
* `devcontainer.json`: VS Code Dev Container configuration
* `Dockerfile`: Base container definition (for reference)
* `.env.example`: Template for container environment variables
* `src/components/`: Reusable UI components. * `src/components/`: Reusable UI components.
* `src/data/`: Data store and persistence layer. * `src/data/`: Data store and persistence layer.
* `db.service.ts`: Database service layer using Prisma ORM * `db.service.ts`: Database service layer using Prisma ORM

1
.gitignore vendored
View File

@@ -35,3 +35,4 @@ pnpm-debug.log*
# Test coverage # Test coverage
coverage/ coverage/
.vscode/mcp.json

View File

@@ -4,9 +4,9 @@
- Windows, macOS, or Linux - Windows, macOS, or Linux
- Git - Git
- Docker Desktop - Node.js (version 18 or higher)
- Visual Studio Code with Remote - Containers extension - npm or yarn
- GitHub CLI - PostgreSQL (local installation or Docker)
## Initial Setup ## Initial Setup
@@ -16,81 +16,31 @@
cd finance cd finance
``` ```
2. **Create Environment Files** 2. **Install Dependencies**
```bash
npm install
```
3. **Create Environment File**
```bash ```bash
cp .devcontainer/.env.example .devcontainer/.env
cp .env.example .env cp .env.example .env
``` ```
## GitHub Personal Access Token (PAT) 4. **Configure Database**
- Edit the `.env` file with your PostgreSQL connection string:
```
DATABASE_URL="postgresql://username:password@localhost:5432/finance"
```
1. **Create a new PAT:** 5. **Set up Database**
- Go to GitHub Settings > Developer settings > Personal access tokens > Tokens (classic)
- Click "Generate new token (classic)"
- Name: `finance-dev-token`
- Set expiration: 90 days (recommended)
- Required scopes:
- `repo` (Full control of private repositories)
- `read:packages` (Download container images)
- `write:packages` (Upload container images)
- `delete:packages` (Optional: manage container versions)
- `workflow` (GitHub Actions integration)
2. **Configure the PAT:**
- Open `.devcontainer/.env`
- Set `GITHUB_PERSONAL_ACCESS_TOKEN=your_token_here`
## Building the Development Container
### Using VS Code (Recommended)
1. Open the project in VS Code
2. When prompted, click "Reopen in Container"
- Or press F1 and run "Dev Containers: Rebuild and Reopen in Container"
### Using Command Line
1. Install the devcontainer CLI:
```bash ```bash
npm install -g @devcontainers/cli # Run database migrations
npx prisma migrate dev
# Seed the database with initial data (optional)
npx prisma db seed
``` ```
2. Build the container:
```bash
devcontainer build .
```
3. Start the container:
```bash
# With post-create command
devcontainer up --workspace-folder .
# Skip post-create command
devcontainer up --workspace-folder . --skip-post-create
```
## Building and Pushing the Container Image
1. Ensure you're in the `.devcontainer` directory
2. Choose your preferred script:
**Using PowerShell:**
```powershell
.\build-and-push.ps1 your_github_username
```
**Using Git Bash/Unix Shell:**
```bash
chmod +x build-and-push.sh
./build-and-push.sh your_github_username
```
Both scripts perform the same functions:
- Validate prerequisites (Docker, GitHub CLI)
- Load GitHub PAT from `.env` file
- Build the container image
- Push to GitHub Container Registry
- Provide next steps for using the image
## Git Hooks ## Git Hooks
This project uses Git hooks via Husky to enforce code quality: This project uses Git hooks via Husky to enforce code quality:
@@ -140,63 +90,29 @@ For hook execution issues:
npm run prepare npm run prepare
``` ```
## Environment Files ## Environment Configuration
The project uses two separate environment files: The project uses an `.env` file for configuration:
1. `.devcontainer/.env`:
- Container-specific configuration
- GitHub PAT
- PostgreSQL settings
- pgAdmin settings
2. `.env`:
- Application-specific configuration - Application-specific configuration
- Database connection string
- Development server port - Development server port
- API base URL - API base URL
- Node environment - Node environment
## Troubleshooting ## Troubleshooting
### Container Build Issues ### Database Issues
- Ensure Docker Desktop is running - Ensure PostgreSQL is running
- Check that your PAT has the correct permissions - Check that your database connection string is correct in `.env`
- Try rebuilding without cache: `devcontainer build . --no-cache` - Try resetting the database: `npx prisma migrate reset`
### GitHub Authentication Issues ### Build Issues
- Verify your PAT in `.devcontainer/.env` - Clear node_modules and reinstall: `Remove-Item -Recurse -Force node_modules; npm install`
- Try logging in manually: `gh auth login` - Check that all environment variables are set correctly
- Check GitHub CLI status: `gh auth status` - Ensure you have the correct Node.js version installed
### Network Issues ### Common Operations
- If DNS resolution fails, try using different DNS servers in `devcontainer.json`
- Check if GitHub Container Registry (ghcr.io) is accessible
- Verify Docker network settings
### VS Code Issues
- Install/update the Remote - Containers extension
- Clear VS Code's container cache
- Check VS Code's "Dev Containers" output panel for detailed logs
## Common Operations
### Rebuilding the Container
```bash
# Using VS Code
F1 -> "Dev Containers: Rebuild Container"
# Using CLI
devcontainer build . --no-cache
```
### Updating the Container Image
1. Make changes to `Dockerfile` or `devcontainer.json`
2. Run the build script:
```bash
./build-and-push.sh your_github_username
```
3. Update image reference in `devcontainer.json`
4. Rebuild container in VS Code
### Starting Development Server ### Starting Development Server
```bash ```bash

View File

@@ -15,19 +15,20 @@ This app is currently deployed using Cloudflare Pages. The logs can be viewed wi
## Development Environment Setup ## Development Environment Setup
For detailed setup instructions, including container building, environment configuration, authentication, and troubleshooting, see [ENVIRONMENT_SETUP.md](ENVIRONMENT_SETUP.md). For detailed setup instructions, including environment configuration and troubleshooting, see [ENVIRONMENT_SETUP.md](ENVIRONMENT_SETUP.md).
### Quick Start ### Quick Start
1. **Prerequisites** 1. **Prerequisites**
- Docker Desktop installed and running - Node.js (version 18 or higher)
- VS Code with Remote - Containers extension - PostgreSQL (local installation or Docker)
- GitHub account with Personal Access Token (PAT) - Git
2. **Setup Steps** 2. **Setup Steps**
- Clone this repository - Clone this repository
- Copy `.devcontainer/.env.example` to `.devcontainer/.env` and add your GitHub PAT - Run `npm install`
- Open in VS Code and select "Reopen in Container" when prompted - Copy `.env.example` to `.env` and configure your database connection
- Run `npx prisma migrate dev` to set up the database
### Database Setup ### Database Setup