Skip to content

kamansoft/vite-plugin-flatwave-react

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

32 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

🌊 vite-plugin-flatwave-react

npm version npm downloads CI status License: MIT Node.js version Discord

Turn Markdown into a fully-typed, i18n-ready, static React site β€” zero runtime, no MDX, no server.

Works in any Vite + React project. Drop it in, point to your content folder, done.


✨ Why Flatwave?

Problem Flatwave Solution
MDX locks you into custom components Pure Markdown β€” use any React component via virtual module
i18n is an afterthought First-class i18n β€” locale routes (/en/about, /es/about), auto hreflang, language switcher
TypeScript support is partial Fully typed β€” virtual module + React hooks with full IntelliSense
SSG requires complex config Zero-config SSG β€” static HTML at build, deploy to Netlify, Vercel, S3, GitHub Pages, Nginx
Content validation is manual Built-in validation β€” catches missing fields, duplicate IDs, broken links at build time

πŸš€ Quick Start (30 seconds)

# 1. Install
npm install @kamansoft/vite-plugin-flatwave-react

# 2. Add to vite.config.ts
import { flatwaveContent } from '@kamansoft/vite-plugin-flatwave-react';
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
import path from 'node:path';

export default defineConfig({
  plugins: [
    react(),
    flatwaveContent({
      contentDir: path.resolve(__dirname, 'src/content'),
      locales: ['en', 'es'],
      defaultLocale: 'en',
    }),
  ],
});

# 3. Create content
mkdir -p src/content/en
cat > src/content/en/index.md <<'EOF'
---
title: 'Welcome'
slug: ''
id: 'home'
public: true
description: 'My first Flatwave page'
---
# Hello Flatwave! 🌊

This is **pure Markdown** β€” no MDX, no custom components needed.
EOF

# 4. Run dev server
npm run dev

Open http://localhost:5173/en/ β€” your page is live with hot reload! πŸŽ‰


🎯 Two Ways to Use It

Mode 1: Composable (Recommended for Existing React Apps)

Use the virtual module hooks + components in your existing React Router setup:

// src/pages/[id].tsx
import { getContent, getAlternatives } from 'virtual:flatwave/content';
import { FlatwaveMDPageComponent } from '@kamansoft/vite-plugin-flatwave-react/react';
import Layout from '../components/Layout';

export default function Page({ params }: { params: { id: string } }) {
  const { id } = params;
  const locale = import.meta.env.VITE_CURRENT_LOCALE || 'en';

  const content = getContent(id, locale);
  const alternatives = getAlternatives(id, locale);

  if (!content) return <div>404 - Not Found</div>;

  return (
    <Layout locale={locale} alternatives={alternatives}>
      <FlatwaveMDPageComponent
        frontmatter={content.frontmatter}
        markdownHtml={content.body}
        locale={locale}
      />
    </Layout>
  );
}

React hooks for use anywhere in your components:

import {
  useFlatwaveContent, // Get single content entry
  useFlatwaveRoutes, // Get all routes (optionally filtered by locale)
  useFlatwaveAlternatives, // Get locale alternatives for language switcher
  useFlatwaveLocales, // Get all configured locales
} from '@kamansoft/vite-plugin-flatwave-react/react';

function BlogPost({ id, locale }) {
  const post = useFlatwaveContent(id, locale);
  const alternatives = useFlatwaveAlternatives(id, locale);
  const locales = useFlatwaveLocales();

  if (!post) return <div>Loading...</div>;

  return (
    <article>
      <h1>{post.frontmatter.title}</h1>
      <nav>
        {Object.entries(alternatives).map(([lang, path]) => (
          <a key={lang} href={path}>
            {lang.toUpperCase()}
          </a>
        ))}
      </nav>
      <FlatwaveMDComponent
        frontmatter={post.frontmatter}
        markdownHtml={post.body}
        locale={locale}
      />
    </article>
  );
}

Mode 2: Integrated (Zero-Config Routing + i18n)

Let Flatwave handle routing, language detection, and rendering automatically:

// src/App.tsx
import {
  FlatwaveLanguageRouter,
  FlatwaveMDPageComponent,
  useFlatwaveRoutes,
  useFlatwaveContent,
} from '@kamansoft/vite-plugin-flatwave-react/react';

export function App() {
  const routes = useFlatwaveRoutes();

  return (
    <FlatwaveLanguageRouter
      supportedLanguages={['en', 'es']}
      defaultLanguage="en"
      routes={routes}
      renderPage={(route, lang) => {
        const content = useFlatwaveContent(route.contentId, lang);
        return (
          <FlatwaveMDPageComponent
            frontmatter={content?.frontmatter}
            markdownHtml={content?.body}
            locale={lang}
          />
        );
      }}
    />
  );
}

That's it. You get:

  • Auto locale detection from browser language
  • Locale-prefixed routes (/en/about, /es/about)
  • Language switcher component built-in
  • SEO meta tags from frontmatter

πŸ“ Content Structure

src/
└── content/
    β”œβ”€β”€ en/
    β”‚   β”œβ”€β”€ index.md        # β†’ /en/
    β”‚   β”œβ”€β”€ about.md        # β†’ /en/about
    β”‚   └── blog/
    β”‚       └── hello.md    # β†’ /en/blog/hello
    └── es/
        β”œβ”€β”€ index.md        # β†’ /es/
        β”œβ”€β”€ about.md        # β†’ /es/about
        └── blog/
            └── hello.md    # β†’ /es/blog/hello

Frontmatter (required fields):

---
title: 'About Us' # Page title β†’ <title>, <h1>, og:title
slug: 'about' # URL segment β†’ /{locale}/about
id: 'about' # Groups translations (same across locales)
public: true # false = hidden from routes, sitemap, manifest
description: 'Short desc' # meta description, og:description
canonical: '/en/about' # Optional, defaults to /{locale}/{slug}
robots: 'index, follow' # Default: index, follow

# SEO Extras
og:
  title: 'Custom OG Title'
  image: '/images/og-about.png'
twitter:
  card: 'summary_large_image'
jsonLd:
  '@context': 'https://schema.org'
  '@type': 'WebPage'

# Navigation
menu: 'main' # 'main' | 'footer' | custom
menu_position: 2 # Sort order in menus

# Any extra keys β†’ preserved in `attributes`
custom_field: 'value'
---
Your markdown content here...

βš™οΈ Configuration

flatwaveContent({
  // Required
  contentDir: './src/content', // Where .md files live
  locales: ['en', 'es', 'pt'], // All supported locales
  defaultLocale: 'en', // Must be in locales[]

  // Validation
  strictMissingLocales: false, // true β†’ missing locale = build error
  requiredFields: ['title', 'slug', 'id', 'public'],

  // SSG (enabled by default)
  ssg: {
    enabled: true,
    compileMarkdown: {
      allowRawHtml: false, // Allow raw HTML in markdown
      remarkPlugins: [], // Custom remark plugins
      rehypePlugins: [], // Custom rehype plugins
    },
    hooks: {
      beforeRender: async (ctx) => {
        /* inject data */
      },
      transformMarkdown: async (md, ctx) => {
        /* pre-process */
      },
      transformHtml: async (html, ctx) => {
        /* post-process */
      },
      afterRender: async (html, ctx) => {
        /* side effects */
      },
      onError: async (err, ctx) => {
        /* fallback HTML */
      },
    },
    strategy: new DefaultRenderStrategy(), // Or custom RenderStrategy
  },

  // SEO
  sitemap: {
    hostname: 'https://mysite.com', // Required for sitemap.xml
  },

  // Output
  emitRouteManifest: true, // route-manifest.json
  emitSitemap: true, // sitemap.xml
  emitRobotsTxt: true, // robots.txt
});

πŸ”„ Migration from MDX / Next.js / Astro

Feature MDX / Next.js / Astro Flatwave
Markdown Standard + JSX βœ… Standard only
Components Import in .mdx βœ… Via virtual module + your components
i18n Plugin/config heavy βœ… Zero-config, locale-first
Types Partial / manual βœ… Full TypeScript from virtual module
SSG Framework-dependent βœ… react-dom/server β€” deploy anywhere
Bundle size Includes runtime βœ… Zero runtime dependencies
Validation Manual / runtime βœ… Build-time, fail-fast

πŸ“š Documentation

Guide Description
πŸ“ Architecture System design, module breakdown, Mermaid diagrams, type system
πŸ› οΈ Development Coding standards, Docker, Husky, Git workflow, local npm linking
πŸš€ CI/CD & Release Semantic-release, OIDC publishing, GitHub Actions pipeline
πŸ”§ API Reference Complete TypeScript API for virtual module, hooks, SSG, config

🀝 Contributing

We welcome contributions! See CONTRIBUTING.md.

Quick checklist for PRs:

  • Conventional Commit title (feat:, fix:, chore:, etc.)
  • npm run validate passes (format + lint + type-check + build + test)
  • Tests added for new features

πŸ“„ License

MIT Β© KamanaSoft


πŸ’¬ Community & Support

  • πŸ› Issue Tracker β€” Bug reports & feature requests
  • πŸ’‘ Discussions β€” Questions, ideas, showcases
  • πŸ’¬ Discord β€” Real-time chat with the Vite community

Built with ❀️ for React developers who love Markdown and static sites.

If this project helps you, please consider giving it a ⭐ on GitHub!

About

No description, website, or topics provided.

Resources

License

Contributing

Stars

Watchers

Forks

Packages

 
 
 

Contributors