@flexiweb/core
v3.66.0
Published
Core plugin for flexiweb. It contains custom PayloadCMS V3 fields, access control and more to make your life easier. Feel free to use them in your projects and customize them to your needs. Contributions are welcome!
Maintainers
Readme
@flexiweb/core
A comprehensive core plugin for PayloadCMS v3 providing reusable custom fields, access control, validations, translations, and utilities for the Flexiweb ecosystem.
Quick Links: License • Documentation • Website
Table of Contents
- Introduction
- Features
- Getting Started
- Components
- Overrides & Customization
- Documentation
- Contributing
- License
Introduction
@flexiweb/core is a powerful, production-ready core plugin for PayloadCMS v3 that provides a comprehensive set of reusable components designed to accelerate development and ensure consistency across Flexiweb projects. Built with extensibility and type-safety in mind, this plugin serves as the foundation for building robust PayloadCMS applications.
The plugin is architected to be fully overridable at every level, allowing you to customize and extend functionality while maintaining a solid base. All components are built on top of PayloadCMS's native APIs and follow best practices for type safety, internationalization, and accessibility.
Key Principles
- 🔧 Fully Overridable: Every component can be customized or extended
- 🌍 i18n Ready: Built-in support for multiple languages (German, English, Hungarian)
- 🛡️ Type Safe: Full TypeScript support with comprehensive type definitions
- ♿ Accessible: Components follow accessibility best practices
- 📦 Modular: Import only what you need via subpath exports
- 🔄 Reusable: Designed to be the foundation for other Flexiweb plugins
Features
🎨 Custom Fields
A collection of production-ready custom fields built on top of the Nouncelabs Custom Fields Plugin, each with:
- Type-safe configurations
- Default sensible settings
- Full override capabilities
- Comprehensive documentation
- Built-in validation
- Accessible UI components
👥 User Management
Pre-configured Users collection with:
- Role-based access control (admin, editor, user, system)
- Overridable field configurations
- Built-in access rules
- Automatic first-user admin assignment
- System user support
🔐 Access Control
Reusable access control functions and builders:
- Role-based access checks
- Field-level access control
- Collection-level access rules
- System permission handling
- Flexible access builders
✅ Validations
Ready-to-use validation functions:
- Date validations (past, future, before, after, etc.)
- Number validations (greater than, less than, etc.)
- Relation validations
- i18n-ready error messages
- Programmatic override support to conditionally skip validations
🌐 Translations
Comprehensive translation system:
- Pre-translated labels and messages
- Support for German, English
- Validation error translations
- Field label translations
- Easy to extend with additional languages
📊 Constants
Reusable constants:
- Country codes and labels
- Common enumerations
- Type definitions
🛠️ Utilities
Helper functions for common tasks:
- Nested object accessors
- Override rule checking
- Logging utilities
Getting Started
Installation
Install the package using your preferred package manager:
# Using pnpm (recommended)
pnpm add @flexiweb/core
# Using npm
npm install @flexiweb/core
# Using yarn
yarn add @flexiweb/corePeer Dependencies
This plugin requires the following peer dependencies:
[email protected]@payloadcms/[email protected]
Basic Usage
1. Add the Plugin to Your Payload Config
import { flexiwebCorePlugin } from '@flexiweb/core'
import { buildConfig } from 'payload'
export default buildConfig({
plugins: [
flexiwebCorePlugin({
// Optional: Configure plugin options
overrides: {
users: {
// Customize user collection
},
},
}),
],
// ... rest of your config
})2. Use Custom Fields in Your Collections
import { AlertBoxField, TelephoneField } from '@flexiweb/core/fields'
export const MyCollection: CollectionConfig = {
slug: 'my-collection',
fields: [
AlertBoxField({
config: {
type: 'info',
message: 'This is an informational alert',
},
overrides: {
name: 'infoAlert',
},
}),
TelephoneField({
config: {
defaultCountry: 'us',
},
overrides: {
name: 'phone',
label: { en: 'Phone Number', de: 'Telefonnummer' },
},
}),
],
}3. Use Access Control Functions
import { hasAdminPermissions, hasEditorPermissions } from '@flexiweb/core/access'
export const MyCollection: CollectionConfig = {
slug: 'my-collection',
access: {
read: ({ req: { user } }) => {
return hasEditorPermissions(user)
},
update: ({ req: { user } }) => {
return hasAdminPermissions(user)
},
},
}4. Use Validations
import { future, greaterThan } from '@flexiweb/core/validations'
export const MyCollection: CollectionConfig = {
slug: 'my-collection',
fields: [
{
name: 'startDate',
type: 'date',
validate: [future()],
},
{
name: 'maxValue',
type: 'number',
validate: [
greaterThan(
{
field: 'minValue',
labels: { en: 'Minimum Value', de: 'Mindestwert' },
},
{ override: false },
),
],
},
],
}Components
Custom Fields
The plugin provides a comprehensive set of custom fields, each designed to solve common use cases while remaining fully customizable.
| Field Name | Type | Description | Documentation | | ---------------- | --------- | ------------------------------------------------- | ---------------------------- | | AlertBox | custom | Display styled alerts with custom types | Docs | | ColourText | text | Text field with color-specific options | Docs | | Combo | composite | Combine multiple subfields into one field | Docs | | Number | number | Enhanced numeric field with validation | Docs | | OpeningHours | custom | Structured opening hours for schedules | Docs | | Pattern | text | Regex-based input validation | Docs | | Range | number | Slider-based numeric range input | Docs | | Slug | text | Auto-generated URL slug with formatting | Docs | | Telephone | text | Phone number field with formatting and validation | Docs |
Field Override Pattern
All custom fields follow a consistent pattern that allows full customization:
FieldName({
config: {
// Field-specific configuration
},
overrides: {
// Any Payload field property can be overridden
name: 'customFieldName',
label: { en: 'Custom Label', de: 'Benutzerdefiniertes Label' },
admin: {
condition: (data) => data.someField === 'value',
},
// ... any other field properties
},
})Key Points:
- All fields are fully overridable - you can override any Payload field property
- Field-specific configuration is separated from general field properties
- Type-safe with full TypeScript support
- Each field has detailed documentation in the
docs/folder
Importing Fields
Fields can be imported individually or as a group:
// Individual field import
import { AlertBoxField } from '@flexiweb/core/fields/Alox'
// All fields
import { AlertBoxField, TelephoneField, SlugField } from '@flexiweb/core/fields'
// Client-side components (if needed)
import { AlertBoxClient } from '@flexiweb/core/fields/AlertBox/client'Access Control
The plugin provides a comprehensive set of access control utilities for managing permissions at different levels.
Role Management
import {
getRole,
hasRoleAtLeast,
isAdminUser,
isEditorUser,
isSystemUser,
hasAdminPermissions,
hasEditorPermissions,
hasSystemPermissions,
} from '@flexiweb/core/access'Available Roles:
system- Highest level, bypasses most restrictionsadmin- Administrative accesseditor- Content editing accessuser- Basic user access
Role Hierarchy:
system > admin > editor > userAccess Builders
import {
hasAdminFieldLevelAccess,
hasEditorFieldLevelAccess,
hasUserFieldLevelAccess,
hasSystemAccess,
} from '@flexiweb/core/access'These functions can be used directly in field or collection access configurations:
{
name: 'sensitiveField',
type: 'text',
access: {
read: hasAdminFieldLevelAccess,
update: hasAdminFieldLevelAccess,
},
}Custom Access Rules
You can build custom access rules using the provided utilities:
import { hasAdminPermissions, isSystemUser } from '@flexiweb/core/access'
const customAccess = ({ req: { user } }) => {
if (isSystemUser(user)) return true
if (hasAdminPermissions(user)) return true
// Custom logic...
return false
}Validations
The plugin provides reusable validation functions for dates, numbers, and relations.
Date Validations
import {
after,
afterOrEqual,
before,
beforeOrEqual,
future,
futureOrEqual,
past,
pastOrEqual,
} from '@flexiweb/core/validations'Field vs Field:
{
name: 'endDate',
type: 'date',
validate: [
after({
field: 'startDate',
labels: { en: 'Start Date', de: 'Startdatum' },
}),
],
}Field vs Now:
{
name: 'publishDate',
type: 'date',
validate: [future()], // Must be in the future
}With Programmatic Override:
{
name: 'eventDate',
type: 'date',
validate: (val, ctx) => {
return past(undefined, {
override: ctx.req?.user?.role === 'admin' // Skip validation for admins
})(val, ctx)
},
}Number Validations
import {
greaterThan,
greaterThanOrEqual,
lessThan,
lessThanOrEqual,
} from '@flexiweb/core/validations'Example:
{
name: 'maxValue',
type: 'number',
validate: (val, ctx) => {
return greaterThan(
{
field: 'minValue',
labels: { en: 'Minimum Value', de: 'Mindestwert' },
},
{ override: ctx.req?.user?.role === 'admin' }, // Skip validation conditionally
)(val, ctx)
},
}Relation Validations
import { relationLinkedUser } from '@flexiweb/core/validations'
{
name: 'assignedUser',
type: 'relationship',
relationTo: 'users',
validate: [relationLinkedUser()],
}Key Features:
- All validations support i18n error messages
- Programmatic override support to conditionally skip validations
- Type-safe with full TypeScript support
- Can compare fields to other fields or constants
Translations
The plugin includes comprehensive translations for German and English
Using Translations
Translations are automatically merged when you use the plugin:
import { flexiwebCorePlugin } from '@flexiweb/core'
export default buildConfig({
plugins: [flexiwebCorePlugin()],
// Translations are automatically added
})Translation Keys
All translation keys follow the pattern: flexiweb-core:{category}:{key}
Categories:
validation:date:*- Date validation messagesvalidation:number:*- Number validation messagesfield:*- Field labels and messagescollection:*- Collection labels
Accessing Translations Programmatically
import { flexiwebCoreTranslations } from '@flexiweb/core/translations'
// Access translations in your code
const translations = flexiwebCoreTranslationsExtending Translations
You can extend or override translations in your Payload config:
export default buildConfig({
plugins: [flexiwebCorePlugin()],
i18n: {
translations: {
'flexiweb-core:validation:date:mustBeInFuture': {
en: 'Custom future message',
de: 'Benutzerdefinierte Zukunftsnachricht',
},
},
},
})Collections
Users Collection
The plugin provides a pre-configured Users collection with sensible defaults.
Features:
- Role-based access control
- System user support
- Automatic first-user admin assignment
- Overridable fields and configuration
- Built-in hooks for user management
Default Fields:
email- User email (required)role- User role (admin, editor, user, system)isSystem- System user flag
Customization:
flexiwebCorePlugin({
overrides: {
users: {
// Add additional fields
additionalFields: [
{
name: 'customField',
type: 'text',
},
],
// Override field configurations
fieldOverrides: {
roleOverrides: {
optionOverrides: {
adminOptionOverrides: {
label: { en: 'Administrator', de: 'Administrator' },
},
},
},
},
// Override collection configuration
overrides: {
admin: {
defaultColumns: ['email', 'role', 'customField'],
},
},
},
},
})Accessing User Collection Utilities:
import {
getUserFields,
createUserAccess,
readUserAccess,
updateUserAccess,
deleteUserAccess,
} from '@flexiweb/core/users'Constants
The plugin exports useful constants for reuse across your application.
Countries
import { countriesWithLabels, Country } from '@flexiweb/core/constants'
// Use in select fields
{
name: 'country',
type: 'select',
options: countriesWithLabels,
}Available Countries:
- All European countries
- Major countries from Americas, Asia, Oceania
- Each with German and English labels
Types
import type { CorePluginConfig, UserFieldOverrides } from '@flexiweb/core/types'Utils
Utility functions for common operations.
import { getItemInNestedObject, checkBaseOverrideRules, logger } from '@flexiweb/core/utils'Functions:
getItemInNestedObject(path, object)- Safely access nested object propertiescheckBaseOverrideRules(user, override)- Check if override rules applylogger- Simple logging utility
Overrides & Customization
One of the core principles of this plugin is that everything is overridable. This allows you to customize the plugin to your needs while maintaining a solid foundation.
Plugin-Level Overrides
flexiwebCorePlugin({
overrides: {
users: {
additionalFields: [], // Add custom fields
fieldOverrides: {}, // Override field configurations
overrides: {}, // Override collection configuration
},
},
})Field-Level Overrides
All custom fields support overriding any Payload field property:
AlertBoxField({
config: {
// Field-specific config
},
overrides: {
name: 'customName',
label: { en: 'Custom', de: 'Benutzerdefiniert' },
admin: {
condition: (data) => data.showAlert,
position: 'sidebar',
},
// Any other field property
},
})Access Overrides
Access rules can be overridden at the field or collection level:
{
name: 'field',
type: 'text',
access: {
read: ({ req: { user } }) => {
// Custom access logic
return hasAdminPermissions(user)
},
},
}Validation Overrides
Validations support programmatic override conditions that allow you to skip validation based on any condition:
{
name: 'publishDate',
type: 'date',
validate: (val, ctx) => {
return future(undefined, {
override: ctx.req?.user?.role === 'admin' // Conditionally skip validation
})(val, ctx)
},
}The override option accepts a boolean value that you can set programmatically based on any condition (user role, field values, etc.). When override: true, the validation is skipped entirely.
Documentation
Field Documentation
Each custom field has detailed documentation in the docs/ folder:
- AlertBox - Display styled alerts
- ColourText - Text field with color options
- Combo - Composite field combining multiple subfields
- Number - Enhanced number field
- OpeningHours - Opening hours management
- Pattern - Regex-based validation
- Range - Slider-based range input
- Slug - Auto-generated URL slugs
- Telephone - Phone number input with validation
Example Collections
Working examples of all fields can be found in dev/collections/:
alert-examples.tscolour-text-examples.tscombo-examples.tsnumber-examples.tsopening-hours-examples.tspattern-examples.tsrange-examples.tsslug-examples.tstelephone-examples.ts
Type Definitions
All types are exported and available for use:
import type { CorePluginConfig, UserFieldOverrides, Country } from '@flexiweb/core/types'Contributing
Contributions are currently not yet being accepted due to the rapid development pace and "move quick, break things" philosophy. However, we welcome:
- Bug reports
- Feature suggestions
- Documentation improvements
Once the plugin stabilizes, we'll open up for contributions. In the meantime, feel free to fork and customize for your needs!
Development Setup
# Clone the repository
git clone https://github.com/Welle-IT/flexiweb-plugin-core.git
# Install dependencies
pnpm install
# Build the project
pnpm build
# Run development server
pnpm dev
# Run tests
pnpm testLicense
This software is provided free of charge for use, modification, and distribution by any individual or legal entity ("Licensee") whose total annual gross revenue does not exceed USD 250,000.
If the Licensee’s annual gross revenue exceeds USD 250,000, a paid commercial license is required. For commercial licensing, contact the maintainer at [email protected].
See LICENSE.md for full license details.
Built with ❤️ for the PayloadCMS community
