mirror of
https://github.com/polaroi8d/cactoide.git
synced 2026-03-22 14:15:28 +00:00
Compare commits
8 Commits
fix/databa
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d18afc43da | ||
|
|
662476f820 | ||
|
|
7ebf95bb16 | ||
|
|
0491ec4c4b | ||
|
|
fcdef065d7 | ||
|
|
a1fa879f36 | ||
|
|
b723aac180 | ||
|
|
277ad3ff14 |
@@ -10,4 +10,14 @@ APP_VERSION=latest
|
|||||||
PORT=5173
|
PORT=5173
|
||||||
HOSTNAME=0.0.0.0
|
HOSTNAME=0.0.0.0
|
||||||
|
|
||||||
|
# Logger configuration
|
||||||
|
LOG_PRETTY=true
|
||||||
|
LOG_LEVEL="trace"
|
||||||
|
|
||||||
|
# If you don't want to use the default home page you can turn off
|
||||||
|
# in this case the /discovery page remain the home of your site
|
||||||
PUBLIC_LANDING_INFO=true
|
PUBLIC_LANDING_INFO=true
|
||||||
|
|
||||||
|
# Federation config
|
||||||
|
FEDERATION_INSTANCE=false
|
||||||
|
|
||||||
|
|||||||
4
.github/workflows/build-and-push.yml
vendored
4
.github/workflows/build-and-push.yml
vendored
@@ -1,5 +1,7 @@
|
|||||||
# .github/workflows/docker-build-and-push.yml
|
|
||||||
name: build & push the images
|
name: build & push the images
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
pull-requests: write
|
||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
|
|||||||
3
.github/workflows/test.yml
vendored
3
.github/workflows/test.yml
vendored
@@ -1,4 +1,7 @@
|
|||||||
name: test & build
|
name: test & build
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
pull-requests: write
|
||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
|
|||||||
17
README.md
17
README.md
@@ -7,7 +7,7 @@ Like the cactus, great events bloom under any condition when managed with care.
|
|||||||
<p align="center">
|
<p align="center">
|
||||||
<a href="https://cactoide.org/" target="blank">
|
<a href="https://cactoide.org/" target="blank">
|
||||||
<picture>
|
<picture>
|
||||||
<img alt="actoide" src="https://github.com/user-attachments/assets/30b87181-1e3b-49d0-869e-bef6dcf7f777" width="840">
|
<img alt="actoide" src="https://github.com/user-attachments/assets/a7f7a732-1279-486e-808c-1d2348c68780" width="840">
|
||||||
</picture>
|
</picture>
|
||||||
</a>
|
</a>
|
||||||
</p>
|
</p>
|
||||||
@@ -59,6 +59,17 @@ make db-only
|
|||||||
npm run dev -- --open
|
npm run dev -- --open
|
||||||
```
|
```
|
||||||
|
|
||||||
|
#### Build the image in local
|
||||||
|
|
||||||
|
```
|
||||||
|
docker build \
|
||||||
|
--build-arg LOG_PRETTY=${LOG_PRETTY:-true} \
|
||||||
|
--build-arg LOG_LEVEL=${LOG_LEVEL:-trace} \
|
||||||
|
--build-arg PUBLIC_LANDING_INFO=${PUBLIC_LANDING_INFO:-true} \
|
||||||
|
--build-arg FEDERATION_INSTANCE=${FEDERATION_INSTANCE:-true} \
|
||||||
|
-t cactoide-example .
|
||||||
|
```
|
||||||
|
|
||||||
Your app will be available at `http://localhost:5173`. You can use the Makefile commands to run the application or the database, eg.: `make db-only`.
|
Your app will be available at `http://localhost:5173`. You can use the Makefile commands to run the application or the database, eg.: `make db-only`.
|
||||||
|
|
||||||
Use the `database/seed.sql` if you want to populate your database with dummy data.
|
Use the `database/seed.sql` if you want to populate your database with dummy data.
|
||||||
@@ -103,12 +114,12 @@ Your instance will automatically expose:
|
|||||||
To add your instance to the global federation list (so other instances can discover your events):
|
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)
|
1. Fork the [Cactoide repository](https://github.com/polaroi8d/cactoide)
|
||||||
2. Add your instance URL to the `instances` array in [`federation.config.js`](https://github.com/polaroi8d/cactoide/blob/main/federation.config.js):
|
2. Add your instance URL to the `instances` array in `federation.config.js`:
|
||||||
3. Open a pull request to the main repository
|
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.
|
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`](https://github.com/polaroi8d/cactoide/blob/main/federation.config.js) file.
|
You can view all registered federated instances in the main repository: `federation.config.js` file.
|
||||||
|
|
||||||
### Options
|
### Options
|
||||||
|
|
||||||
|
|||||||
@@ -37,6 +37,10 @@ services:
|
|||||||
DATABASE_URL: ${DATABASE_URL:-postgres://cactoide:cactoide_password@postgres:5432/cactoide_database}
|
DATABASE_URL: ${DATABASE_URL:-postgres://cactoide:cactoide_password@postgres:5432/cactoide_database}
|
||||||
PORT: 3000
|
PORT: 3000
|
||||||
HOSTNAME: ${HOSTNAME:-0.0.0.0}
|
HOSTNAME: ${HOSTNAME:-0.0.0.0}
|
||||||
|
LOG_PRETTY: ${LOG_PRETTY:-true}
|
||||||
|
LOG_LEVEL: ${LOG_LEVEL:-trace}
|
||||||
|
PUBLIC_LANDING_INFO: ${PUBLIC_LANDING_INFO:-true}
|
||||||
|
FEDERATION_INSTANCE: ${FEDERATION_INSTANCE:-true}
|
||||||
depends_on:
|
depends_on:
|
||||||
postgres:
|
postgres:
|
||||||
condition: service_healthy
|
condition: service_healthy
|
||||||
|
|||||||
19
src/lib/components/FeatureCard.svelte
Normal file
19
src/lib/components/FeatureCard.svelte
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import { t } from '$lib/i18n/i18n.js';
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
emoji: string;
|
||||||
|
titleKey: string;
|
||||||
|
descriptionKey: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
let { emoji, titleKey, descriptionKey }: Props = $props();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div class="rounded-sm border p-4 text-center">
|
||||||
|
<div class="mx-auto mb-2 flex h-20 w-20 items-center justify-center rounded-full">
|
||||||
|
<span class="text-4xl">{emoji}</span>
|
||||||
|
</div>
|
||||||
|
<h3 class="mb-4 text-xl font-bold text-white">{t(titleKey)}</h3>
|
||||||
|
<p class="">{t(descriptionKey)}</p>
|
||||||
|
</div>
|
||||||
@@ -1,9 +1,9 @@
|
|||||||
const config = {
|
const config = {
|
||||||
name: 'Cactoide Genesis',
|
name: 'Cactoide Genesis',
|
||||||
instances: [
|
instances: [
|
||||||
{
|
// {
|
||||||
url: 'cactoide.org'
|
// url: 'cactoide.org'
|
||||||
}
|
// }
|
||||||
// {
|
// {
|
||||||
// url: 'YOUR_INSTANCE_URL'
|
// url: 'YOUR_INSTANCE_URL'
|
||||||
// }
|
// }
|
||||||
@@ -1,76 +1,18 @@
|
|||||||
import { readFileSync } from 'fs';
|
|
||||||
import { join } from 'path';
|
|
||||||
import { logger } from '$lib/logger';
|
import { logger } from '$lib/logger';
|
||||||
import type { Event } from '$lib/types';
|
import type { Event } from '$lib/types';
|
||||||
|
|
||||||
import config from '../../federation.config.js';
|
import config from '$lib/config/federation.config.js';
|
||||||
|
|
||||||
console.log(config.instances);
|
|
||||||
|
|
||||||
interface FederationConfig {
|
|
||||||
name: string;
|
|
||||||
instances: Array<{ url: string }>;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface FederationEventsResponse {
|
interface FederationEventsResponse {
|
||||||
events: Array<Event & { federation?: boolean }>;
|
events: Array<Event & { federation?: boolean }>;
|
||||||
count?: number;
|
count?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Reads the federation config file
|
|
||||||
*/
|
|
||||||
async function readFederationConfig(): Promise<FederationConfig | null> {
|
|
||||||
try {
|
|
||||||
const configPath = join(process.cwd(), 'federation.config.js');
|
|
||||||
|
|
||||||
// Use dynamic import to load the config file as a module
|
|
||||||
// This is safer than eval and works with ES modules
|
|
||||||
const configModule = await import(configPath + '?t=' + Date.now());
|
|
||||||
const config = (configModule.default || configModule.config) as FederationConfig;
|
|
||||||
|
|
||||||
if (config && config.instances && Array.isArray(config.instances)) {
|
|
||||||
return config;
|
|
||||||
}
|
|
||||||
|
|
||||||
logger.warn('Invalid federation config structure');
|
|
||||||
return null;
|
|
||||||
} catch (error) {
|
|
||||||
// If dynamic import fails, try reading as text and parsing
|
|
||||||
try {
|
|
||||||
const configPath = join(process.cwd(), 'federation.config.js');
|
|
||||||
const configContent = readFileSync(configPath, 'utf-8');
|
|
||||||
|
|
||||||
// Try to extract JSON-like structure
|
|
||||||
const configMatch = configContent.match(/instances:\s*\[([\s\S]*?)\]/);
|
|
||||||
if (configMatch) {
|
|
||||||
// Simple parsing - extract URLs
|
|
||||||
const urlMatches = configContent.matchAll(/url:\s*['"]([^'"]+)['"]/g);
|
|
||||||
const instances = Array.from(urlMatches, (match) => ({ url: match[1] }));
|
|
||||||
|
|
||||||
if (instances.length > 0) {
|
|
||||||
return {
|
|
||||||
name: 'Federated Instances',
|
|
||||||
instances
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (fallbackError) {
|
|
||||||
logger.error({ error: fallbackError }, 'Error parsing federation.config.js as fallback');
|
|
||||||
}
|
|
||||||
|
|
||||||
logger.error({ error }, 'Error reading federation.config.js');
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fetches events from a single federated instance
|
* Fetches events from a single federated instance
|
||||||
*/
|
*/
|
||||||
async function fetchEventsFromInstance(instanceUrl: string): Promise<Event[]> {
|
async function fetchEventsFromInstance(instanceUrl: string): Promise<Event[]> {
|
||||||
try {
|
try {
|
||||||
// Ensure URL has protocol and append /api/federation/events
|
|
||||||
|
|
||||||
const apiUrl = `http://${instanceUrl}/api/federation/events`;
|
const apiUrl = `http://${instanceUrl}/api/federation/events`;
|
||||||
|
|
||||||
logger.debug({ apiUrl }, 'Fetching events from federated instance');
|
logger.debug({ apiUrl }, 'Fetching events from federated instance');
|
||||||
@@ -120,18 +62,11 @@ async function fetchEventsFromInstance(instanceUrl: string): Promise<Event[]> {
|
|||||||
* Fetches events from all configured federated instances
|
* Fetches events from all configured federated instances
|
||||||
*/
|
*/
|
||||||
export async function fetchAllFederatedEvents(): Promise<Event[]> {
|
export async function fetchAllFederatedEvents(): Promise<Event[]> {
|
||||||
const config = await readFederationConfig();
|
|
||||||
|
|
||||||
if (!config || !config.instances || config.instances.length === 0) {
|
if (!config || !config.instances || config.instances.length === 0) {
|
||||||
logger.debug('No federation config or instances found');
|
logger.debug('No federation config or instances found');
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.info(
|
|
||||||
{ instanceCount: config.instances.length },
|
|
||||||
'Fetching events from federated instances'
|
|
||||||
);
|
|
||||||
|
|
||||||
// Fetch from all instances in parallel
|
// Fetch from all instances in parallel
|
||||||
const fetchPromises = config.instances.map((instance) => fetchEventsFromInstance(instance.url));
|
const fetchPromises = config.instances.map((instance) => fetchEventsFromInstance(instance.url));
|
||||||
|
|
||||||
|
|||||||
@@ -107,7 +107,10 @@
|
|||||||
"description": "Create and manage event RSVPs. No registration required, instant sharing.",
|
"description": "Create and manage event RSVPs. No registration required, instant sharing.",
|
||||||
"mainTitle": "Cactoide(ea)",
|
"mainTitle": "Cactoide(ea)",
|
||||||
"subtitle": "The Ultimate RSVP Platform",
|
"subtitle": "The Ultimate RSVP Platform",
|
||||||
"tagline": "Create, share, and manage events with zero friction.",
|
"tagline": "A federated 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.",
|
||||||
|
"openSourceTitle": "Open Source & Self-Hostable",
|
||||||
|
"openSourceDescription": "Cactoide is open source and easily self-hostable. View the source code, contribute, or host your own instance.",
|
||||||
|
"viewOnGitHub": "View on GitHub",
|
||||||
"whyCactoideTitle": "Why Cactoide(ae)?🌵",
|
"whyCactoideTitle": "Why Cactoide(ae)?🌵",
|
||||||
"whyCactoideDescription": "Like the cactus, great events bloom under any condition when managed with care. Cactoide(ae) helps you streamline RSVPs, simplify coordination, and keep every detail efficient—so your gatherings are resilient, vibrant, and unforgettable.",
|
"whyCactoideDescription": "Like the cactus, great events bloom under any condition when managed with care. Cactoide(ae) helps you streamline RSVPs, simplify coordination, and keep every detail efficient—so your gatherings are resilient, vibrant, and unforgettable.",
|
||||||
"createEventNow": "Create Event Now",
|
"createEventNow": "Create Event Now",
|
||||||
@@ -127,6 +130,10 @@
|
|||||||
"smartLimitsDescription": "Choose between unlimited RSVPs or set a limited capacity. Perfect for any event size.",
|
"smartLimitsDescription": "Choose between unlimited RSVPs or set a limited capacity. Perfect for any event size.",
|
||||||
"effortlessSimplicityTitle": "Effortless Simplicity",
|
"effortlessSimplicityTitle": "Effortless Simplicity",
|
||||||
"effortlessSimplicityDescription": "Designed to be instantly clear and easy. No learning curve — just open, create, and go.",
|
"effortlessSimplicityDescription": "Designed to be instantly clear and easy. No learning curve — just open, create, and go.",
|
||||||
|
"inviteLinksTitle": "Invite Links",
|
||||||
|
"inviteLinksDescription": "Create invite-only events with special links. Only people with the specific invite link can RSVP, giving you full control over who can attend.",
|
||||||
|
"federationTitle": "Federation",
|
||||||
|
"federationDescription": "Connect with other Cactoide instances to discover events across the network. Share your public events and create a decentralized event discovery network.",
|
||||||
"howItWorksTitle": "How It Works",
|
"howItWorksTitle": "How It Works",
|
||||||
"step1Title": "Create Event",
|
"step1Title": "Create Event",
|
||||||
"step1Description": "Fill out a simple form with event details. Choose between limited or unlimited capacity.",
|
"step1Description": "Fill out a simple form with event details. Choose between limited or unlimited capacity.",
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { goto } from '$app/navigation';
|
import { goto } from '$app/navigation';
|
||||||
import { t } from '$lib/i18n/i18n.js';
|
import { t } from '$lib/i18n/i18n.js';
|
||||||
|
import FeatureCard from '$lib/components/FeatureCard.svelte';
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<svelte:head>
|
<svelte:head>
|
||||||
@@ -22,6 +23,34 @@
|
|||||||
{t('home.tagline')}
|
{t('home.tagline')}
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
<!-- Open Source Section -->
|
||||||
|
<div class="mt-8 flex items-center justify-center gap-3">
|
||||||
|
<a
|
||||||
|
href="https://github.com/polaroi8d/cactoide"
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
class="group flex items-center gap-2 rounded-sm border-2 border-violet-500/50 px-6 py-3 text-sm font-medium transition-all duration-300 hover:scale-105 hover:border-violet-500 hover:bg-violet-500/10 md:text-base"
|
||||||
|
aria-label={t('home.viewOnGitHub')}
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
class="h-5 w-5 transition-transform group-hover:scale-110"
|
||||||
|
fill="currentColor"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
aria-hidden="true"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
fill-rule="evenodd"
|
||||||
|
d="M12 2C6.477 2 2 6.484 2 12.017c0 4.425 2.865 8.18 6.839 9.504.5.092.682-.217.682-.483 0-.237-.008-.868-.013-1.703-2.782.605-3.369-1.343-3.369-1.343-.454-1.158-1.11-1.466-1.11-1.466-.908-.62.069-.608.069-.608 1.003.07 1.531 1.032 1.531 1.032.892 1.53 2.341 1.088 2.91.832.092-.647.35-1.088.636-1.338-2.22-.253-4.555-1.113-4.555-4.951 0-1.093.39-1.988 1.029-2.688-.103-.253-.446-1.272.098-2.65 0 0 .84-.27 2.75 1.026A9.564 9.564 0 0112 6.844c.85.004 1.705.115 2.504.337 1.909-1.296 2.747-1.027 2.747-1.027.546 1.379.202 2.398.1 2.651.64.7 1.028 1.595 1.028 2.688 0 3.848-2.339 4.695-4.566 4.943.359.309.678.92.678 1.855 0 1.338-.012 2.419-.012 2.747 0 .268.18.58.688.482A10.019 10.019 0 0022 12.017C22 6.484 17.522 2 12 2z"
|
||||||
|
clip-rule="evenodd"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
<span>{t('home.viewOnGitHub')}</span>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
<p class="mt-4 text-sm text-slate-400 md:text-base">
|
||||||
|
{t('home.openSourceDescription')}
|
||||||
|
</p>
|
||||||
|
|
||||||
<h2 class="mt-6 pt-8 text-xl md:text-2xl">
|
<h2 class="mt-6 pt-8 text-xl md:text-2xl">
|
||||||
{t('home.whyCactoideTitle')}<span class="text-violet-400"
|
{t('home.whyCactoideTitle')}<span class="text-violet-400"
|
||||||
><a href="https://en.wikipedia.org/wiki/Cactoideae" target="_blank">*</a></span
|
><a href="https://en.wikipedia.org/wiki/Cactoideae" target="_blank">*</a></span
|
||||||
@@ -65,72 +94,54 @@
|
|||||||
<h2 class=" mb-16 text-center text-4xl font-bold">
|
<h2 class=" mb-16 text-center text-4xl font-bold">
|
||||||
{t('home.whyCactoideFeatureTitle')}
|
{t('home.whyCactoideFeatureTitle')}
|
||||||
</h2>
|
</h2>
|
||||||
<div class="grid gap-8 md:grid-cols-2 lg:grid-cols-3">
|
<div class="grid gap-8 md:grid-cols-2 lg:grid-cols-4">
|
||||||
<!-- Feature 1 -->
|
<FeatureCard
|
||||||
<div class="rounded-sm border p-8 text-center">
|
emoji="🎯"
|
||||||
<div class="mx-auto mb-6 flex h-20 w-20 items-center justify-center rounded-full">
|
titleKey="home.instantEventCreationTitle"
|
||||||
<span class="text-4xl">🎯</span>
|
descriptionKey="home.instantEventCreationDescription"
|
||||||
</div>
|
/>
|
||||||
<h3 class="mb-4 text-xl font-bold text-white">{t('home.instantEventCreationTitle')}</h3>
|
|
||||||
<p class="">
|
|
||||||
{t('home.instantEventCreationDescription')}
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Feature 2 -->
|
<FeatureCard
|
||||||
<div class="rounded-sm border p-8 text-center">
|
emoji="🔗"
|
||||||
<div class="mx-auto mb-6 flex h-20 w-20 items-center justify-center rounded-full">
|
titleKey="home.oneClickSharingTitle"
|
||||||
<span class="text-4xl">🔗</span>
|
descriptionKey="home.oneClickSharingDescription"
|
||||||
</div>
|
/>
|
||||||
<h3 class="mb-4 text-xl font-bold text-white">{t('home.oneClickSharingTitle')}</h3>
|
|
||||||
<p class="">
|
|
||||||
{t('home.oneClickSharingDescription')}
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Feature 2 -->
|
<FeatureCard
|
||||||
<div class="rounded-sm border p-8 text-center">
|
emoji="🔍"
|
||||||
<div class="mx-auto mb-6 flex h-20 w-20 items-center justify-center rounded-full">
|
titleKey="home.allInOneClarityTitle"
|
||||||
<span class="text-4xl">🔍</span>
|
descriptionKey="home.allInOneClarityDescription"
|
||||||
</div>
|
/>
|
||||||
<h3 class="mb-4 text-xl font-bold text-white">{t('home.allInOneClarityTitle')}</h3>
|
|
||||||
<p class="">
|
|
||||||
{t('home.allInOneClarityDescription')}
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Feature 4 -->
|
<FeatureCard
|
||||||
<div class="rounded-sm border p-8 text-center">
|
emoji="👤"
|
||||||
<div class="mx-auto mb-6 flex h-20 w-20 items-center justify-center rounded-full">
|
titleKey="home.noHassleNoSignUpsTitle"
|
||||||
<span class="text-4xl">👤</span>
|
descriptionKey="home.noHassleNoSignUpsDescription"
|
||||||
</div>
|
/>
|
||||||
<h3 class="mb-4 text-xl font-bold text-white">{t('home.noHassleNoSignUpsTitle')}</h3>
|
|
||||||
<p class="">
|
|
||||||
{t('home.noHassleNoSignUpsDescription')}
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Feature 5 -->
|
<FeatureCard
|
||||||
<div class="rounded-sm border p-8 text-center">
|
emoji="🛡️"
|
||||||
<div class="mx-auto mb-6 flex h-20 w-20 items-center justify-center rounded-full">
|
titleKey="home.smartLimitsTitle"
|
||||||
<span class="text-4xl">🛡️</span>
|
descriptionKey="home.smartLimitsDescription"
|
||||||
</div>
|
/>
|
||||||
<h3 class="mb-4 text-xl font-bold text-white">{t('home.smartLimitsTitle')}</h3>
|
|
||||||
<p class="">
|
|
||||||
{t('home.smartLimitsDescription')}
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Feature 5 -->
|
<FeatureCard
|
||||||
<div class="rounded-sm border p-8 text-center">
|
emoji="✨"
|
||||||
<div class="mx-auto mb-6 flex h-20 w-20 items-center justify-center rounded-full">
|
titleKey="home.effortlessSimplicityTitle"
|
||||||
<span class="text-4xl">✨</span>
|
descriptionKey="home.effortlessSimplicityDescription"
|
||||||
</div>
|
/>
|
||||||
<h3 class="mb-4 text-xl font-bold text-white">{t('home.effortlessSimplicityTitle')}</h3>
|
|
||||||
<p class="">
|
<FeatureCard
|
||||||
{t('home.effortlessSimplicityDescription')}
|
emoji="🎫"
|
||||||
</p>
|
titleKey="home.inviteLinksTitle"
|
||||||
</div>
|
descriptionKey="home.inviteLinksDescription"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<FeatureCard
|
||||||
|
emoji="🌐"
|
||||||
|
titleKey="home.federationTitle"
|
||||||
|
descriptionKey="home.federationDescription"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import { database } from '$lib/database/db';
|
|||||||
import { events } from '$lib/database/schema';
|
import { events } from '$lib/database/schema';
|
||||||
import { eq, count } from 'drizzle-orm';
|
import { eq, count } from 'drizzle-orm';
|
||||||
import { logger } from '$lib/logger';
|
import { logger } from '$lib/logger';
|
||||||
import federationConfig from '../../../../../federation.config.js';
|
import federationConfig from '$lib/config/federation.config.js';
|
||||||
|
|
||||||
import { FEDERATION_INSTANCE } from '$env/static/private';
|
import { FEDERATION_INSTANCE } from '$env/static/private';
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import type { PageServerLoad } from './$types';
|
import type { PageServerLoad } from './$types';
|
||||||
import { logger } from '$lib/logger';
|
import { logger } from '$lib/logger';
|
||||||
import federationConfig from '../../../federation.config.js';
|
import federationConfig from '$lib/config/federation.config.js';
|
||||||
|
|
||||||
interface InstanceInfo {
|
interface InstanceInfo {
|
||||||
name: string;
|
name: string;
|
||||||
|
|||||||
@@ -130,10 +130,7 @@
|
|||||||
|
|
||||||
<p class="py-8 text-center text-slate-400">
|
<p class="py-8 text-center text-slate-400">
|
||||||
{t('instance.description')}
|
{t('instance.description')}
|
||||||
<a
|
{t('instance.configFile')}
|
||||||
href="https://github.com/cactoide/cactoide/blob/main/federation.config.js"
|
|
||||||
class="text-violet-300/80">{t('instance.configFile')}</a
|
|
||||||
>
|
|
||||||
{t('instance.file')}
|
{t('instance.file')}
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user