mirror of
https://github.com/polaroi8d/cactoide.git
synced 2026-03-22 06:05:28 +00:00
Compare commits
8 Commits
feat/feder
...
fix/fix-i1
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6155cc44da | ||
|
|
719cd23350 | ||
|
|
87d2275373 | ||
|
|
6e314af82b | ||
|
|
2cb74bccd0 | ||
|
|
0ecaf54227 | ||
|
|
4179bca981 | ||
|
|
406a669a98 |
12
Makefile
12
Makefile
@@ -22,7 +22,7 @@ help:
|
||||
@echo " logs - Show logs from all services"
|
||||
@echo " db-clean - Clean up all Docker resources"
|
||||
@echo " prune - Clean up everything (containers, images, volumes)"
|
||||
@echo " i18n - Validate translation files"
|
||||
@echo " i18n - List missing keys in translation file (use FILE=path/to/file.json)"
|
||||
@echo " lint - Lint the project"
|
||||
@echo " format - Format the project"
|
||||
@echo " migrate-up - Apply invite-only events migration"
|
||||
@@ -94,8 +94,10 @@ format:
|
||||
@echo "Formatting the project..."
|
||||
npm run format
|
||||
|
||||
#TODO: not working yet
|
||||
# List missing keys in a translation file
|
||||
i18n:
|
||||
@echo "Validating translation files..."
|
||||
@if [ -n "$(FILE)" ]; then \
|
||||
./scripts/i18n-check.sh $(FILE); \
|
||||
@if [ -z "$(FILE)" ]; then \
|
||||
echo "Error: FILE variable is required. Example: make i18n FILE=src/lib/i18n/it.json"; \
|
||||
exit 1; \
|
||||
fi
|
||||
@./scripts/i18n-check.sh --missing-only $(FILE)
|
||||
|
||||
@@ -34,7 +34,7 @@ services:
|
||||
ports:
|
||||
- '${PORT:-5111}:3000'
|
||||
environment:
|
||||
DATABASE_URL: ${DATABASE_URL}
|
||||
DATABASE_URL: ${DATABASE_URL:-postgres://cactoide:cactoide_password@postgres:5432/cactoide_database}
|
||||
PORT: 3000
|
||||
HOSTNAME: ${HOSTNAME:-0.0.0.0}
|
||||
depends_on:
|
||||
|
||||
7
package-lock.json
generated
7
package-lock.json
generated
@@ -24,12 +24,8 @@
|
||||
"@tailwindcss/forms": "^0.5.9",
|
||||
"@tailwindcss/typography": "^0.5.15",
|
||||
"@tailwindcss/vite": "^4.0.0",
|
||||
<<<<<<< HEAD
|
||||
"drizzle-kit": "^0.31.5",
|
||||
=======
|
||||
"@types/node": "^24.9.1",
|
||||
"drizzle-kit": "^0.31.4",
|
||||
>>>>>>> 222c2ee (feat: add pino logger for serverside)
|
||||
"eslint": "^9.18.0",
|
||||
"eslint-config-prettier": "^10.0.1",
|
||||
"eslint-plugin-svelte": "^3.0.0",
|
||||
@@ -2108,8 +2104,6 @@
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
<<<<<<< HEAD
|
||||
=======
|
||||
"node_modules/@types/node": {
|
||||
"version": "24.9.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-24.9.1.tgz",
|
||||
@@ -2121,7 +2115,6 @@
|
||||
"undici-types": "~7.16.0"
|
||||
}
|
||||
},
|
||||
>>>>>>> 222c2ee (feat: add pino logger for serverside)
|
||||
"node_modules/@types/resolve": {
|
||||
"version": "1.20.2",
|
||||
"resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.20.2.tgz",
|
||||
|
||||
@@ -1,191 +1,89 @@
|
||||
#!/bin/bash
|
||||
#!/usr/bin/env bash
|
||||
# Find keys present in messages.json but missing in a translation file.
|
||||
|
||||
# Translation validation script
|
||||
# Compares a translation file against the source messages.json to find missing keys
|
||||
set -euo pipefail
|
||||
|
||||
set -e
|
||||
SOURCE_DEFAULT="src/lib/i18n/messages.json"
|
||||
|
||||
# Colors for output
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
NC='\033[0m' # No Color
|
||||
|
||||
# Default paths
|
||||
SOURCE_FILE="src/lib/i18n/messages.json"
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
PROJECT_ROOT="$(dirname "$SCRIPT_DIR")"
|
||||
|
||||
# Function to show usage
|
||||
show_usage() {
|
||||
echo "Usage: $0 [LANGUAGE_FILE]"
|
||||
echo ""
|
||||
echo "Validates a translation file against the source messages.json"
|
||||
echo ""
|
||||
echo "Arguments:"
|
||||
echo " LANGUAGE_FILE Path to the translation file to validate (e.g., src/lib/i18n/it.json)"
|
||||
echo ""
|
||||
echo "Examples:"
|
||||
echo " $0 src/lib/i18n/it.json"
|
||||
echo " $0 src/lib/i18n/fr.json"
|
||||
echo ""
|
||||
echo "If no file is provided, it will check all .json files in src/lib/i18n/ except messages.json"
|
||||
}
|
||||
|
||||
# Function to get all keys from a JSON file recursively
|
||||
get_keys() {
|
||||
local file="$1"
|
||||
local prefix="$2"
|
||||
|
||||
# Use jq to extract all keys recursively
|
||||
jq -r 'paths(scalars) as $p | $p | join(".")' "$file" | while read -r key; do
|
||||
if [ -n "$prefix" ]; then
|
||||
echo "${prefix}.${key}"
|
||||
else
|
||||
echo "$key"
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
# Function to validate a single translation file
|
||||
validate_file() {
|
||||
local translation_file="$1"
|
||||
local source_file="$2"
|
||||
|
||||
echo -e "${YELLOW}Validating: $translation_file${NC}"
|
||||
echo "----------------------------------------"
|
||||
|
||||
# Check if files exist
|
||||
if [ ! -f "$source_file" ]; then
|
||||
echo -e "${RED}Error: Source file $source_file not found${NC}"
|
||||
return 1
|
||||
fi
|
||||
|
||||
if [ ! -f "$translation_file" ]; then
|
||||
echo -e "${RED}Error: Translation file $translation_file not found${NC}"
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Get all keys from source file
|
||||
local source_keys
|
||||
source_keys=$(get_keys "$source_file")
|
||||
|
||||
# Get all keys from translation file
|
||||
local translation_keys
|
||||
translation_keys=$(get_keys "$translation_file")
|
||||
|
||||
# Find missing keys
|
||||
local missing_keys
|
||||
missing_keys=$(comm -23 <(echo "$source_keys" | sort) <(echo "$translation_keys" | sort))
|
||||
|
||||
# Find extra keys (in translation but not in source)
|
||||
local extra_keys
|
||||
extra_keys=$(comm -13 <(echo "$source_keys" | sort) <(echo "$translation_keys" | sort))
|
||||
|
||||
# Count missing and extra keys
|
||||
local missing_count
|
||||
if [ -z "$missing_keys" ]; then
|
||||
missing_count=0
|
||||
else
|
||||
missing_count=$(echo "$missing_keys" | wc -l | tr -d ' ')
|
||||
fi
|
||||
|
||||
local extra_count
|
||||
if [ -z "$extra_keys" ]; then
|
||||
extra_count=0
|
||||
else
|
||||
extra_count=$(echo "$extra_keys" | wc -l | tr -d ' ')
|
||||
fi
|
||||
|
||||
# Report results
|
||||
if [ "$missing_count" -eq 0 ] && [ "$extra_count" -eq 0 ]; then
|
||||
echo -e "${GREEN} Perfect! All keys match.${NC}"
|
||||
return 0
|
||||
fi
|
||||
|
||||
if [ "$missing_count" -gt 0 ]; then
|
||||
echo -e "${RED} Missing $missing_count key(s) in translation:${NC}"
|
||||
echo "$missing_keys" | while read -r key; do
|
||||
echo -e " ${RED}• $key${NC}"
|
||||
done
|
||||
echo ""
|
||||
fi
|
||||
|
||||
if [ "$extra_count" -gt 0 ]; then
|
||||
echo -e "${YELLOW} Extra $extra_count key(s) in translation (not in source):${NC}"
|
||||
echo "$extra_keys" | while read -r key; do
|
||||
echo -e " ${YELLOW}• $key${NC}"
|
||||
done
|
||||
echo ""
|
||||
fi
|
||||
|
||||
# Return error code if there are missing keys
|
||||
if [ "$missing_count" -gt 0 ]; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
# Main function
|
||||
main() {
|
||||
local translation_file="$1"
|
||||
local source_file="$PROJECT_ROOT/$SOURCE_FILE"
|
||||
local exit_code=0
|
||||
|
||||
# Change to project root directory
|
||||
cd "$PROJECT_ROOT"
|
||||
|
||||
# If no file specified, check all translation files
|
||||
if [ -z "$translation_file" ]; then
|
||||
echo -e "${YELLOW}No file specified. Checking all translation files...${NC}"
|
||||
echo ""
|
||||
|
||||
# Find all .json files in i18n directory except messages.json
|
||||
local files
|
||||
files=$(find src/lib/i18n -name "*.json" -not -name "messages.json" 2>/dev/null || true)
|
||||
|
||||
if [ -z "$files" ]; then
|
||||
echo -e "${YELLOW}No translation files found in src/lib/i18n/${NC}"
|
||||
return 0
|
||||
fi
|
||||
|
||||
# Validate each file
|
||||
echo "$files" | while read -r file; do
|
||||
if [ -n "$file" ]; then
|
||||
if ! validate_file "$file" "$source_file"; then
|
||||
exit_code=1
|
||||
fi
|
||||
echo ""
|
||||
fi
|
||||
done
|
||||
|
||||
return $exit_code
|
||||
fi
|
||||
|
||||
# Validate the specified file
|
||||
if ! validate_file "$translation_file" "$source_file"; then
|
||||
exit_code=1
|
||||
fi
|
||||
|
||||
return $exit_code
|
||||
usage() {
|
||||
echo "Usage: $0 [--missing-only] <translation.json> [source_messages.json]"
|
||||
echo "Compares <translation.json> against messages.json and prints missing keys."
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Check if jq is installed
|
||||
if ! command -v jq &> /dev/null; then
|
||||
echo -e "${RED}Error: jq is required but not installed.${NC}"
|
||||
echo "Please install jq:"
|
||||
echo " macOS: brew install jq"
|
||||
echo " Ubuntu/Debian: sudo apt-get install jq"
|
||||
echo " CentOS/RHEL: sudo yum install jq"
|
||||
exit 1
|
||||
command -v jq >/dev/null 2>&1 || {
|
||||
echo "Error: jq is required but not installed." >&2
|
||||
echo "Please install jq:" >&2
|
||||
echo " macOS: brew install jq" >&2
|
||||
echo " Ubuntu/Debian: sudo apt-get install jq" >&2
|
||||
echo " CentOS/RHEL: sudo yum install jq" >&2
|
||||
exit 127
|
||||
}
|
||||
|
||||
# Parse arguments (handle --missing-only flag for Makefile compatibility)
|
||||
TRANSLATION=""
|
||||
SOURCE="$SOURCE_DEFAULT"
|
||||
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case "$1" in
|
||||
--missing-only|-m)
|
||||
# Flag is accepted but ignored (this script only does missing keys)
|
||||
shift
|
||||
;;
|
||||
--help|-h)
|
||||
usage
|
||||
;;
|
||||
-*)
|
||||
echo "Error: Unknown option: $1" >&2
|
||||
usage
|
||||
;;
|
||||
*)
|
||||
if [[ -z "$TRANSLATION" ]]; then
|
||||
TRANSLATION="$1"
|
||||
elif [[ "$SOURCE" == "$SOURCE_DEFAULT" ]]; then
|
||||
SOURCE="$1"
|
||||
else
|
||||
echo "Error: Too many arguments" >&2
|
||||
usage
|
||||
fi
|
||||
shift
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
# Validate arguments
|
||||
[[ -z "$TRANSLATION" ]] && {
|
||||
echo "Error: Translation file is required" >&2
|
||||
usage
|
||||
}
|
||||
|
||||
# Validate files exist
|
||||
[[ -f "$SOURCE" ]] || {
|
||||
echo "Error: Source file not found: $SOURCE" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
[[ -f "$TRANSLATION" ]] || {
|
||||
echo "Error: Translation file not found: $TRANSLATION" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Extract all keys from a JSON file (dot-joined paths to scalar values)
|
||||
keys() {
|
||||
jq -r 'paths(scalars) | join(".")' "$1" | sort -u
|
||||
}
|
||||
|
||||
# Find missing keys: in SOURCE but not in TRANSLATION
|
||||
missing=$(comm -23 <(keys "$SOURCE") <(keys "$TRANSLATION"))
|
||||
|
||||
if [[ -z "$missing" ]]; then
|
||||
echo "No missing keys found."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Handle help flag
|
||||
if [ "$1" = "-h" ] || [ "$1" = "--help" ]; then
|
||||
show_usage
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Run main function
|
||||
main "$1"
|
||||
echo "Missing keys in $(basename "$TRANSLATION"):"
|
||||
echo "$missing" | sed 's/^/ - /'
|
||||
echo
|
||||
echo "Total missing keys: $(echo "$missing" | wc -l | tr -d ' ')"
|
||||
exit 1
|
||||
|
||||
@@ -1,6 +1,16 @@
|
||||
import pino from 'pino';
|
||||
import { LOG_PRETTY, LOG_LEVEL } from '$env/static/private';
|
||||
|
||||
try {
|
||||
if (LOG_PRETTY && LOG_LEVEL) {
|
||||
console.debug(
|
||||
`Initializing logger with pretty logs: LOG_PRETTY: ${LOG_PRETTY} and LOG_LEVEL: ${LOG_LEVEL}`
|
||||
);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error initializing logger', error);
|
||||
}
|
||||
|
||||
const USE_PRETTY_LOGS = LOG_PRETTY === 'true';
|
||||
|
||||
const transport = USE_PRETTY_LOGS
|
||||
@@ -10,6 +20,14 @@ const transport = USE_PRETTY_LOGS
|
||||
colorize: true,
|
||||
translateTime: 'SYS:standard',
|
||||
ignore: 'pid,hostname'
|
||||
},
|
||||
customLevels: {
|
||||
trace: 10,
|
||||
debug: 20,
|
||||
info: 30,
|
||||
warn: 40,
|
||||
error: 50,
|
||||
fatal: 60
|
||||
}
|
||||
}
|
||||
: undefined;
|
||||
|
||||
151
static/llms.txt
Normal file
151
static/llms.txt
Normal file
@@ -0,0 +1,151 @@
|
||||
# Cactoide
|
||||
|
||||
> A federated mobile-first event RSVP platform built with SvelteKit. Cactoide is an open-source alternative to big tech event platforms like Meetup.com, Eventbrite, and Luma. It allows users to create events, share unique URLs, and collect RSVPs without any registration required. Features include built-in federation for decentralized event discovery across multiple instances, iCal integration, smart capacity limits, and a no-signup approach. The platform uses PostgreSQL with Drizzle ORM, implements federation via configurable instance lists, and supports multiple languages through a simple i18n system.
|
||||
|
||||
Cactoide is an open-source event management platform licensed under AGPL-3.0, designed as a privacy-focused alternative to centralized event platforms. Unlike Meetup.com, Eventbrite, Luma, and other big tech solutions, Cactoide requires no user accounts, collects minimal data, and operates on a federated model that gives users control over their events and data. Events can be public, private, or invite-only. The platform supports both limited and unlimited RSVP capacity.
|
||||
|
||||
## Architecture
|
||||
|
||||
The project is built with:
|
||||
- **Frontend**: SvelteKit 5 with TypeScript, Tailwind CSS
|
||||
- **Backend**: SvelteKit server routes and API endpoints
|
||||
- **Database**: PostgreSQL with Drizzle ORM
|
||||
- **Deployment**: Docker and Docker Compose support
|
||||
|
||||
Key architectural decisions:
|
||||
- File-based routing (SvelteKit conventions)
|
||||
- Server-side rendering for all pages
|
||||
- Cookie-based user identification (no authentication system)
|
||||
- Federation via HTTP API endpoints between instances
|
||||
|
||||
## API Endpoints
|
||||
|
||||
- [Health Check](/api/healthz): Returns instance health status and response time in milliseconds
|
||||
- [Federation Events](/api/federation/events): Returns all public events from the instance (requires FEDERATION_INSTANCE env variable)
|
||||
- [Federation Info](/api/federation/info): Returns instance name and public events count (requires FEDERATION_INSTANCE env variable)
|
||||
|
||||
## Database Schema
|
||||
|
||||
The database uses three main tables:
|
||||
- **events**: Stores event information (id, name, date, time, location, type, visibility, attendee_limit, user_id)
|
||||
- **rsvps**: Stores RSVP responses (id, event_id, name, user_id, created_at)
|
||||
- **invite_tokens**: Stores invite tokens for invite-only events (id, event_id, token, expires_at)
|
||||
|
||||
Event visibility can be: public, private, or invite-only. Event types can be: limited or unlimited.
|
||||
|
||||
## Federation
|
||||
|
||||
Federation allows multiple Cactoide instances to share and discover public events. Configuration is managed through `federation.config.js` which contains:
|
||||
- Instance name (display name for the instance)
|
||||
- Instance list (array of federated instance URLs to discover events from)
|
||||
|
||||
To enable federation on an instance:
|
||||
1. Set `FEDERATION_INSTANCE=true` environment variable
|
||||
2. Configure instance name in `federation.config.js`
|
||||
3. Add other instance URLs to the instances array to discover their events
|
||||
|
||||
Federated instances are displayed at `/instance` with health status, response times, and event counts.
|
||||
|
||||
## Routes
|
||||
|
||||
- `/` - Landing page (can be disabled with PUBLIC_LANDING_INFO=false)
|
||||
- `/create` - Event creation form
|
||||
- `/discover` - Public events discovery page with search and filters
|
||||
- `/event/[id]` - Individual event page with RSVP functionality
|
||||
- `/instance` - Federation instances status page
|
||||
|
||||
## Code Structure
|
||||
|
||||
### src/routes/
|
||||
SvelteKit file-based routing system. Each folder represents a route, with `+page.svelte` for UI and `+page.server.ts` for server-side data loading.
|
||||
|
||||
- [src/routes/](https://github.com/polaroi8d/cactoide/tree/main/src/routes): Main routing directory
|
||||
- `+layout.svelte` / `+layout.server.ts`: Root layout component and server-side data loading for all pages
|
||||
- `+page.svelte` / `+page.server.ts`: Landing/home page
|
||||
- `+error.svelte`: Global error page component
|
||||
- [src/routes/create/](https://github.com/polaroi8d/cactoide/tree/main/src/routes/create): Event creation form page
|
||||
- [src/routes/discover/](https://github.com/polaroi8d/cactoide/tree/main/src/routes/discover): Public events discovery page with search and filtering
|
||||
- [src/routes/event/[id]/](https://github.com/polaroi8d/cactoide/tree/main/src/routes/event/[id]): Dynamic route for individual event pages
|
||||
- `edit/`: Event editing functionality
|
||||
- `invite/[token]/`: Invite-only event access via token
|
||||
- [src/routes/instance/](https://github.com/polaroi8d/cactoide/tree/main/src/routes/instance): Federation instances status monitoring page
|
||||
- [src/routes/api/](https://github.com/polaroi8d/cactoide/tree/main/src/routes/api): API endpoints
|
||||
- `healthz/+server.ts`: Health check endpoint with response time
|
||||
- `federation/events/+server.ts`: Returns public events for federation (requires FEDERATION_INSTANCE)
|
||||
- `federation/info/+server.ts`: Returns instance name and public events count (requires FEDERATION_INSTANCE)
|
||||
|
||||
### src/lib/
|
||||
Shared library code accessible via `$lib` alias throughout the application.
|
||||
|
||||
- [src/lib/](https://github.com/polaroi8d/cactoide/tree/main/src/lib): Core library directory
|
||||
- [src/lib/components/](https://github.com/polaroi8d/cactoide/tree/main/src/lib/components): Reusable Svelte components
|
||||
- `Navbar.svelte`: Main navigation bar component
|
||||
- `CalendarModal.svelte`: Calendar integration modal for iCal downloads
|
||||
- [src/lib/database/](https://github.com/polaroi8d/cactoide/tree/main/src/lib/database): Database layer
|
||||
- `schema.ts`: Drizzle ORM schema definitions (events, rsvps, invite_tokens tables)
|
||||
- `db.ts`: Database connection and Drizzle instance setup
|
||||
- `healthCheck.ts`: Database health check utilities
|
||||
- [src/lib/i18n/](https://github.com/polaroi8d/cactoide/tree/main/src/lib/i18n): Internationalization
|
||||
- `i18n.ts`: i18n initialization and translation function
|
||||
- `messages.json`: Default English translations
|
||||
- `it.json`: Italian translation file (example of additional language)
|
||||
- `types.ts`: TypeScript type definitions (Event, RSVP, EventType, EventVisibility, LocationType, etc.)
|
||||
- `dateHelpers.ts`: Date and time formatting utilities, time range filtering for events
|
||||
- `calendarHelpers.ts`: iCal file generation and calendar service link creation (Google Calendar, Outlook, etc.)
|
||||
- `fetchFederatedEvents.ts`: Federation logic for fetching events from other Cactoide instances
|
||||
- `inviteTokenHelpers.ts`: Invite token generation and expiration calculation utilities
|
||||
- `generateUserId.ts`: User ID generation for cookie-based user identification
|
||||
- `logger.ts`: Pino-based logging configuration
|
||||
- `index.ts`: Library entry point (currently placeholder)
|
||||
|
||||
### src/
|
||||
Root source directory containing application configuration and entry points.
|
||||
|
||||
- `app.html`: HTML template for the application
|
||||
- `app.css`: Global CSS styles and Tailwind imports
|
||||
- `app.d.ts`: TypeScript type declarations
|
||||
- `hooks.server.ts`: SvelteKit server hooks for request handling, user ID cookie management, and error handling
|
||||
|
||||
### Root Level Directories
|
||||
|
||||
- [database/](https://github.com/polaroi8d/cactoide/tree/main/database): Database initialization and migration files
|
||||
- `init.sql`: Database schema initialization script (creates tables, enums, indexes)
|
||||
- `seed.sql`: Sample data for development and testing
|
||||
- [database/migrations/](https://github.com/polaroi8d/cactoide/tree/main/database/migrations): SQL migration files for schema changes
|
||||
- [static/](https://github.com/polaroi8d/cactoide/tree/main/static): Static assets served directly by the web server
|
||||
- `favicon.ico`: Site favicon
|
||||
- `robots.txt`: Search engine crawler directives
|
||||
- `llms.txt`: This file - LLM-friendly project documentation
|
||||
- [scripts/](https://github.com/polaroi8d/cactoide/tree/main/scripts): Utility scripts
|
||||
- `i18n-check.sh`: Translation file validation script
|
||||
- [docs/](https://github.com/polaroi8d/cactoide/tree/main/docs): Documentation assets
|
||||
- `federation_example.png`: Screenshot example for federation documentation
|
||||
|
||||
### Configuration Files
|
||||
|
||||
- `federation.config.js`: Federation configuration (instance name and list of federated instance URLs)
|
||||
- `package.json`: Node.js dependencies and scripts
|
||||
- `svelte.config.js`: SvelteKit configuration (adapter, preprocessors)
|
||||
- `vite.config.ts`: Vite build tool configuration
|
||||
- `tailwind.config.js`: Tailwind CSS configuration
|
||||
- `tsconfig.json`: TypeScript compiler configuration
|
||||
- `eslint.config.js`: ESLint linting rules
|
||||
- `docker-compose.yml`: Docker Compose setup for local development with PostgreSQL
|
||||
- `Dockerfile`: Production Docker image configuration
|
||||
- `Makefile`: Development command shortcuts (db-only, i18n validation, etc.)
|
||||
|
||||
## Configuration
|
||||
|
||||
Key environment variables:
|
||||
- `DATABASE_URL`: PostgreSQL connection string
|
||||
- `FEDERATION_INSTANCE`: Set to `true` to enable federation API endpoints
|
||||
- `PUBLIC_LANDING_INFO`: Set to `false` to disable landing page and redirect to `/discover`
|
||||
|
||||
## Optional
|
||||
|
||||
- [docker-compose.yml](https://github.com/polaroi8d/cactoide/blob/main/docker-compose.yml): Docker Compose configuration for local development
|
||||
- [Dockerfile](https://github.com/polaroi8d/cactoide/blob/main/Dockerfile): Production Docker image configuration
|
||||
- [database/init.sql](https://github.com/polaroi8d/cactoide/blob/main/database/init.sql): Database initialization SQL
|
||||
- [database/migrations/](https://github.com/polaroi8d/cactoide/tree/main/database/migrations): Database migration files
|
||||
- [Makefile](https://github.com/polaroi8d/cactoide/blob/main/Makefile): Development commands and shortcuts
|
||||
|
||||
Reference in New Issue
Block a user