Category: Tutorials

  • WordPress Plugin Compatibility: What Works with FlatWP

    One question we get constantly: “Will my favorite WordPress plugins work with FlatWP?”

    The short answer is: most of them, yes. But it depends on what the plugin does.

    Plugins That Work Great

    Content & SEO Plugins:

    • Advanced Custom Fields (ACF) – Full support via WPGraphQL
    • Yoast SEO – Meta data accessible through GraphQL
    • Rank Math – Similar to Yoast, works perfectly
    • Custom Post Type UI – Create custom post types, query via GraphQL

    Media & Assets:

    • Any media library plugin – Images flow through next/image optimization
    • ShortPixel – Optimize before Next.js processes them
    • Cloudinary – Can integrate as image source

    Forms:

    • Contact Form 7 – Works with our form adapter
    • WPForms – REST API integration available
    • Gravity Forms – GraphQL extension available

    Plugins That Need Adapters

    Some plugins require custom integration but are totally doable:

    WooCommerce: FlatWP Pro will include a headless storefront. You can also use WPGraphQL for WooCommerce for custom implementations.

    Multilingual (WPML/Polylang): Works with proper GraphQL queries. FlatWP Pro includes multi-language routing.

    Membership plugins: Require custom authentication flow but compatible.

    Plugins That Won’t Work

    Anything that depends on WordPress themes or relies on server-side rendering:

    • Page builders (Elementor, Divi) – Use ACF Flexible Content instead
    • Caching plugins (WP Rocket, etc.) – Next.js handles caching
    • Theme-specific plugins – Your frontend is React, not PHP

    Our Compatibility Roadmap

    We’re actively testing and documenting plugin compatibility. Current priorities:

    1. WooCommerce integration (in progress)
    2. Popular form plugins
    3. Multilingual support
    4. Events plugins (The Events Calendar)

    If there’s a plugin you need, let us know. We’re building adapters based on community demand.

  • Preview Mode: Let Editors See Drafts Before Publishing

    One of the biggest challenges with headless WordPress is preview functionality. Editors want to see their drafts before publishing, but your static site only shows published content.

    FlatWP’s preview mode solves this elegantly.

    How It Works

    When an editor clicks “Preview” in WordPress, our plugin generates a special URL:

    https://flatwp.com/api/preview?secret=xyz&id=123&type=post

    This hits your Next.js preview API route, which:

    1. Verifies the secret token
    2. Enables Next.js draft mode via cookies
    3. Redirects to the post URL

    Now when Next.js renders the page, it queries WordPress for draft content instead of published content.

    The Implementation

    Your preview API route:

    export async function GET(request: Request) {
      const { searchParams } = new URL(request.url);
      const secret = searchParams.get('secret');
      const id = searchParams.get('id');
    
      // Verify secret
      if (secret !== process.env.PREVIEW_SECRET) {
        return new Response('Invalid token', { status: 401 });
      }
    
      // Enable draft mode
      draftMode().enable();
    
      // Redirect to the post
      redirect(`/blog/${slug}`);
    }

    Then in your page component:

    export default async function Post({ params }) {
      const { isEnabled } = draftMode();
      
      // Fetch draft if preview mode is enabled
      const post = await fetchPost(params.slug, {
        preview: isEnabled
      });
      
      return <PostTemplate post={post} />;
    }

    The WordPress Side

    Our plugin adds a “Preview on Frontend” button to the WordPress editor that generates the preview URL automatically.

    It also handles authentication – only logged-in WordPress users can generate preview links, keeping your drafts secure.

    Exit Preview

    We add a banner to preview pages:

    {draftMode().isEnabled && (
      <div className="bg-yellow-100 p-4">
        <p>You are viewing a preview.</p>
        <a href="/api/exit-preview">Exit Preview</a>
      </div>
    )}

    The exit route simply clears the draft mode cookie.

    Why This Matters

    Without preview mode, editors have to publish content to see how it looks. This breaks their workflow and risks publishing unfinished work.

    With FlatWP’s preview mode, editors can iterate on drafts, share preview links with teammates, and only publish when ready.

    It’s a small feature that makes a huge difference in adoption.

  • Deploying FlatWP: Vercel, Netlify, or Self-Hosted?

    FlatWP works on any platform that supports Next.js, but the deployment choice significantly impacts performance and developer experience.

    Vercel (Recommended)

    Vercel created Next.js, so integration is seamless:

    Pros:

    • Zero-config deployment – just connect GitHub
    • ISR works perfectly out of the box
    • Global edge network for fast delivery
    • On-demand revalidation built-in
    • Excellent free tier (100GB bandwidth, unlimited builds)
    • Preview deployments for every PR

    Cons:

    • Can get expensive at scale ($20/user/month for teams)
    • Vendor lock-in (though you can export)

    Best for: Most projects, especially if you value DX and don’t mind the cost at scale.

    Netlify

    Netlify has excellent Next.js support via their Essential Next.js plugin:

    Pros:

    • Strong free tier (100GB bandwidth)
    • Great build performance
    • Form handling built-in
    • Split testing features
    • Slightly cheaper than Vercel at scale

    Cons:

    • ISR support is newer, less battle-tested
    • Some Next.js features lag behind Vercel
    • Build times can be slower for large sites

    Best for: Teams already on Netlify or those wanting to save costs.

    Cloudflare Pages

    Cloudflare now supports Next.js via their @cloudflare/next-on-pages adapter:

    Pros:

    • Incredibly generous free tier (unlimited requests)
    • Cloudflare’s global network
    • R2 storage for assets
    • Very cost-effective at scale

    Cons:

    • Requires adapter configuration
    • Some Next.js features not supported
    • Newer, less documentation
    • ISR implementation differs from Vercel

    Best for: High-traffic sites on a budget.

    Self-Hosted (Node.js)

    You can deploy Next.js to any Node.js server:

    Pros:

    • Full control
    • No platform fees
    • Can use your existing infrastructure

    Cons:

    • You manage scaling, CDN, caching
    • More DevOps overhead
    • ISR requires Redis or similar for cache
    • No automatic preview deployments

    Best for: Enterprise with existing infrastructure or strict data requirements.

    Our Recommendation

    Start with Vercel. The DX is unmatched and the free tier is generous enough for most projects. Once you’re at scale and costs matter, evaluate Netlify or Cloudflare.

    For the WordPress backend, use any WordPress host – FlatWP doesn’t care where WordPress lives as long as GraphQL is accessible.

  • Form Handling in Headless WordPress: Three Approaches

    Forms are everywhere – contact forms, newsletter signups, lead capture. Here’s how to handle them in a headless WordPress setup.

    Approach 1: WordPress Forms (Recommended)

    Use Contact Form 7 or WPForms in WordPress, submit from Next.js:

    // Server action in Next.js
    async function handleSubmit(formData: FormData) {
      const response = await fetch(
        'https://dev-cms.flatwp.com/wp-json/contact-form-7/v1/contact-forms/123/feedback',
        {
          method: 'POST',
          body: formData,
        }
      );
      
      return response.json();
    }

    Pros:

    • Editors manage form fields in WordPress
    • Email notifications handled by WordPress
    • Submissions stored in WordPress database
    • Works with existing WordPress plugins

    Cons:

    • Extra API call to WordPress
    • WordPress becomes a dependency for forms

    Approach 2: Next.js Server Actions

    Handle forms entirely in Next.js with server actions:

    // app/contact/actions.ts
    'use server'
    
    export async function submitContact(formData: FormData) {
      const data = {
        name: formData.get('name'),
        email: formData.get('email'),
        message: formData.get('message'),
      };
      
      // Send email via Resend, SendGrid, etc.
      await sendEmail(data);
      
      // Store in database if needed
      await db.contacts.create(data);
    }

    Pros:

    • No WordPress dependency
    • Full control over validation and processing
    • Modern server actions pattern
    • Can integrate with any email service

    Cons:

    • Editors can’t manage form fields
    • Need separate storage for submissions
    • More code to maintain

    Approach 3: Third-Party Services

    Use Formspree, Tally, or similar:

    <form action="https://formspree.io/f/your-id" method="POST">
      <input name="email" type="email" />
      <button type="submit">Submit</button>
    </form>

    Pros:

    • Zero backend code
    • Spam protection included
    • Email notifications handled
    • Nice dashboard for submissions

    Cons:

    • Monthly cost ($0-$20)
    • Less customization
    • Another service to manage

    FlatWP’s Approach

    We include adapters for all three approaches. Our default recommendation:

    • Use WordPress forms for marketing sites (editors need control)
    • Use server actions for apps (more dynamic needs)
    • Use third-party for MVPs (fastest to ship)

    The beauty of headless is you’re not locked in. Start with one, switch to another as needs change.

    Validation with Zod

    Regardless of approach, validate with Zod:

    const contactSchema = z.object({
      name: z.string().min(2),
      email: z.string().email(),
      message: z.string().min(10),
    });
    
    export async function submitContact(formData: FormData) {
      const data = contactSchema.parse({
        name: formData.get('name'),
        email: formData.get('email'),
        message: formData.get('message'),
      });
      
      // data is now typed and validated
    }

    Type-safe forms with runtime validation. Beautiful.