Replace all marketing placeholder content with real MYeasyCMS content
Some checks failed
Workflow / ʦ TypeScript (push) Failing after 6m12s
Workflow / ⚫️ Test (push) Has been skipped

- Logo: Replace generic Makerkit SVG with MYeasyCMS branded logo (grid icon + styled text)
- Blog: Replace 3 SaaS placeholder posts with 5 real articles (Vereinsverwaltung, SEPA, Website, DSGVO, Mitglieder-Tipps)
- Changelog: Replace 6 generic entries with real feature announcements (Verbandsverwaltung, Fischerei, Dateien, Kurse, Einladungen, i18n)
- Documentation: Rewrite all 20 docs from Makerkit references to MYeasyCMS content
- FAQ: Replace 6 generic SaaS questions with 10 real MYeasyCMS questions
- Navigation: Replace Changelog link with Contact in main nav
- Footer: Reorganize into Product/Company/Legal sections
- Translations: Update all EN marketing strings to match real Com.BISS content
This commit is contained in:
Zaid Marzguioui
2026-04-01 21:09:06 +02:00
parent bbb33aa63d
commit a5bbf42901
49 changed files with 1320 additions and 4735 deletions

View File

@@ -2,37 +2,44 @@ import { Footer } from '@kit/ui/marketing';
import { Trans } from '@kit/ui/trans'; import { Trans } from '@kit/ui/trans';
import { AppLogo } from '~/components/app-logo'; import { AppLogo } from '~/components/app-logo';
import appConfig from '~/config/app.config';
export function SiteFooter() { export function SiteFooter() {
return ( return (
<Footer <Footer
logo={<AppLogo className="w-[85px] md:w-[95px]" />} logo={<AppLogo className="w-[120px] md:w-[140px]" />}
description={<Trans i18nKey="marketing.footerDescription" />} description={<Trans i18nKey="marketing.footerDescription" />}
copyright={ copyright={
<Trans <Trans
i18nKey="marketing.copyright" i18nKey="marketing.copyright"
values={{ values={{
product: appConfig.name,
year: new Date().getFullYear(), year: new Date().getFullYear(),
}} }}
/> />
} }
sections={[ sections={[
{
heading: <Trans i18nKey="marketing.about" />,
links: [
{ href: '/blog', label: <Trans i18nKey="marketing.blog" /> },
{ href: '/contact', label: <Trans i18nKey="marketing.contact" /> },
],
},
{ {
heading: <Trans i18nKey="marketing.product" />, heading: <Trans i18nKey="marketing.product" />,
links: [ links: [
{
href: '/pricing',
label: <Trans i18nKey="marketing.pricing" />,
},
{ {
href: '/docs', href: '/docs',
label: <Trans i18nKey="marketing.documentation" />, label: <Trans i18nKey="marketing.documentation" />,
}, },
{
href: '/changelog',
label: <Trans i18nKey="marketing.changelog" />,
},
],
},
{
heading: <Trans i18nKey="marketing.about" />,
links: [
{ href: '/blog', label: <Trans i18nKey="marketing.blog" /> },
{ href: '/faq', label: <Trans i18nKey="marketing.faq" /> },
{ href: '/contact', label: <Trans i18nKey="marketing.contact" /> },
], ],
}, },
{ {

View File

@@ -18,10 +18,6 @@ const links = {
label: 'marketing.blog', label: 'marketing.blog',
path: '/blog', path: '/blog',
}, },
Changelog: {
label: 'marketing.changelog',
path: '/changelog',
},
Docs: { Docs: {
label: 'marketing.documentation', label: 'marketing.documentation',
path: '/docs', path: '/docs',
@@ -34,6 +30,10 @@ const links = {
label: 'marketing.faq', label: 'marketing.faq',
path: '/faq', path: '/faq',
}, },
Contact: {
label: 'marketing.contact',
path: '/contact',
},
}; };
export function SiteNavigation() { export function SiteNavigation() {

View File

@@ -19,33 +19,56 @@ export const generateMetadata = async () => {
async function FAQPage() { async function FAQPage() {
const t = await getTranslations('marketing'); const t = await getTranslations('marketing');
// replace this content with translations
const faqItems = [ const faqItems = [
{ {
// or: t('faq.question1') question: 'Was ist MYeasyCMS?',
question: `Do you offer a free trial?`, answer:
// or: t('faq.answer1') 'MYeasyCMS ist eine webbasierte Vereins- und Verbandsverwaltung. Sie verwalten Mitglieder, Beiträge, Kurse, Veranstaltungen, Finanzen und mehr — alles über den Browser, ohne Software-Installation.',
answer: `Yes, we offer a 14-day free trial. You can cancel at any time during the trial period and you won't be charged.`,
}, },
{ {
question: `Can I cancel my subscription?`, question: 'Für welche Vereine ist MYeasyCMS geeignet?',
answer: `You can cancel your subscription at any time. You can do this from your account settings.`, answer:
'MYeasyCMS eignet sich für alle Arten von Vereinen: Sportvereine, Fischereivereine, Kulturvereine, Bildungseinrichtungen, Verbände und kommunale Organisationen. Über 90 Vereine in Bayern arbeiten bereits mit der Plattform.',
}, },
{ {
question: `Where can I find my invoices?`, question: 'Gibt es einen kostenlosen Testzugang?',
answer: `You can find your invoices in your account settings.`, answer:
'Ja, wir richten Ihnen einen kostenlosen Testzugang ein und führen Sie persönlich durch die Plattform. Rufen Sie uns an unter 09451 9499-09 oder nutzen Sie das Kontaktformular.',
}, },
{ {
question: `What payment methods do you accept?`, question: 'Muss ich Software installieren?',
answer: `We accept all major credit cards and PayPal.`, answer:
'Nein. MYeasyCMS ist vollständig webbasiert und läuft in jedem modernen Browser (Chrome, Firefox, Safari, Edge). Es gibt keinen Download, keine Installation und keine manuellen Updates.',
}, },
{ {
question: `Can I upgrade or downgrade my plan?`, question: 'Wie viele Benutzer kann ich anlegen?',
answer: `Yes, you can upgrade or downgrade your plan at any time. You can do this from your account settings.`, answer:
'Es gibt keine Begrenzung der Benutzeranzahl. Alle Tarife enthalten unbegrenzte Zugänge für Vorstandsmitglieder, Kassenwarte, Kursleiter und andere Mitarbeiter.',
}, },
{ {
question: `Do you offer discounts for non-profits?`, question: 'Ist MYeasyCMS DSGVO-konform?',
answer: `Yes, we offer a 50% discount for non-profits. Please contact us to learn more.`, answer:
'Ja. Alle Daten liegen auf Servern in Deutschland. Rollenbasierte Zugriffsrechte, verschlüsselte Datenübertragung und Funktionen für Auskunfts- und Löschungsanfragen sind integriert. Ein Auftragsverarbeitungsvertrag (AVV) wird bereitgestellt.',
},
{
question: 'Kann ich bestehende Mitgliederlisten importieren?',
answer:
'Ja. Der Import-Assistent unterstützt Excel- und CSV-Dateien. Sie laden Ihre bestehende Mitgliederliste hoch, ordnen die Spalten zu und importieren die Daten. Bei Bedarf unterstützt Sie das Com.BISS-Team persönlich.',
},
{
question: 'Wie funktioniert der SEPA-Beitragseinzug?',
answer:
'MYeasyCMS erzeugt SEPA-XML-Dateien (pain.008) aus den hinterlegten Mandaten und offenen Beiträgen. Sie laden die Datei herunter und reichen sie im Online-Banking Ihrer Bank ein. Mandatsverwaltung und IBAN-Prüfung sind integriert.',
},
{
question: 'Wie erreiche ich den Support?',
answer:
'Direkt und persönlich — kein anonymes Ticketsystem. Telefon: 09451 9499-09, E-Mail: info@combiss.de. Sie sprechen mit den Menschen, die Ihre Software entwickeln.',
},
{
question: 'Was kostet MYeasyCMS?',
answer:
'Die Preise richten sich nach der Vereinsgröße (Mitgliederzahl). Alle Module und Funktionen sind in jedem Tarif enthalten. Für ein individuelles Angebot kontaktieren Sie uns — wir beraten Sie gerne.',
}, },
]; ];

View File

@@ -3,14 +3,12 @@ import Link from 'next/link';
import { cn } from '@kit/ui/utils'; import { cn } from '@kit/ui/utils';
/** /**
* App Logo Image - modify this with your own logo * App Logo — MYeasyCMS by Com.BISS GmbH
* @param className - The class name to apply to the logo * SVG text-based logo for the MYeasyCMS platform
* @param width - The width of the logo
* @returns
*/ */
export function LogoImage({ export function LogoImage({
className, className,
width = 105, width = 160,
}: { }: {
className?: string; className?: string;
width?: number; width?: number;
@@ -18,16 +16,84 @@ export function LogoImage({
return ( return (
<svg <svg
width={width} width={width}
className={cn(`w-20 lg:w-[95px]`, className)} className={cn('w-[120px] lg:w-[160px]', className)}
viewBox="0 0 733 140" viewBox="0 0 320 48"
fill="none" fill="none"
xmlns="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg"
aria-label="MYeasyCMS"
> >
<path {/* Icon — stylized grid/module squares */}
className={'fill-primary dark:fill-white'} <rect
d="M119.081 138V73.209C119.081 67.551 117.08 62.79 113.078 58.926C109.214 55.062 104.453 53.13 98.7951 53.13C93.2751 53.13 88.4451 55.062 84.3051 58.926C80.3031 62.652 78.3021 67.344 78.3021 73.002V138H59.4651V73.002C59.4651 67.206 57.5331 62.514 53.6691 58.926C49.5291 55.062 44.6301 53.13 38.9721 53.13C33.4521 53.13 28.7601 55.062 24.8961 58.926C20.7561 63.066 18.6861 67.965 18.6861 73.623V138H0.0560548V36.984H18.6861V44.643C21.0321 41.745 24.0681 39.33 27.7941 37.398C31.6581 35.466 35.3841 34.5 38.9721 34.5C45.0441 34.5 50.5641 35.742 55.5321 38.226C60.6381 40.572 65.0541 43.884 68.7801 48.162C72.5061 43.884 76.9221 40.572 82.0281 38.226C87.1341 35.742 92.7231 34.5 98.7951 34.5C104.177 34.5 109.214 35.466 113.906 37.398C118.598 39.33 122.738 42.09 126.326 45.678C129.914 49.266 132.674 53.475 134.606 58.305C136.676 62.997 137.711 67.965 137.711 73.209V138H119.081ZM242.173 138V122.268C237.757 127.374 232.651 131.445 226.855 134.481C221.059 137.517 214.918 139.035 208.432 139.035C201.256 139.035 194.494 137.724 188.146 135.102C181.936 132.48 176.416 128.754 171.586 123.924C166.756 119.232 162.961 113.712 160.201 107.364C157.579 100.878 156.268 94.116 156.268 87.078C156.268 80.04 157.579 73.347 160.201 66.999C162.961 60.513 166.756 54.855 171.586 50.025C176.416 45.195 181.936 41.469 188.146 38.847C194.494 36.225 201.256 34.914 208.432 34.914C215.056 34.914 221.266 36.294 227.062 39.054C232.996 41.814 238.033 45.678 242.173 50.646V36.984H260.803V138H242.173ZM208.432 53.337C203.878 53.337 199.462 54.234 195.184 56.028C191.044 57.684 187.456 60.03 184.42 63.066C181.384 66.102 178.969 69.759 177.175 74.037C175.519 78.177 174.691 82.524 174.691 87.078C174.691 91.632 175.519 95.979 177.175 100.119C178.969 104.259 181.384 107.847 184.42 110.883C187.456 113.919 191.044 116.334 195.184 118.128C199.462 119.784 203.878 120.612 208.432 120.612C212.986 120.612 217.333 119.784 221.473 118.128C225.613 116.334 229.201 113.919 232.237 110.883C235.273 107.847 237.619 104.259 239.275 100.119C241.069 95.979 241.966 91.632 241.966 87.078C241.966 82.524 241.069 78.177 239.275 74.037C237.619 69.759 235.273 66.102 232.237 63.066C229.201 60.03 225.613 57.684 221.473 56.028C217.333 54.234 212.986 53.337 208.432 53.337ZM331.127 138L299.663 99.705V138H281.447V0.344996H299.663V59.754L327.815 33.258H354.932L305.873 78.798L355.139 138H331.127ZM379.299 94.116C379.299 97.428 380.472 100.878 382.818 104.466C385.302 108.054 388.131 111.09 391.305 113.574C397.101 118.128 403.863 120.405 411.591 120.405C423.873 120.405 433.878 114.471 441.606 102.603L457.338 111.918C451.956 120.612 445.332 127.305 437.466 131.997C429.6 136.689 420.975 139.035 411.591 139.035C404.553 139.035 397.86 137.724 391.512 135.102C385.164 132.342 379.575 128.547 374.745 123.717C369.915 118.887 366.12 113.298 363.36 106.95C360.738 100.602 359.427 93.909 359.427 86.871C359.427 79.833 360.738 73.14 363.36 66.792C366.12 60.306 369.915 54.648 374.745 49.818C379.437 44.988 384.957 41.262 391.305 38.64C397.791 36.018 404.553 34.707 411.591 34.707C418.629 34.707 425.322 36.018 431.67 38.64C438.156 41.262 443.745 44.988 448.437 49.818C458.649 60.306 463.755 72.45 463.755 86.25C463.755 88.734 463.548 91.356 463.134 94.116H379.299ZM411.591 51.681C405.933 51.681 400.62 52.923 395.652 55.407C390.684 57.891 386.682 61.203 383.646 65.343C380.748 69.345 379.299 73.623 379.299 78.177H443.883C443.883 73.623 442.365 69.345 439.329 65.343C436.431 61.203 432.498 57.891 427.53 55.407C422.562 52.923 417.249 51.681 411.591 51.681ZM528.543 54.372C525.231 52.854 522.264 52.095 519.642 52.095C514.122 52.095 509.568 54.027 505.98 57.891C502.116 62.031 500.184 66.792 500.184 72.174V138H482.382V72.174C482.382 64.722 484.245 57.891 487.971 51.681C491.835 45.471 497.079 40.641 503.703 37.191C508.671 34.845 513.984 33.672 519.642 33.672C524.196 33.672 528.543 34.5 532.683 36.156C536.823 37.812 541.17 40.503 545.724 44.229L528.543 54.372ZM610.092 138L578.628 99.705V138H560.412V0.344996H578.628V59.754L606.78 33.258H633.897L584.838 78.798L634.104 138H610.092ZM656.049 19.596C653.427 19.596 651.15 18.699 649.218 16.905C647.424 14.973 646.527 12.696 646.527 10.074C646.527 7.45199 647.424 5.24399 649.218 3.44999C651.15 1.51799 653.427 0.551993 656.049 0.551993C658.671 0.551993 660.879 1.51799 662.673 3.44999C664.605 5.24399 665.571 7.45199 665.571 10.074C665.571 12.696 664.605 14.973 662.673 16.905C660.879 18.699 658.671 19.596 656.049 19.596ZM647.562 138V34.5H664.95V138H647.562ZM717.4 53.13V138H699.805V53.13H684.28V34.5H699.805V0.344996H717.4V34.5H732.925V53.13H717.4Z" x="0"
fill="url(#paint0_linear_1666_2)" y="8"
width="14"
height="14"
rx="3"
className="fill-primary"
/> />
<rect
x="17"
y="8"
width="14"
height="14"
rx="3"
className="fill-primary/70"
/>
<rect
x="0"
y="25"
width="14"
height="14"
rx="3"
className="fill-primary/70"
/>
<rect
x="17"
y="25"
width="14"
height="14"
rx="3"
className="fill-primary/40"
/>
{/* "MY" in bold */}
<text
x="42"
y="35"
className="fill-primary dark:fill-white"
fontFamily="system-ui, -apple-system, 'Segoe UI', sans-serif"
fontSize="28"
fontWeight="700"
letterSpacing="-0.5"
>
MY
</text>
{/* "easy" in regular weight */}
<text
x="88"
y="35"
className="fill-secondary-foreground dark:fill-white/80"
fontFamily="system-ui, -apple-system, 'Segoe UI', sans-serif"
fontSize="28"
fontWeight="400"
letterSpacing="-0.5"
>
easy
</text>
{/* "CMS" in medium weight */}
<text
x="160"
y="35"
className="fill-primary dark:fill-white"
fontFamily="system-ui, -apple-system, 'Segoe UI', sans-serif"
fontSize="28"
fontWeight="600"
letterSpacing="-0.5"
>
CMS
</text>
</svg> </svg>
); );
} }
@@ -47,7 +113,7 @@ export function AppLogo({
return ( return (
<Link <Link
aria-label={label ?? 'Home Page'} aria-label={label ?? 'MYeasyCMS — Startseite'}
href={href ?? '/'} href={href ?? '/'}
prefetch={true} prefetch={true}
className="mx-auto md:mx-0" className="mx-auto md:mx-0"

View File

@@ -1,35 +0,0 @@
---
title: "Advanced analytics dashboard"
description: "Get deeper insights into your data with our new analytics dashboard featuring real-time metrics, custom reports, and exportable data visualizations."
categories: []
tags: []
image: ""
publishedAt: 2025-10-08
status: "published"
---
> **Note:** This is mock/placeholder content for demonstration purposes.
We're excited to introduce our new advanced analytics dashboard that gives you deeper insights into your data and usage patterns.
## Real-time Metrics
Monitor your key performance indicators in real-time with live-updating charts and graphs:
- **Active users** - See who's online and what they're working on
- **Response times** - Track system performance metrics
- **Usage patterns** - Understand how your team uses the platform
## Custom Reports
Create custom reports tailored to your specific needs:
- Drag-and-drop report builder
- Save and share reports with your team
- Schedule automated report generation
## Data Export
Export your data in multiple formats including CSV, JSON, and Excel. All exports maintain full data integrity and include comprehensive metadata.
Access the new analytics dashboard from your account settings.

View File

@@ -1,38 +0,0 @@
---
title: "API improvements and rate limiting"
description: "We've upgraded our API with better performance, new endpoints, and smarter rate limiting to help you build more powerful integrations."
categories: []
tags: []
image: ""
publishedAt: 2025-09-15
status: "published"
---
> **Note:** This is mock/placeholder content for demonstration purposes.
Our API has received significant upgrades to provide better performance and more flexibility for developers building integrations.
## New REST Endpoints
We've added 15 new REST endpoints covering:
- Advanced search and filtering
- Bulk operations
- Webhook management
- Team administration
## GraphQL Support
You can now query our API using GraphQL, giving you more control over the data you receive and reducing the number of requests needed.
## Smarter Rate Limiting
We've implemented a new token bucket rate limiting system that's more fair and predictable:
- Burst allowances for occasional spikes
- Per-endpoint rate limits
- Clear rate limit headers in responses
## Improved Documentation
Our API documentation has been completely rewritten with interactive examples, code snippets in multiple languages, and detailed error response information.
Check out the [API documentation](/docs/api) to get started.

View File

@@ -1,39 +0,0 @@
---
title: "Custom workflows and automation"
description: "Build powerful custom workflows with our new automation engine. Create multi-step workflows that respond to events and automate repetitive tasks."
categories: []
tags: []
image: ""
publishedAt: 2025-09-01
status: "published"
---
> **Note:** This is mock/placeholder content for demonstration purposes.
We're launching a powerful new automation engine that lets you create custom workflows without writing code.
## Visual Workflow Builder
Our drag-and-drop workflow builder makes it easy to create complex automation:
- Connect triggers to actions
- Add conditional logic
- Transform data between steps
- Test workflows before deploying
## 100+ Integrations
Connect to popular services including:
- Slack, Discord, and Teams for notifications
- GitHub, GitLab, and Bitbucket for development workflows
- Zapier and Make for extended integration possibilities
- Custom webhooks for any service
## Templates
Get started quickly with pre-built workflow templates:
- Automated project creation
- Issue escalation rules
- Status update notifications
- Daily team summaries
Workflows are available on Pro and Enterprise plans. Visit the [Automation](/automation) section to start building.

View File

@@ -0,0 +1,35 @@
---
title: "Dateiverwaltung und Modul-Verbesserungen"
description: "Neue Dateiverwaltung zum Hochladen und Organisieren von Dokumenten. Erweiterte Moduleinstellungen mit Berechtigungen und Beziehungen."
categories: []
tags: []
image: ""
publishedAt: 2026-01-25
status: "published"
---
Zwei häufig gewünschte Funktionen sind jetzt verfügbar: eine zentrale Dateiverwaltung und erweiterte Einstellungen für individuelle Module.
## Dateiverwaltung
Laden Sie Dokumente, Bilder und andere Dateien direkt in MYeasyCMS hoch. Organisieren Sie Ihre Vereinsdokumente an einem zentralen Ort — vom Satzungsdokument bis zum Protokoll.
- **Hochladen** per Drag-and-Drop oder Dateiauswahl
- **Übersichtliche Tabelle** mit Dateiname, Größe, Datum und Vorschau
- **Löschen** mit Bestätigungsdialog zur Vermeidung versehentlicher Löschungen
## Moduleinstellungen erweitert
Individuelle Module bieten jetzt mehr Konfigurationsmöglichkeiten:
### Berechtigungen
Steuern Sie, wer Datensätze in einem Modul lesen, erstellen, bearbeiten oder löschen darf. Berechtigungen werden pro Benutzerrolle vergeben.
### Beziehungen zwischen Modulen
Verknüpfen Sie Module miteinander — zum Beispiel ein Gewässermodul mit einem Besatzmodul. Beziehungen werden in der Detailansicht angezeigt.
### Moduleinstellungen
Konfigurieren Sie Name, Beschreibung, Icon und Sortierung Ihrer individuellen Module. Module können jetzt auch gelöscht werden, wenn sie nicht mehr benötigt werden.

View File

@@ -0,0 +1,31 @@
---
title: "Einladungssystem und Mitgliederportal"
description: "Neues Einladungssystem für Vereinsmitglieder und erweitertes Mitgliederportal mit Kontoverknüpfung."
categories: []
tags: []
image: ""
publishedAt: 2025-11-01
status: "published"
---
Zwei Verbesserungen, die die Zusammenarbeit zwischen Vorstand und Mitgliedern erleichtern.
## Einladungssystem
Laden Sie neue Benutzer direkt per E-Mail in Ihren Vereins-Account ein. Die Einladungsverwaltung zeigt alle offenen und angenommenen Einladungen mit Status und Datum.
- **Einladungen versenden** — Per E-Mail mit automatischem Registrierungslink
- **Status verfolgen** — Offen, angenommen oder abgelaufen
- **Erneut senden** — Abgelaufene Einladungen mit einem Klick erneuern
## Mitgliederportal: Kontoverknüpfung
Mitglieder können jetzt mehrere Konten mit ihrem Portal-Zugang verknüpfen. Das ist besonders nützlich für:
- Mitglieder, die in mehreren Vereinen aktiv sind
- Familienmitglieder, die einen gemeinsamen Zugang nutzen
- Verbandsfunktionäre mit Zugriff auf mehrere Organisationen
## Verbesserter Portal-Login
Der Login-Prozess im Mitgliederportal wurde überarbeitet und ist jetzt schneller und benutzerfreundlicher.

View File

@@ -0,0 +1,31 @@
---
title: "Neue Fischereiverwaltung"
description: "Umfassende Erweiterung der Fischereiverwaltung: Pachtverträge, Wettbewerbe, Erlaubnisscheine und erweiterte Besatzdokumentation."
categories: []
tags: []
image: ""
publishedAt: 2026-02-15
status: "published"
---
Die Fischereiverwaltung wurde grundlegend erweitert — mit neuen Modulen für alle Bereiche der Vereinsarbeit im Fischereiverein.
## Pachtverträge
Verwalten Sie Pachtverträge für Gewässer direkt in MYeasyCMS: Vertragspartner, Laufzeit, Kosten und Kündigungsfristen. Mit Erinnerungsfunktion vor Vertragsablauf.
## Erlaubnisscheine
Erstellen und verwalten Sie Fischereierlaubnisscheine — Tages-, Wochen- und Jahreskarten. Mit Druckfunktion und Nachverfolgung, wer welchen Schein erhalten hat.
## Wettbewerbe
Planen Sie Angelwettbewerbe: Teilnehmer erfassen, Ergebnisse dokumentieren, Ranglisten erstellen. Vom Königsfischen bis zum Jugendangeln.
## Erweiterte Besatzdokumentation
Dokumentieren Sie Besatzmaßnahmen detaillierter: Fischart, Menge, Herkunft, Kosten und Gewässerabschnitt. Mit Bearbeitungsfunktion für nachträgliche Korrekturen.
## Gewässer bearbeiten
Gewässerstammdaten können jetzt direkt bearbeitet werden — Beschreibung, Fischereiordnung und Zugangshinweise aktualisieren, ohne den Datensatz neu anlegen zu müssen.

View File

@@ -0,0 +1,35 @@
---
title: "Internationalisierung und Übersetzungen"
description: "Alle Module sind jetzt vollständig in Deutsch und Englisch verfügbar. Neue Übersetzungsdateien für alle Funktionsbereiche."
categories: []
tags: []
image: ""
publishedAt: 2025-10-15
status: "published"
---
MYeasyCMS unterstützt ab sofort vollständige Mehrsprachigkeit in allen Modulen.
## Vollständige deutsche und englische Übersetzungen
Alle Funktionsbereiche wurden mit eigenen Übersetzungsdateien versehen:
- Mitgliederverwaltung
- Kursverwaltung
- Veranstaltungen
- Finanzen und Beiträge
- Fischereiverwaltung
- Sitzungsprotokolle
- Verbandsverwaltung
- Newsletter
- Raumbuchungen
- Dokumentenverwaltung
- Site-Builder
## Sprachumschaltung
Benutzer können die Sprache jederzeit in den persönlichen Einstellungen ändern. Die gewählte Sprache wird gespeichert und bei jedem Login automatisch wiederhergestellt.
## Gemeindeutsche Bezeichnungen
Besonderes Augenmerk wurde auf korrekte und verständliche deutsche Bezeichnungen gelegt — kein „denglisch", sondern Begriffe, die ehrenamtliche Vorstände sofort verstehen.

View File

@@ -0,0 +1,31 @@
---
title: "Kurs- und Eventbearbeitung"
description: "Kurse und Veranstaltungen können jetzt direkt bearbeitet und gelöscht werden. Neue Dialoge für Kategorien, Dozenten und Veranstaltungsorte."
categories: []
tags: []
image: ""
publishedAt: 2025-12-10
status: "published"
---
Kurse und Veranstaltungen lassen sich jetzt schneller und flexibler verwalten.
## Kurse bearbeiten und löschen
Kurse können jetzt direkt über die Detailansicht bearbeitet werden — Titel, Beschreibung, Termine und Dozenten ändern, ohne den Kurs neu anlegen zu müssen. Nicht mehr benötigte Kurse können mit einem Klick gelöscht werden.
## Veranstaltungen bearbeiten und löschen
Auch Veranstaltungen bieten jetzt eine Bearbeitungsseite und eine Löschfunktion. Änderungen an Datum, Ort oder Beschreibung sind sofort möglich.
## Schnell-Erstellung
Neue Dialoge ermöglichen die schnelle Erstellung direkt aus der Übersicht:
- **Kurskategorien** — Neue Kategorien ohne Seitenwechsel anlegen
- **Dozenten** — Dozenten mit allen relevanten Daten direkt erfassen
- **Veranstaltungsorte** — Neue Orte mit Adresse und Kapazität hinzufügen
## Verbesserter Newsletter-Versand
Der Newsletter-Versand wurde überarbeitet: Ein neuer Dispatch-Button zeigt den Status des Versands an und verhindert versehentliches Doppelsenden. Newsletter-Kampagnen können nachträglich bearbeitet werden.

View File

@@ -1,27 +0,0 @@
---
title: "Mobile app redesign"
description: "We've refreshed our iOS and Android apps with a new visual design system. Both now use a custom frosted glass material that adds depth and contrast to the UI."
categories: []
tags: []
image: ""
publishedAt: 2025-10-16
status: "published"
---
> **Note:** This is mock/placeholder content for demonstration purposes.
We've refreshed our iOS and Android apps with a new visual design system. Both now use a custom frosted glass material that adds depth and contrast to the UI.
Navigation has been rebuilt with a new bottom toolbar for quick access to core workflows. You'll also now find a "Create Issue" button at the top of every screen.
## Factory agent
Users of Factory AI coding agents can now access them directly within the app. Delegate an issue to Factory to spin up a remote workspace and launch a coding agent.
Factory's remote workspaces allow you to create custom development environments for coding agents, so you can delegate several issues simultaneously to run in consistent, isolated environments.
## Issue SLAs now available on Business plans
We've made issue SLAs available on Business plans. You can now set response and resolution time targets for different issue types and priorities. Track compliance and get alerts when issues are at risk of breaching their SLA.
Update now in the [App Store](https://apps.apple.com) and [Play Store](https://play.google.com/store).

View File

@@ -1,45 +0,0 @@
---
title: "Security enhancements and SSO"
description: "Major security updates including SAML SSO, audit logs, and enhanced access controls to keep your data safe and compliant."
categories: []
tags: []
image: ""
publishedAt: 2025-08-20
status: "published"
---
> **Note:** This is mock/placeholder content for demonstration purposes.
We've implemented comprehensive security improvements to give you greater control and visibility over your data.
## SAML Single Sign-On
Enterprise customers can now configure SAML SSO with popular identity providers:
- Okta
- Azure Active Directory
- Google Workspace
- OneLogin
## Advanced Audit Logs
Track every action in your account with detailed audit logs:
- User authentication events
- Data access and modifications
- Configuration changes
- API requests
Export logs in JSON or CSV format for compliance and security analysis.
## Enhanced Access Controls
New granular permissions allow you to:
- Create custom roles with specific permissions
- Set IP allowlists for account access
- Require 2FA for sensitive operations
- Configure session timeout policies
## Security Webhooks
Receive real-time notifications about security events like failed login attempts, permission changes, or suspicious activity.
Contact our sales team to enable Enterprise security features.

View File

@@ -1,31 +0,0 @@
---
title: "Team collaboration features"
description: "Introducing real-time collaboration features including live cursors, team presence, and collaborative editing for a more connected team experience."
categories: []
tags: []
image: ""
publishedAt: 2025-09-28
status: "published"
---
> **Note:** This is mock/placeholder content for demonstration purposes.
We're excited to introduce a suite of new team collaboration features designed to help your team work together more effectively.
## Live Presence
See who's online and what they're working on in real-time. Team member avatars now appear throughout the app, showing you who's viewing the same page or editing the same document.
## Collaborative Editing
Multiple team members can now edit documents simultaneously. See real-time cursors and changes as your teammates type, making collaboration seamless and efficient.
## Activity Feed
A new activity feed shows recent changes and updates from your team, helping you stay informed about what's happening across your projects.
## Team Chat Integration
We've integrated team chat directly into the platform, so you can discuss issues, share ideas, and coordinate work without leaving the app.
These features are available now for all team accounts.

View File

@@ -0,0 +1,31 @@
---
title: "Verbandsverwaltung mit Hierarchien"
description: "Neue Funktionen für Verbände: Organisationshierarchien, vereinsübergreifende Mitgliedersuche, Mitgliedertransfer und konsolidierte Berichte."
categories: []
tags: []
image: ""
publishedAt: 2026-03-20
status: "published"
---
Das größte Update für Verbände seit dem Start von MYeasyCMS. Dachverbände und Kreisverbände können ihre Unterglieder jetzt strukturiert verwalten.
## Organisationshierarchie
Bilden Sie Ihre Verbandsstruktur in MYeasyCMS ab — vom Landesverband über Bezirksverbände bis zu den einzelnen Ortsvereinen. Die Baumstruktur zeigt auf einen Blick, welche Vereine zu welchem Verband gehören.
## Vereinsübergreifende Mitgliedersuche
Suchen Sie Mitglieder über alle angeschlossenen Vereine hinweg. Ideal für die Prüfung von Doppelmitgliedschaften oder die Kontaktaufnahme bei Verbandsprojekten.
## Mitgliedertransfer
Beim Umzug eines Mitglieds in einen anderen Verein können Stammdaten jetzt digital übertragen werden — ohne erneute Dateneingabe und unter Wahrung des Datenschutzes.
## Konsolidierte Berichte
Erstellen Sie Statistiken und Berichte über alle Unterglieder: Mitgliederzahlen, Altersstruktur, Entwicklung über die Jahre. Die Daten werden automatisch aus den Vereinen aggregiert.
## Gemeinsame Vorlagen
Verbände können Dokumentvorlagen zentral bereitstellen, die von allen Untergliedern verwendet werden können — einheitliches Erscheinungsbild ohne doppelte Arbeit.

View File

@@ -1,25 +1,37 @@
--- ---
title: "Authentication Overview" title: "Benutzerkonten"
description: "Learn how to set up authentication in your MakerKit application." description: "Benutzerkonten in MYeasyCMS — Registrierung, Login und Profilverwaltung."
publishedAt: 2024-04-11 publishedAt: 2024-04-11
order: 1 order: 0
status: "published" status: "published"
--- ---
MakerKit uses Supabase to manage authentication within your application. Jeder Benutzer in MYeasyCMS hat ein persönliches Konto mit eigenen Zugangsdaten und Berechtigungen.
By default, every kit comes with the following built-in authentication methods: ## Anmeldung
- **Email/Password** - we added, by default, the traditional way of signing in
- **Third Party Providers** - we also added by default Google Auth sign-in
- **Email Links**
- **Phone Number**
You're free to add (or remove) any of the methods supported by Supabase's Melden Sie sich mit Ihrer E-Mail-Adresse und Ihrem Passwort an. Beim ersten Login werden Sie aufgefordert, Ihr Passwort zu ändern.
Authentication: we will see how.
This documentation will help you with the following: ## Rollen
- **Setup** - setting up your Supabase project
- **SSR** - use SSR to persist your users' authentication, adding new Jedem Benutzer wird eine Rolle zugewiesen, die seinen Zugriff steuert:
providers
- **Customization** - an overview of how MakerKit works so that you can adapt - **Administrator** — Vollzugriff auf alle Module und Einstellungen
it to your own application's needs - **Kassenwart** — Finanzen, Beiträge, Mitgliederdaten
- **Kursleiter** — Kurse, Teilnehmer
- **Schriftführer** — Protokolle, Dokumente
- **Mitglied** — Zugriff über das Mitgliederportal (eingeschränkt)
## Profil
Unter **Profil** können Sie Ihre persönlichen Daten aktualisieren:
- Name und Kontaktdaten
- E-Mail-Adresse
- Passwort ändern
- Sprache wählen (Deutsch / Englisch)
- Multi-Faktor-Authentifizierung aktivieren
## Multi-Faktor-Authentifizierung (MFA)
Für zusätzliche Sicherheit können Sie MFA aktivieren. Bei der Anmeldung wird dann neben dem Passwort ein zusätzlicher Code abgefragt — über eine Authenticator-App auf Ihrem Smartphone.

View File

@@ -1,55 +1,28 @@
--- ---
title: "Configuration" title: "Anmeldung konfigurieren"
description: "Learn how authentication works in MakerKit and how to configure it." description: "Login-Optionen und Sicherheitseinstellungen in MYeasyCMS konfigurieren."
publishedAt: 2024-04-11 publishedAt: 2024-04-11
order: 1 order: 1
status: "published" status: "published"
--- ---
The way you want your users to authenticate can be driven via configuration. MYeasyCMS bietet verschiedene Anmeldemethoden, die vom Administrator konfiguriert werden können.
If you open the global configuration at `src/configuration.ts`, you'll find ## E-Mail und Passwort
the `auth` object:
```tsx title="configuration.ts" Die Standard-Anmeldung erfolgt mit E-Mail-Adresse und Passwort. Passwörter müssen eine Mindestlänge von 8 Zeichen haben und sollten Groß- und Kleinbuchstaben sowie Zahlen enthalten.
import type { Provider } from '@supabase/gotrue-js/src/lib/types';
auth: { ## Passwort zurücksetzen
requireEmailConfirmation: false,
providers: {
emailPassword: true,
phoneNumber: false,
emailLink: false,
oAuth: ['google'] as Provider[],
},
}
```
As you can see, the `providers` object can be configured to only display the Benutzer können ihr Passwort über die "Passwort vergessen"-Funktion zurücksetzen. Ein Link zur Passworterstellung wird per E-Mail zugesandt.
auth methods we want to use.
1. For example, by setting both `phoneNumber` and `emailLink` to `true`, the ## Multi-Faktor-Authentifizierung
authentication pages will display the `Email Link` authentication
and the `Phone Number` authentication forms.
2. Instead, by setting `emailPassword` to `false`, we will remove the
`email/password` form from the authentication and user profile pages.
## Requiring Email Verification Für zusätzliche Sicherheit kann MFA aktiviert werden. Unterstützt werden:
This setting needs to match what you have set up in Supabase. If you require email confirmation before your users can sign in, you will have to flip the following flag in your configuration: - **Authenticator-Apps** — Google Authenticator, Authy oder vergleichbare TOTP-Apps
- **Passkeys** — Biometrische Anmeldung über Fingerabdruck oder Gesichtserkennung
```ts ## Sitzungsdauer
auth: {
requireEmailConfirmation: false,
}
```
When the flag is set to `true`, the user will not be redirected to the onboarding flow, but will instead see a successful alert asking them to confirm their email. After confirmation, they will be able to sign in. Anmeldesitzungen laufen nach einer konfigurierbaren Zeitspanne ab. Benutzer werden automatisch abgemeldet, wenn sie längere Zeit inaktiv sind.
When the flag is set to `false`, the application will redirect them directly to the onboarding flow.
## Emails sent by Supabase
Supabase spins up an [InBucket](http://localhost:54324/) instance where all the emails are sent: this is where you can find emails related to password reset, sign-in links, and email verifications.
To access the InBucket instance, you can go to the following URL: [http://localhost:54324/](http://localhost:54324/). Save this URL, you will use it very often.

View File

@@ -1,382 +1,29 @@
--- ---
title: "Email & Password" title: "E-Mail und Passwort"
description: "Traditional email and password authentication." description: "Anmeldung mit E-Mail-Adresse und Passwort — die Standard-Authentifizierung in MYeasyCMS."
publishedAt: 2024-04-11 publishedAt: 2024-04-11
order: 2 order: 2
status: "published" status: "published"
--- ---
> **Note:** This is mock/placeholder content for demonstration purposes. Die Anmeldung mit E-Mail und Passwort ist die Standard-Authentifizierungsmethode in MYeasyCMS.
Email and password authentication is the traditional way users sign up and sign in. ## Registrierung
## Overview Neue Benutzer registrieren sich mit ihrer E-Mail-Adresse und einem selbst gewählten Passwort. Nach der Registrierung wird eine Bestätigungs-E-Mail versendet.
Email/password authentication provides: ## Passwortanforderungen
- User registration with email verification
- Secure password storage
- Password reset functionality
- Session management
## Sign Up Flow - Mindestens 8 Zeichen
- Kombination aus Buchstaben und Zahlen empfohlen
- Das Passwort kann jederzeit in den Profileinstellungen geändert werden
### User Registration ## Passwort vergessen
```typescript Über die "Passwort vergessen"-Funktion auf der Login-Seite kann ein neues Passwort angefordert werden. Der Benutzer erhält einen Link per E-Mail, um ein neues Passwort festzulegen.
import { signUpAction } from '~/lib/auth/actions';
const result = await signUpAction({ ## Sicherheitshinweise
email: 'user@example.com',
password: 'SecurePassword123!',
});
```
### Server Action Implementation - Verwenden Sie ein einzigartiges Passwort für MYeasyCMS
- Geben Sie Ihre Zugangsdaten nicht an andere weiter
```typescript - Aktivieren Sie die Multi-Faktor-Authentifizierung für zusätzliche Sicherheit
'use server';
import { enhanceAction } from '@kit/next/actions';
import * as z from 'zod';
const SignUpSchema = z.object({
email: z.string().email(),
password: z.string().min(8),
});
export const signUpAction = enhanceAction(
async (data) => {
const client = getSupabaseServerClient();
const { data: authData, error } = await client.auth.signUp({
email: data.email,
password: data.password,
options: {
emailRedirectTo: `${process.env.NEXT_PUBLIC_SITE_URL}/auth/callback`,
},
});
if (error) throw error;
return { success: true, data: authData };
},
{ schema: SignUpSchema }
);
```
### Sign Up Component
```tsx
'use client';
import { useForm } from 'react-hook-form';
import { signUpAction } from '../_lib/actions';
export function SignUpForm() {
const { register, handleSubmit, formState: { errors } } = useForm();
const onSubmit = async (data) => {
const result = await signUpAction(data);
if (result.success) {
toast.success('Check your email to confirm your account');
}
};
return (
<form onSubmit={handleSubmit(onSubmit)}>
<div>
<label>Email</label>
<input
type="email"
{...register('email', { required: true })}
/>
{errors.email && <span>Email is required</span>}
</div>
<div>
<label>Password</label>
<input
type="password"
{...register('password', { required: true, minLength: 8 })}
/>
{errors.password && <span>Password must be 8+ characters</span>}
</div>
<button type="submit">Sign Up</button>
</form>
);
}
```
## Sign In Flow
### User Login
```typescript
export const signInAction = enhanceAction(
async (data) => {
const client = getSupabaseServerClient();
const { error } = await client.auth.signInWithPassword({
email: data.email,
password: data.password,
});
if (error) throw error;
redirect('/home');
},
{ schema: SignInSchema }
);
```
### Sign In Component
```tsx
'use client';
export function SignInForm() {
const { register, handleSubmit } = useForm();
const onSubmit = async (data) => {
try {
await signInAction(data);
} catch (error) {
toast.error('Invalid email or password');
}
};
return (
<form onSubmit={handleSubmit(onSubmit)}>
<input
type="email"
{...register('email')}
placeholder="Email"
/>
<input
type="password"
{...register('password')}
placeholder="Password"
/>
<button type="submit">Sign In</button>
</form>
);
}
```
## Email Verification
### Requiring Email Confirmation
Configure in Supabase dashboard or config:
```typescript
// config/auth.config.ts
export const authConfig = {
requireEmailConfirmation: true,
};
```
### Handling Unconfirmed Emails
```typescript
export const signInAction = enhanceAction(
async (data) => {
const client = getSupabaseServerClient();
const { data: authData, error } = await client.auth.signInWithPassword({
email: data.email,
password: data.password,
});
if (error) {
if (error.message.includes('Email not confirmed')) {
return {
success: false,
error: 'Please confirm your email before signing in',
};
}
throw error;
}
redirect('/home');
},
{ schema: SignInSchema }
);
```
## Password Reset
### Request Password Reset
```typescript
export const requestPasswordResetAction = enhanceAction(
async (data) => {
const client = getSupabaseServerClient();
const { error } = await client.auth.resetPasswordForEmail(data.email, {
redirectTo: `${process.env.NEXT_PUBLIC_SITE_URL}/auth/reset-password`,
});
if (error) throw error;
return {
success: true,
message: 'Check your email for reset instructions',
};
},
{
schema: z.object({
email: z.string().email(),
}),
}
);
```
### Reset Password Form
```tsx
'use client';
export function PasswordResetRequestForm() {
const { register, handleSubmit } = useForm();
const onSubmit = async (data) => {
const result = await requestPasswordResetAction(data);
if (result.success) {
toast.success(result.message);
}
};
return (
<form onSubmit={handleSubmit(onSubmit)}>
<input
type="email"
{...register('email')}
placeholder="Enter your email"
/>
<button type="submit">Send Reset Link</button>
</form>
);
}
```
### Update Password
```typescript
export const updatePasswordAction = enhanceAction(
async (data) => {
const client = getSupabaseServerClient();
const { error } = await client.auth.updateUser({
password: data.newPassword,
});
if (error) throw error;
redirect('/home');
},
{
schema: z.object({
newPassword: z.string().min(8),
}),
}
);
```
## Password Requirements
### Validation Schema
```typescript
const PasswordSchema = z
.string()
.min(8, 'Password must be at least 8 characters')
.regex(/[A-Z]/, 'Password must contain an uppercase letter')
.regex(/[a-z]/, 'Password must contain a lowercase letter')
.regex(/[0-9]/, 'Password must contain a number')
.regex(/[^A-Za-z0-9]/, 'Password must contain a special character');
```
### Password Strength Indicator
```tsx
'use client';
import { useState } from 'react';
export function PasswordInput() {
const [password, setPassword] = useState('');
const strength = calculatePasswordStrength(password);
return (
<div>
<input
type="password"
value={password}
onChange={(e) => setPassword(e.target.value)}
/>
<div className="flex gap-1">
{[1, 2, 3, 4].map((level) => (
<div
key={level}
className={cn(
'h-1 flex-1 rounded',
strength >= level ? 'bg-green-500' : 'bg-gray-200'
)}
/>
))}
</div>
<span className="text-sm">
{strength === 4 && 'Strong password'}
{strength === 3 && 'Good password'}
{strength === 2 && 'Fair password'}
{strength === 1 && 'Weak password'}
</span>
</div>
);
}
```
## Session Management
### Checking Authentication Status
```typescript
import { getSupabaseServerClient } from '@kit/supabase/server-client';
export async function requireAuth() {
const client = getSupabaseServerClient();
const { data: { user } } = await client.auth.getUser();
if (!user) {
redirect('/auth/sign-in');
}
return user;
}
```
### Sign Out
```typescript
export const signOutAction = enhanceAction(
async () => {
const client = getSupabaseServerClient();
await client.auth.signOut();
redirect('/auth/sign-in');
}
);
```
## Security Best Practices
1. **Enforce strong passwords** - Minimum 8 characters, mixed case, numbers, symbols
2. **Rate limit login attempts** - Prevent brute force attacks
3. **Use HTTPS only** - Encrypt data in transit
4. **Enable email verification** - Confirm email ownership
5. **Implement account lockout** - After failed attempts
6. **Log authentication events** - Track sign-ins and failures
7. **Support 2FA** - Add extra security layer

View File

@@ -1,392 +1,30 @@
--- ---
title: "Magic Links" title: "Einladungslinks"
description: "Passwordless authentication with email magic links." description: "Benutzer per E-Mail-Einladung in den Vereins-Account einladen."
publishedAt: 2024-04-11 publishedAt: 2024-04-11
order: 4 order: 4
status: "published" status: "published"
--- ---
> **Note:** This is mock/placeholder content for demonstration purposes. Administratoren können neue Benutzer per Einladungslink in den Vereins-Account einladen.
Magic links provide passwordless authentication by sending a one-time link to the user's email. ## So funktioniert die Einladung
## How It Works 1. Navigieren Sie zu **Einstellungen → Mitarbeiter → Einladen**
2. Geben Sie die E-Mail-Adresse des neuen Benutzers ein
3. Wählen Sie die Rolle (Administrator, Kassenwart, Kursleiter, etc.)
4. Klicken Sie auf **Einladung senden**
1. User enters their email address Der eingeladene Benutzer erhält eine E-Mail mit einem Registrierungslink. Nach der Registrierung hat er sofort Zugriff auf die Funktionen, die seiner Rolle entsprechen.
2. System sends an email with a unique link
3. User clicks the link in their email
4. User is automatically signed in
## Benefits ## Einladungen verwalten
- **No password to remember** - Better UX Unter **Mitglieder → Einladungen** sehen Sie alle offenen und angenommenen Einladungen:
- **More secure** - No password to steal
- **Lower friction** - Faster sign-up process
- **Email verification** - Confirms email ownership
## Implementation - **Offen** — Einladung wurde versendet, aber noch nicht angenommen
- **Angenommen** — Benutzer hat die Einladung angenommen und sein Konto erstellt
- **Abgelaufen** — Einladungslink ist nicht mehr gültig (kann erneut gesendet werden)
### Magic Link Form ## Erneut einladen
```tsx Abgelaufene oder nicht angenommene Einladungen können mit einem Klick erneut versendet werden.
'use client';
import { useForm } from 'react-hook-form';
import { sendMagicLinkAction } from '../_lib/actions';
export function MagicLinkForm() {
const { register, handleSubmit, formState: { isSubmitting } } = useForm();
const [sent, setSent] = useState(false);
const onSubmit = async (data) => {
const result = await sendMagicLinkAction(data);
if (result.success) {
setSent(true);
}
};
if (sent) {
return (
<div className="text-center">
<h2>Check your email</h2>
<p>We've sent you a magic link to sign in.</p>
</div>
);
}
return (
<form onSubmit={handleSubmit(onSubmit)}>
<div>
<label>Email address</label>
<input
type="email"
{...register('email', { required: true })}
placeholder="you@example.com"
/>
</div>
<button type="submit" disabled={isSubmitting}>
{isSubmitting ? 'Sending...' : 'Send magic link'}
</button>
</form>
);
}
```
### Server Action
```typescript
'use server';
import { enhanceAction } from '@kit/next/actions';
import { getSupabaseServerClient } from '@kit/supabase/server-client';
import * as z from 'zod';
export const sendMagicLinkAction = enhanceAction(
async (data) => {
const client = getSupabaseServerClient();
const origin = process.env.NEXT_PUBLIC_SITE_URL!;
const { error } = await client.auth.signInWithOtp({
email: data.email,
options: {
emailRedirectTo: `${origin}/auth/callback`,
shouldCreateUser: true,
},
});
if (error) throw error;
return {
success: true,
message: 'Check your email for the magic link',
};
},
{
schema: z.object({
email: z.string().email(),
}),
}
);
```
## Configuration
### Enable in Supabase
1. Go to **Authentication** → **Providers** → **Email**
2. Enable "Enable Email Provider"
3. Enable "Enable Email Confirmations"
### Configure Email Template
Customize the magic link email in Supabase Dashboard:
1. Go to **Authentication** → **Email Templates**
2. Select "Magic Link"
3. Customize the template:
```html
<h2>Sign in to {{ .SiteURL }}</h2>
<p>Click the link below to sign in:</p>
<p><a href="{{ .ConfirmationURL }}">Sign in</a></p>
<p>This link expires in {{ .TokenExpiryHours }} hours.</p>
```
## Callback Handler
Handle the magic link callback:
```typescript
// app/auth/callback/route.ts
import { createRouteHandlerClient } from '@supabase/auth-helpers-nextjs';
import { cookies } from 'next/headers';
import { NextResponse } from 'next/server';
export async function GET(request: Request) {
const requestUrl = new URL(request.url);
const token_hash = requestUrl.searchParams.get('token_hash');
const type = requestUrl.searchParams.get('type');
if (token_hash && type === 'magiclink') {
const cookieStore = cookies();
const supabase = createRouteHandlerClient({ cookies: () => cookieStore });
const { error } = await supabase.auth.verifyOtp({
token_hash,
type: 'magiclink',
});
if (!error) {
return NextResponse.redirect(new URL('/home', request.url));
}
}
// Return error if verification failed
return NextResponse.redirect(
new URL('/auth/sign-in?error=invalid_link', request.url)
);
}
```
## Advanced Features
### Custom Redirect
Specify where users go after clicking the link:
```typescript
await client.auth.signInWithOtp({
email: data.email,
options: {
emailRedirectTo: `${origin}/onboarding`,
},
});
```
### Disable Auto Sign-Up
Require users to sign up first:
```typescript
await client.auth.signInWithOtp({
email: data.email,
options: {
shouldCreateUser: false, // Don't create new users
},
});
```
### Token Expiry
Configure link expiration (default: 1 hour):
```sql
-- In Supabase SQL Editor
ALTER TABLE auth.users
SET default_token_lifetime = '15 minutes';
```
## Rate Limiting
Prevent abuse by rate limiting magic link requests:
```typescript
import { ratelimit } from '~/lib/rate-limit';
export const sendMagicLinkAction = enhanceAction(
async (data, user, request) => {
// Rate limit by IP
const ip = request.headers.get('x-forwarded-for') || 'unknown';
const { success } = await ratelimit.limit(ip);
if (!success) {
throw new Error('Too many requests. Please try again later.');
}
const client = getSupabaseServerClient();
await client.auth.signInWithOtp({
email: data.email,
});
return { success: true };
},
{ schema: EmailSchema }
);
```
## Security Considerations
### Link Expiration
Magic links should expire quickly:
- Default: 1 hour
- Recommended: 15-30 minutes for production
- Shorter for sensitive actions
### One-Time Use
Links should be invalidated after use:
```typescript
// Supabase handles this automatically
// Each link can only be used once
```
### Email Verification
Ensure emails are verified:
```typescript
const { data: { user } } = await client.auth.getUser();
if (!user.email_confirmed_at) {
redirect('/verify-email');
}
```
## User Experience
### Loading State
Show feedback while sending:
```tsx
export function MagicLinkForm() {
const [status, setStatus] = useState<'idle' | 'sending' | 'sent'>('idle');
const onSubmit = async (data) => {
setStatus('sending');
await sendMagicLinkAction(data);
setStatus('sent');
};
return (
<>
{status === 'idle' && <EmailForm onSubmit={onSubmit} />}
{status === 'sending' && <SendingMessage />}
{status === 'sent' && <CheckEmailMessage />}
</>
);
}
```
### Resend Link
Allow users to request a new link:
```tsx
export function ResendMagicLink({ email }: { email: string }) {
const [canResend, setCanResend] = useState(false);
const [countdown, setCountdown] = useState(60);
useEffect(() => {
if (countdown > 0) {
const timer = setTimeout(() => setCountdown(countdown - 1), 1000);
return () => clearTimeout(timer);
} else {
setCanResend(true);
}
}, [countdown]);
const handleResend = async () => {
await sendMagicLinkAction({ email });
setCountdown(60);
setCanResend(false);
};
return (
<button onClick={handleResend} disabled={!canResend}>
{canResend ? 'Resend link' : `Resend in ${countdown}s`}
</button>
);
}
```
## Email Deliverability
### SPF, DKIM, DMARC
Configure email authentication:
1. Add SPF record to DNS
2. Enable DKIM signing
3. Set up DMARC policy
### Custom Email Domain
Use your own domain for better deliverability:
1. Go to **Project Settings** → **Auth**
2. Configure custom SMTP
3. Verify domain ownership
### Monitor Bounces
Track email delivery issues:
```typescript
// Handle email bounces
export async function handleEmailBounce(email: string) {
await client.from('email_bounces').insert({
email,
bounced_at: new Date(),
});
// Notify user via other channel
}
```
## Testing
### Local Development
In development, emails go to InBucket:
```
http://localhost:54324
```
Check this URL to see magic link emails during testing.
### Test Mode
Create a test link without sending email:
```typescript
if (process.env.NODE_ENV === 'development') {
console.log('Magic link URL:', confirmationUrl);
}
```
## Best Practices
1. **Clear communication** - Tell users to check spam
2. **Short expiry** - 15-30 minutes for security
3. **Rate limiting** - Prevent abuse
4. **Fallback option** - Offer password auth as backup
5. **Custom domain** - Better deliverability
6. **Monitor delivery** - Track bounces and failures
7. **Resend option** - Let users request new link
8. **Mobile-friendly** - Ensure links work on mobile

View File

@@ -1,395 +1,31 @@
--- ---
title: "OAuth" title: "Mitgliederportal"
description: "Sign in with Google, GitHub, and other OAuth providers." description: "Das Mitgliederportal ermöglicht Vereinsmitgliedern den Zugriff auf ihre eigenen Daten."
publishedAt: 2024-04-11 publishedAt: 2024-04-11
order: 3 order: 3
status: "published" status: "published"
--- ---
> **Note:** This is mock/placeholder content for demonstration purposes. Das Mitgliederportal ist der Bereich von MYeasyCMS, der für die Vereinsmitglieder selbst zugänglich ist.
Allow users to sign in with their existing accounts from Google, GitHub, and other providers. ## Funktionen für Mitglieder
## Supported Providers Über das Portal können Mitglieder:
Supabase supports many OAuth providers: - **Stammdaten einsehen und aktualisieren** — Adresse, Telefonnummer, E-Mail
- Google - **Kursanmeldungen** — Sich für Kurse und Veranstaltungen anmelden
- GitHub - **Beitragshistorie** — Ihre Zahlungshistorie einsehen
- GitLab - **Dokumente** — Persönliche Dokumente herunterladen (Ausweis, Bestätigungen)
- Bitbucket - **Newsletter** — Newsletter-Abonnement verwalten
- Azure
- Facebook
- Twitter
- Discord
- Slack
- And more...
## Setting Up OAuth ## Zugang einrichten
### Configure in Supabase Dashboard Mitglieder erhalten Zugang zum Portal über die Vereinswebsite. Der Login erfolgt mit E-Mail-Adresse und Passwort.
1. Go to **Authentication** → **Providers** ## Datenschutz
2. Enable your desired provider (e.g., Google)
3. Add your OAuth credentials:
- **Client ID**
- **Client Secret**
- **Redirect URL**: `https://your-project.supabase.co/auth/v1/callback`
### Google OAuth Setup Jedes Mitglied sieht ausschließlich seine eigenen Daten. Ein Zugriff auf andere Mitgliederdaten oder Verwaltungsfunktionen ist nicht möglich.
1. Go to [Google Cloud Console](https://console.cloud.google.com) ## Kontoverknüpfung
2. Create a new project or select existing
3. Enable Google+ API
4. Create OAuth 2.0 credentials
5. Add authorized redirect URIs:
- Production: `https://your-project.supabase.co/auth/v1/callback`
- Development: `http://localhost:54321/auth/v1/callback`
### GitHub OAuth Setup Mitglieder, die in mehreren Vereinen aktiv sind, können ihre Konten verknüpfen und zwischen den Vereinen wechseln, ohne sich erneut anmelden zu müssen.
1. Go to GitHub Settings → Developer Settings → OAuth Apps
2. Click "New OAuth App"
3. Fill in details:
- **Application name**: Your App
- **Homepage URL**: `https://yourapp.com`
- **Authorization callback URL**: `https://your-project.supabase.co/auth/v1/callback`
4. Copy Client ID and Client Secret to Supabase
## Implementation
### OAuth Sign In Button
```tsx
'use client';
import { signInWithOAuthAction } from '../_lib/actions';
export function OAuthButtons() {
const handleGoogleSignIn = async () => {
await signInWithOAuthAction('google');
};
const handleGitHubSignIn = async () => {
await signInWithOAuthAction('github');
};
return (
<div className="space-y-2">
<button
onClick={handleGoogleSignIn}
className="w-full flex items-center justify-center gap-2 border rounded-lg p-2"
>
<GoogleIcon />
Continue with Google
</button>
<button
onClick={handleGitHubSignIn}
className="w-full flex items-center justify-center gap-2 border rounded-lg p-2"
>
<GitHubIcon />
Continue with GitHub
</button>
</div>
);
}
```
### Server Action
```typescript
'use server';
import { enhanceAction } from '@kit/next/actions';
import { getSupabaseServerClient } from '@kit/supabase/server-client';
import * as z from 'zod';
const OAuthProviderSchema = z.enum([
'google',
'github',
'gitlab',
'azure',
'facebook',
]);
export const signInWithOAuthAction = enhanceAction(
async (provider) => {
const client = getSupabaseServerClient();
const origin = process.env.NEXT_PUBLIC_SITE_URL!;
const { data, error } = await client.auth.signInWithOAuth({
provider,
options: {
redirectTo: `${origin}/auth/callback`,
},
});
if (error) throw error;
// Redirect to OAuth provider
redirect(data.url);
},
{
schema: OAuthProviderSchema,
}
);
```
### OAuth Callback Handler
```typescript
// app/auth/callback/route.ts
import { createRouteHandlerClient } from '@supabase/auth-helpers-nextjs';
import { cookies } from 'next/headers';
import { NextResponse } from 'next/server';
export async function GET(request: Request) {
const requestUrl = new URL(request.url);
const code = requestUrl.searchParams.get('code');
if (code) {
const cookieStore = cookies();
const supabase = createRouteHandlerClient({ cookies: () => cookieStore });
await supabase.auth.exchangeCodeForSession(code);
}
// Redirect to home page
return NextResponse.redirect(new URL('/home', request.url));
}
```
## Customizing OAuth Flow
### Scopes
Request specific permissions:
```typescript
await client.auth.signInWithOAuth({
provider: 'google',
options: {
scopes: 'email profile https://www.googleapis.com/auth/calendar',
},
});
```
### Query Parameters
Pass custom parameters:
```typescript
await client.auth.signInWithOAuth({
provider: 'azure',
options: {
queryParams: {
prompt: 'consent',
access_type: 'offline',
},
},
});
```
### Skip Browser Redirect
For mobile apps or custom flows:
```typescript
const { data } = await client.auth.signInWithOAuth({
provider: 'google',
options: {
skipBrowserRedirect: true,
},
});
// data.url contains the OAuth URL
// Handle redirect manually
```
## Account Linking
### Linking Additional Providers
Allow users to link multiple OAuth accounts:
```typescript
export const linkOAuthProviderAction = enhanceAction(
async (provider) => {
const client = getSupabaseServerClient();
const user = await requireAuth();
const { data, error } = await client.auth.linkIdentity({
provider,
});
if (error) throw error;
redirect(data.url);
},
{ schema: OAuthProviderSchema, auth: true }
);
```
### Unlinking Providers
```typescript
export const unlinkOAuthProviderAction = enhanceAction(
async ({ provider, identityId }) => {
const client = getSupabaseServerClient();
const { error } = await client.auth.unlinkIdentity({
identity_id: identityId,
});
if (error) throw error;
revalidatePath('/settings/security');
},
{
schema: z.object({
provider: z.string(),
identityId: z.string(),
}),
auth: true,
}
);
```
### Viewing Linked Identities
```typescript
import { getSupabaseServerClient } from '@kit/supabase/server-client';
export async function getLinkedIdentities() {
const client = getSupabaseServerClient();
const { data: { user } } = await client.auth.getUser();
return user?.identities || [];
}
```
## User Data from OAuth
### Accessing Provider Data
```typescript
const { data: { user } } = await client.auth.getUser();
// User metadata from provider
const {
full_name,
avatar_url,
email,
} = user.user_metadata;
// Provider-specific data
const identities = user.identities || [];
const googleIdentity = identities.find(i => i.provider === 'google');
console.log(googleIdentity?.identity_data);
```
### Storing Additional Data
```typescript
export const completeOAuthProfileAction = enhanceAction(
async (data) => {
const client = getSupabaseServerClient();
const user = await requireAuth();
// Update user metadata
await client.auth.updateUser({
data: {
username: data.username,
bio: data.bio,
},
});
// Update profile in database
await client.from('profiles').upsert({
id: user.id,
username: data.username,
bio: data.bio,
avatar_url: user.user_metadata.avatar_url,
});
redirect('/home');
},
{ schema: ProfileSchema, auth: true }
);
```
## Configuration
### Enable OAuth in Config
```typescript
// config/auth.config.ts
export const authConfig = {
providers: {
emailPassword: true,
oAuth: ['google', 'github'],
},
};
```
### Conditional Rendering
```tsx
import { authConfig } from '~/config/auth.config';
export function AuthProviders() {
return (
<>
{authConfig.providers.emailPassword && <EmailPasswordForm />}
{authConfig.providers.oAuth?.includes('google') && (
<GoogleSignInButton />
)}
{authConfig.providers.oAuth?.includes('github') && (
<GitHubSignInButton />
)}
</>
);
}
```
## Troubleshooting
### Redirect URI Mismatch
Ensure redirect URIs match exactly:
- Check Supabase Dashboard → Authentication → URL Configuration
- Verify OAuth app settings in provider console
- Use exact URLs (including http/https)
### Missing Email
Some providers don't share email by default:
```typescript
const { data: { user } } = await client.auth.getUser();
if (!user.email) {
// Request email separately or prompt user
redirect('/auth/complete-profile');
}
```
### Rate Limiting
OAuth providers may rate limit requests:
- Cache OAuth tokens appropriately
- Don't make excessive authorization requests
- Handle rate limit errors gracefully
## Best Practices
1. **Request minimum scopes** - Only ask for what you need
2. **Handle errors gracefully** - OAuth can fail for many reasons
3. **Verify email addresses** - Some providers don't verify emails
4. **Support account linking** - Let users connect multiple providers
5. **Provide fallback** - Always offer email/password as backup
6. **Log OAuth events** - Track sign-ins and linking attempts
7. **Test thoroughly** - Test with real provider accounts

View File

@@ -1,15 +1,32 @@
--- ---
title: "Billing & Payments" title: "Tarife und Preise"
description: "Learn how to set up billing and payment processing in your MakerKit application." description: "Faire Preise nach Vereinsgröße — alle Funktionen inklusive."
publishedAt: 2024-04-11 publishedAt: 2024-04-11
order: 5 order: 5
status: "published" status: "published"
--- ---
MakerKit integrates with popular payment providers to handle subscriptions and billing. MYeasyCMS bietet faire Preise, die sich an der Größe Ihres Vereins orientieren.
This section covers: ## Preismodell
- Setting up payment providers
- Managing subscriptions Die Preise richten sich nach der Anzahl der verwalteten Mitglieder. Alle Module und Funktionen sind in jedem Tarif enthalten — es gibt keine kostenpflichtigen Zusatzmodule.
- Handling webhooks
- Pricing plans and tiers ## Was ist inklusive?
- **Alle Module** — Mitglieder, Finanzen, Kurse, Veranstaltungen, Newsletter, Dokumente, Site-Builder
- **Unbegrenzte Benutzer** — Keine Begrenzung der Benutzeranzahl
- **Persönliche Einrichtung** — Das Com.BISS-Team richtet Ihren Account ein
- **Support** — Direkter, persönlicher Support per Telefon und E-Mail
- **Updates** — Neue Funktionen und Verbesserungen automatisch
## Testzugang
Fordern Sie einen kostenlosen Testzugang an, um MYeasyCMS unverbindlich kennenzulernen. Das Team führt Sie persönlich durch die Plattform.
## Kontakt für Preisanfragen
Für ein individuelles Angebot wenden Sie sich an:
- **Telefon:** 09451 9499-09
- **E-Mail:** info@combiss.de

View File

@@ -1,186 +1,35 @@
--- ---
title: "Pricing Plans" title: "Tarifübersicht"
description: "How to configure and customize pricing plans for your SaaS application." description: "Übersicht der verfügbaren Tarife für Vereine und Verbände."
publishedAt: 2024-04-11 publishedAt: 2024-04-11
order: 1 order: 1
status: "published" status: "published"
--- ---
> **Note:** This is mock/placeholder content for demonstration purposes. MYeasyCMS bietet drei Tarife, die sich an der Vereinsgröße orientieren.
Configure your pricing structure to match your business model. ## Tarife
## Plan Structure ### Basis
Each pricing plan consists of: Für kleine Vereine mit bis zu 200 Mitgliedern. Alle Kernmodule enthalten.
- **ID** - Unique identifier
- **Name** - Display name
- **Price** - Amount in your currency
- **Interval** - Billing frequency (month, year)
- **Features** - List of included features
- **Limits** - Usage constraints
## Example Configuration ### Standard
```typescript Für mittelgroße Vereine und Organisationen. Alle Module inklusive erweiterter Funktionen wie Fischereiverwaltung und Sitzungsprotokolle.
// config/billing.config.ts
export const billingConfig = {
provider: 'stripe', // or 'paddle'
currency: 'usd',
plans: [
{
id: 'free',
name: 'Free',
description: 'Perfect for getting started',
price: 0,
features: [
'5 projects',
'Basic analytics',
'Community support',
],
limits: {
projects: 5,
members: 1,
},
},
{
id: 'starter',
name: 'Starter',
description: 'For small teams',
price: 19,
interval: 'month',
features: [
'25 projects',
'Advanced analytics',
'Email support',
'API access',
],
limits: {
projects: 25,
members: 5,
},
},
{
id: 'pro',
name: 'Professional',
description: 'For growing businesses',
price: 49,
interval: 'month',
popular: true,
features: [
'Unlimited projects',
'Advanced analytics',
'Priority support',
'API access',
'Custom integrations',
],
limits: {
projects: -1, // unlimited
members: 20,
},
},
],
};
```
## Feature Gating ### Verband
Restrict features based on subscription plan: Für Dachverbände und Kreisverbände mit Untergliedern. Enthält die Verbandsverwaltung mit Hierarchien, vereinsübergreifender Suche und konsolidierten Berichten.
```typescript ## Gemeinsam für alle Tarife
import { hasFeature } from '~/lib/billing/features';
async function createProject() { - Unbegrenzte Benutzeranzahl
const subscription = await getSubscription(accountId); - Persönliche Einrichtung durch das Com.BISS-Team
- Direkter Support per Telefon und E-Mail
- Automatische Updates und neue Funktionen
- Server in Deutschland, DSGVO-konform
if (!hasFeature(subscription, 'api_access')) { ## Individuelle Angebote
throw new Error('API access requires Pro plan');
}
// Create project Für Verbände mit vielen Untergliedern oder besondere Anforderungen erstellen wir individuelle Angebote. Sprechen Sie uns an.
}
```
## Usage Limits
Enforce usage limits per plan:
```typescript
import { checkLimit } from '~/lib/billing/limits';
async function addTeamMember() {
const canAdd = await checkLimit(accountId, 'members');
if (!canAdd) {
throw new Error('Member limit reached. Upgrade to add more members.');
}
// Add member
}
```
## Annual Billing
Offer discounted annual plans:
```typescript
{
id: 'pro-annual',
name: 'Professional Annual',
price: 470, // ~20% discount
interval: 'year',
discount: '20% off',
features: [ /* same as monthly */ ],
}
```
## Trial Periods
Configure free trial periods:
```typescript
export const trialConfig = {
enabled: true,
duration: 14, // days
plans: ['starter', 'pro'], // plans eligible for trial
requirePaymentMethod: true,
};
```
## Customizing the Pricing Page
The pricing page automatically generates from your configuration:
```tsx
import { billingConfig } from '~/config/billing.config';
export default function PricingPage() {
return (
<PricingTable
plans={billingConfig.plans}
currency={billingConfig.currency}
/>
);
}
```
## Adding Custom Features
Extend plan features with custom attributes:
```typescript
{
id: 'enterprise',
name: 'Enterprise',
price: null, // Contact for pricing
custom: true,
features: [
'Everything in Pro',
'Dedicated support',
'Custom SLA',
'On-premise deployment',
],
ctaText: 'Contact Sales',
ctaUrl: '/contact',
}
```

View File

@@ -1,143 +1,33 @@
--- ---
title: "Billing Overview" title: "Abrechnung"
description: "Learn how to manage subscriptions and billing in your application." description: "Wie die Abrechnung für MYeasyCMS funktioniert — Zahlungsmodalitäten und Rechnungen."
publishedAt: 2024-04-11 publishedAt: 2024-04-11
order: 0 order: 0
status: "published" status: "published"
--- ---
> **Note:** This is mock/placeholder content for demonstration purposes. Die Abrechnung für MYeasyCMS ist transparent und unkompliziert.
The billing system supports subscription-based pricing with multiple tiers and payment providers. ## Zahlungsrhythmus
## Supported Providers MYeasyCMS wird jährlich abgerechnet. Sie erhalten eine Rechnung per E-Mail mit den üblichen Zahlungsfristen.
### Stripe ## Zahlungsmethoden
Industry-standard payment processing with comprehensive features:
- Credit card payments
- Subscription management
- Invoice generation
- Tax calculation
- Customer portal
### Paddle - **Überweisung** — Die gängigste Zahlungsart für Vereine
Merchant of record solution that handles: - **SEPA-Lastschrift** — Bequem und automatisch
- Global tax compliance
- Payment processing
- Subscription billing
- Revenue recovery
## Subscription Tiers ## Rechnungen
Define your subscription tiers in the billing configuration: Rechnungen werden als PDF per E-Mail zugestellt. Sie enthalten alle relevanten Angaben für die Buchhaltung des Vereins.
```typescript ## Kündigung
export const plans = [
{
id: 'free',
name: 'Free',
price: 0,
features: ['Feature 1', 'Feature 2'],
},
{
id: 'pro',
name: 'Professional',
price: 29,
interval: 'month',
features: ['All Free features', 'Feature 3', 'Feature 4'],
},
{
id: 'enterprise',
name: 'Enterprise',
price: 99,
interval: 'month',
features: ['All Pro features', 'Feature 5', 'Priority support'],
},
];
```
## Subscription Lifecycle Die Kündigung ist zum Ende des Vertragsjahres möglich. Ihre Daten bleiben nach Vertragsende noch für einen vereinbarten Zeitraum verfügbar, damit Sie sie exportieren können.
1. **Customer selects plan** - User chooses subscription tier ## Fragen zur Abrechnung
2. **Payment processed** - Provider handles payment collection
3. **Webhook received** - Your app receives confirmation
4. **Subscription activated** - User gains access to features
5. **Recurring billing** - Automatic renewal each period
6. **Cancellation** - User can cancel anytime
## Managing Subscriptions Bei Fragen zur Abrechnung wenden Sie sich direkt an das Com.BISS-Team:
### Creating a Subscription - **Telefon:** 09451 9499-09
- **E-Mail:** info@combiss.de
```typescript
import { createCheckoutSession } from '~/lib/billing/checkout';
const session = await createCheckoutSession({
accountId: user.accountId,
planId: 'pro',
returnUrl: '/dashboard',
});
// Redirect user to payment page
redirect(session.url);
```
### Checking Subscription Status
```typescript
import { getSubscription } from '~/lib/billing/subscription';
const subscription = await getSubscription(accountId);
if (subscription.status === 'active') {
// User has active subscription
}
```
### Canceling a Subscription
```typescript
import { cancelSubscription } from '~/lib/billing/subscription';
await cancelSubscription(subscriptionId);
```
## Webhook Handling
Webhooks notify your application of billing events:
```typescript
export async function POST(request: Request) {
const signature = request.headers.get('stripe-signature');
const payload = await request.text();
const event = stripe.webhooks.constructEvent(
payload,
signature,
process.env.STRIPE_WEBHOOK_SECRET
);
switch (event.type) {
case 'customer.subscription.created':
await handleSubscriptionCreated(event.data.object);
break;
case 'customer.subscription.updated':
await handleSubscriptionUpdated(event.data.object);
break;
case 'customer.subscription.deleted':
await handleSubscriptionCanceled(event.data.object);
break;
}
return new Response('OK');
}
```
## Testing
Use test mode credentials for development:
- Test card: 4242 4242 4242 4242
- Any future expiry date
- Any CVC
All test transactions will appear in your provider's test dashboard.

View File

@@ -1,194 +1,33 @@
--- ---
title: "Webhook Integration" title: "Schnittstellen"
description: "Setting up and handling payment provider webhooks for subscription events." description: "Schnittstellen und Exportmöglichkeiten in MYeasyCMS."
publishedAt: 2024-04-11 publishedAt: 2024-04-11
order: 2 order: 2
status: "published" status: "published"
--- ---
> **Note:** This is mock/placeholder content for demonstration purposes. MYeasyCMS bietet verschiedene Schnittstellen für den Datenaustausch.
Webhooks notify your application when billing events occur, ensuring your app stays synchronized with your payment provider. ## SEPA-Export
## Why Webhooks? Die wichtigste Schnittstelle für die meisten Vereine: der Export von SEPA-Sammellastschriften als XML-Datei (pain.008) für den Bankeinzug.
Webhooks are essential for: ## Datenimport
- **Real-time updates** - Instant notification of payment events
- **Reliability** - Handles events even if users close their browser
- **Security** - Server-to-server communication
- **Automation** - Automatic subscription status updates
## Webhook Endpoint Importieren Sie Mitgliederdaten aus Excel- oder CSV-Dateien. Der Import-Assistent unterstützt die Zuordnung der Spalten und prüft die Daten auf Vollständigkeit.
Your webhook endpoint receives events from the payment provider: ## Datenexport
```typescript Exportieren Sie Ihre Daten in verschiedenen Formaten:
// app/api/billing/webhook/route.ts
export async function POST(request: Request) {
const body = await request.text();
const signature = request.headers.get('stripe-signature');
// Verify webhook signature - Excel (.xlsx) für Tabellenkalkulationen
const event = stripe.webhooks.constructEvent( - CSV für den universellen Datenaustausch
body, - PDF für druckfertige Berichte
signature,
process.env.STRIPE_WEBHOOK_SECRET
);
// Handle the event ## E-Mail-Versand
await handleBillingEvent(event);
return new Response('OK', { status: 200 }); MYeasyCMS versendet E-Mails für Newsletter, Einladungen und Benachrichtigungen. Der Versand erfolgt über die konfigurierte E-Mail-Infrastruktur.
}
```
## Common Events ## Mitgliederportal
### Subscription Created Das Portal stellt eine Schnittstelle zwischen Vereinsverwaltung und Mitgliedern dar. Mitglieder können ihre Daten einsehen und aktualisieren, ohne dass der Vorstand eingreifen muss.
```typescript
case 'customer.subscription.created':
await prisma.subscription.create({
data: {
id: event.data.object.id,
accountId: event.data.object.metadata.accountId,
status: 'active',
planId: event.data.object.items.data[0].price.id,
currentPeriodEnd: new Date(event.data.object.current_period_end * 1000),
},
});
break;
```
### Subscription Updated
```typescript
case 'customer.subscription.updated':
await prisma.subscription.update({
where: { id: event.data.object.id },
data: {
status: event.data.object.status,
planId: event.data.object.items.data[0].price.id,
currentPeriodEnd: new Date(event.data.object.current_period_end * 1000),
},
});
break;
```
### Subscription Deleted
```typescript
case 'customer.subscription.deleted':
await prisma.subscription.update({
where: { id: event.data.object.id },
data: {
status: 'canceled',
canceledAt: new Date(),
},
});
break;
```
### Payment Failed
```typescript
case 'invoice.payment_failed':
const subscription = await prisma.subscription.findUnique({
where: { id: event.data.object.subscription },
});
// Send payment failure notification
await sendPaymentFailureEmail(subscription.accountId);
break;
```
## Setting Up Webhooks
### Stripe
1. **Local Development** (using Stripe CLI):
```bash
stripe listen --forward-to localhost:3000/api/billing/webhook
```
2. **Production**:
- Go to Stripe Dashboard → Developers → Webhooks
- Add endpoint: `https://yourdomain.com/api/billing/webhook`
- Select events to listen to
- Copy webhook signing secret to your `.env`
### Paddle
1. **Configure webhook URL** in Paddle dashboard
2. **Add webhook secret** to environment variables
3. **Verify webhook signature**:
```typescript
const signature = request.headers.get('paddle-signature');
const verified = paddle.webhooks.verify(body, signature);
if (!verified) {
return new Response('Invalid signature', { status: 401 });
}
```
## Security Best Practices
1. **Always verify signatures** - Prevents unauthorized requests
2. **Use HTTPS** - Encrypts webhook data in transit
3. **Validate event data** - Check for required fields
4. **Handle idempotently** - Process duplicate events safely
5. **Return 200 quickly** - Acknowledge receipt, process async
## Error Handling
```typescript
async function handleBillingEvent(event: Event) {
try {
await processEvent(event);
} catch (error) {
// Log error for debugging
console.error('Webhook error:', error);
// Store failed event for retry
await prisma.failedWebhook.create({
data: {
eventId: event.id,
type: event.type,
payload: event,
error: error.message,
},
});
// Throw to trigger provider retry
throw error;
}
}
```
## Testing Webhooks
### Using Provider's CLI Tools
```bash
# Stripe
stripe trigger customer.subscription.created
# Test specific scenarios
stripe trigger payment_intent.payment_failed
```
### Manual Testing
```bash
curl -X POST https://your-app.com/api/billing/webhook \
-H "Content-Type: application/json" \
-H "stripe-signature: test_signature" \
-d @test-event.json
```
## Monitoring
Track webhook delivery:
- Response times
- Success/failure rates
- Event processing duration
- Failed events requiring manual intervention
Most providers offer webhook monitoring dashboards showing delivery attempts and failures.

View File

@@ -1,16 +1,36 @@
--- ---
title: "Database" title: "Datensicherheit"
description: "Learn how to work with the Supabase database in your MakerKit application." description: "Wie MYeasyCMS Ihre Vereinsdaten schützt — Verschlüsselung, Zugriffsrechte und Backups."
publishedAt: 2024-04-11 publishedAt: 2024-04-11
order: 2 order: 0
status: "published" status: "published"
--- ---
MakerKit uses Supabase Postgres for database management with built-in security and performance. Die Sicherheit Ihrer Vereinsdaten hat für uns höchste Priorität. MYeasyCMS setzt auf mehrere Schutzebenen.
This section covers: ## Verschlüsselung
- Database schema and structure
- Running migrations Alle Daten werden verschlüsselt übertragen (TLS/SSL). Die Verbindung zwischen Ihrem Browser und dem Server ist jederzeit geschützt — erkennbar am Schloss-Symbol in der Adressleiste.
- Row Level Security (RLS)
- Querying data ## Server in Deutschland
- Functions and triggers
Alle Daten werden auf Servern in deutschen Rechenzentren gespeichert. Es findet keine Datenübertragung in Drittländer statt.
## Zugriffsrechte
MYeasyCMS verwendet ein rollenbasiertes Berechtigungssystem:
- Jeder Benutzer sieht nur die Daten, die für seine Rolle relevant sind
- Der Kassenwart hat Zugriff auf Finanzdaten, nicht auf Protokolle
- Kursleiter sehen ihre Teilnehmer, nicht die Bankverbindungen
- Nur Administratoren können Einstellungen und Benutzer verwalten
## Backups
Regelmäßige automatische Backups schützen gegen Datenverlust. Im Fall eines Problems kann der letzte Stand wiederhergestellt werden.
## Passwortschutz
- Sichere Passwortrichtlinien bei der Registrierung
- Möglichkeit zur Multi-Faktor-Authentifizierung (MFA)
- Automatische Sperrung bei wiederholten Fehlversuchen

View File

@@ -1,446 +1,34 @@
--- ---
title: "Functions & Triggers" title: "Automatisierungen"
description: "Create database functions and triggers for automated logic." description: "Automatische Funktionen in MYeasyCMS — Beitragsberechnung, Benachrichtigungen und mehr."
publishedAt: 2024-04-11 publishedAt: 2024-04-11
order: 4 order: 4
status: "published" status: "published"
--- ---
> **Note:** This is mock/placeholder content for demonstration purposes. MYeasyCMS automatisiert wiederkehrende Aufgaben, damit Sie sich auf die Vereinsarbeit konzentrieren können.
Database functions and triggers enable server-side logic and automation. ## Beitragsberechnung
## Database Functions Beiträge werden automatisch basierend auf den zugewiesenen Beitragskategorien berechnet. Bei Eintritt oder Austritt während des Geschäftsjahres erfolgt die anteilige Berechnung.
### Creating a Function ## SEPA-Erzeugung
```sql Die SEPA-Sammellastschrift wird automatisch aus den hinterlegten Mandaten und offenen Beiträgen zusammengestellt. Sie müssen nur noch prüfen und herunterladen.
CREATE OR REPLACE FUNCTION get_user_projects(user_id UUID)
RETURNS TABLE (
id UUID,
name TEXT,
created_at TIMESTAMPTZ
)
LANGUAGE plpgsql
SECURITY DEFINER
AS $$
BEGIN
RETURN QUERY
SELECT p.id, p.name, p.created_at
FROM projects p
INNER JOIN accounts_memberships am ON am.account_id = p.account_id
WHERE am.user_id = get_user_projects.user_id;
END;
$$;
```
### Calling from TypeScript ## E-Mail-Benachrichtigungen
```typescript Das System versendet automatische Benachrichtigungen bei:
const { data, error } = await client.rpc('get_user_projects', {
user_id: userId,
});
```
## Common Function Patterns - Neuen Kursanmeldungen
- Eingehenden Mitgliedsanträgen
- Fälligen Beiträgen
- Ablaufenden SEPA-Mandaten
### Get User Accounts ## Newsletter-Abonnement
```sql Die An- und Abmeldung von Newslettern wird automatisch verwaltet — inklusive Double-Opt-In und Dokumentation der Einwilligung.
CREATE OR REPLACE FUNCTION get_user_accounts(user_id UUID)
RETURNS TABLE (account_id UUID)
LANGUAGE sql
SECURITY DEFINER
AS $$
SELECT account_id
FROM accounts_memberships
WHERE user_id = $1;
$$;
```
### Check Permission ## Dokumentengenerierung
```sql Mitgliedsausweise, Rechnungen und Serienbriefe werden automatisch aus Vorlagen generiert. Platzhalter werden mit den aktuellen Mitgliederdaten befüllt.
CREATE OR REPLACE FUNCTION has_permission(
user_id UUID,
account_id UUID,
required_role TEXT
)
RETURNS BOOLEAN
LANGUAGE plpgsql
SECURITY DEFINER
AS $$
DECLARE
user_role TEXT;
BEGIN
SELECT role INTO user_role
FROM accounts_memberships
WHERE user_id = has_permission.user_id
AND account_id = has_permission.account_id;
RETURN user_role = required_role OR user_role = 'owner';
END;
$$;
```
### Search Function
```sql
CREATE OR REPLACE FUNCTION search_projects(
search_term TEXT,
account_id UUID
)
RETURNS TABLE (
id UUID,
name TEXT,
description TEXT,
relevance REAL
)
LANGUAGE plpgsql
SECURITY DEFINER
AS $$
BEGIN
RETURN QUERY
SELECT
p.id,
p.name,
p.description,
ts_rank(
to_tsvector('english', p.name || ' ' || COALESCE(p.description, '')),
plainto_tsquery('english', search_term)
) AS relevance
FROM projects p
WHERE p.account_id = search_projects.account_id
AND (
to_tsvector('english', p.name || ' ' || COALESCE(p.description, ''))
@@ plainto_tsquery('english', search_term)
)
ORDER BY relevance DESC;
END;
$$;
```
## Triggers
### Auto-Update Timestamp
```sql
-- Create trigger function
CREATE OR REPLACE FUNCTION update_updated_at_column()
RETURNS TRIGGER
LANGUAGE plpgsql
AS $$
BEGIN
NEW.updated_at = NOW();
RETURN NEW;
END;
$$;
-- Attach to table
CREATE TRIGGER update_projects_updated_at
BEFORE UPDATE ON projects
FOR EACH ROW
EXECUTE FUNCTION update_updated_at_column();
```
### Audit Log Trigger
```sql
-- Create audit log table
CREATE TABLE audit_log (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
table_name TEXT NOT NULL,
record_id UUID NOT NULL,
action TEXT NOT NULL,
old_data JSONB,
new_data JSONB,
user_id UUID,
created_at TIMESTAMPTZ DEFAULT NOW()
);
-- Create trigger function
CREATE OR REPLACE FUNCTION log_changes()
RETURNS TRIGGER
LANGUAGE plpgsql
AS $$
BEGIN
IF TG_OP = 'INSERT' THEN
INSERT INTO audit_log (table_name, record_id, action, new_data, user_id)
VALUES (TG_TABLE_NAME, NEW.id, 'INSERT', to_jsonb(NEW), auth.uid());
RETURN NEW;
ELSIF TG_OP = 'UPDATE' THEN
INSERT INTO audit_log (table_name, record_id, action, old_data, new_data, user_id)
VALUES (TG_TABLE_NAME, NEW.id, 'UPDATE', to_jsonb(OLD), to_jsonb(NEW), auth.uid());
RETURN NEW;
ELSIF TG_OP = 'DELETE' THEN
INSERT INTO audit_log (table_name, record_id, action, old_data, user_id)
VALUES (TG_TABLE_NAME, OLD.id, 'DELETE', to_jsonb(OLD), auth.uid());
RETURN OLD;
END IF;
END;
$$;
-- Attach to table
CREATE TRIGGER audit_projects
AFTER INSERT OR UPDATE OR DELETE ON projects
FOR EACH ROW
EXECUTE FUNCTION log_changes();
```
### Cascade Soft Delete
```sql
CREATE OR REPLACE FUNCTION soft_delete_cascade()
RETURNS TRIGGER
LANGUAGE plpgsql
AS $$
BEGIN
-- Soft delete related tasks
UPDATE tasks
SET deleted_at = NOW()
WHERE project_id = OLD.id
AND deleted_at IS NULL;
RETURN OLD;
END;
$$;
CREATE TRIGGER soft_delete_project_tasks
BEFORE DELETE ON projects
FOR EACH ROW
EXECUTE FUNCTION soft_delete_cascade();
```
## Validation Triggers
### Enforce Business Rules
```sql
CREATE OR REPLACE FUNCTION validate_project_budget()
RETURNS TRIGGER
LANGUAGE plpgsql
AS $$
BEGIN
IF NEW.budget < 0 THEN
RAISE EXCEPTION 'Budget cannot be negative';
END IF;
IF NEW.budget > 1000000 THEN
RAISE EXCEPTION 'Budget cannot exceed 1,000,000';
END IF;
RETURN NEW;
END;
$$;
CREATE TRIGGER check_project_budget
BEFORE INSERT OR UPDATE ON projects
FOR EACH ROW
EXECUTE FUNCTION validate_project_budget();
```
### Prevent Orphaned Records
```sql
CREATE OR REPLACE FUNCTION prevent_owner_removal()
RETURNS TRIGGER
LANGUAGE plpgsql
AS $$
DECLARE
owner_count INTEGER;
BEGIN
IF OLD.role = 'owner' THEN
SELECT COUNT(*) INTO owner_count
FROM accounts_memberships
WHERE account_id = OLD.account_id
AND role = 'owner'
AND id != OLD.id;
IF owner_count = 0 THEN
RAISE EXCEPTION 'Cannot remove the last owner of an account';
END IF;
END IF;
RETURN OLD;
END;
$$;
CREATE TRIGGER check_owner_before_delete
BEFORE DELETE ON accounts_memberships
FOR EACH ROW
EXECUTE FUNCTION prevent_owner_removal();
```
## Computed Columns
### Virtual Column with Function
```sql
CREATE OR REPLACE FUNCTION project_task_count(project_id UUID)
RETURNS INTEGER
LANGUAGE sql
STABLE
AS $$
SELECT COUNT(*)::INTEGER
FROM tasks
WHERE project_id = $1
AND deleted_at IS NULL;
$$;
-- Use in queries
SELECT
id,
name,
project_task_count(id) as task_count
FROM projects;
```
## Event Notifications
### Notify on Changes
```sql
CREATE OR REPLACE FUNCTION notify_project_change()
RETURNS TRIGGER
LANGUAGE plpgsql
AS $$
BEGIN
PERFORM pg_notify(
'project_changes',
json_build_object(
'operation', TG_OP,
'record', NEW
)::text
);
RETURN NEW;
END;
$$;
CREATE TRIGGER project_change_notification
AFTER INSERT OR UPDATE ON projects
FOR EACH ROW
EXECUTE FUNCTION notify_project_change();
```
### Listen in TypeScript
```typescript
const channel = client
.channel('project_changes')
.on(
'postgres_changes',
{
event: '*',
schema: 'public',
table: 'projects',
},
(payload) => {
console.log('Project changed:', payload);
}
)
.subscribe();
```
## Security Functions
### Row Level Security Helper
```sql
CREATE OR REPLACE FUNCTION is_account_member(account_id UUID)
RETURNS BOOLEAN
LANGUAGE sql
SECURITY DEFINER
STABLE
AS $$
SELECT EXISTS (
SELECT 1
FROM accounts_memberships
WHERE account_id = $1
AND user_id = auth.uid()
);
$$;
-- Use in RLS policy
CREATE POLICY "Users can access their account's projects"
ON projects FOR ALL
USING (is_account_member(account_id));
```
## Scheduled Functions
### Using pg_cron Extension
```sql
-- Enable pg_cron extension
CREATE EXTENSION IF NOT EXISTS pg_cron;
-- Schedule cleanup job
SELECT cron.schedule(
'cleanup-old-sessions',
'0 2 * * *', -- Every day at 2 AM
$$
DELETE FROM sessions
WHERE expires_at < NOW();
$$
);
```
## Best Practices
1. **Use SECURITY DEFINER carefully** - Can bypass RLS
2. **Add error handling** - Use EXCEPTION blocks
3. **Keep functions simple** - One responsibility per function
4. **Document functions** - Add comments
5. **Test thoroughly** - Unit test database functions
6. **Use STABLE/IMMUTABLE** - Performance optimization
7. **Avoid side effects** - Make functions predictable
8. **Return proper types** - Use RETURNS TABLE for clarity
## Testing Functions
```sql
-- Test function
DO $$
DECLARE
result INTEGER;
BEGIN
SELECT project_task_count('some-uuid') INTO result;
ASSERT result >= 0, 'Task count should not be negative';
RAISE NOTICE 'Test passed: task count = %', result;
END;
$$;
```
## Debugging
### Enable Function Logging
```sql
CREATE OR REPLACE FUNCTION debug_function()
RETURNS void
LANGUAGE plpgsql
AS $$
BEGIN
RAISE NOTICE 'Debug: Processing started';
RAISE NOTICE 'Debug: Current user is %', auth.uid();
-- Your function logic
RAISE NOTICE 'Debug: Processing completed';
END;
$$;
```
### Check Function Execution
```sql
-- View function execution stats
SELECT
schemaname,
funcname,
calls,
total_time,
self_time
FROM pg_stat_user_functions
ORDER BY total_time DESC;
```

View File

@@ -1,68 +1,27 @@
--- ---
title: "Migrations" title: "Updates und Änderungen"
description: "Learn how to create and manage database migrations in your application." description: "Wie MYeasyCMS aktualisiert wird — automatische Updates ohne Aufwand für den Verein."
publishedAt: 2024-04-11 publishedAt: 2024-04-11
order: 1 order: 1
status: "published" status: "published"
--- ---
> **Note:** This is mock/placeholder content for demonstration purposes. MYeasyCMS wird kontinuierlich weiterentwickelt. Neue Funktionen und Verbesserungen stehen automatisch zur Verfügung.
Database migrations allow you to version control your database schema changes and apply them consistently across environments. ## Automatische Updates
## Creating a Migration Als webbasierte Plattform wird MYeasyCMS zentral aktualisiert. Sie müssen:
To create a new migration, use the following command: - Keine Software herunterladen
- Keine Installation durchführen
- Keine Datenbank-Updates ausführen
```bash Alle Änderungen werden vom Com.BISS-Team eingespielt und getestet, bevor sie live gehen.
pnpm --filter web supabase:db:diff
```
This will generate a new migration file in the `apps/web/supabase/migrations` directory based on the differences between your local database and the schema files. ## Änderungsprotokoll
## Applying Migrations Unter **Changelog** auf der Website informieren wir über neue Funktionen, Verbesserungen und Fehlerbehebungen. Bei größeren Änderungen werden Sie zusätzlich per E-Mail informiert.
To apply migrations to your local database: ## Feedback und Wünsche
```bash Haben Sie Ideen für neue Funktionen oder Verbesserungen? Sprechen Sie uns an — viele Funktionen in MYeasyCMS sind auf Wunsch unserer Kunden entstanden. Neuentwicklungen zu festen Preisen, keine Überraschungen.
pnpm --filter web supabase migrations up
```
## Migration Best Practices
1. **Always test migrations locally first** before applying to production
2. **Make migrations reversible** when possible by including DOWN statements
3. **Use transactions** to ensure atomic operations
4. **Add indexes** for foreign keys and frequently queried columns
5. **Include RLS policies** in the same migration as table creation
## Example Migration
```sql
-- Create a new table
CREATE TABLE tasks (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
account_id UUID NOT NULL REFERENCES accounts(id) ON DELETE CASCADE,
title TEXT NOT NULL,
completed BOOLEAN DEFAULT false,
created_at TIMESTAMPTZ DEFAULT now()
);
-- Add RLS
ALTER TABLE tasks ENABLE ROW LEVEL SECURITY;
-- Create policies
CREATE POLICY "Users can view their account tasks"
ON tasks FOR SELECT
USING (account_id IN (SELECT get_user_accounts(auth.uid())));
```
## Resetting the Database
To completely reset your local database with the latest schema:
```bash
pnpm supabase:web:reset
```
This will drop all tables and reapply all migrations from scratch.

View File

@@ -1,430 +1,34 @@
--- ---
title: "Querying Data" title: "Datenexport"
description: "Learn how to query and filter data from your database." description: "Exportieren Sie Ihre Vereinsdaten in verschiedenen Formaten — für Berichte, Auswertungen und Datensicherung."
publishedAt: 2024-04-11 publishedAt: 2024-04-11
order: 3 order: 1
status: "published" status: "published"
--- ---
> **Note:** This is mock/placeholder content for demonstration purposes. MYeasyCMS bietet umfangreiche Exportmöglichkeiten für alle Ihre Vereinsdaten.
Efficiently query and filter data using Supabase's query builder. ## Exportformate
## Basic Queries - **Excel (.xlsx)** — Für die Weiterverarbeitung in Tabellenkalkulationen
- **CSV** — Universelles Format für den Datenaustausch
- **PDF** — Für druckfertige Berichte und Dokumente
- **SEPA XML (pain.008)** — Für den Bankeinzug per Lastschrift
### Select All ## Was kann exportiert werden?
```typescript ### Mitgliederdaten
const { data, error } = await client Exportieren Sie die vollständige Mitgliederliste oder gefilterte Teilmengen — nach Abteilung, Status, Eintrittsdatum oder anderen Kriterien.
.from('projects')
.select('*');
```
### Select Specific Columns ### Finanzdaten
Beitragsübersichten, offene Posten, Zahlungshistorie und SEPA-Dateien für den Bankeinzug.
```typescript ### Kurs- und Veranstaltungsdaten
const { data, error } = await client Teilnehmerlisten, Kursübersichten und Anwesenheitslisten.
.from('projects')
.select('id, name, created_at');
```
### Select with Related Data ### Dokumente
Generierte Dokumente (Ausweise, Rechnungen, Briefe) als PDF herunterladen.
```typescript ## Datensicherung
const { data, error } = await client
.from('projects')
.select(`
id,
name,
account:accounts(id, name),
tasks(id, title, completed)
`);
```
## Filtering Für die eigene Datensicherung können Sie regelmäßig einen Gesamtexport Ihrer Mitgliederdaten erstellen. Dies dient als zusätzliche Sicherheit neben den automatischen Server-Backups.
### Equal
```typescript
const { data } = await client
.from('projects')
.select('*')
.eq('status', 'active');
```
### Not Equal
```typescript
const { data } = await client
.from('projects')
.select('*')
.neq('status', 'deleted');
```
### Greater Than / Less Than
```typescript
const { data } = await client
.from('projects')
.select('*')
.gt('created_at', '2024-01-01')
.lt('budget', 10000);
```
### In Array
```typescript
const { data } = await client
.from('projects')
.select('*')
.in('status', ['active', 'pending']);
```
### Like (Pattern Matching)
```typescript
const { data } = await client
.from('projects')
.select('*')
.like('name', '%website%');
```
### Full-Text Search
```typescript
const { data } = await client
.from('projects')
.select('*')
.textSearch('description', 'design & development');
```
## Ordering
### Order By
```typescript
const { data } = await client
.from('projects')
.select('*')
.order('created_at', { ascending: false });
```
### Multiple Order By
```typescript
const { data } = await client
.from('projects')
.select('*')
.order('status')
.order('created_at', { ascending: false });
```
## Pagination
### Limit
```typescript
const { data } = await client
.from('projects')
.select('*')
.limit(10);
```
### Range (Offset)
```typescript
const page = 2;
const pageSize = 10;
const from = (page - 1) * pageSize;
const to = from + pageSize - 1;
const { data, count } = await client
.from('projects')
.select('*', { count: 'exact' })
.range(from, to);
```
## Aggregations
### Count
```typescript
const { count } = await client
.from('projects')
.select('*', { count: 'exact', head: true });
```
### Count with Filters
```typescript
const { count } = await client
.from('projects')
.select('*', { count: 'exact', head: true })
.eq('status', 'active');
```
## Advanced Queries
### Multiple Filters
```typescript
const { data } = await client
.from('projects')
.select('*')
.eq('account_id', accountId)
.eq('status', 'active')
.gte('created_at', startDate)
.lte('created_at', endDate)
.order('created_at', { ascending: false })
.limit(20);
```
### OR Conditions
```typescript
const { data } = await client
.from('projects')
.select('*')
.or('status.eq.active,status.eq.pending');
```
### Nested OR
```typescript
const { data } = await client
.from('projects')
.select('*')
.or('and(status.eq.active,priority.eq.high),status.eq.urgent');
```
## Joins
### Inner Join
```typescript
const { data } = await client
.from('projects')
.select(`
*,
account:accounts!inner(
id,
name
)
`)
.eq('account.name', 'Acme Corp');
```
### Left Join
```typescript
const { data } = await client
.from('projects')
.select(`
*,
tasks(*)
`);
```
## Null Handling
### Is Null
```typescript
const { data } = await client
.from('projects')
.select('*')
.is('completed_at', null);
```
### Not Null
```typescript
const { data} = await client
.from('projects')
.select('*')
.not('completed_at', 'is', null);
```
## Insert Data
### Single Insert
```typescript
const { data, error } = await client
.from('projects')
.insert({
name: 'New Project',
account_id: accountId,
status: 'active',
})
.select()
.single();
```
### Multiple Insert
```typescript
const { data, error } = await client
.from('projects')
.insert([
{ name: 'Project 1', account_id: accountId },
{ name: 'Project 2', account_id: accountId },
])
.select();
```
## Update Data
### Update with Filter
```typescript
const { data, error } = await client
.from('projects')
.update({ status: 'completed' })
.eq('id', projectId)
.select()
.single();
```
### Update Multiple Rows
```typescript
const { data, error } = await client
.from('projects')
.update({ status: 'archived' })
.eq('account_id', accountId)
.lt('updated_at', oldDate);
```
## Delete Data
### Delete with Filter
```typescript
const { error } = await client
.from('projects')
.delete()
.eq('id', projectId);
```
### Delete Multiple
```typescript
const { error } = await client
.from('projects')
.delete()
.in('id', projectIds);
```
## Upsert
### Insert or Update
```typescript
const { data, error } = await client
.from('projects')
.upsert({
id: projectId,
name: 'Updated Name',
status: 'active',
})
.select()
.single();
```
## RPC (Stored Procedures)
### Call Database Function
```typescript
const { data, error } = await client
.rpc('get_user_projects', {
user_id: userId,
});
```
### With Complex Parameters
```typescript
const { data, error } = await client
.rpc('search_projects', {
search_term: 'design',
account_ids: [1, 2, 3],
min_budget: 5000,
});
```
## Error Handling
### Basic Error Handling
```typescript
const { data, error } = await client
.from('projects')
.select('*');
if (error) {
console.error('Error fetching projects:', error.message);
throw error;
}
return data;
```
### Typed Error Handling
```typescript
import { PostgrestError } from '@supabase/supabase-js';
function handleDatabaseError(error: PostgrestError) {
switch (error.code) {
case '23505': // unique_violation
throw new Error('A project with this name already exists');
case '23503': // foreign_key_violation
throw new Error('Invalid account reference');
default:
throw new Error('Database error: ' + error.message);
}
}
```
## TypeScript Types
### Generated Types
```typescript
import { Database } from '~/types/database.types';
type Project = Database['public']['Tables']['projects']['Row'];
type ProjectInsert = Database['public']['Tables']['projects']['Insert'];
type ProjectUpdate = Database['public']['Tables']['projects']['Update'];
```
### Typed Queries
```typescript
const { data } = await client
.from('projects')
.select('*')
.returns<Project[]>();
```
## Performance Tips
1. **Select only needed columns** - Don't use `select('*')` unnecessarily
2. **Use indexes** - Create indexes on frequently filtered columns
3. **Limit results** - Always paginate large datasets
4. **Avoid N+1 queries** - Use joins instead of multiple queries
5. **Use RPC for complex queries** - Move logic to database
6. **Cache when possible** - Use React Query or similar
7. **Profile queries** - Use `EXPLAIN ANALYZE` in SQL
## Best Practices
1. **Always handle errors** - Check error responses
2. **Validate input** - Use Zod or similar
3. **Use TypeScript** - Generate and use types
4. **Consistent naming** - Follow database naming conventions
5. **Document complex queries** - Add comments
6. **Test queries** - Unit test database operations
7. **Monitor performance** - Track slow queries

View File

@@ -1,88 +1,41 @@
--- ---
title: "Row Level Security" title: "Zugriffsrechte"
description: "Understanding and implementing Row Level Security (RLS) for data protection." description: "Rollenbasierte Zugriffsrechte — wer welche Daten sehen und bearbeiten darf."
publishedAt: 2024-04-11 publishedAt: 2024-04-11
order: 2 order: 2
status: "published" status: "published"
--- ---
> **Note:** This is mock/placeholder content for demonstration purposes. MYeasyCMS schützt Ihre Daten durch ein feingranulares Berechtigungssystem.
Row Level Security (RLS) is PostgreSQL's built-in authorization system that controls which rows users can access in database tables. ## Rollenkonzept
## Why RLS? Jeder Benutzer erhält eine Rolle, die seinen Zugriff auf Module und Daten steuert. Das Prinzip: Jeder sieht nur das, was er für seine Aufgabe braucht.
RLS provides several advantages: ## Standardrollen
- **Database-level security** - Protection even if application code has bugs
- **Automatic enforcement** - No need for manual authorization checks
- **Multi-tenant isolation** - Ensures users only see their own data
- **Performance** - Optimized at the database level
## Enabling RLS | Rolle | Zugriff |
|-------|---------|
| **Administrator** | Alle Module, Einstellungen, Benutzerverwaltung |
| **Kassenwart** | Finanzen, Beiträge, Mitgliederdaten, SEPA |
| **Kursleiter** | Kurse, Teilnehmer, Anwesenheit |
| **Schriftführer** | Protokolle, Dokumente |
| **Mitglied** | Eigene Daten über das Portal |
All tables should have RLS enabled: ## Datenebene
```sql Die Zugriffsrechte wirken auf Datenebene:
ALTER TABLE your_table ENABLE ROW LEVEL SECURITY;
```
## Common Policy Patterns - Ein Kursleiter sieht nur die Teilnehmer seiner Kurse
- Ein Mitglied sieht nur seine eigenen Daten im Portal
- SEPA-Mandate und Bankverbindungen sind nur für den Kassenwart und Administratoren sichtbar
### Personal Account Access ## Administratorrechte
```sql Nur Administratoren können:
CREATE POLICY "Users can access their personal account data"
ON your_table FOR ALL
USING (account_id = auth.uid());
```
### Team Account Access - Neue Benutzer einladen
- Rollen zuweisen
```sql - Module aktivieren/deaktivieren
CREATE POLICY "Users can access their team account data" - Vereinseinstellungen ändern
ON your_table FOR ALL - Das Audit-Protokoll einsehen
USING (
account_id IN (
SELECT account_id FROM accounts_memberships
WHERE user_id = auth.uid()
)
);
```
### Read vs Write Permissions
```sql
-- All members can read
CREATE POLICY "Team members can view data"
ON your_table FOR SELECT
USING (account_id IN (SELECT get_user_accounts(auth.uid())));
-- Only owners can modify
CREATE POLICY "Only owners can modify data"
ON your_table FOR UPDATE
USING (
account_id IN (
SELECT account_id FROM accounts_memberships
WHERE user_id = auth.uid() AND role = 'owner'
)
);
```
## Testing RLS Policies
Always test your RLS policies to ensure they work correctly:
```sql
-- Test as specific user
SET request.jwt.claims.sub = 'user-uuid-here';
-- Try to select data
SELECT * FROM your_table;
-- Reset
RESET request.jwt.claims.sub;
```
## Admin Bypass
Service role keys bypass RLS. Use with extreme caution and always implement manual authorization checks when using the admin client.

View File

@@ -1,43 +1,38 @@
--- ---
title: "Database Overview" title: "Datenstruktur"
description: "Understanding the database schema and table structure in your application." description: "Wie MYeasyCMS Ihre Vereinsdaten organisiert — Stammdaten, Module und Verknüpfungen."
publishedAt: 2024-04-11 publishedAt: 2024-04-11
order: 0 order: 0
status: "published" status: "published"
--- ---
> **Note:** This is mock/placeholder content for demonstration purposes. MYeasyCMS organisiert Ihre Vereinsdaten in einer durchdachten Struktur.
The database schema is designed with a multi-tenant architecture that supports both personal and team accounts. ## Mitgliederstamm
## Core Tables Im Zentrum steht der Mitgliederstamm. Jedes Mitglied hat:
### Users Table - **Persönliche Daten** — Name, Geburtsdatum, Geschlecht
The `users` table stores user authentication data and is managed by Supabase Auth: - **Kontaktdaten** — Adresse, Telefon, E-Mail
- `id` - Unique user identifier - **Vereinsdaten** — Eintrittsdatum, Mitgliedsnummer, Status
- `email` - User's email address - **Abteilungen** — Zugehörigkeit zu einer oder mehreren Abteilungen
- `created_at` - Account creation timestamp - **SEPA-Mandat** — Bankverbindung und Mandatsdaten
- **Notizen** — Freitextfeld für Anmerkungen
### Accounts Table ## Verknüpfungen
The `accounts` table represents both personal and team accounts:
- `id` - Unique account identifier
- `name` - Account display name
- `slug` - URL-friendly identifier
- `is_personal_account` - Boolean flag for personal vs team accounts
### Projects Table Mitgliederdaten sind mit anderen Modulen verknüpft:
Store your application's project data:
- `id` - Unique project identifier
- `account_id` - Foreign key to accounts table
- `name` - Project name
- `description` - Project description
- `created_at` - Creation timestamp
## Relationships - **Beiträge** — Welche Beiträge sind fällig, bezahlt oder offen?
- **Kurse** — An welchen Kursen nimmt das Mitglied teil?
- **Veranstaltungen** — Für welche Events ist es angemeldet?
- **Dokumente** — Welche Ausweise und Rechnungen wurden generiert?
All data in the application is tied to accounts through foreign key relationships. This ensures proper data isolation and access control through Row Level Security (RLS). ## Individuelle Module
## Next Steps Mit dem Modul-Baukasten können Sie eigene Datenmodule erstellen:
- Learn about [migrations](/docs/database/migrations) - **Felder definieren** — Text, Zahl, Datum, Auswahl, Dateiupload und mehr
- Understand [RLS policies](/docs/database/row-level-security) - **Formulare gestalten** — Layout und Reihenfolge der Felder festlegen
- **Beziehungen** — Module miteinander verknüpfen
- **Import/Export** — Daten aus Excel oder CSV importieren

View File

@@ -1,279 +1,37 @@
--- ---
title: "Features Overview" title: "E-Mail & Newsletter"
description: "Send emails and notifications to your users." description: "Kommunizieren Sie mit Ihren Mitgliedern per E-Mail und Newsletter — direkt aus MYeasyCMS."
publishedAt: 2024-04-11 publishedAt: 2024-04-11
order: 0 order: 1
status: "published" status: "published"
--- ---
> **Note:** This is mock/placeholder content for demonstration purposes. MYeasyCMS integriert E-Mail-Kommunikation und Newsletter-Versand direkt in die Vereinsverwaltung.
The application includes email functionality for transactional messages and user notifications. ## Newsletter erstellen
## Email Configuration Erstellen Sie Newsletter mit dem integrierten Editor:
### Supabase Email (Default) 1. **Kampagne anlegen** — Betreff und Absender festlegen
2. **Inhalt gestalten** — Text, Bilder und Formatierungen hinzufügen
3. **Empfänger wählen** — Alle Mitglieder, einzelne Abteilungen oder manuelle Auswahl
4. **Vorschau prüfen** — So sieht der Newsletter im Posteingang aus
5. **Versenden** — Sofort oder zu einem geplanten Zeitpunkt
By default, emails are sent through Supabase: ## Abonnentenverwaltung
- Authentication emails (sign-up, password reset, magic links)
- Email verification
- Email change confirmation
### Custom SMTP - **Anmeldung** — Neue Abonnenten über die Vereinswebsite mit Double-Opt-In
- **Abmeldung** — Automatischer Abmeldelink in jeder E-Mail
- **Statusverfolgung** — Aktive und inaktive Abonnenten im Überblick
For transactional emails, configure your own SMTP provider: ## Vorlagen
```bash Erstellen Sie Vorlagen für wiederkehrende Newsletter — zum Beispiel den monatlichen Vereinsrundbrief oder Einladungen zu Veranstaltungen.
# .env
SMTP_HOST=smtp.example.com
SMTP_PORT=587
SMTP_USER=your-username
SMTP_PASSWORD=your-password
SMTP_FROM_EMAIL=noreply@yourdomain.com
SMTP_FROM_NAME=Your App Name
```
## Sending Emails ## Datenschutz
### Using the Email Service Der Newsletter-Versand entspricht den DSGVO-Anforderungen:
```typescript - Double-Opt-In für die Anmeldung
import { sendEmail } from '~/lib/email/send-email'; - Dokumentation der Einwilligung
- Einfache Abmeldemöglichkeit in jeder E-Mail
await sendEmail({
to: 'user@example.com',
subject: 'Welcome to Our App',
html: '<h1>Welcome!</h1><p>Thanks for signing up.</p>',
});
```
### Using Email Templates
Create reusable email templates:
```typescript
// lib/email/templates/welcome-email.tsx
import { EmailTemplate } from '~/lib/email/email-template';
interface WelcomeEmailProps {
name: string;
loginUrl: string;
}
export function WelcomeEmail({ name, loginUrl }: WelcomeEmailProps) {
return (
<EmailTemplate>
<h1>Welcome, {name}!</h1>
<p>We're excited to have you on board.</p>
<a href={loginUrl}>Get Started</a>
</EmailTemplate>
);
}
// Send the email
import { render } from '@react-email/render';
import { WelcomeEmail } from '~/lib/email/templates/welcome-email';
const html = render(
<WelcomeEmail name="John" loginUrl="https://app.com/login" />
);
await sendEmail({
to: 'john@example.com',
subject: 'Welcome to Our App',
html,
});
```
## Email Types
### Transactional Emails
Emails triggered by user actions:
- Welcome emails
- Order confirmations
- Password resets
- Account notifications
- Billing updates
### Marketing Emails
Promotional and engagement emails:
- Product updates
- Feature announcements
- Newsletters
- Onboarding sequences
## Email Providers
### Recommended Providers
**Resend** - Developer-friendly email API
```bash
npm install resend
```
```typescript
import { Resend } from 'resend';
const resend = new Resend(process.env.RESEND_API_KEY);
await resend.emails.send({
from: 'noreply@yourdomain.com',
to: 'user@example.com',
subject: 'Welcome',
html: emailHtml,
});
```
**SendGrid** - Comprehensive email platform
```bash
npm install @sendgrid/mail
```
```typescript
import sgMail from '@sendgrid/mail';
sgMail.setApiKey(process.env.SENDGRID_API_KEY);
await sgMail.send({
to: 'user@example.com',
from: 'noreply@yourdomain.com',
subject: 'Welcome',
html: emailHtml,
});
```
**Postmark** - Fast transactional email
```bash
npm install postmark
```
## In-App Notifications
### Notification System
Send in-app notifications to users:
```typescript
import { createNotification } from '~/lib/notifications';
await createNotification({
userId: user.id,
title: 'New Message',
message: 'You have a new message from John',
type: 'info',
link: '/messages/123',
});
```
### Notification Types
```typescript
type NotificationType = 'info' | 'success' | 'warning' | 'error';
await createNotification({
userId: user.id,
title: 'Payment Successful',
message: 'Your subscription has been renewed',
type: 'success',
});
```
### Fetching Notifications
```typescript
import { getUserNotifications } from '~/lib/notifications';
const notifications = await getUserNotifications(userId, {
limit: 10,
unreadOnly: true,
});
```
### Marking as Read
```typescript
import { markNotificationAsRead } from '~/lib/notifications';
await markNotificationAsRead(notificationId);
```
## Real-time Notifications
Use Supabase Realtime for instant notifications:
```typescript
'use client';
import { useEffect } from 'react';
import { useSupabase } from '@kit/supabase/hooks/use-supabase';
export function NotificationListener() {
const supabase = useSupabase();
useEffect(() => {
const channel = supabase
.channel('notifications')
.on(
'postgres_changes',
{
event: 'INSERT',
schema: 'public',
table: 'notifications',
filter: `user_id=eq.${userId}`,
},
(payload) => {
// Show toast notification
toast.info(payload.new.title);
}
)
.subscribe();
return () => {
supabase.removeChannel(channel);
};
}, [supabase]);
return null;
}
```
## Email Templates Best Practices
1. **Keep it simple** - Plain text and minimal HTML
2. **Mobile responsive** - Most emails are read on mobile
3. **Clear CTAs** - Make action buttons prominent
4. **Personalize** - Use user's name and relevant data
5. **Test rendering** - Check across email clients
6. **Include plain text** - Always provide text alternative
7. **Unsubscribe link** - Required for marketing emails
## Testing Emails
### Local Development
In development, emails are caught by InBucket:
```
http://localhost:54324
```
### Preview Emails
Use React Email to preview templates:
```bash
npm run email:dev
```
Visit `http://localhost:3001` to see email previews.
## Deliverability Tips
1. **Authenticate your domain** - Set up SPF, DKIM, DMARC
2. **Warm up your domain** - Start with low volumes
3. **Monitor bounce rates** - Keep below 5%
4. **Avoid spam triggers** - Don't use all caps, excessive punctuation
5. **Provide value** - Only send relevant, useful emails
6. **Easy unsubscribe** - Make it one-click simple

View File

@@ -1,16 +1,73 @@
--- ---
title: "Features" title: "Funktionen"
description: "Learn about the built-in features available in MakerKit." description: "Überblick über die Kernfunktionen von MYeasyCMS — Mitgliederverwaltung, Finanzen, Kurse, Veranstaltungen und mehr."
publishedAt: 2024-04-11 publishedAt: 2024-04-11
order: 3 order: 0
status: "published" status: "published"
--- ---
MakerKit comes with a rich set of features to help you build your SaaS quickly. MYeasyCMS bietet eine umfassende Palette von Funktionen für die tägliche Vereinsarbeit.
This section covers: ## Mitgliederverwaltung
- Team collaboration
- File uploads - **Stammdaten** — Name, Adresse, Kontaktdaten, Geburtsdatum, Fotos
- Email functionality - **Abteilungen** — Mitglieder verschiedenen Abteilungen zuordnen
- User management - **SEPA-Mandate** — Lastschriftmandate direkt im Mitgliedsstamm verwalten
- And more built-in features - **Mitgliedsausweise** — Ausweise aus Vorlagen generieren (mit Foto und Barcode)
- **Ein-/Austritte** — Historisierte Dokumentation aller Statusänderungen
- **Import/Export** — Mitgliederlisten aus Excel/CSV importieren und exportieren
- **Statistiken** — Mitgliederentwicklung, Altersstruktur, Abteilungsverteilung
## Finanzen & SEPA
- **Beitragskategorien** — Verschiedene Beitragssätze definieren und zuordnen
- **SEPA-Sammellastschrift** — XML-Dateien (pain.008) für den Bankeinzug erzeugen
- **Rechnungen** — Erstellen, versenden und nachverfolgen
- **Zahlungsverfolgung** — Offene Posten, Mahnwesen, Rückläufer
- **Geschäftsjahre** — Jahresabschluss und Übertrag
## Kursverwaltung
- **Kurse anlegen** — Titel, Beschreibung, Termine, Dozent, Kosten
- **Teilnehmerverwaltung** — Anmeldungen, Wartelisten, Anwesenheit
- **Kalender** — Übersichtliche Terminplanung mit Ferien- und Feiertagsberücksichtigung
- **Kategorien und Orte** — Kurstypen und Veranstaltungsorte verwalten
- **Online-Anmeldung** — Teilnehmer können sich über die Vereinswebsite anmelden
## Veranstaltungen
- **Eventplanung** — Veranstaltungen mit Beschreibung, Ort, Datum und Kapazität
- **Registrierungen** — Online-Anmeldung und Teilnehmerlisten
- **Ferienpässe** — Verwaltung von Ferienprogrammen (entwickelt mit der Stadt Regensburg)
## Newsletter
- **Kampagnen erstellen** — E-Mails mit Vorlagen gestalten
- **Empfänger verwalten** — Versand an Abteilungen, Gruppen oder individuelle Listen
- **An-/Abmeldung** — Automatische Verwaltung mit Double-Opt-In
## Dokumente
- **Vorlagen** — Briefvorlagen, Etiketten, Ausweise, Zertifikate
- **Seriendokumente** — Massengenerierung für alle Mitglieder oder Gruppen
- **Export** — PDF- und Excel-Export
## Site-Builder
- **Drag-and-Drop** — Seiten visuell zusammenbauen
- **Vereinsdaten einbinden** — Kurse, Veranstaltungen und Kontakte direkt anzeigen
- **Responsive** — Automatisch für alle Bildschirmgrößen optimiert
## Fischereiverwaltung
- **Gewässer** — Gewässerverzeichnis mit Details und Karten
- **Besatzmaßnahmen** — Dokumentation von Fischbesatz
- **Fangbücher** — Digitale Fangbuchführung
- **Erlaubnisscheine** — Ausgabe und Verwaltung von Fischereierlaubnisscheinen
- **Statistiken** — Fang- und Besatzauswertungen
## Sitzungsprotokolle
- **Protokolle** — Sitzungsprotokolle mit Tagesordnungspunkten erstellen
- **Aufgaben** — Aufgaben aus Protokollen ableiten und nachverfolgen
- **Beschlüsse** — Beschlüsse dokumentieren und archivieren

View File

@@ -1,398 +1,37 @@
--- ---
title: "File Uploads" title: "Dateien und Dokumente"
description: "Handle file uploads with Supabase Storage." description: "Verwalten und generieren Sie Dokumente — Mitgliedsausweise, Rechnungen, Briefe und mehr."
publishedAt: 2024-04-11 publishedAt: 2024-04-11
order: 2 order: 3
status: "published" status: "published"
--- ---
> **Note:** This is mock/placeholder content for demonstration purposes. MYeasyCMS bietet integrierte Dokumentenverwaltung und -generierung.
Enable users to upload and manage files using Supabase Storage. ## Dokumentenvorlagen
## Setup Erstellen Sie Vorlagen für häufig benötigte Dokumente:
### Create Storage Bucket - **Mitgliedsausweise** — Mit Foto, Mitgliedsnummer und Barcode
- **Rechnungen** — Für Beiträge, Kursgebühren und sonstige Leistungen
- **Briefe** — Serienbriefe an Mitglieder oder Gruppen
- **Etiketten** — Adressetiketten für den Postversand
- **Zertifikate** — Teilnahmebestätigungen für Kurse und Lehrgänge
- **Berichte** — Mitgliederlisten und Statistiken
```sql ## Seriendokumente
-- Create a public bucket for avatars
INSERT INTO storage.buckets (id, name, public)
VALUES ('avatars', 'avatars', true);
-- Create a private bucket for documents Generieren Sie Dokumente für mehrere Mitglieder gleichzeitig. Platzhalter in der Vorlage werden automatisch mit den Mitgliederdaten gefüllt.
INSERT INTO storage.buckets (id, name, public)
VALUES ('documents', 'documents', false);
```
### Set Storage Policies ## Dateiverwaltung
```sql Laden Sie Dateien direkt in MYeasyCMS hoch und organisieren Sie Ihre Vereinsdokumente:
-- Allow users to upload their own avatars
CREATE POLICY "Users can upload their own avatar"
ON storage.objects FOR INSERT
WITH CHECK (
bucket_id = 'avatars' AND
auth.uid()::text = (storage.foldername(name))[1]
);
-- Allow users to view their own avatars - Satzung und Geschäftsordnung
CREATE POLICY "Users can view their own avatar" - Protokolle und Beschlüsse
ON storage.objects FOR SELECT - Formulare und Vordrucke
USING ( - Fotos und Medien
bucket_id = 'avatars' AND
auth.uid()::text = (storage.foldername(name))[1]
);
-- Allow users to delete their own avatars ## Export
CREATE POLICY "Users can delete their own avatar"
ON storage.objects FOR DELETE
USING (
bucket_id = 'avatars' AND
auth.uid()::text = (storage.foldername(name))[1]
);
```
## Upload Component Alle generierten Dokumente können als PDF heruntergeladen werden. Listen und Auswertungen sind zusätzlich als Excel-Export verfügbar.
### Basic File Upload
```tsx
'use client';
import { useState } from 'react';
import { uploadFileAction } from '../_lib/actions';
export function FileUpload() {
const [uploading, setUploading] = useState(false);
const [file, setFile] = useState<File | null>(null);
const handleUpload = async () => {
if (!file) return;
setUploading(true);
const formData = new FormData();
formData.append('file', file);
const result = await uploadFileAction(formData);
if (result.success) {
toast.success('File uploaded successfully');
}
setUploading(false);
};
return (
<div>
<input
type="file"
onChange={(e) => setFile(e.files?.[0] || null)}
accept="image/*"
/>
<button
onClick={handleUpload}
disabled={!file || uploading}
>
{uploading ? 'Uploading...' : 'Upload'}
</button>
</div>
);
}
```
### Server Action
```typescript
'use server';
import { enhanceAction } from '@kit/next/actions';
import { getSupabaseServerClient } from '@kit/supabase/server-client';
export const uploadFileAction = enhanceAction(
async (formData: FormData, user) => {
const file = formData.get('file') as File;
if (!file) {
throw new Error('No file provided');
}
const client = getSupabaseServerClient();
const fileExt = file.name.split('.').pop();
const fileName = `${user.id}/${Date.now()}.${fileExt}`;
const { data, error } = await client.storage
.from('avatars')
.upload(fileName, file, {
cacheControl: '3600',
upsert: false,
});
if (error) throw error;
// Get public URL
const { data: { publicUrl } } = client.storage
.from('avatars')
.getPublicUrl(fileName);
return {
success: true,
url: publicUrl,
path: data.path,
};
},
{ auth: true }
);
```
## Drag and Drop Upload
```tsx
'use client';
import { useCallback } from 'react';
import { useDropzone } from 'react-dropzone';
export function DragDropUpload() {
const onDrop = useCallback(async (acceptedFiles: File[]) => {
for (const file of acceptedFiles) {
const formData = new FormData();
formData.append('file', file);
await uploadFileAction(formData);
}
}, []);
const { getRootProps, getInputProps, isDragActive } = useDropzone({
onDrop,
accept: {
'image/*': ['.png', '.jpg', '.jpeg', '.gif'],
},
maxSize: 5 * 1024 * 1024, // 5MB
});
return (
<div
{...getRootProps()}
className={cn(
'border-2 border-dashed rounded-lg p-8 text-center cursor-pointer',
isDragActive && 'border-primary bg-primary/10'
)}
>
<input {...getInputProps()} />
{isDragActive ? (
<p>Drop files here...</p>
) : (
<p>Drag and drop files here, or click to select</p>
)}
</div>
);
}
```
## File Validation
### Client-Side Validation
```typescript
function validateFile(file: File) {
const maxSize = 5 * 1024 * 1024; // 5MB
const allowedTypes = ['image/jpeg', 'image/png', 'image/gif'];
if (file.size > maxSize) {
throw new Error('File size must be less than 5MB');
}
if (!allowedTypes.includes(file.type)) {
throw new Error('File type must be JPEG, PNG, or GIF');
}
return true;
}
```
### Server-Side Validation
```typescript
export const uploadFileAction = enhanceAction(
async (formData: FormData, user) => {
const file = formData.get('file') as File;
// Validate file size
if (file.size > 5 * 1024 * 1024) {
throw new Error('File too large');
}
// Validate file type
const allowedTypes = ['image/jpeg', 'image/png', 'image/gif'];
if (!allowedTypes.includes(file.type)) {
throw new Error('Invalid file type');
}
// Validate dimensions for images
if (file.type.startsWith('image/')) {
const dimensions = await getImageDimensions(file);
if (dimensions.width > 4000 || dimensions.height > 4000) {
throw new Error('Image dimensions too large');
}
}
// Continue with upload...
},
{ auth: true }
);
```
## Image Optimization
### Resize on Upload
```typescript
import sharp from 'sharp';
export const uploadAvatarAction = enhanceAction(
async (formData: FormData, user) => {
const file = formData.get('file') as File;
const buffer = Buffer.from(await file.arrayBuffer());
// Resize image
const resized = await sharp(buffer)
.resize(200, 200, {
fit: 'cover',
position: 'center',
})
.jpeg({ quality: 90 })
.toBuffer();
const client = getSupabaseServerClient();
const fileName = `${user.id}/avatar.jpg`;
const { error } = await client.storage
.from('avatars')
.upload(fileName, resized, {
contentType: 'image/jpeg',
upsert: true,
});
if (error) throw error;
return { success: true };
},
{ auth: true }
);
```
## Progress Tracking
```tsx
'use client';
import { useState } from 'react';
export function UploadWithProgress() {
const [progress, setProgress] = useState(0);
const handleUpload = async (file: File) => {
const client = getSupabaseBrowserClient();
const { error } = await client.storage
.from('documents')
.upload(`uploads/${file.name}`, file, {
onUploadProgress: (progressEvent) => {
const percent = (progressEvent.loaded / progressEvent.total) * 100;
setProgress(Math.round(percent));
},
});
if (error) throw error;
};
return (
<div>
<input type="file" onChange={(e) => handleUpload(e.target.files![0])} />
{progress > 0 && (
<div className="w-full bg-gray-200 rounded-full h-2">
<div
className="bg-primary h-2 rounded-full transition-all"
style={{ width: `${progress}%` }}
/>
</div>
)}
</div>
);
}
```
## Downloading Files
### Get Public URL
```typescript
const { data } = client.storage
.from('avatars')
.getPublicUrl('user-id/avatar.jpg');
console.log(data.publicUrl);
```
### Download Private File
```typescript
const { data, error } = await client.storage
.from('documents')
.download('private-file.pdf');
if (data) {
const url = URL.createObjectURL(data);
const a = document.createElement('a');
a.href = url;
a.download = 'file.pdf';
a.click();
}
```
### Generate Signed URL
```typescript
const { data, error } = await client.storage
.from('documents')
.createSignedUrl('private-file.pdf', 3600); // 1 hour
console.log(data.signedUrl);
```
## Deleting Files
```typescript
export const deleteFileAction = enhanceAction(
async (data, user) => {
const client = getSupabaseServerClient();
const { error } = await client.storage
.from('avatars')
.remove([data.path]);
if (error) throw error;
return { success: true };
},
{
schema: z.object({
path: z.string(),
}),
auth: true,
}
);
```
## Best Practices
1. **Validate on both sides** - Client and server
2. **Limit file sizes** - Prevent abuse
3. **Sanitize filenames** - Remove special characters
4. **Use unique names** - Prevent collisions
5. **Optimize images** - Resize before upload
6. **Set storage policies** - Control access
7. **Monitor usage** - Track storage costs
8. **Clean up unused files** - Regular maintenance
9. **Use CDN** - For public files
10. **Implement virus scanning** - For user uploads

View File

@@ -1,276 +1,32 @@
--- ---
title: "Team Collaboration" title: "Teamarbeit"
description: "Manage team members, roles, and permissions in your application." description: "Arbeiten Sie im Team — mit Rollen, Berechtigungen und gemeinsamer Datenpflege."
publishedAt: 2024-04-11 publishedAt: 2024-04-11
order: 1 order: 2
status: "published" status: "published"
--- ---
> **Note:** This is mock/placeholder content for demonstration purposes. MYeasyCMS ist für die Zusammenarbeit im Vereinsvorstand konzipiert. Mehrere Benutzer können gleichzeitig arbeiten.
Enable teams to collaborate effectively with built-in team management features. ## Mehrere Benutzer
## Team Accounts Fügen Sie beliebig viele Benutzer zu Ihrem Vereins-Account hinzu. Es gibt keine Begrenzung der Benutzeranzahl — alle Tarife enthalten unbegrenzte Zugänge.
The application supports multi-tenant team accounts where multiple users can collaborate. ## Rollenbasierte Zugriffskontrolle
### Creating a Team Jeder Benutzer sieht nur die Daten, die für seine Aufgabe relevant sind:
Users can create new team accounts: | Rolle | Zugriff |
|-------|---------|
| Administrator | Alle Module und Einstellungen |
| Kassenwart | Finanzen, Beiträge, Mitgliederdaten |
| Kursleiter | Kursverwaltung, Teilnehmer |
| Schriftführer | Protokolle, Dokumente |
```typescript ## Einladungen
import { createTeamAccount } from '~/lib/teams/create-team';
const team = await createTeamAccount({ Neue Benutzer werden per E-Mail eingeladen. Die Einladung enthält einen Registrierungslink, über den der neue Benutzer sein Konto erstellt.
name: 'Acme Corp',
slug: 'acme-corp',
ownerId: currentUser.id,
});
```
### Team Workspace ## Aktivitätsprotokoll
Each team has its own workspace with isolated data: Unter **Verwaltung → Audit** sehen Administratoren, wer wann welche Änderungen vorgenommen hat. Das Protokoll hilft bei der Nachverfolgung und Qualitätssicherung.
- Projects and resources
- Team-specific settings
- Billing and subscription
- Activity logs
## Inviting Members
### Send Invitations
Invite new members to your team:
```typescript
import { inviteTeamMember } from '~/lib/teams/invitations';
await inviteTeamMember({
teamId: team.id,
email: 'member@example.com',
role: 'member',
});
```
### Invitation Flow
1. Owner sends invitation via email
2. Recipient receives email with invitation link
3. Recipient accepts invitation
4. Member gains access to team workspace
### Managing Invitations
```tsx
import { PendingInvitations } from '~/components/teams/pending-invitations';
<PendingInvitations teamId={team.id} />
```
## Roles and Permissions
### Default Roles
**Owner**
- Full access to team and settings
- Manage billing and subscriptions
- Invite and remove members
- Delete team
**Admin**
- Manage team members
- Manage team resources
- Cannot access billing
- Cannot delete team
**Member**
- View team resources
- Create and edit own content
- Limited team settings access
### Custom Roles
Define custom roles with specific permissions:
```typescript
const customRole = {
name: 'Editor',
permissions: [
'read:projects',
'write:projects',
'read:members',
],
};
```
### Checking Permissions
```typescript
import { checkPermission } from '~/lib/teams/permissions';
const canEdit = await checkPermission(userId, teamId, 'write:projects');
if (!canEdit) {
throw new Error('Insufficient permissions');
}
```
## Member Management
### Listing Members
```typescript
import { getTeamMembers } from '~/lib/teams/members';
const members = await getTeamMembers(teamId);
```
### Updating Member Role
```typescript
import { updateMemberRole } from '~/lib/teams/members';
await updateMemberRole({
memberId: member.id,
role: 'admin',
});
```
### Removing Members
```typescript
import { removeMember } from '~/lib/teams/members';
await removeMember(memberId);
```
## Team Settings
### Updating Team Info
```tsx
'use client';
import { useForm } from 'react-hook-form';
import { updateTeamAction } from '../_lib/server/actions';
export function TeamSettingsForm({ team }) {
const { register, handleSubmit } = useForm({
defaultValues: {
name: team.name,
description: team.description,
},
});
const onSubmit = async (data) => {
await updateTeamAction({ teamId: team.id, ...data });
};
return (
<form onSubmit={handleSubmit(onSubmit)}>
<input {...register('name')} placeholder="Team name" />
<textarea {...register('description')} placeholder="Description" />
<button type="submit">Save Changes</button>
</form>
);
}
```
### Team Avatar
```typescript
import { uploadTeamAvatar } from '~/lib/teams/avatar';
const avatarUrl = await uploadTeamAvatar({
teamId: team.id,
file: avatarFile,
});
```
## Activity Log
Track team activity for transparency:
```typescript
import { logActivity } from '~/lib/teams/activity';
await logActivity({
teamId: team.id,
userId: user.id,
action: 'member_invited',
metadata: {
invitedEmail: 'new@example.com',
},
});
```
### Viewing Activity
```typescript
import { getTeamActivity } from '~/lib/teams/activity';
const activities = await getTeamActivity(teamId, {
limit: 50,
offset: 0,
});
```
## Team Switching
Allow users to switch between their teams:
```tsx
'use client';
import { useTeamAccountWorkspace } from '@kit/team-accounts/hooks/use-team-account-workspace';
export function TeamSwitcher() {
const { accounts, account } = useTeamAccountWorkspace();
return (
<select
value={account.id}
onChange={(e) => switchTeam(e.target.value)}
>
{accounts.map((team) => (
<option key={team.id} value={team.id}>
{team.name}
</option>
))}
</select>
);
}
```
## Notifications
### Member Joined
```typescript
await createNotification({
teamId: team.id,
title: 'New Member',
message: `${user.name} joined the team`,
type: 'info',
});
```
### Role Changed
```typescript
await createNotification({
userId: member.userId,
title: 'Role Updated',
message: `Your role was changed to ${newRole}`,
type: 'info',
});
```
## Best Practices
1. **Clear role hierarchy** - Define roles that make sense for your use case
2. **Principle of least privilege** - Give minimum required permissions
3. **Audit trail** - Log important team actions
4. **Easy onboarding** - Simple invitation process
5. **Self-service** - Let members manage their own settings
6. **Transparent billing** - Show usage and costs clearly

View File

@@ -1,350 +1,43 @@
--- ---
title: "Configuration" title: "Konfiguration"
description: "Configure your application settings and feature flags." description: "MYeasyCMS an Ihren Verein anpassen — Stammdaten, Module, Rollen und Grundeinstellungen konfigurieren."
publishedAt: 2024-04-11 publishedAt: 2024-04-11
order: 4 order: 2
status: "published" status: "published"
--- ---
> **Note:** This is mock/placeholder content for demonstration purposes. Nach dem ersten Login sollten Sie die Grundeinstellungen Ihres Vereins konfigurieren.
Customize your application behavior through configuration files. ## Vereinsstammdaten
## Configuration Files Unter **Einstellungen → Vereinsdaten** hinterlegen Sie:
All configuration files are located in `apps/web/config/`: - **Vereinsname** — Der offizielle Name laut Satzung
- **Adresse** — Anschrift des Vereinssitzes
- **Kontaktdaten** — Telefon, E-Mail, Website
- **Bankverbindung** — IBAN und BIC für den SEPA-Einzug
- **Gläubiger-ID** — Ihre SEPA-Gläubiger-Identifikationsnummer
- **Vereinslogo** — Wird auf Ausweisen, Rechnungen und der Website angezeigt
``` ## Abteilungen und Gruppen
config/
├── paths.config.ts # Route paths
├── billing.config.ts # Billing & pricing
├── feature-flags.config.ts # Feature toggles
├── personal-account-navigation.config.tsx
├── team-account-navigation.config.tsx
└── i18n.settings.ts # Internationalization
```
## Feature Flags Unter **Mitglieder → Abteilungen** legen Sie die Struktur Ihres Vereins an. Abteilungen werden für die Beitragsberechnung, Kommunikation und Statistiken verwendet.
Control feature availability: ## Beitragskategorien
```typescript Unter **Finanzen → Beitragskategorien** definieren Sie die verschiedenen Beitragssätze:
// config/feature-flags.config.ts
export const featureFlags = {
enableTeamAccounts: true,
enableBilling: true,
enableNotifications: true,
enableFileUploads: false,
enableAnalytics: true,
enableChat: false,
};
```
### Using Feature Flags - **Bezeichnung** — z.B. „Erwachsene", „Jugendliche", „Familie"
- **Jahresbeitrag** — Der reguläre Beitragssatz
- **Aufnahmegebühr** — Einmalige Gebühr bei Eintritt (optional)
- **Abrechnungszeitraum** — Jährlich, halbjährlich oder quartalsweise
```typescript ## Rollen und Berechtigungen
import { featureFlags } from '~/config/feature-flags.config';
export function ConditionalFeature() { MYeasyCMS verwendet ein rollenbasiertes Berechtigungssystem. Jeder Benutzer erhält eine oder mehrere Rollen, die seinen Zugriff steuern.
if (!featureFlags.enableChat) {
return null;
}
return <ChatWidget />; Die Rollen können unter **Einstellungen → Mitarbeiter** zugewiesen werden.
}
```
## Path Configuration ## E-Mail-Einstellungen
Define application routes: Für den Versand von Newslettern und Benachrichtigungen konfigurieren Sie unter **Einstellungen → E-Mail** Ihre Absenderdaten.
```typescript
// config/paths.config.ts
export const pathsConfig = {
auth: {
signIn: '/auth/sign-in',
signUp: '/auth/sign-up',
passwordReset: '/auth/password-reset',
callback: '/auth/callback',
},
app: {
home: '/home',
personalAccount: '/home',
teamAccount: '/home/[account]',
settings: '/home/settings',
billing: '/home/settings/billing',
},
admin: {
home: '/admin',
users: '/admin/users',
analytics: '/admin/analytics',
},
};
```
### Using Paths
```typescript
import { pathsConfig } from '~/config/paths.config';
import Link from 'next/link';
<Link href={pathsConfig.app.settings}>
Settings
</Link>
```
## Navigation Configuration
### Personal Account Navigation
```typescript
// config/personal-account-navigation.config.tsx
import { HomeIcon, SettingsIcon } from 'lucide-react';
export default [
{
label: 'common.routes.home',
path: pathsConfig.app.personalAccount,
Icon: <HomeIcon className="w-4" />,
end: true,
},
{
label: 'common.routes.settings',
path: pathsConfig.app.settings,
Icon: <SettingsIcon className="w-4" />,
},
];
```
### Team Account Navigation
```typescript
// config/team-account-navigation.config.tsx
export default [
{
label: 'common.routes.dashboard',
path: createPath(pathsConfig.app.teamAccount, account),
Icon: <LayoutDashboardIcon className="w-4" />,
end: true,
},
{
label: 'common.routes.projects',
path: createPath(pathsConfig.app.projects, account),
Icon: <FolderIcon className="w-4" />,
},
{
label: 'common.routes.members',
path: createPath(pathsConfig.app.members, account),
Icon: <UsersIcon className="w-4" />,
},
];
```
## Billing Configuration
```typescript
// config/billing.config.ts
export const billingConfig = {
provider: 'stripe', // 'stripe' | 'paddle'
enableTrial: true,
trialDays: 14,
plans: [
{
id: 'free',
name: 'Free',
price: 0,
features: ['5 projects', 'Basic support'],
limits: {
projects: 5,
members: 1,
},
},
{
id: 'pro',
name: 'Professional',
price: 29,
interval: 'month',
features: ['Unlimited projects', 'Priority support'],
limits: {
projects: -1, // unlimited
members: 10,
},
},
],
};
```
## Internationalization
```typescript
// lib/i18n/i18n.settings.ts
export const i18nSettings = {
defaultLocale: 'en',
locales: ['en', 'es', 'fr', 'de'],
defaultNamespace: 'common',
namespaces: ['common', 'auth', 'billing', 'errors'],
};
```
## Email Configuration
```typescript
// config/email.config.ts
export const emailConfig = {
from: {
email: process.env.EMAIL_FROM || 'noreply@example.com',
name: process.env.EMAIL_FROM_NAME || 'Your App',
},
provider: 'resend', // 'resend' | 'sendgrid' | 'postmark'
};
```
## SEO Configuration
```typescript
// config/seo.config.ts
export const seoConfig = {
title: 'Your App Name',
description: 'Your app description',
ogImage: '/images/og-image.png',
twitterHandle: '@yourapp',
locale: 'en_US',
// Per-page overrides
pages: {
home: {
title: 'Home - Your App',
description: 'Welcome to your app',
},
pricing: {
title: 'Pricing - Your App',
description: 'Simple, transparent pricing',
},
},
};
```
## Theme Configuration
```typescript
// config/theme.config.ts
export const themeConfig = {
defaultTheme: 'system', // 'light' | 'dark' | 'system'
enableColorSchemeToggle: true,
colors: {
primary: 'blue',
accent: 'purple',
},
};
```
## Analytics Configuration
```typescript
// config/analytics.config.ts
export const analyticsConfig = {
googleAnalytics: {
enabled: true,
measurementId: process.env.NEXT_PUBLIC_GA_ID,
},
posthog: {
enabled: false,
apiKey: process.env.NEXT_PUBLIC_POSTHOG_KEY,
},
plausible: {
enabled: false,
domain: process.env.NEXT_PUBLIC_PLAUSIBLE_DOMAIN,
},
};
```
## Rate Limiting
```typescript
// config/rate-limit.config.ts
export const rateLimitConfig = {
api: {
windowMs: 15 * 60 * 1000, // 15 minutes
max: 100, // requests per window
},
auth: {
windowMs: 15 * 60 * 1000,
max: 5, // login attempts
},
};
```
## Upload Configuration
```typescript
// config/upload.config.ts
export const uploadConfig = {
maxFileSize: 5 * 1024 * 1024, // 5MB
allowedMimeTypes: [
'image/jpeg',
'image/png',
'image/gif',
'image/webp',
'application/pdf',
],
storage: {
provider: 'supabase', // 'supabase' | 's3' | 'cloudinary'
bucket: 'uploads',
},
};
```
## Environment-Specific Config
```typescript
// config/app.config.ts
const isDev = process.env.NODE_ENV === 'development';
const isProd = process.env.NODE_ENV === 'production';
export const appConfig = {
environment: process.env.NODE_ENV,
apiUrl: isProd
? 'https://api.yourapp.com'
: 'http://localhost:3000/api',
features: {
enableDebugTools: isDev,
enableErrorReporting: isProd,
enableAnalytics: isProd,
},
};
```
## Best Practices
1. **Use environment variables** for secrets
2. **Type your configs** for autocomplete and safety
3. **Document options** with comments
4. **Validate on startup** to catch errors early
5. **Keep configs simple** - avoid complex logic
6. **Use feature flags** for gradual rollouts
7. **Environment-specific values** for dev/prod differences
## Loading Configuration
Configs are automatically loaded but you can validate:
```typescript
// lib/config/validate-config.ts
import * as z from 'zod';
const ConfigSchema = z.object({
apiUrl: z.string().url(),
enableFeatureX: z.boolean(),
});
export function validateConfig(config: unknown) {
return ConfigSchema.parse(config);
}
```

View File

@@ -1,30 +1,50 @@
--- ---
title: "Introduction" title: "Einführung"
description: "Makerkit is a SaaS Starter Kit that helps you build a SaaS. Learn how to get started with Makerkit." description: "MYeasyCMS ist die webbasierte Vereins- und Verbandsverwaltung von Com.BISS GmbH. Seit 2004 unterstützt die Plattform Vereine, Verbände und Bildungseinrichtungen in ganz Bayern."
publishedAt: 2024-04-11 publishedAt: 2024-04-11
order: 0 order: 0
status: "published" status: "published"
--- ---
> **Note:** This is mock/placeholder content for demonstration purposes. MYeasyCMS ist die webbasierte Verwaltungsplattform für Vereine, Verbände und Organisationen. Entwickelt von der Com.BISS GmbH in Schierling bei Regensburg, wird die Software seit 2004 kontinuierlich weiterentwickelt und betreut über 69.000 Mitglieder in mehr als 90 angebundenen Vereinen.
Makerkit is a SaaS Starter Kit that helps you build a SaaS. It provides you with a set of tools and best practices to help you build a SaaS quickly and efficiently. ## Für wen ist MYeasyCMS?
## Getting started - **Vereine** — Sportvereine, Fischereivereine, Kulturvereine und andere gemeinnützige Organisationen
- **Verbände** — Bezirksfischereiverbände, Kreisverbände und Dachorganisationen mit Untergliedern
- **Bildungseinrichtungen** — Volkshochschulen und andere Kursanbieter
- **Kommunale Einrichtungen** — Städte und Gemeinden mit Veranstaltungs- und Raumbuchungsverwaltung
To get started follow these steps: ## Module im Überblick
1. Sign up for an account on the [website](#). MYeasyCMS ist modular aufgebaut. Sie aktivieren nur die Module, die Ihr Verein tatsächlich braucht:
2. Create a new project by clicking on the "New Project" button.
3. Choose a template for your project. Makerkit provides several templates to help you get started quickly.
## Features | Modul | Funktion |
|-------|----------|
| **Mitgliederverwaltung** | Stammdaten, Abteilungen, Mandate, Ausweise, Statistiken |
| **Kursverwaltung** | Kurse, Dozenten, Teilnehmer, Kalender, Online-Anmeldung |
| **Veranstaltungen** | Eventplanung, Anmeldungen, Ferienpässe |
| **Raumbuchungen** | Reservierungen, Kalender, Schlüsselverwaltung |
| **Finanzen & SEPA** | Beiträge, Rechnungen, SEPA-Lastschrift, Kontenverwaltung |
| **Newsletter** | E-Mail-Versand, Vorlagen, Abonnentenverwaltung |
| **Dokumente** | Ausweise, Rechnungen, Briefe, Etiketten aus Vorlagen |
| **Site-Builder** | Vereinswebsite mit Drag-and-Drop-Editor |
| **Individuelle Module** | Eigene Datenmodule für Gewässer, Fangbücher, etc. |
| **Fischereiverwaltung** | Gewässer, Besatzmaßnahmen, Fangbücher, Erlaubnisscheine |
| **Sitzungsprotokolle** | Protokolle, Tagesordnungspunkte, Aufgaben |
| **Verbandsverwaltung** | Hierarchien, Unterglieder, vereinsübergreifende Suche |
Makerkit provides the following features to help you build a SaaS: ## Technische Grundlagen
1. User authentication
2. User management
3. Subscription management
4. Billing and payments
5. Super Admin
... and many more! - **Webbasiert** — Zugriff über jeden modernen Browser (Chrome, Firefox, Safari, Edge)
- **Responsive** — Funktioniert auf Desktop, Tablet und Smartphone
- **Server in Deutschland** — Hosting in deutschen Rechenzentren
- **DSGVO-konform** — Rollenbasierte Zugriffsrechte, verschlüsselte Datenübertragung
## Support
Bei Fragen erreichen Sie das Com.BISS-Team direkt:
- **Telefon:** 09451 9499-09
- **E-Mail:** info@combiss.de
- **Persönlich:** Kein anonymes Ticketsystem — Sie sprechen direkt mit den Menschen, die Ihre Software entwickeln.

View File

@@ -1,23 +1,46 @@
--- ---
title: "Installing Dependencies" title: "Abhängigkeiten installieren"
description: "Learn how to install dependencies for your project." description: "Voraussetzungen und Systemanforderungen für die Nutzung von MYeasyCMS."
publishedAt: 2024-04-11 publishedAt: 2024-04-11
order: 1 order: 4
status: "published" status: "published"
--- ---
> **Note:** This is mock/placeholder content for demonstration purposes. MYeasyCMS ist eine vollständig webbasierte Anwendung. Es muss keine Software installiert werden.
To install dependencies in your project, please install `pnpm` by running the following command: ## Systemanforderungen
```bash ### Browser
npm install -g pnpm
```
Next, navigate to your project directory and run the following command: MYeasyCMS funktioniert mit allen modernen Browsern:
```bash - **Google Chrome** (empfohlen) — ab Version 90
pnpm install - **Mozilla Firefox** — ab Version 90
``` - **Microsoft Edge** — ab Version 90
- **Apple Safari** — ab Version 14
This will install all the dependencies listed in your `package.json` file. ### Internetverbindung
Eine stabile Internetverbindung ist erforderlich. MYeasyCMS funktioniert auch bei langsameren Verbindungen, empfohlen wird jedoch eine Bandbreite von mindestens 2 Mbit/s.
### Endgeräte
- **Desktop-Computer** oder Laptop (empfohlen für die tägliche Arbeit)
- **Tablet** (geeignet für Kursverwaltung und Veranstaltungen vor Ort)
- **Smartphone** (geeignet für schnelle Abfragen und Statusprüfungen)
## Keine Installation nötig
Anders als klassische Vereinssoftware muss MYeasyCMS nicht auf einzelnen Rechnern installiert werden:
- Kein Download oder Setup-Programm
- Keine lokale Datenbank
- Keine manuellen Updates — neue Funktionen stehen automatisch zur Verfügung
- Kein IT-Aufwand für den Verein
## Zugangsdaten
Die Zugangsdaten erhalten Sie vom Com.BISS-Team nach der Einrichtung Ihres Vereins-Accounts. Bei Fragen wenden Sie sich an:
- **Telefon:** 09451 9499-09
- **E-Mail:** info@combiss.de

View File

@@ -1,247 +1,54 @@
--- ---
title: "Project Structure" title: "Projektstruktur"
description: "Understanding the monorepo structure and organization." description: "Überblick über die Struktur von MYeasyCMS — Module, Pakete und Konfiguration."
publishedAt: 2024-04-11 publishedAt: 2024-04-11
order: 3 order: 3
status: "published" status: "published"
--- ---
> **Note:** This is mock/placeholder content for demonstration purposes. MYeasyCMS ist als modulare Plattform aufgebaut. Jedes Funktionsmodul kann unabhängig aktiviert oder deaktiviert werden.
Learn how the codebase is organized and where to find things. ## Modulstruktur
## Monorepo Overview Die Plattform gliedert sich in folgende Bereiche:
This project uses Turborepo to manage a monorepo with multiple apps and packages. ### Kernmodule
``` Diese Module bilden das Fundament der Vereinsverwaltung:
project-root/
├── apps/ # Applications
│ ├── web/ # Main Next.js app
│ ├── e2e/ # Playwright E2E tests
│ └── dev-tool/ # Development utilities
├── packages/ # Shared packages
│ ├── features/ # Feature packages
│ ├── ui/ # UI components
│ ├── supabase/ # Supabase utilities
│ └── billing/ # Billing integrations
├── tooling/ # Development tools
├── supabase/ # Database schema & migrations
└── docs/ # Documentation
```
## Main Application (`apps/web`) - **Mitgliederverwaltung** — Stammdaten, Abteilungen, Mandate
- **Finanzen** — Beiträge, SEPA, Rechnungen
- **Benutzer- und Rechteverwaltung** — Rollen, Zugriffsrechte
The primary Next.js application: ### Erweiterte Module
``` Diese Module erweitern die Plattform um spezifische Funktionen:
apps/web/
├── app/ # Next.js App Router
│ ├── (marketing)/ # Public pages
│ ├── (auth)/ # Authentication
│ ├── home/ # Main application
│ │ ├── (user)/ # Personal account
│ │ └── [account]/ # Team accounts
│ ├── admin/ # Admin panel
│ └── api/ # API routes
├── components/ # Shared components
├── config/ # Configuration files
├── lib/ # Utility functions
├── public/ # Static assets
└── supabase/ # Supabase setup
```
## Route Structure - **Kursverwaltung** — Kursplanung mit Dozenten und Teilnehmern
- **Veranstaltungen** — Eventmanagement mit Registrierungen
- **Raumbuchungen** — Ressourcenverwaltung und Kalender
- **Newsletter** — E-Mail-Kommunikation
- **Dokumente** — Vorlagen und Seriendruckfunktionen
- **Site-Builder** — Vereinswebsite
### Marketing Routes (`(marketing)`) ### Spezialmodule
Public-facing pages: Module für spezifische Vereinstypen:
``` - **Fischereiverwaltung** — Gewässer, Besatz, Fangbücher, Erlaubnisscheine
app/(marketing)/ - **Sitzungsprotokolle** — Protokolle, Beschlüsse, Aufgaben
├── page.tsx # Landing page - **Verbandsverwaltung** — Hierarchien, Unterglieder, vereinsübergreifende Verwaltung
├── pricing/ # Pricing page
├── blog/ # Blog
└── docs/ # Documentation
```
### Auth Routes (`(auth)`) ### Individuelle Module
Authentication pages: Mit dem Modul-Baukasten können Sie eigene Datenmodule erstellen — ohne Programmierung. Definieren Sie Felder, Formulare und Ansichten für beliebige Vereinsdaten.
``` ## Einstellungen
app/(auth)/
├── sign-in/
├── sign-up/
├── password-reset/
└── verify/
```
### Application Routes (`home`) Unter **Einstellungen** konfigurieren Sie:
Main application: - Vereinsstammdaten und Logo
- Benutzer und Rollen
``` - Modulaktivierung
app/home/ - E-Mail-Einstellungen
├── (user)/ # Personal account context - SEPA-Konfiguration
│ ├── page.tsx # Personal dashboard
│ ├── settings/ # User settings
│ └── projects/ # Personal projects
└── [account]/ # Team account context
├── page.tsx # Team dashboard
├── settings/ # Team settings
├── projects/ # Team projects
└── members/ # Team members
```
## Packages Structure
### Feature Packages (`packages/features/`)
Modular features:
```
packages/features/
├── accounts/ # Account management
├── auth/ # Authentication
├── team-accounts/ # Team features
├── billing/ # Billing & subscriptions
├── admin/ # Admin features
└── notifications/ # Notification system
```
### UI Package (`packages/ui/`)
Shared UI components:
```
packages/ui/
└── src/
├── components/ # Shadcn UI components
│ ├── button.tsx
│ ├── input.tsx
│ ├── dialog.tsx
│ └── ...
└── utils/ # UI utilities
```
### Supabase Package (`packages/supabase/`)
Database utilities:
```
packages/supabase/
├── schema/ # Declarative schemas
│ ├── accounts.schema.ts
│ ├── auth.schema.ts
│ └── ...
├── src/
│ ├── clients/ # Supabase clients
│ ├── hooks/ # React hooks
│ └── middleware/ # Auth middleware
└── migrations/ # SQL migrations
```
## Configuration Files
### Root Level
```
project-root/
├── package.json # Root package.json
├── turbo.json # Turborepo config
├── pnpm-workspace.yaml # PNPM workspace
└── tsconfig.json # Base TypeScript config
```
### Application Level
```
apps/web/
├── next.config.js # Next.js configuration
├── tailwind.config.ts # Tailwind CSS
├── tsconfig.json # TypeScript config
└── .env.local # Environment variables
```
### Feature Configuration
```
apps/web/config/
├── paths.config.ts # Route paths
├── billing.config.ts # Billing settings
├── feature-flags.config.ts # Feature flags
├── personal-account-navigation.config.tsx
└── team-account-navigation.config.tsx
```
## Naming Conventions
### Files
- **Pages**: `page.tsx` (Next.js convention)
- **Layouts**: `layout.tsx`
- **Components**: `kebab-case.tsx`
- **Utilities**: `kebab-case.ts`
- **Types**: `types.ts` or `component-name.types.ts`
### Directories
- **Route segments**: `[param]` for dynamic
- **Route groups**: `(group)` for organization
- **Private folders**: `_components`, `_lib`
- **Parallel routes**: `@folder`
### Code Organization
```
feature/
├── page.tsx # Route page
├── layout.tsx # Route layout
├── loading.tsx # Loading state
├── error.tsx # Error boundary
├── _components/ # Private components
│ ├── feature-list.tsx
│ └── feature-form.tsx
└── _lib/ # Private utilities
├── server/ # Server-side code
│ ├── loaders.ts
│ └── actions.ts
└── schemas/ # Validation schemas
└── feature.schema.ts
```
## Import Paths
Use TypeScript path aliases:
```typescript
// Absolute imports from packages
import { Button } from '@kit/ui/button';
import { createClient } from '@kit/supabase/server-client';
// Relative imports within app
import { FeatureList } from './_components/feature-list';
import { loadData } from './_lib/server/loaders';
```
## Best Practices
1. **Keep route-specific code private** - Use `_components` and `_lib`
2. **Share reusable code** - Extract to packages
3. **Collocate related files** - Keep files near where they're used
4. **Use consistent naming** - Follow established patterns
5. **Organize by feature** - Not by file type
## Finding Your Way
| Looking for... | Location |
|----------------|----------|
| UI Components | `packages/ui/src/components/` |
| Database Schema | `packages/supabase/schema/` |
| API Routes | `apps/web/app/api/` |
| Auth Logic | `packages/features/auth/` |
| Billing Code | `packages/features/billing/` |
| Team Features | `packages/features/team-accounts/` |
| Config Files | `apps/web/config/` |
| Types | `*.types.ts` files throughout |

View File

@@ -1,133 +1,59 @@
--- ---
title: "Quick Start" title: "Schnellstart"
description: "Get your application running in minutes with this quick start guide." description: "In wenigen Schritten mit MYeasyCMS loslegen — Testzugang einrichten, Module aktivieren und die erste Mitgliederliste importieren."
publishedAt: 2024-04-11 publishedAt: 2024-04-11
order: 2 order: 1
status: "published" status: "published"
--- ---
> **Note:** This is mock/placeholder content for demonstration purposes. Dieser Schnellstart-Guide führt Sie durch die ersten Schritte mit MYeasyCMS.
Get your development environment up and running quickly. ## 1. Testzugang anfordern
## Prerequisites Fordern Sie einen kostenlosen Testzugang an. Das Team von Com.BISS richtet Ihren Vereins-Account ein und gibt Ihnen eine persönliche Einführung.
Before you begin, ensure you have: - **Online:** Über das Kontaktformular auf der Website
- **Node.js** 18.x or higher - **Telefon:** 09451 9499-09
- **pnpm** 8.x or higher - **E-Mail:** info@combiss.de
- **Git** for version control
- A **Supabase** account (free tier works great)
## Step 1: Clone the Repository ## 2. Anmelden
```bash Nach der Einrichtung erhalten Sie Ihre Zugangsdaten per E-Mail. Melden Sie sich unter der bereitgestellten URL an. Beim ersten Login werden Sie aufgefordert, Ihr Passwort zu ändern.
git clone https://github.com/yourorg/yourapp.git
cd yourapp
```
## Step 2: Install Dependencies ## 3. Module aktivieren
```bash Unter **Einstellungen → Module** sehen Sie alle verfügbaren Module. Aktivieren Sie die Module, die Ihr Verein benötigt:
pnpm install
```
This will install all required dependencies across the monorepo. - **Mitgliederverwaltung** — Fast immer der erste Schritt
- **Finanzen & SEPA** — Wenn Sie Beiträge per Lastschrift einziehen
- **Kursverwaltung** — Für Vereine mit Kursangebot
- **Veranstaltungen** — Für Eventplanung
## Step 3: Set Up Environment Variables Nicht benötigte Module können jederzeit aktiviert oder deaktiviert werden.
Copy the example environment file: ## 4. Mitglieder importieren
```bash Unter **Mitglieder → Import** können Sie bestehende Mitgliederlisten hochladen:
cp apps/web/.env.example apps/web/.env.local
```
Update the following variables: 1. Laden Sie die Importvorlage als Excel-Datei herunter
2. Tragen Sie Ihre Mitgliederdaten in die Vorlage ein
3. Laden Sie die ausgefüllte Datei hoch
4. Prüfen Sie die Zuordnung der Spalten
5. Starten Sie den Import
```bash Das System zeigt Ihnen eine Vorschau und weist auf mögliche Probleme hin (fehlende Pflichtfelder, doppelte Einträge).
# Supabase Configuration
NEXT_PUBLIC_SUPABASE_URL=http://localhost:54321
NEXT_PUBLIC_SUPABASE_ANON_KEY=your-anon-key-here
SUPABASE_SERVICE_ROLE_KEY=your-service-role-key-here
# Application ## 5. Team einladen
NEXT_PUBLIC_SITE_URL=http://localhost:3000
```
## Step 4: Start Supabase Unter **Einstellungen → Mitarbeiter** können Sie weitere Benutzer einladen. Vergeben Sie Rollen, um den Zugriff zu steuern:
Start your local Supabase instance: - **Administrator** — Vollzugriff auf alle Module und Einstellungen
- **Kassenwart** — Zugriff auf Finanzen, Beiträge und Mitgliederdaten
- **Kursleiter** — Zugriff auf Kursverwaltung und Teilnehmer
- **Schriftführer** — Zugriff auf Protokolle und Dokumente
```bash ## Nächste Schritte
pnpm supabase:web:start
```
This will: - [Module konfigurieren](/docs/getting-started/configuration) — Passen Sie die Module an Ihren Verein an
- Start PostgreSQL database - [Beiträge einrichten](/docs/features/features) — SEPA-Mandate und Beitragskategorien definieren
- Start Supabase Studio (localhost:54323) - [Website erstellen](/docs/features/features) — Vereinswebsite mit dem Site-Builder aufbauen
- Apply all migrations
- Seed initial data
## Step 5: Start Development Server
```bash
pnpm dev
```
Your application will be available at:
- **App**: http://localhost:3000
- **Supabase Studio**: http://localhost:54323
- **Email Testing**: http://localhost:54324
## Step 6: Create Your First User
1. Navigate to http://localhost:3000/auth/sign-up
2. Enter your email and password
3. Check http://localhost:54324 for the confirmation email
4. Click the confirmation link
5. You're ready to go!
## Next Steps
Now that your app is running:
1. **Explore the Dashboard** - Check out the main features
2. **Review the Code** - Familiarize yourself with the structure
3. **Read the Docs** - Learn about key concepts
4. **Build Your Feature** - Start customizing
## Common Issues
### Port Already in Use
If port 3000 is already in use:
```bash
# Find and kill the process
lsof -i :3000
kill -9 <PID>
```
### Supabase Won't Start
Try resetting Supabase:
```bash
pnpm supabase:web:stop
docker system prune -a # Clean Docker
pnpm supabase:web:start
```
### Database Connection Error
Ensure Docker is running and restart Supabase:
```bash
docker ps # Check Docker is running
pnpm supabase:web:reset
```
## What's Next?
- Learn about the [project structure](/docs/getting-started/project-structure)
- Understand [configuration options](/docs/getting-started/configuration)
- Follow [best practices](/docs/development/workflow)

View File

@@ -1,35 +0,0 @@
---
title: "Brainstorming ideas for your next Micro SaaS"
description: "When it comes to choosing a SaaS starter kit for your business, it's essential to look for certain features that will ensure the smooth functioning and growth of your operations. Here are five must-have features that every SaaS starter kit should include."
categories: ['blog']
tags: []
image: "/images/posts/brainstorming.webp"
publishedAt: 2024-04-11
status: "published"
---
> **Note:** This is mock/placeholder content for demonstration purposes.
When it comes to choosing a SaaS starter kit for your business, it's essential to look for certain features that will ensure the smooth functioning and growth of your operations. Here are five must-have features that every SaaS starter kit should include:
## 1. User Management
User management is a crucial feature that allows you to control access to your SaaS platform and manage user permissions effectively. Look for a starter kit that offers robust user management capabilities, including the ability to create user accounts, assign roles and permissions, and revoke access when needed. This feature ensures that your data remains secure and that only authorized users can access sensitive information.
## 2. Analytics and Reporting
Insightful analytics and reporting tools are essential for monitoring the performance of your SaaS application and gaining valuable insights into user behavior and usage patterns. Choose a starter kit that provides comprehensive analytics dashboards and reporting features, allowing you to track key metrics, identify trends, and make data-driven decisions to optimize your product and services.
## 3. Customizable Templates
Flexibility and customization are crucial for tailoring your SaaS application to meet the unique needs and preferences of your business and users. Look for a starter kit that offers customizable templates and themes, allowing you to design a user interface that reflects your brand identity and provides an intuitive and engaging user experience. Customizable templates make it easy to create and deploy new pages, modules, and features without the need for extensive coding or design skills.
## 4. API Access
API access is essential for integrating your SaaS application with other software systems and third-party services, enabling seamless data exchange and workflow automation. Choose a starter kit that provides well-documented APIs and developer-friendly tools, making it easy for your team to build custom integrations and extend the functionality of your application. API access empowers you to connect your SaaS platform with CRM systems, payment gateways, marketing tools, and more, enhancing the value and versatility of your product.
## 5. Security Measures
Security is paramount when it comes to SaaS applications, as you need to protect sensitive data and ensure compliance with data privacy regulations. Look for a starter kit that prioritizes security and provides robust measures to safeguard your infrastructure, data, and user information. This includes features such as encryption, authentication mechanisms, secure access controls, and regular security audits and updates. Choosing a SaaS starter kit with strong security measures helps mitigate the risk of data breaches and instills trust and confidence in your users.
In conclusion, when evaluating SaaS starter kits for your business, make sure to prioritize these five must-have features: user management, analytics and reporting, customizable templates, API access, and security measures. By selecting a starter kit that offers these essential features, you can build a powerful and scalable SaaS application that meets the needs of your business and users while driving growth and innovation.

View File

@@ -0,0 +1,51 @@
---
title: "Warum Vereine auf digitale Verwaltung umsteigen sollten"
description: "Papierordner, Excel-Listen und manuelles Beitragswesen kosten Ehrenamtliche Stunden pro Woche. Erfahren Sie, wie eine digitale Vereinsverwaltung Zeit spart und Fehler reduziert."
categories: ['blog']
tags: ['Vereinsverwaltung', 'Digitalisierung', 'Ehrenamt']
image: "/images/posts/digitale-verwaltung.webp"
publishedAt: 2025-09-15
status: "published"
---
Viele Vereine arbeiten noch mit Excel-Tabellen, Papierordnern und handschriftlichen Listen. Was jahrzehntelang funktioniert hat, stößt heute an Grenzen: Mitgliederzahlen ändern sich, die DSGVO stellt Anforderungen an die Datenhaltung, und ehrenamtliche Vorstände haben immer weniger Zeit für Verwaltungsaufgaben.
## Die häufigsten Probleme bei manueller Vereinsverwaltung
**Doppelte Datenhaltung.** Mitgliederlisten existieren als Excel-Datei, als Ausdruck im Ordner und nochmal beim Kassenwart. Änderungen — zum Beispiel eine neue Adresse — müssen an mehreren Stellen gepflegt werden. Das führt zu Inkonsistenzen und Fehlern.
**Zeitaufwand für Beiträge.** Die Beitragsverwaltung ist in vielen Vereinen der größte Aufwand. Lastschriften manuell zusammenstellen, SEPA-Dateien erzeugen, Rückläufer bearbeiten — das alles kostet Stunden, die besser in die Vereinsarbeit fließen könnten.
**Keine Übersicht.** Wie viele Mitglieder sind aktiv? Welche Beiträge stehen offen? Wer hat den Jahreslehrgang schon bezahlt? Ohne zentrale Software lassen sich diese Fragen nur schwer beantworten.
**DSGVO-Risiko.** Personenbezogene Daten in unverschlüsselten Excel-Dateien, die auf privaten Rechnern liegen — das ist ein Datenschutzproblem, das der Verein im Ernstfall teuer bezahlen muss.
## Was eine digitale Verwaltung ändert
Eine webbasierte Vereinsverwaltung wie MYeasyCMS löst diese Probleme, weil alle Daten an einem zentralen, sicheren Ort liegen. Jeder Berechtigte greift über den Browser auf die gleichen, aktuellen Informationen zu.
### Mitgliederverwaltung an einem Ort
Stammdaten, Kontaktinformationen, Abteilungszugehörigkeiten, SEPA-Mandate und Notizen — alles wird zentral gepflegt. Ändert ein Mitglied seine Adresse, reicht ein einziger Eintrag. Die Daten sind sofort für Beitragseinzug, Mitgliedsausweise und Serienbriefe aktuell.
### Beiträge und SEPA auf Knopfdruck
MYeasyCMS erzeugt SEPA-XML-Dateien für den Lastschrifteinzug direkt aus den hinterlegten Mandaten. Der Kassenwart lädt die Datei herunter und reicht sie bei der Bank ein — fertig. Rückläufer werden im System markiert, offene Posten sind jederzeit einsehbar.
### DSGVO-konform ohne Zusatzaufwand
Die Daten liegen auf Servern in Deutschland, verschlüsselt und geschützt. Zugriffsrechte lassen sich nach Rollen vergeben. Das Recht auf Auskunft und Löschung lässt sich mit wenigen Klicks erfüllen.
### Statistiken und Auswertungen
Mitgliederentwicklung, Altersstruktur, Abteilungsverteilung, Beitragsübersicht — MYeasyCMS liefert Auswertungen, für die Vorstände früher Stunden mit Excel verbracht haben.
## Der Umstieg ist einfacher als gedacht
Bestehende Mitgliederlisten lassen sich über den Import-Assistenten aus Excel oder CSV direkt übernehmen. Das Team von Com.BISS unterstützt persönlich bei der Einrichtung — kein anonymes Ticketsystem, sondern direkter Kontakt mit den Entwicklern.
Viele Vereine in Bayern haben den Umstieg bereits erfolgreich gemacht: Fischereivereine, Sportvereine, Bildungseinrichtungen und Verbände arbeiten seit Jahren zuverlässig mit MYeasyCMS.
## Fazit
Digitale Vereinsverwaltung ist keine Frage der Vereinsgröße, sondern der Effizienz. Wer Ehrenamtlichen die Verwaltungsarbeit erleichtert, stärkt das Engagement — und hat mehr Zeit für das, was einen Verein wirklich ausmacht.

View File

@@ -0,0 +1,80 @@
---
title: "DSGVO im Verein: Checkliste für Vorstände"
description: "Auch Vereine müssen die DSGVO einhalten. Diese Checkliste zeigt, worauf es ankommt — von der Mitgliederverwaltung bis zur Newsletter-Einwilligung."
categories: ['blog']
tags: ['DSGVO', 'Datenschutz', 'Compliance']
image: "/images/posts/dsgvo-vereine.webp"
publishedAt: 2026-02-14
status: "published"
---
Die Datenschutz-Grundverordnung (DSGVO) gilt seit Mai 2018 — auch für Vereine. Viele Vorstände sind unsicher, was das konkret für ihren Verein bedeutet. Diese Checkliste gibt einen praktischen Überblick über die wichtigsten Punkte.
## 1. Verzeichnis der Verarbeitungstätigkeiten
Jeder Verein muss dokumentieren, welche personenbezogenen Daten er verarbeitet. Das klingt bürokratisch, ist aber im Kern einfach:
- Welche Daten werden erhoben? (Name, Adresse, Geburtsdatum, Bankverbindung, E-Mail)
- Zu welchem Zweck? (Mitgliederverwaltung, Beitragseinzug, Kursverwaltung)
- Wer hat Zugriff? (Vorstand, Kassenwart, Kursleiter)
- Wie lange werden die Daten gespeichert?
- Werden Daten an Dritte weitergegeben? (Dachverband, Versicherung)
## 2. Rechtsgrundlage für die Datenverarbeitung
Vereine verarbeiten Mitgliederdaten in der Regel auf Basis des Vereinsvertrags (Art. 6 Abs. 1 lit. b DSGVO). Für darüber hinausgehende Verarbeitung — zum Beispiel Fotos auf der Website oder Newsletter — braucht es eine Einwilligung.
## 3. Einwilligungen richtig einholen
Für den Newsletter-Versand, die Veröffentlichung von Fotos oder die Weitergabe von Daten an den Dachverband brauchen Sie eine dokumentierte Einwilligung. Diese muss:
- **Freiwillig** sein — kein Kopplungsverbot mit der Mitgliedschaft
- **Informiert** sein — der Zweck muss klar benannt werden
- **Widerrufbar** sein — mit Hinweis auf das Widerrufsrecht
## 4. Auskunfts- und Löschungsrechte
Jedes Mitglied hat das Recht auf:
- **Auskunft** darüber, welche Daten der Verein über es speichert
- **Berichtigung** falscher Daten
- **Löschung** nach Austritt (unter Beachtung gesetzlicher Aufbewahrungsfristen)
- **Datenübertragbarkeit** in einem maschinenlesbaren Format
## 5. Technische und organisatorische Maßnahmen
Der Verein muss die Daten angemessen schützen:
- **Zugriffskontrolle** — Nicht jeder braucht Zugriff auf alle Daten. Rollensystem nutzen.
- **Verschlüsselung** — Daten sollten verschlüsselt gespeichert und übertragen werden.
- **Backup** — Regelmäßige Sicherungen gegen Datenverlust.
- **Passwortschutz** — Starke Passwörter, keine geteilten Zugänge.
## 6. Auftragsverarbeitung
Nutzt der Verein externe Dienste (Cloud-Speicher, E-Mail-Versand, Vereinssoftware), braucht es einen Auftragsverarbeitungsvertrag (AVV) mit dem Anbieter. Achten Sie darauf, dass die Server in der EU — besser noch in Deutschland — stehen.
## Wie MYeasyCMS die DSGVO-Compliance unterstützt
MYeasyCMS wurde mit Datenschutz im Blick entwickelt:
- **Server in Deutschland** — Alle Daten liegen auf Servern in deutschen Rechenzentren.
- **Rollenbasierte Zugriffsrechte** — Der Kassenwart sieht Finanzdaten, der Kursleiter sieht Kursteilnehmer, der Vorstand hat Gesamtübersicht.
- **Auskunft per Export** — Mitgliederdaten können als PDF oder Excel exportiert werden, um Auskunftsanfragen zu erfüllen.
- **Löschung mit Protokoll** — Beim Löschen eines Mitglieds wird der Vorgang dokumentiert.
- **Newsletter mit Double-Opt-In** — Die Newsletter-Funktion unterstützt die korrekte Einholung und Dokumentation von Einwilligungen.
- **AVV inklusive** — Com.BISS stellt einen Auftragsverarbeitungsvertrag bereit.
## Checkliste zum Abhaken
- ☐ Verzeichnis der Verarbeitungstätigkeiten erstellt
- ☐ Datenschutzerklärung auf der Website aktualisiert
- ☐ Einwilligungen für Newsletter und Fotos dokumentiert
- ☐ Zugriff auf Mitgliederdaten auf notwendige Personen beschränkt
- ☐ Auftragsverarbeitungsvertrag mit Softwareanbieter abgeschlossen
- ☐ Prozess für Auskunfts- und Löschungsanfragen definiert
- ☐ Datenschutzbeauftragten benannt (bei mehr als 20 Personen mit regelmäßigem Datenzugriff)
## Fazit
Die DSGVO muss kein Schreckgespenst sein. Mit einer durchdachten Vereinssoftware, klaren Prozessen und gesundem Menschenverstand lässt sich der Datenschutz im Verein gut umsetzen. Und das Ergebnis ist nicht nur Compliance, sondern auch Vertrauen bei den Mitgliedern.

View File

@@ -0,0 +1,69 @@
---
title: "Effiziente Mitgliederverwaltung: 7 Tipps für Vereinsvorstände"
description: "Von der Stammdatenpflege bis zum Mitgliedsausweis — so organisieren erfolgreiche Vereine ihre Mitgliederverwaltung."
categories: ['blog']
tags: ['Mitgliederverwaltung', 'Organisation', 'Tipps']
image: "/images/posts/mitgliederverwaltung.webp"
publishedAt: 2026-03-05
status: "published"
---
Die Mitgliederverwaltung ist das Herzstück jedes Vereins. Wenn sie gut funktioniert, läuft alles andere reibungsloser — vom Beitragseinzug über die Kommunikation bis hin zur Statistik für den Dachverband. Hier sind sieben bewährte Tipps aus der Praxis.
## 1. Eine einzige Datenquelle
Die größte Fehlerquelle in der Mitgliederverwaltung: Daten an mehreren Stellen. Die Mitgliederliste als Excel beim Vorsitzenden, die Bankdaten beim Kassenwart, die E-Mail-Adressen beim Schriftführer. Sobald ein Mitglied umzieht, müssen alle drei ihre Listen aktualisieren — und mindestens einer vergisst es.
**Lösung:** Ein zentrales System, auf das alle Berechtigten zugreifen. Jeder arbeitet mit den gleichen, aktuellen Daten.
## 2. Pflichtfelder definieren
Nicht jedes Mitglied muss eine Handynummer haben — aber eine gültige E-Mail-Adresse und die Bankverbindung sollten Pflicht sein. Definieren Sie bei der Neuaufnahme, welche Felder ausgefüllt sein müssen, bevor ein Mitglied angelegt werden kann.
In MYeasyCMS lassen sich Pflichtfelder im Aufnahmeformular konfigurieren. So landet kein unvollständiger Datensatz im System.
## 3. Abteilungen und Gruppen nutzen
Die meisten Vereine haben Unterstrukturen: Abteilungen, Altersgruppen, Arbeitskreise. Bilden Sie diese in der Verwaltung ab. Das erleichtert:
- **Gezielte Kommunikation** — Newsletter nur an die Jugendabteilung senden.
- **Korrekte Beitragsberechnung** — Verschiedene Beitragssätze pro Abteilung.
- **Statistiken** — Wie viele Mitglieder hat jede Abteilung?
## 4. Ein- und Austritte sauber dokumentieren
Jeder Ein- und Austritt sollte mit Datum und Grund protokolliert werden. Bei Austritten ist wichtig:
- Ab wann gilt der Austritt? (Satzung beachten — oft zum Jahresende)
- Sind alle offenen Beiträge bezahlt?
- Muss das SEPA-Mandat widerrufen werden?
- Gibt es ausgeliehenes Vereinseigentum?
## 5. Mitgliedsausweise automatisieren
Viele Vereine stellen Mitgliedsausweise noch manuell aus. Mit MYeasyCMS können Ausweise aus Vorlagen generiert werden — mit Foto, Mitgliedsnummer, Gültigkeitsdatum und Barcode. Entweder als PDF zum Selbstausdruck oder als druckfertiges Format.
## 6. Regelmäßige Datenbereinigung
Einmal im Jahr sollte die Mitgliederliste bereinigt werden:
- Gibt es Mitglieder ohne gültige E-Mail-Adresse?
- Sind alle SEPA-Mandate noch aktuell?
- Gibt es Karteileichen — Mitglieder, die längst ausgetreten sind, aber nie formal abgemeldet wurden?
MYeasyCMS bietet Filterfunktionen, um solche Fälle schnell zu finden.
## 7. Selbstbedienung für Mitglieder
Moderne Vereinsverwaltung bedeutet auch: Mitglieder können selbst aktiv werden. Über das Mitglieder-Portal von MYeasyCMS können Mitglieder:
- Ihre eigenen Stammdaten aktualisieren
- Sich für Kurse und Veranstaltungen anmelden
- Ihre Beitragshistorie einsehen
- Dokumente herunterladen
Das entlastet den Vorstand und stellt sicher, dass die Daten aktuell bleiben.
## Fazit
Gute Mitgliederverwaltung ist kein Hexenwerk. Sie braucht ein zentrales System, klare Prozesse und ein bisschen Disziplin. Die Investition zahlt sich aus — in eingesparter Zeit, weniger Fehlern und zufriedeneren Mitgliedern.

View File

@@ -1,43 +0,0 @@
---
title: "5 Must-Have Features Every SaaS Starter Kit Should Include"
description: "In this blog post, we will discuss the 5 must-have features that every SaaS starter kit should include. These features will help you build a successful SaaS product and get your business off the ground quickly."
categories: []
tags: []
image: "/images/posts/indie-hacker.webp"
publishedAt: 2024-04-12
status: "published"
---
> **Note:** This is mock/placeholder content for demonstration purposes.
Consider identifying a specific niche or industry with underserved needs. Whether it's project management tools tailored for creative freelancers or appointment scheduling software for niche healthcare practitioners, targeting a specific market can lead to a loyal customer base hungry for tailored solutions.
## Automation Tools
In today's fast-paced world, businesses are constantly seeking ways to streamline their operations. Develop automation tools that help businesses save time and resources, whether it's automating repetitive tasks, simplifying data analysis, or optimizing workflow processes.
## Integration Enhancements
Many businesses use multiple software tools to manage various aspects of their operations. Create a micro SaaS solution that integrates seamlessly with popular platforms, offering enhanced functionality, smoother data transfer, and a unified user experience.
## AI-Powered Solutions
Leverage the power of artificial intelligence to develop innovative solutions that anticipate and adapt to user needs. Whether it's intelligent chatbots for customer support, predictive analytics for sales forecasting, or personalized recommendation engines, AI can add significant value to your micro SaaS offering.
## Mobile-First Applications
With the increasing prevalence of mobile devices, there's a growing demand for micro SaaS solutions that are optimized for smartphones and tablets. Consider developing mobile-first applications that offer convenience, accessibility, and intuitive user experiences on-the-go.
## Subscription Box Services
Tap into the growing trend of subscription-based business models by offering a micro SaaS solution in the form of a subscription box service. Whether it's curated content, digital assets, or software tools delivered regularly to subscribers, this model can provide recurring revenue and foster community engagement.
## Green-Tech Solutions
As sustainability becomes a top priority for businesses worldwide, there's a growing demand for eco-friendly solutions. Develop micro SaaS offerings that help businesses reduce their environmental footprint, whether it's energy management tools, carbon footprint calculators, or sustainable supply chain optimization platforms.
## Hyper-Local Services
Focus on serving the needs of local businesses and communities with hyper-local micro SaaS solutions. Whether it's neighborhood-focused marketplace platforms, local event management tools, or community engagement platforms, catering to the unique needs of local markets can lead to strong customer loyalty and word-of-mouth referrals.
In conclusion, the possibilities for creating innovative micro SaaS solutions are endless. By identifying niche markets, leveraging emerging technologies, and focusing on delivering value to customers, you can develop a successful micro SaaS venture that meets the needs of today's dynamic business landscape. So roll up your sleeves, unleash your creativity, and get ready to build the next big thing in the world of micro SaaS!

View File

@@ -1,47 +0,0 @@
---
title: "A Comprehensive Starter Kit for Indie Hackers"
description: "A comprehensive starter kit tailored specifically for SaaS and indie hackers, providing insights and resources to navigate the complexities of SaaS entrepreneurship."
categories: ['blog']
tags: []
image: "/images/posts/saas-starter-blog-post.webp"
publishedAt: 2024-04-10
status: "published"
---
> **Note:** This is mock/placeholder content for demonstration purposes.
In the dynamic world of entrepreneurship, the Software as a Service (SaaS) model has emerged as a beacon of opportunity for indie hackers individuals or small teams with big dreams of creating impactful software solutions. With the right tools and strategies, launching a successful SaaS startup is within reach for anyone with passion, dedication, and a clear vision. To empower aspiring entrepreneurs on this journey, we've curated a comprehensive starter kit tailored specifically for SaaS and indie hackers.
## 1. Idea Generation and Validation
Every successful SaaS startup begins with a compelling idea. To kickstart your journey, leverage idea generation techniques such as problem identification, market research, and brainstorming sessions. Validate your idea by seeking feedback from potential users and analyzing market demand through surveys, interviews, and competitor analysis.
## 2. MVP Development
The Minimal Viable Product (MVP) approach is a cornerstone of SaaS startup development. Focus on building a basic version of your product with core features that address the identified problem. Utilize prototyping tools, development frameworks, and outsourcing platforms to expedite MVP development while maintaining quality and cost-effectiveness.
## 3. Platform Selection
Choosing the right platform for your SaaS startup is crucial for scalability, flexibility, and long-term success. Evaluate factors such as hosting options, scalability features, security measures, and integration capabilities when selecting a platform. Popular choices include cloud-based solutions like Amazon Web Services (AWS), Microsoft Azure, and Google Cloud Platform (GCP).
## 4. Product Design and User Experience
A seamless user experience is paramount for SaaS success. Invest in intuitive product design, responsive UI/UX, and user-centric features to enhance customer satisfaction and retention. Leverage prototyping tools, usability testing, and user feedback loops to iterate and improve your product design continuously.
## 5. Marketing and Growth Strategies
Effective marketing and growth strategies are essential for acquiring, retaining, and monetizing customers. Develop a robust marketing plan encompassing content marketing, social media engagement, search engine optimization (SEO), email campaigns, and influencer partnerships. Leverage analytics tools and A/B testing to optimize your marketing efforts and maximize ROI.
## 6. Customer Support and Feedback Loop
Providing exceptional customer support is key to building a loyal customer base and fostering long-term relationships. Implement multi-channel support options, such as live chat, email support, and knowledge bases, to address customer inquiries promptly and effectively. Establish a feedback loop to gather insights from users and prioritize product enhancements accordingly.
## 7. Monetization Strategies
Explore diverse monetization strategies to generate revenue from your SaaS product. Options include subscription-based models, tiered pricing plans, usage-based billing, and freemium offerings. Conduct pricing experiments, competitor analysis, and customer surveys to determine the optimal pricing strategy for your target market.
## 8. Legal and Compliance Considerations
Ensure legal compliance and protect your SaaS startup from potential risks and liabilities. Consult legal experts to draft robust terms of service, privacy policies, and data protection agreements. Familiarize yourself with relevant regulations such as GDPR, CCPA, and PCI DSS to safeguard user data and maintain regulatory compliance.
Launching a SaaS startup as an indie hacker is a challenging yet rewarding journey. By leveraging the insights and resources provided in this comprehensive starter kit, you can navigate the complexities of SaaS entrepreneurship with confidence and drive sustainable growth for your venture. Embrace experimentation, iteration, and continuous learning as you embark on this exciting entrepreneurial adventure. Remember, the path to success is paved with resilience, determination, and a relentless pursuit of excellence.

View File

@@ -0,0 +1,66 @@
---
title: "SEPA-Lastschrift im Verein: So funktioniert der Beitragseinzug"
description: "Der Beitragseinzug per SEPA-Lastschrift ist für viele Vereine die effizienteste Methode. Wir erklären, wie Sie Mandate verwalten, XML-Dateien erzeugen und häufige Fehler vermeiden."
categories: ['blog']
tags: ['SEPA', 'Beitragsverwaltung', 'Finanzen']
image: "/images/posts/sepa-lastschrift.webp"
publishedAt: 2025-11-20
status: "published"
---
Der jährliche Beitragseinzug gehört zu den wichtigsten — und zeitaufwändigsten — Aufgaben eines Vereins. SEPA-Lastschrift ist dabei die bevorzugte Methode: Mitglieder erteilen ein Mandat, der Verein zieht den Beitrag zum festgelegten Termin ein. Doch die Umsetzung hat ihre Tücken.
## Grundlagen: Was braucht ein Verein für den SEPA-Einzug?
### Gläubiger-ID
Jeder Verein, der Lastschriften einziehen möchte, braucht eine Gläubiger-Identifikationsnummer. Diese wird kostenlos bei der Deutschen Bundesbank beantragt und ist dauerhaft gültig.
### SEPA-Mandat
Für jedes Mitglied muss ein gültiges SEPA-Lastschriftmandat vorliegen. Das Mandat enthält den Namen des Kontoinhabers, die IBAN, das Datum der Mandatserteilung und die Mandatsreferenz. Ohne gültiges Mandat darf keine Lastschrift eingezogen werden.
### SEPA-XML-Datei
Die Bank erwartet eine XML-Datei im Format „pain.008" (SEPA Direct Debit). Diese Datei enthält alle Lastschriften eines Einzugslaufs mit den zugehörigen Mandatsdaten.
## Typische Probleme beim manuellen Einzug
- **Fehlerhafte IBANs:** Ein Zahlendreher reicht, damit die Lastschrift zurückkommt. Die Rücklastschriftgebühren trägt der Verein.
- **Abgelaufene Mandate:** Wird ein Mandat 36 Monate lang nicht genutzt, verfällt es. Der Verein muss ein neues einholen.
- **Unvollständige Dateien:** Fehlende Pflichtfelder in der XML-Datei führen zur Ablehnung durch die Bank.
- **Verschiedene Fälligkeitstermine:** Erst- und Folgelastschriften haben unterschiedliche Vorlauffristen. Werden diese nicht beachtet, lehnt die Bank den Einzug ab.
## Wie MYeasyCMS den Prozess vereinfacht
### Mandatsverwaltung
In MYeasyCMS wird das SEPA-Mandat direkt im Mitgliedsstamm hinterlegt — mit IBAN, BIC, Mandatsreferenz und Erteilungsdatum. Das System prüft die IBAN-Prüfsumme automatisch und warnt bei offensichtlichen Fehlern.
### Beitragskategorien
Beiträge lassen sich nach Abteilung, Altersgruppe oder individuellem Tarif definieren. Bei der Beitragsberechnung berücksichtigt das System automatisch, welche Kategorien einem Mitglied zugeordnet sind.
### SEPA-Sammellastschrift erzeugen
Mit wenigen Klicks wird eine SEPA-Sammellastschrift erstellt:
1. **Zeitraum und Fälligkeitsdatum wählen** — Das System berechnet automatisch die korrekte Vorlaufzeit.
2. **Mitglieder prüfen** — Mitglieder ohne gültiges Mandat oder mit fehlenden Daten werden herausgefiltert und angezeigt.
3. **XML-Datei herunterladen** — Die fertige pain.008-Datei wird im Online-Banking der Bank hochgeladen.
4. **Status im System** — Eingezogene Beiträge werden automatisch als bezahlt markiert. Rückläufer können manuell erfasst werden.
### Rechnungen und Dokumentation
Zu jedem Einzug kann MYeasyCMS automatisch Rechnungen oder Beitragsbestätigungen generieren — als PDF zum Versand per E-Mail oder zum Ausdruck.
## Best Practices für den Beitragseinzug
1. **Mandate regelmäßig prüfen.** Einmal im Jahr prüfen, ob alle Mandate aktuell sind und ob IBANs noch stimmen.
2. **Vorab-Information versenden.** Die SEPA-Regelung verlangt eine Pre-Notification mindestens 14 Tage vor dem Einzug (sofern im Mandat nicht anders vereinbart).
3. **Rückläufer zeitnah bearbeiten.** Geplatzte Lastschriften sofort klären — je länger man wartet, desto schwieriger wird die Nachverfolgung.
4. **Geschäftsjahre sauber abschließen.** Am Jahresende den Abschluss im System machen, damit offene Posten nicht ins nächste Jahr verschleppt werden.
## Fazit
SEPA-Lastschrift ist für Vereine der effizienteste Weg, Beiträge einzuziehen. Mit einer Software wie MYeasyCMS, die Mandate, Beitragskategorien und XML-Export integriert, wird der Prozess vom zeitfressenden Verwaltungsakt zur Routineaufgabe — und der Kassenwart hat wieder Zeit für die eigentliche Vereinsarbeit.

View File

@@ -0,0 +1,70 @@
---
title: "Vereinswebsite erstellen — ohne Programmierkenntnisse"
description: "Eine professionelle Vereinswebsite muss nicht teuer sein. Mit dem integrierten Website-Baukasten von MYeasyCMS erstellen Sie Ihre Vereinsseite direkt aus der Verwaltungssoftware."
categories: ['blog']
tags: ['Website', 'Site-Builder', 'Vereinskommunikation']
image: "/images/posts/vereinswebsite.webp"
publishedAt: 2026-01-10
status: "published"
---
Jeder Verein braucht eine Website — aber nicht jeder hat ein Mitglied, das programmieren kann. Externe Agenturen sind teuer, und Content-Management-Systeme wie WordPress erfordern regelmäßige Updates und Wartung. Der integrierte Site-Builder von MYeasyCMS bietet eine Alternative: eine Vereinswebsite, die direkt aus der Verwaltungssoftware heraus erstellt und gepflegt wird.
## Warum eine separate Website-Lösung oft scheitert
Viele Vereine starten motiviert mit einer WordPress-Seite. Nach ein paar Monaten zeigt sich das Problem: Niemand pflegt die Inhalte, Updates werden nicht eingespielt, und die Seite wird zum Sicherheitsrisiko. Oder der Vorstand wechselt, und niemand hat mehr die Zugangsdaten.
Das Grundproblem: Die Website ist ein separates System, das zusätzlichen Aufwand bedeutet — und im Ehrenamt fehlt genau diese Zeit.
## Die Lösung: Website direkt aus der Vereinsverwaltung
Der Site-Builder in MYeasyCMS ist kein eigenständiges CMS, sondern ein integrierter Bestandteil der Plattform. Das bedeutet:
- **Kein separates Login** — wer in MYeasyCMS arbeitet, kann auch die Website bearbeiten.
- **Keine Updates** — die Website wird als Teil der Plattform automatisch aktuell gehalten.
- **Keine Hosting-Kosten** — die Seite läuft auf der gleichen Infrastruktur wie die Verwaltung.
## Funktionen des Site-Builders
### Drag-and-Drop-Editor
Seiten werden visuell zusammengebaut. Blöcke für Text, Bilder, Karten, Kontaktformulare und Veranstaltungslisten lassen sich per Drag-and-Drop platzieren und konfigurieren.
### Vereinsdaten automatisch einbinden
Das Besondere: Der Site-Builder kann Daten direkt aus der Verwaltung einbinden:
- **Kursangebot** — Das aktuelle Kursprogramm erscheint automatisch auf der Website, inklusive Online-Anmeldung.
- **Veranstaltungen** — Kommende Events werden angezeigt, Mitglieder können sich direkt anmelden.
- **Kontaktinformationen** — Vorstandsdaten aus der Mitgliederverwaltung, immer aktuell.
- **News und Blog** — Neuigkeiten für Mitglieder und Interessenten veröffentlichen.
### Responsive Design
Alle Seiten sind automatisch für Smartphones und Tablets optimiert. Kein manuelles Anpassen nötig.
### Eigene Domain
Die Vereinswebsite kann unter einer eigenen Domain (z.B. www.fischereiverein-musterstadt.de) erreichbar gemacht werden.
## Praxisbeispiel: Fischereiverein
Ein Fischereiverein in Niederbayern nutzt den Site-Builder für seine öffentliche Website. Auf der Startseite sehen Besucher:
- Das aktuelle Kursprogramm (Casting-Kurse, Jugendarbeit)
- Kommende Veranstaltungen (Königsfischen, Hege-Termine)
- Ein Kontaktformular für Aufnahmeanträge
- Die Gewässerordnung als Download
Der Vorstand pflegt die Inhalte selbst — direkt in MYeasyCMS, das er ohnehin täglich für die Mitgliederverwaltung nutzt. Kein zusätzliches System, keine zusätzliche Einarbeitungszeit.
## Tipps für eine gute Vereinswebsite
1. **Weniger ist mehr.** Konzentrieren Sie sich auf die Informationen, die Besucher wirklich suchen: Ansprechpartner, Veranstaltungen, Beitrittsinformationen.
2. **Aktuelle Inhalte.** Eine Seite mit Veranstaltungen von 2019 wirkt verwaist. Mit dem Site-Builder werden Termine automatisch aktualisiert.
3. **Kontaktmöglichkeit.** Ein einfaches Kontaktformular ist Pflicht. Interessenten sollten sofort eine Möglichkeit finden, den Verein zu erreichen.
4. **Impressum und Datenschutz.** Gesetzliche Pflichtangaben nicht vergessen — auch Vereine brauchen ein Impressum und eine Datenschutzerklärung.
## Fazit
Eine Vereinswebsite muss kein Projekt sein. Mit dem integrierten Site-Builder von MYeasyCMS wird sie zum natürlichen Bestandteil der Vereinsverwaltung — gepflegt von den gleichen Leuten, mit den gleichen Daten, ohne zusätzlichen Aufwand.

View File

@@ -2,117 +2,117 @@
"blog": "Blog", "blog": "Blog",
"blogSubtitle": "News and updates about the platform", "blogSubtitle": "News and updates about the platform",
"changelog": "Changelog", "changelog": "Changelog",
"changelogSubtitle": "Latest updates and improvements to the platform", "changelogSubtitle": "Latest updates and improvements",
"noChangelogEntries": "No changelog entries found", "noChangelogEntries": "No changelog entries found",
"changelogPaginationNext": "Next Page", "changelogPaginationNext": "Next Page",
"changelogPaginationPrevious": "Previous Page", "changelogPaginationPrevious": "Previous Page",
"changelogNavigationPrevious": "Previous", "changelogNavigationPrevious": "Previous",
"changelogNavigationNext": "Next", "changelogNavigationNext": "Next",
"documentation": "Documentation", "documentation": "Documentation",
"documentationSubtitle": "Tutorials and guide to get started with the platform", "documentationSubtitle": "Guides and help to get started",
"faq": "FAQ", "faq": "FAQ",
"faqSubtitle": "Frequently asked questions about the platform", "faqSubtitle": "Frequently asked questions about MYeasyCMS",
"pricing": "Pricing", "pricing": "Pricing",
"pricingSubtitle": "Pricing plans and payment options", "pricingSubtitle": "Plans and pricing options",
"backToBlog": "Back to blog", "backToBlog": "Back to blog",
"noPosts": "No posts found", "noPosts": "No posts found",
"blogPaginationNext": "Next Page", "blogPaginationNext": "Next Page",
"blogPaginationPrevious": "Previous Page", "blogPaginationPrevious": "Previous Page",
"readMore": "Read more", "readMore": "Read more",
"contactFaq": "If you have any questions, please contact us", "contactFaq": "Have more questions? Contact us directly",
"contact": "Contact", "contact": "Contact",
"about": "About", "about": "Company",
"product": "Product", "product": "Product",
"legal": "Legal", "legal": "Legal",
"termsOfService": "Terms of Service", "termsOfService": "Terms of Service",
"termsOfServiceDescription": "Our terms and conditions", "termsOfServiceDescription": "Our terms and conditions",
"cookiePolicy": "Cookie Policy", "cookiePolicy": "Cookie Policy",
"cookiePolicyDescription": "Our cookie policy and how we use them", "cookiePolicyDescription": "Our cookie policy",
"privacyPolicy": "Privacy Policy", "privacyPolicy": "Privacy Policy",
"privacyPolicyDescription": "Our privacy policy and how we use your data", "privacyPolicyDescription": "Our privacy policy and data handling",
"contactDescription": "Contact us for any questions or feedback", "contactDescription": "Contact us for questions, demos, and custom offers",
"contactHeading": "Send us a message", "contactHeading": "We're here for you",
"contactSubheading": "We will get back to you as soon as possible", "contactSubheading": "Personal consultation, test access, and custom offers — get in touch.",
"contactName": "Your Name", "contactName": "Your Name",
"contactEmail": "Your Email", "contactEmail": "Your Email",
"contactMessage": "Your Message", "contactMessage": "Your Message",
"sendMessage": "Send Message", "sendMessage": "Send Message",
"contactSuccess": "Your message has been sent successfully", "contactSuccess": "Your message has been sent successfully",
"contactError": "An error occurred while sending your message", "contactError": "An error occurred while sending your message",
"contactSuccessDescription": "We have received your message and will get back to you as soon as possible", "contactSuccessDescription": "We have received your message and will get back to you shortly",
"contactErrorDescription": "An error occurred while sending your message. Please try again later", "contactErrorDescription": "An error occurred while sending your message. Please try again later",
"footerDescription": "The all-in-one management platform for associations, clubs, and organizations. Built by Com.BISS GmbH.", "footerDescription": "Association and federation management from Bavaria — personal, reliable, and fair since 2004. Developed by Com.BISS GmbH, Schierling.",
"copyright": Copyright {year} {product}. All Rights Reserved.", "copyright": 2004{year} Com.BISS GmbH. All Rights Reserved.",
"heroPill": "The next generation of association management", "heroPill": "Since 2004 — 22 years of experience",
"heroTitle": "Manage your organization. Simply and efficiently.", "heroTitle": "Association management that grows with you",
"heroSubtitle": "MyEasyCMS is the all-in-one platform for associations, clubs, and organizations. Manage members, courses, events, finances, and more — all from one place.", "heroSubtitle": "From member management to SEPA direct debit — the software trusted by associations and federations across Bavaria for two decades. 69,000 managed members, 90+ connected organizations.",
"trustedBy": "Trusted by associations and clubs across Germany", "trustedBy": "Trusted by associations and federations across Bavaria",
"trustAssociations": "Associations", "trustAssociations": "3 District Fishing Federations",
"trustSchools": "Educational Institutions", "trustSchools": "Adult Education Centers",
"trustClubs": "Sports & Fishing Clubs", "trustClubs": "90+ Connected Clubs",
"trustOrganizations": "Non-Profit Organizations", "trustOrganizations": "City of Regensburg since 2010",
"featuresHeading": "Everything your organization needs", "featuresHeading": "Everything your organization needs",
"featuresSubheading": "From member management to finance — all the tools you need in one modern, easy-to-use platform.", "featuresSubheading": "MYeasyCMS was built specifically for associations and federations — modular, web-based, accessible from any browser.",
"featuresLabel": "Core Modules", "featuresLabel": "Core Modules",
"featureMembersTitle": "Member Management", "featureMembersTitle": "Member Management",
"featureMembersDesc": "Manage all your members with departments, dues tracking, membership cards, applications, and detailed statistics.", "featureMembersDesc": "Master data, contact information, mandates, honors, history, and notes — all in one place. With departments, dues tracking, and membership cards.",
"featureCoursesTitle": "Course Management", "featureCoursesTitle": "Course Management",
"featureCoursesDesc": "Organize courses with scheduling, instructor assignment, attendance tracking, categories, and locations.", "featureCoursesDesc": "Course, instructor, and participant management with calendar, holiday consideration, cost calculation, and online registration.",
"featureBookingsTitle": "Room Bookings", "featureBookingsTitle": "Room Bookings",
"featureBookingsDesc": "Book rooms and resources with a visual calendar, manage guests, and track availability at a glance.", "featureBookingsDesc": "Reservation management with occupancy overview, holiday consideration, and key management for building access.",
"featureEventsTitle": "Event Management", "featureEventsTitle": "Event Management",
"featureEventsDesc": "Plan and manage events with registrations, holiday passes, and participant tracking.", "featureEventsDesc": "Plan and manage events with registrations, holiday passes, and participant tracking — developed in cooperation with the City of Regensburg.",
"featureFinanceTitle": "Finance & Billing", "featureFinanceTitle": "Dues & SEPA",
"featureFinanceDesc": "Handle invoices, payments, and SEPA direct debit collections — keep your finances organized effortlessly.", "featureFinanceDesc": "Dues and fee management, SEPA direct debit mandates, XML export, and account management by fiscal year. Invoices and payments under control.",
"featureNewsletterTitle": "Newsletter", "featureNewsletterTitle": "Email & Newsletter",
"featureNewsletterDesc": "Create and send professional newsletters with templates. Keep your members informed and engaged.", "featureNewsletterDesc": "Email communication with members and newsletter distribution with templates. Keep your members informed.",
"showcaseHeading": "A powerful dashboard at your fingertips", "showcaseHeading": "A powerful dashboard at a glance",
"showcaseDescription": "Get a complete overview of your organization with our intuitive dashboard. Access everything you need — members, courses, events, and finances — from one central hub.", "showcaseDescription": "Get a complete overview of your organization — members, courses, open invoices, and events — all from one central place. Quick actions for the most common tasks.",
"additionalFeaturesHeading": "And there's more", "additionalFeaturesHeading": "And there's more",
"additionalFeaturesSubheading": "Additional tools to streamline every aspect of your organization's daily work.", "additionalFeaturesSubheading": "Additional tools that simplify every aspect of daily association work.",
"additionalFeaturesLabel": "More Features", "additionalFeaturesLabel": "More Features",
"featureDocumentsTitle": "Document Management", "featureDocumentsTitle": "Documents & Cards",
"featureDocumentsDesc": "Generate documents from templates, manage files, and keep all your important documents organized.", "featureDocumentsDesc": "Membership cards, invoices, labels, reports, letters, and certificates — generated from templates, exportable as PDF and Excel.",
"featureSiteBuilderTitle": "Website Builder", "featureSiteBuilderTitle": "Club Website",
"featureSiteBuilderDesc": "Create and manage your organization's website without any programming knowledge. Update content with ease.", "featureSiteBuilderDesc": "Create your club's public website without programming — with a drag-and-drop editor, events, and course offerings directly from the CMS.",
"featureModulesTitle": "Custom Modules", "featureModulesTitle": "Custom Modules",
"featureModulesDesc": "Extend the platform with custom modules tailored to your specific needs. Import data and configure settings.", "featureModulesDesc": "Extend the platform with custom data modules for waters, catch books, work duties, or any other club data.",
"whyChooseHeading": "Why organizations choose MyEasyCMS", "whyChooseHeading": "Why organizations trust Com.BISS",
"whyChooseDescription": "Built with over 20 years of experience serving associations, clubs, and non-profit organizations across Germany.", "whyChooseDescription": "In 2004, five women came together and founded a web agency. Since then, we've worked hand in hand with our customers — personal, fair, and reliable. Managing directors: Brit Schiergl and Elisabeth Zehetbauer.",
"whyResponsiveTitle": "Mobile-Friendly", "whyResponsiveTitle": "Personal",
"whyResponsiveDesc": "Access your data from any device. Our responsive design works perfectly on desktop, tablet, and smartphone.", "whyResponsiveDesc": "We know our customers and their requirements. No anonymous ticket system — direct contact with the people who develop your software.",
"whySecureTitle": "Secure & Reliable", "whySecureTitle": "Reliable",
"whySecureDesc": "Your data is protected with enterprise-grade security. Regular backups ensure nothing is ever lost.", "whySecureDesc": "22 years of customer relationships speak for themselves. We support you outside of regular business hours — quickly and straightforwardly.",
"whySupportTitle": "Personal Support", "whySupportTitle": "Fair",
"whySupportDesc": "Get direct, personal support from our team. We speak your language and understand your needs.", "whySupportDesc": "Fair prices, fast and flexible implementation of customer requests. New features and changes at fixed prices — no surprises.",
"whyGdprTitle": "GDPR Compliant", "whyGdprTitle": "100% Servers in Germany",
"whyGdprDesc": "Fully compliant with European data protection regulations. Your members' data is handled with care.", "whyGdprDesc": "Based in Schierling near Regensburg. Servers in Germany. GDPR compliant. Your data stays here.",
"howItWorksHeading": "Get started in three easy steps", "howItWorksHeading": "Get started in three simple steps",
"howItWorksSubheading": "Setting up your organization on MyEasyCMS takes just minutes.", "howItWorksSubheading": "Setting up your organization on MYeasyCMS takes just minutes.",
"howStep1Title": "Create your account", "howStep1Title": "Request test access",
"howStep1Desc": "Sign up for free and set up your organization profile. No credit card required to get started.", "howStep1Desc": "Request a free test account — we set everything up for you and personally guide you through the platform.",
"howStep2Title": "Configure your modules", "howStep2Title": "Configure modules",
"howStep2Desc": "Activate the modules you need — members, courses, events, finance — and customize them to fit your workflow.", "howStep2Desc": "Activate the modules you need — members, dues, waters, SEPA — and customize them to fit your organization.",
"howStep3Title": "Invite your team", "howStep3Title": "Start managing",
"howStep3Desc": "Add team members with different roles and permissions. Start managing your organization collaboratively.", "howStep3Desc": "Import your existing member lists and get started right away — with personal support from our team.",
"pricingPillLabel": "Start for free", "pricingPillLabel": "Fair Pricing",
"pricingPillText": "No credit card required.", "pricingPillText": "No limit on number of users",
"pricingHeading": "Fair pricing for all types of organizations", "pricingHeading": "Fair pricing based on club size",
"pricingSubheading": "Get started on our free plan and upgrade when you are ready.", "pricingSubheading": "All features included. No hidden costs. Personal setup with every plan.",
"ctaHeading": "Ready to simplify your organization's management?", "ctaHeading": "Ready for management that simply works?",
"ctaDescription": "Join hundreds of associations, clubs, and organizations who already use MyEasyCMS to streamline their work.", "ctaDescription": "Request a free test account — or get personal consultation. Phone: 09451 9499-09.",
"ctaButtonPrimary": "Get Started for Free", "ctaButtonPrimary": "Request free test access",
"ctaButtonSecondary": "Contact Us", "ctaButtonSecondary": "Get personal consultation",
"ctaNote": "No credit card required. Free plan available." "ctaNote": "No risk. Personal setup included. GDPR compliant."
} }