Skip to content

Plus Site - Block organization and glob queries #4482

Description

@endigo9740

Describe the feature in detail (code, mocks, or screenshots encouraged)

This will be a two parter:

Repo Block Organization

The free/premium repos need the Blocks section update to handle our scalable structure for long term support.

/blocks
    /marketing
        /hero-sections
            /react
                block-1.tsx
            /svelte
                block-1.svelte
        /...
    /applications
        /...
    /ecommerce
        /...
/...

Vite Glob Queries

We'll use Vite's import.meta.glob to "query" against directories, get counts, and retrieve the components and code to display.

1. Sections with file count

Glob everything at build time, then derive counts from the key paths at runtime:

const svelteBlocks = import.meta.glob('/blocks/**/*.svelte');

const sections: Record<string, number> = {};
for (const path of Object.keys(svelteBlocks)) {
  // path: /blocks/marketing/hero-sections/svelte/block-1.svelte
  const [, , category, section] = path.split('/');
  const key = `${category}/${section}`;
  sections[key] = (sections[key] ?? 0) + 1;
}
// { 'marketing/hero-sections': 3, 'applications/dashboards': 2, ... }

2. Query all blocks for a given framework

Glob all frameworks at build time, filter by framework param at runtime:

const allBlocks = import.meta.glob('/blocks/**/{react,svelte}/**/*.{tsx,svelte}');

function getBlocks(category: string, section: string, framework: string) {
  const prefix = `/blocks/${category}/${section}/${framework}/`;
  return Object.fromEntries(
    Object.entries(allBlocks).filter(([path]) => path.startsWith(prefix))
  );
}

Vite resolves the glob at build time, so the filter is just a runtime key lookup on a flat object — fast and fully tree-shakeable.

3. Single query or two for Svelte preview + framework code view

Two globs — you need them to be distinct because the two purposes require different import modes:

// For rendering: normal module imports (gives you Svelte component constructors)
const previewComponents = import.meta.glob('/blocks/**/svelte/*.svelte');

// For code display: raw string imports (all frameworks)
const rawCode = import.meta.glob('/blocks/**/*.{svelte,tsx,jsx,vue}', {
  query: '?raw',
  import: 'default',
});

You can't reuse a ?raw glob for rendering — it gives you a string, not a component. The two globs share the same path keys for .svelte files, so cross-referencing them is trivial.

4. ?raw for source code

Yes, exactly right. The Vite idiomatic form:

const rawCode = import.meta.glob('/blocks/**/*.svelte', {
  query: '?raw',
  import: 'default', // the raw string is the default export
});

// Usage (lazy-loaded)
const code = await rawCode['/blocks/marketing/hero-sections/svelte/block-1.svelte']();
// code is the full source string

The inline form also works for one-offs: import src from './block-1.svelte?raw'


Summary: the two-glob pattern

// Build-time: eager for counts/routing, lazy for actual loading
const svelteComponents = import.meta.glob('/blocks/**/svelte/*.svelte');
const allRawSource     = import.meta.glob('/blocks/**/*.{svelte,tsx,jsx,vue}', {
  query: '?raw', import: 'default',
});

Everything else — section lists, counts, framework filtering — is just key manipulation on those two objects.

Provide relevant links, wireframes, prototypes, or additional information.

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    feature requestRequest a feature or introduce and update to the project.

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions