diff --git a/README.md b/README.md index 51ddc5d..0d92a41 100644 --- a/README.md +++ b/README.md @@ -14,17 +14,25 @@ Like the cactus, great events bloom under any condition when managed with care. #### What is it? -A mobile-first event RSVP platform that lets you create events, share unique URLs, and collect RSVPs without any registration required. +A mobile-first event RSVP platform that lets you create events, share unique URLs, and collect RSVPs without any registration required. With built-in federation, discover and share events across a decentralized network of instances. ### ✨ Features -- **🎯 Instant Event Creation** - Create events in seconds with our streamlined form. No accounts, no waiting, just pure efficiency. -- **πŸ”— One-Click Sharing** - Each event gets a unique, memorable URL. Share instantly via any platform or messaging app. -- **πŸ” All-in-One Clarity** - No more scrolling through endless chats and reactions. See everyone's availability and responses neatly in one place. -- **πŸ“… iCal Integration** - One-tap add-to-calendar via ICS/webcal links. Works with Apple Calendar, Google Calendar, and Outlook, with automatic time zone handling. -- **πŸ‘€ No Hassle, No Sign-Ups** - Skip registrations and endless forms. Unlike other event platforms, you create and share instantly β€” no accounts, no barriers. -- **πŸ›‘οΈ Smart Limits** - Choose between unlimited RSVPs or set a limited capacity. Perfect for any event size. -- **✨ Effortless Simplicity** - Designed to be instantly clear and easy. No learning curve β€” just open, create, and go. +**🎯 Instant Event Creation** - Create events in seconds with our streamlined form. No accounts, no waiting, just pure efficiency. + +**πŸ”— One-Click Sharing** - Each event gets a unique, memorable URL. Share instantly via any platform or messaging app. + +**🌐 Federation** - Connect with other Cactoide instances to discover events across the network. Share your public events and creating a decentralized event discovery network. + +**πŸ” All-in-One Clarity** - No more scrolling through endless chats and reactions. See everyone's availability and responses neatly in one place. + +**πŸ“… iCal Integration** - One-tap add-to-calendar via ICS/webcal links. Works with Apple Calendar, Google Calendar, and Outlook, with automatic time zone handling. + +**πŸ‘€ No Hassle, No Sign-Ups** - Skip registrations and endless forms. Unlike other event platforms, you create and share instantly β€” no accounts, no barriers. + +**πŸ›‘οΈ Smart Limits** - Choose between unlimited RSVPs or set a limited capacity. Perfect for any event size. + +**✨ Effortless Simplicity** - Designed to be instantly clear and easy. No learning curve β€” just open, create, and go. ### Quick Start @@ -55,6 +63,55 @@ Your app will be available at `http://localhost:5173`. You can use the Makefile Use the `database/seed.sql` if you want to populate your database with dummy data. +### Federation + +Cactoide supports federation, allowing multiple instances to share and discover public events across the network. This enables users to discover events from other Cactoide instances, creating a decentralized event discovery network. + +

+ Federation Example +

+ +#### How Federation Works + +Federation is managed through the `federation.config.js` file, which contains: + +- **Instance name**: The display name for your instance +- **Instance list**: An array of federated instance URLs + +```javascript +const config = { + name: 'Cactoide Genesis', + instances: [{ url: 'cactoide.org' }, { url: 'cactoide.dalev.hu' }] +}; +``` + +#### Opting In to Federation + +To enable federation on your instance, you need to: + +1. **Set the environment variable**: Add `FEDERATION_INSTANCE=true` to your `.env` file. This enables the federation API endpoints on your instance. + +2. **Configure your instance name**: Update the `name` field in your `federation.config.js` file to set your instance's display name. + +3. **Expose required endpoints**: Your instance will automatically expose: + - `/api/federation/events` - Returns all public events from your instance + - `/api/federation/info` - Returns your instance name and public events count + +#### Adding Your Instance to the Global Federation + +To add your instance to the global federation list (so other instances can discover your events): + +1. Fork the [Cactoide repository](https://github.com/polaroi8d/cactoide) +2. Add your instance URL to the `instances` array in `federation.config.js`: + ```javascript + instances: [{ url: 'your-instance.com' }]; + ``` +3. Open a pull request to the main repository + +Once merged, your instance will appear in the federation network, and other instances will be able to discover and display your public events. + +You can view all registered federated instances in the main repository: `federation.config.js` file. + ### Options #### 1. Landing page option @@ -90,7 +147,6 @@ It isn’t backed by a big company. Development depends on the support and gener You can support in a few ways: -- Send a one-time donation via [paypal.me/zenoazurben](paypal.me/zenoazurben) - Reach me directly: leventeorb[@]gmail.com If you enjoy using Cactoide, or if your business depends on it, please consider sponsoring its development. Your support keeps the project alive, improves it for everyone, and helps create educational content like blog posts and videos for the whole Cactoide community. diff --git a/docs/federation_example.png b/docs/federation_example.png new file mode 100644 index 0000000..7511041 Binary files /dev/null and b/docs/federation_example.png differ diff --git a/src/lib/fetchFederatedEvents.ts b/src/lib/fetchFederatedEvents.ts index bd2c721..02db235 100644 --- a/src/lib/fetchFederatedEvents.ts +++ b/src/lib/fetchFederatedEvents.ts @@ -69,9 +69,9 @@ async function readFederationConfig(): Promise { */ async function fetchEventsFromInstance(instanceUrl: string): Promise { try { - // Ensure URL has protocol and append /api/events + // Ensure URL has protocol and append /api/federation/events - const apiUrl = `http://${instanceUrl}/api/events`; + const apiUrl = `http://${instanceUrl}/api/federation/events`; logger.debug({ apiUrl }, 'Fetching events from federated instance'); diff --git a/src/routes/api/events/+server.ts b/src/routes/api/federation/events/+server.ts similarity index 100% rename from src/routes/api/events/+server.ts rename to src/routes/api/federation/events/+server.ts diff --git a/src/routes/api/federation/info/+server.ts b/src/routes/api/federation/info/+server.ts index 4fd054a..13519a6 100644 --- a/src/routes/api/federation/info/+server.ts +++ b/src/routes/api/federation/info/+server.ts @@ -6,8 +6,13 @@ import { eq, count } from 'drizzle-orm'; import { logger } from '$lib/logger'; import federationConfig from '../../../../../federation.config.js'; +import { FEDERATION_INSTANCE } from '$env/static/private'; + export const GET: RequestHandler = async () => { try { + if (!FEDERATION_INSTANCE) { + return json({ error: 'Federation API is not enabled on this instance' }, { status: 403 }); + } // Count public events const publicEventsCount = await database .select({ count: count() }) @@ -31,4 +36,3 @@ export const GET: RequestHandler = async () => { ); } }; -