Skip to content

fronttheme/onemeta

Repository files navigation

OneMeta - Custom Meta Fields

OneMeta β€” Custom Meta Fields Made Simple

A free, open-source, lightweight alternative to ACF for WordPress. Build powerful custom fields with a beautiful visual builder β€” no bloat, no paywalls.

WordPress PHP License Version

Features Β· Field Types Β· Installation Β· Usage Β· Export Β· Contributing


Full Documentation


✨ Features

  • 🎨 Visual Drag & Drop Builder β€” Build field groups with an intuitive interface
  • ⚑ Live PHP Code Preview β€” See generated PHP code update in real time as you build
  • πŸ“¦ Export as PHP Code β€” Export field groups to use in your theme or plugin without OneMeta installed
  • πŸ” Repeater Fields β€” Create repeatable sub-field groups for complex data structures
  • πŸ”€ Conditional Logic β€” Show or hide fields based on the value of other fields
  • 🌐 REST API Support β€” Access your field data via the WordPress REST API
  • πŸͺΆ Zero Dependencies β€” No jQuery, no bloat β€” built with vanilla JS and modern tooling (Vite)
  • 🎯 14 Field Types β€” Everything you need, nothing you don't
  • πŸ’… Modern UI β€” Clean, polished admin interface that feels native to WordPress

🧩 Field Types

Category Fields
Basic Text, Textarea, URL, Email, Date
Choice Toggle, Select, Radio, Button Group
Multiple Checkbox
Media Image, File, Gallery
Advanced Repeater

πŸ“‹ Requirements

Requirement Version
WordPress 6.8 or higher
PHP 8.2 or higher

πŸš€ Installation

Option 1 β€” Download ZIP (Recommended for most users)

  1. Go to Releases
  2. Download the latest onemeta.zip
  3. In your WordPress admin go to Plugins β†’ Add New β†’ Upload Plugin
  4. Upload the ZIP and click Activate

Option 2 β€” Clone via Git

cd wp-content/plugins
git clone https://github.com/fronttheme/onemeta.git

Then activate the plugin from Plugins in your WordPress admin.

Option 3 β€” WordPress.org (coming soon)

OneMeta will be available in the official WordPress plugin directory soon.


πŸ› οΈ Usage

1. Create a Field Group

Go to OneMeta β†’ Add New in your WordPress admin. Give your field group a key and title, then select whether it applies to Post/Page Meta or User Meta.

2. Add Fields

Click Add Field or drag a field type from the sidebar. Configure each field's label, key, description, placeholder, and any advanced options (choices, conditional logic, repeater sub-fields).

3. Use in Your Theme

Use the built-in helper functions to retrieve field values:

// Get a post/page meta value
$value = onemeta_get_meta( get_the_ID(), 'field_key' );

// Get a user meta value
$value = onemeta_get_user_meta( $user_id, 'field_key' );

// With a default fallback
$value = onemeta_get_meta( get_the_ID(), 'field_key', 'Default Value' );

Note: Do not include the onemeta_ prefix in your field key β€” it is added automatically.


πŸ“– Helper Functions

Post / Page Meta

// Get
$value = onemeta_get_meta( $post_id, 'field_key', 'default' );

// Update
onemeta_update_meta( $post_id, 'field_key', $value );

// Delete
onemeta_delete_meta( $post_id, 'field_key' );

User Meta

// Get
$value = onemeta_get_user_meta( $user_id, 'field_key', 'default' );

// Update
onemeta_update_user_meta( $user_id, 'field_key', $value );

// Delete
onemeta_delete_user_meta( $user_id, 'field_key' );

Field Return Types Reference

Field Type Returns Example
Text, Textarea, URL, Email, Date string "Hello World"
Toggle string "0" or "1"
Select, Radio, Button Group string "option_value"
Checkbox array ["val1", "val2"]
Image, File int 123 (attachment ID)
Gallery array [123, 456, 789]
Repeater array [["title" => "Item 1"], ...]

🧩 Field Type Usage

Text

$text = onemeta_get_meta( get_the_ID(), 'custom_title' );
echo '<h2>' . esc_html( $text ) . '</h2>';

Textarea

$content = onemeta_get_meta( get_the_ID(), 'field_description' );
// Preserve line breaks and escape
echo wp_kses_post( wpautop( $content ) );

URL

$url = onemeta_get_meta( get_the_ID(), 'field_website' );
if ( $url ) {
    echo '<a href="' . esc_url( $url ) . '" target="_blank" rel="noopener">Visit Website</a>';
}

Email

$email = onemeta_get_meta( get_the_ID(), 'field_email' );
if ( $email ) {
    echo '<a href="mailto:' . esc_attr( $email ) . '">' . esc_html( $email ) . '</a>';
}

Date

$date = onemeta_get_meta( get_the_ID(), 'field_event_date' );
if ( $date ) {
    // Returns Y-m-d format β€” convert to any display format
    echo '<time datetime="' . esc_attr( $date ) . '">';
    echo date_i18n( get_option( 'date_format' ), strtotime( $date ) );
    echo '</time>';
}

Toggle

// Returns "1" for on, empty string for off β€” not boolean
$is_featured = onemeta_get_meta( get_the_ID(), 'is_featured' );
if ( $is_featured === '1' ) {
    echo '<span class="badge">⭐ Featured</span>';
}

Select / Radio / Button Group

// All return the selected value as a string
$layout = onemeta_get_meta( get_the_ID(), 'field_layout' );
echo '<div class="layout-' . esc_attr( $layout ) . '">';

// Map values to labels
$choices = [ 'grid' => 'Grid View', 'list' => 'List View' ];
echo esc_html( $choices[ $layout ] ?? $layout );

Checkbox

// Returns array of selected values
$features = onemeta_get_meta( get_the_ID(), 'field_features' );
if ( is_array( $features ) && ! empty( $features ) ) {
    foreach ( $features as $feature ) {
        echo '<span class="badge">' . esc_html( $feature ) . '</span>';
    }
}

// Check if a specific value is selected
if ( in_array( 'wifi', $features, true ) ) {
    echo 'πŸ“Ά WiFi Available';
}

Image

// Returns attachment ID (integer)
$image_id = onemeta_get_meta( get_the_ID(), 'featured_image' );
if ( $image_id ) {
    // Recommended: use wp_get_attachment_image() for srcset, lazy loading, etc.
    echo wp_get_attachment_image( $image_id, 'large', false, [
        'class' => 'featured-image',
        'alt'   => get_the_title(),
    ] );
}

File

// Returns attachment ID (integer)
$file_id = onemeta_get_meta( get_the_ID(), 'field_document' );
if ( $file_id ) {
    $file_url  = wp_get_attachment_url( $file_id );
    $file_name = basename( get_attached_file( $file_id ) );
    $file_size = size_format( filesize( get_attached_file( $file_id ) ) );
    echo '<a href="' . esc_url( $file_url ) . '" download>';
    echo esc_html( $file_name ) . ' (' . $file_size . ')';
    echo '</a>';
}

Gallery

// Returns array of attachment IDs
$gallery = onemeta_get_meta( get_the_ID(), 'field_gallery' );
if ( is_array( $gallery ) && ! empty( $gallery ) ) {
    echo '<div class="gallery">';
    foreach ( $gallery as $image_id ) {
        echo wp_get_attachment_image( $image_id, 'medium', false, [
            'class' => 'gallery-item',
        ] );
    }
    echo '</div>';
}

Repeater

// Returns array of row arrays β€” each row contains your sub-field values
$team = onemeta_get_meta( get_the_ID(), 'field_team_members' );
if ( is_array( $team ) && ! empty( $team ) ) {
    echo '<div class="team-grid">';
    foreach ( $team as $member ) {
        echo '<div class="team-member">';
        if ( ! empty( $member['member_avatar'] ) ) {
            echo wp_get_attachment_image( $member['member_avatar'], 'thumbnail', false, [
                'alt' => esc_attr( $member['member_name'] ?? '' ),
            ] );
        }
        echo '<h3>' . esc_html( $member['member_name'] ?? '' ) . '</h3>';
        echo wp_kses_post( wpautop( $member['member_bio'] ?? '' ) );
        echo '</div>';
    }
    echo '</div>';
}

πŸ”€ Conditional Logic

Show or hide fields dynamically based on the value of another field:

'my_field' => [
    'type'        => 'text',
    'label'       => 'My Text Field',
    'conditional' => [
        'field'    => 'my_other_field',
        'operator' => '!=',
        'value'    => '',
    ],
],

Supported operators:

Operator Description
== Equal to
!= Not equal to
contains Contains text (case-insensitive)
!contains Does not contain text (case-insensitive)

πŸ“€ Export as PHP

OneMeta lets you export any field group as clean PHP code. This means you can:

  • Bundle field groups into your theme or plugin without requiring OneMeta to be installed
  • Version control your field configurations alongside your code
  • Share field structures with other developers

Click Export PHP in the builder or visit OneMeta β†’ Documentation β†’ Export Field Groups.


πŸ”Œ REST API

OneMeta field data is accessible via the WordPress REST API. Field values are exposed on their respective post or user endpoints.


πŸ‘©β€πŸ’» Development

Prerequisites

  • Node.js 18+
  • npm
  • Local WordPress install (e.g. LocalWP, Laragon, MAMP)

Setup

cd wp-content/plugins
git clone https://github.com/fronttheme/onemeta.git
cd onemeta
npm install

Enable Dev Mode

OneMeta includes a dev mode that loads JS and CSS directly from the Vite dev server (localhost:3000) with Hot Module Replacement (HMR). To enable it, add the following constants to your wp-config.php:

define( 'WP_DEBUG', true );
define( 'ONEMETA_DEV_MODE', true );
define( 'WP_DEBUG_LOG', true );
define( 'WP_DEBUG_DISPLAY', false );
define( 'WP_ENVIRONMENT_TYPE', 'local' );

Important: ONEMETA_DEV_MODE must be the boolean true β€” not the string "true".

How dev mode works per context:

Context Condition to activate dev mode
Admin builder (JS + CSS) ONEMETA_DEV_MODE === true
Frontend field assets (JS + CSS) WP_DEBUG === true and ONEMETA_DEV_MODE === true

Then start the Vite dev server:

npm run dev

Changes to any file in src/js/ or src/scss/ will now hot-reload instantly in the browser.

Disable Dev Mode

To test the production build locally, comment out ONEMETA_DEV_MODE:

// define( 'ONEMETA_DEV_MODE', true );

Then run a production build:

npm run build

The plugin will now load compiled assets from assets/js/ and assets/css/ β€” exactly as it does for end users.

Commands

# Start Vite dev server with HMR (requires ONEMETA_DEV_MODE)
npm run dev

# Production build
npm run build

# Watch mode β€” rebuilds on change, no HMR
npm run watch

# Generate translation .pot file
npm run pot

# Build and package release ZIP
npm run package

Tech Stack

  • Build Tool: Vite 5
  • CSS: SCSS (modular 7-1 architecture)
  • JS: Vanilla ES Modules (no jQuery)
  • PHP: PSR-4 autoloaded, singleton pattern
  • Database: Custom wp_onemeta_field_groups table

🀝 Contributing

Contributions are welcome! Please:

  1. Fork the repository
  2. Create a feature branch: git checkout -b feature/your-feature
  3. Commit your changes: git commit -m 'Add your feature'
  4. Push to the branch: git push origin feature/your-feature
  5. Open a Pull Request

Please follow WordPress coding standards for PHP and keep JS changes consistent with the existing modular architecture.

For a full contribution guide including how to add new field types, see CONTRIBUTING.md.


πŸ“„ License

OneMeta is licensed under the GPL-2.0-or-later license β€” the same license as WordPress itself. You are free to use, modify, and distribute this plugin.


πŸ‘€ Author

Faruk Ahmed


Made with ❀️ for the WordPress community · fronttheme.com