pub const options = zx.PageOptions{
    .methods = &.{ .GET, .POST },
};

pub fn Page(ctx: zx.PageContext) !zx.Component {
    if (ctx.request.method != .GET) {
        return error.MethodNotAllowed;
    }

    const allocator = ctx.arena;

    // Greeting example
    var aw_greeting: std.io.Writer.Allocating = .init(allocator);
    const zx_greeting = @embedFile("./examples/greeting.zx");
    const zig_greeting = @embedFile("./examples/greeting.zig");
    const html_page_greeting = @import("./examples/greeting.zig").HelloWorld(allocator);
    html_page_greeting.render(&aw_greeting.writer) catch unreachable;
    const html_greeting = allocator.dupe(u8, aw_greeting.written()) catch unreachable;

    // Markup example
    var aw_markup: std.io.Writer.Allocating = .init(allocator);
    const zx_markup = @embedFile("./examples/markup.zx");
    const zig_markup = @embedFile("./examples/markup.zig");
    const html_page_markup = @import("./examples/markup.zig").AboutSection(allocator);
    html_page_markup.render(&aw_markup.writer) catch unreachable;
    const html_markup = allocator.dupe(u8, aw_markup.written()) catch unreachable;

    // Text expression example
    var aw_text: std.io.Writer.Allocating = .init(allocator);
    const zx_text = @embedFile("./examples/text_expr.zx");
    const zig_text = @embedFile("./examples/text_expr.zig");
    const html_page_text = @import("./examples/text_expr.zig").UserGreeting(allocator);
    html_page_text.render(&aw_text.writer) catch unreachable;
    const html_text = allocator.dupe(u8, aw_text.written()) catch unreachable;

    // Format expression example (now just showing types)
    var aw_format: std.io.Writer.Allocating = .init(allocator);
    const zx_format = @embedFile("./examples/format_expr.zx");
    const zig_format = @embedFile("./examples/format_expr.zig");
    const html_page_format = @import("./examples/format_expr.zig").ProductInfo(allocator);
    html_page_format.render(&aw_format.writer) catch unreachable;
    const html_format = allocator.dupe(u8, aw_format.written()) catch unreachable;

    // Conditional example
    var aw_conditional: std.io.Writer.Allocating = .init(allocator);
    const zx_conditional = @embedFile("./examples/conditional.zx");
    const zig_conditional = @embedFile("./examples/conditional.zig");
    const html_page_conditional = @import("./examples/conditional.zig").UserStatus(allocator);
    html_page_conditional.render(&aw_conditional.writer) catch unreachable;
    const html_conditional = allocator.dupe(u8, aw_conditional.written()) catch unreachable;

    // Switch example
    var aw_switch: std.io.Writer.Allocating = .init(allocator);
    const zx_switch = @embedFile("./examples/switch_expr.zx");
    const zig_switch = @embedFile("./examples/switch_expr.zig");
    const html_page_switch = @import("./examples/switch_expr.zig").RoleBadge(allocator);
    html_page_switch.render(&aw_switch.writer) catch unreachable;
    const html_switch = allocator.dupe(u8, aw_switch.written()) catch unreachable;

    // List example
    var aw_list: std.io.Writer.Allocating = .init(allocator);
    const zx_list = @embedFile("./examples/list.zx");
    const zig_list = @embedFile("./examples/list.zig");
    const html_page_list = @import("./examples/list.zig").ProductList(allocator);
    html_page_list.render(&aw_list.writer) catch unreachable;
    const html_list = allocator.dupe(u8, aw_list.written()) catch unreachable;

    // Props example
    var aw_props: std.io.Writer.Allocating = .init(allocator);
    const zx_props = @embedFile("./examples/props.zx");
    const zig_props = @embedFile("./examples/props.zig");
    const html_page_props = @import("./examples/props.zig").ButtonDemo(allocator);
    html_page_props.render(&aw_props.writer) catch unreachable;
    const html_props = allocator.dupe(u8, aw_props.written()) catch unreachable;

    // Page example
    var aw_page: std.io.Writer.Allocating = .init(allocator);
    const zx_page = @embedFile("./examples/page_example.zx");
    const zig_page = @embedFile("./examples/page_example.zig");
    const html_page_page = @import("./examples/page_example.zig").Page(ctx);
    html_page_page.render(&aw_page.writer) catch unreachable;
    const html_page = allocator.dupe(u8, aw_page.written()) catch unreachable;

    // Layout example (just show code, no preview)
    const zx_layout = @embedFile("./examples/layout_example.zx");

    // Build manual example
    const build_manual_code = @embedFile("./examples/build_manual.zig");

    // Dynamic route example
    var aw_dynamic: std.io.Writer.Allocating = .init(allocator);
    const zx_dynamic = @embedFile("./examples/dynamic_route.zx");
    const zig_dynamic = @embedFile("./examples/dynamic_route.zig");
    const html_page_dynamic = @import("./examples/dynamic_route.zig").UserProfile(ctx);
    html_page_dynamic.render(&aw_dynamic.writer) catch unreachable;
    const html_dynamic = allocator.dupe(u8, aw_dynamic.written()) catch unreachable;

    // Fragment example
    var aw_fragment: std.io.Writer.Allocating = .init(allocator);
    const zx_fragment = @embedFile("./examples/fragment.zx");
    const zig_fragment = @embedFile("./examples/fragment.zig");
    const html_page_fragment = @import("./examples/fragment.zig").FragmentDemo(allocator);
    html_page_fragment.render(&aw_fragment.writer) catch unreachable;
    const html_fragment = allocator.dupe(u8, aw_fragment.written()) catch unreachable;

    // Children example
    var aw_children: std.io.Writer.Allocating = .init(allocator);
    const zx_children = @embedFile("./examples/children.zx");
    const zig_children = @embedFile("./examples/children.zig");
    const html_page_children = @import("./examples/children.zig").CardDemo(allocator);
    html_page_children.render(&aw_children.writer) catch unreachable;
    const html_children = allocator.dupe(u8, aw_children.written()) catch unreachable;

    // Dynamic attributes example
    var aw_dynattr: std.io.Writer.Allocating = .init(allocator);
    const zx_dynattr = @embedFile("./examples/dynamic_attr.zx");
    const zig_dynattr = @embedFile("./examples/dynamic_attr.zig");
    const html_page_dynattr = @import("./examples/dynamic_attr.zig").DynamicAttrs(allocator);
    html_page_dynattr.render(&aw_dynattr.writer) catch unreachable;
    const html_dynattr = allocator.dupe(u8, aw_dynattr.written()) catch unreachable;

    // API route example
    const zig_api = @embedFile("./examples/route.zig");

    return (
        <fragment @{allocator}>
            <LearnHeader />
            // <YouWillLearn />
            <Installation />
            <CreateProject build_manual_code={build_manual_code} />
            <EditorSetup />
            <CreatingComponents zx_code={zx_greeting} zig_code={zig_greeting} html_code={html_greeting} />
            <WritingMarkup zx_code={zx_markup} zig_code={zig_markup} html_code={html_markup} />
            <Fragments zx_code={zx_fragment} zig_code={zig_fragment} html_code={html_fragment} />
            <DisplayingData zx_text={zx_text} zig_text={zig_text} html_text={html_text} zx_format={zx_format} zig_format={zig_format} html_format={html_format} />
            <DynamicAttributes zx_code={zx_dynattr} zig_code={zig_dynattr} html_code={html_dynattr} />
            <ConditionalRendering zx_conditional={zx_conditional} zig_conditional={zig_conditional} html_conditional={html_conditional} zx_switch={zx_switch} zig_switch={zig_switch} html_switch={html_switch} />
            <RenderingLists zx_code={zx_list} zig_code={zig_list} html_code={html_list} />
            <PassingProps zx_code={zx_props} zig_code={zig_props} html_code={html_props} />
            <ChildrenProps zx_code={zx_children} zig_code={zig_children} html_code={html_children} />
            <PagesAndLayouts zx_page={zx_page} zig_page={zig_page} html_page={html_page} zx_layout={zx_layout} zx_dynamic={zx_dynamic} zig_dynamic={zig_dynamic} html_dynamic={html_dynamic} />
            <APIRoutes zig_code={zig_api} />
            <Plugins />
            <NextSteps />
        </fragment>
    );
}

fn LearnHeader(allocator: zx.Allocator) zx.Component {
    return (
        <section class="section learn-header" style="margin-bottom: 0;" @allocator={allocator}>
            <p class="section-category">Learn ZX</p>
            <h1>Quick Start</h1>
            <p class="lead">Welcome to the ZX documentation! This page will give you an introduction to the core concepts you'll use daily when building web applications with ZX.</p>
        </section>
    );
}

fn YouWillLearn(allocator: zx.Allocator) zx.Component {
    return (
        <div class="callout learn-callout" @allocator={allocator}>
            <p class="callout-title"><strong>You will learn</strong></p>
            <ul>
                <li>How to install ZX and set up your environment</li>
                <li>How to create and nest components</li>
                <li>How to write markup and use fragments</li>
                <li>How to display data with expressions</li>
                <li>How to use dynamic attributes</li>
                <li>How to render conditionally and render lists</li>
                <li>How to pass props and children to components</li>
                <li>How to create pages, layouts, and dynamic routes</li>
                <li>How to create API routes</li>
            </ul>
        </div>
    );
}

fn Installation(allocator: zx.Allocator) !zx.Component {
    return (
        <section id="installation" class="section" @allocator={allocator}>
            <h2>Installation</h2>
            <p>Install the ZX CLI to get started:</p>

            <InstallCLI />

            <p style="margin-top: 1rem;">If you prefer not to install the CLI, you can create a project manually. See the <a href="#create-project">Create a Project</a> section for the manual setup option, or check the <a href="/reference#cli">CLI documentation</a> for all available commands.</p>

            <h3>Install Zig</h3>
            <p>ZX <code>{zx.info.version}</code> requires Zig <code>{zx.info.minimum_zig_version}</code>:</p>

            <InstallZig />
        </section>
    );
}

const CreateProjectProps = struct {
    build_manual_code: []const u8,
};

fn CreateProject(allocator: zx.Allocator, props: CreateProjectProps) zx.Component {
    return (
        <section id="create-project" class="section" @allocator={allocator}>
            <h2>Create a Project</h2>
            <p><strong>CLI:</strong> Use the CLI to quickly scaffold a new ZX project. It automatically sets up the project structure, build configuration, and template files for you.</p>
            <p><strong>Manual:</strong> If you prefer not to install the CLI, you can simply add the ZX dependency to your <code>build.zig</code> file and initialize the project manually, or use the <code>zx</code> build step available after configuring <code>zx.init</code>.</p>
            <div>
                <div class="simple-tab-header">
                    <input type="radio" id="tab-cli" name="create-project" class="simple-tab-radio" checked="true" aria-label="CLI setup method" />
                    <input type="radio" id="tab-manual" name="create-project" class="simple-tab-radio" aria-label="Manual setup method" />
                    <label for="tab-cli" class="simple-tab-label">CLI</label>
                    <label for="tab-manual" class="simple-tab-label">Manual</label>
                </div>
                <div class="simple-tab-content" id="content-cli">
                    <p>Create a new ZX project using the CLI:</p>
                    <div class="install-box install-box-simple">
                        <div class="install-box-content">
                            <div class="install-code" style="min-height: 28px; margin-top: 5px;">
                                <span class="install-prompt">$ </span>
                                <span class="function">zx</span>
                                <span class="operator"> init </span>
                                <span class="variable">my-app</span>
                            </div>
                        </div>
                    </div>

                    <p style="margin-top: 1.5rem;">Start the ZX app in development mode with hot reloading:</p>
                    <div class="install-box install-box-simple">
                        <div class="install-box-content">
                            <div class="install-code install-code-multiline">
                                <div><span class="install-prompt">$ </span><span class="function">cd </span><span class="variable">my-app</span></div>
                                <div><span class="install-prompt">$ </span><span class="function">zig </span><span class="operator">build </span><span class="variable">dev</span></div>
                            </div>
                        </div>
                    </div>

                    <p style="margin-top: 1.5rem;">Open <code>http://localhost:3000</code> in your browser!</p>
                </div>
                <div class="simple-tab-content" id="content-manual">
                    <p>First initialize a Zig project if you haven't already:</p>
                    <div class="install-box install-box-simple">
                        <div class="install-box-content">
                            <div class="install-code">
                                <span class="install-prompt">$ </span>
                                <span class="function">zig</span>
                                <span class="operator"> init</span>
                            </div>
                        </div>
                    </div>

                    <p style="margin-top: 1.5rem;">Add ZX as a dependency:</p>
                    <div class="install-box install-box-simple">
                        <div class="install-box-content">
                            <div class="install-code">
                                <span class="install-prompt">$ </span>
                                <span class="function">zig</span>
                                <span class="operator"> fetch </span>
                                <span class="operator">--save </span>
                                <span class="variable">git+{zx.info.repository}</span>
                            </div>
                        </div>
                    </div>

                    <p>Update your <code translate="no">build.zig</code> to the following:</p>
                    <CodeBlock code={props.build_manual_code} filename="build.zig" translate="no" /> 

                    <p style="margin-top: 1.5rem;">Then initialize the project with the default template:</p>
                    <div class="install-box install-box-simple">
                        <div class="install-box-content">
                            <div class="install-code">
                                <span class="install-prompt">$ </span>
                                <span class="function">zig</span>
                                <span class="operator"> build </span>
                                <span class="variable">zx</span>
                                <span class="operator"> -- </span>
                                <span class="function">init</span>
                                <span class="operator"> --existing</span>
                            </div>
                        </div>
                    </div>

                    <p style="margin-top: 1.5rem;">Start the ZX app in development mode with hot reloading:</p>
                    <div class="install-box install-box-simple">
                        <div class="install-box-content">
                            <div class="install-code install-code-multiline">
                                <div><span class="install-prompt">$ </span><span class="function">zig </span><span class="operator">build </span><span class="variable">dev</span></div>
                            </div>
                        </div>
                    </div>

                    <p style="margin-top: 1.5rem;">Open <code>http://localhost:3000</code> in your browser!</p>
                </div>
            </div>

            <h3>Project Structure</h3>
            <ProjectTree />
            <div class="callout tip">
                <strong>Tip:</strong>
                 The 
                <code>app/pages/</code>
                 directory uses file-based routing. Each 
                <code>page.zx</code>
                 file becomes a route.
            </div>
        </section>
    );
}

fn EditorSetup(allocator: zx.Allocator) zx.Component {
    return (
        <section id="editor-setup" class="section" @allocator={allocator}>
            <h2>Editor Setup</h2>
            <p>Set up your editor for the best ZX development experience.</p>
            <div>
                <div class="simple-tab-header">
                    <input type="radio" id="tab-editor-vscode" name="editor-setup" class="simple-tab-radio" checked="true" aria-label="VS Code / Cursor" />
                    <input type="radio" id="tab-editor-neovim" name="editor-setup" class="simple-tab-radio" aria-label="Neovim" />
                    <input type="radio" id="tab-editor-helix" name="editor-setup" class="simple-tab-radio" aria-label="Helix" />
                    <input type="radio" id="tab-editor-zed" name="editor-setup" class="simple-tab-radio" aria-label="Zed" />
                    <label for="tab-editor-vscode" class="simple-tab-label">VS Code</label>
                    <label for="tab-editor-neovim" class="simple-tab-label">Neovim</label>
                    <label for="tab-editor-helix" class="simple-tab-label">Helix</label>
                    <label for="tab-editor-zed" class="simple-tab-label">Zed</label>
                </div>
                <div class="simple-tab-content" id="content-editor-vscode">
                    <p>Install the official ZX extension for the best development experience.</p>
                    <p>Install from:</p>
                    <ul>
                        <li><a href="https://marketplace.visualstudio.com/items?itemName=ziex.ziex" target="_blank" rel="noopener noreferrer">VS Code Marketplace</a></li>
                        <li><a href="https://open-vsx.org/extension/ziex/ziex" target="_blank" rel="noopener noreferrer">Open VSX Registry</a> (for Cursor and other forks)</li>
                    </ul>
                    <p>Or from command palette: <code>ext install ziex.ziex</code></p>
                    <p><strong>Features:</strong> Syntax highlighting, IntelliSense, error diagnostics, bracket matching, and code folding.</p>
                </div>
                <div class="simple-tab-content" id="content-editor-neovim">
                    <p>With <a href="https://github.com/folke/lazy.nvim" target="_blank" rel="noopener noreferrer">lazy.nvim</a>, add <code>{zx.info.repository["https://github.com/".len..]}</code> as a plugin with <code>nvim-treesitter</code> as a dependency.</p>
                    <p>See the <a href=`{zx.info.repository}/tree/main/ide/neovim` target="_blank" rel="noopener noreferrer">Neovim setup guide</a> for the full configuration.</p>
                    <p><strong>Features:</strong> Tree-sitter syntax highlighting, LSP support, and file icons.</p>
                </div>
                <div class="simple-tab-content" id="content-editor-helix">
                    <p>See the <a href=`{zx.info.repository}/tree/main/ide/helix` target="_blank" rel="noopener noreferrer">Helix setup guide</a> for the full configuration.</p>
                    <p><strong>Features:</strong> Tree-sitter syntax highlighting, and LSP support.</p>
                </div>
                <div class="simple-tab-content" id="content-editor-zed">
                    <p>Manual installation (pending marketplace approval):</p>
                    <ol>
                        <li>Clone: <code>git clone {zx.info.repository}</code></li>
                        <li>Open Extensions panel (Cmd/Ctrl + Shift + P)</li>
                        <li>Select "Install Dev Extension"</li>
                        <li>Navigate to <code>ide/zed</code> in the cloned repo</li>
                    </ol>
                    <p>See the <a href=`{zx.info.repository}/tree/main/ide/zed` target="_blank" rel="noopener noreferrer">Zed setup guide</a> for details.</p>
                </div>
            </div>
            <script src=`/assets/docs.js?v={zx.info.version}` defer="true"></script>
        </section>
    );
}

const CreatingComponentsProps = struct {
    zx_code: []const u8,
    zig_code: []const u8,
    html_code: []const u8,
};

fn CreatingComponents(allocator: zx.Allocator, props: CreatingComponentsProps) zx.Component {
    return (
        <section id="creating-components" class="section" @allocator={allocator}>
            <h2>Creating and nesting components</h2>
            <p>ZX apps are made out of <em>components</em>. A component is a function that returns a <code>zx.Component</code> type. Components can be as small as a button or as large as an entire page.</p>
            <p>ZX components are Zig functions that return markup. Notice how <code>{"<Greeting />"}</code> starts with a capital letter - that's how ZX distinguishes between custom components and HTML elements:</p>
            <ExampleBlock id="greeting" zx_code={props.zx_code} zig_code={props.zig_code} html_code={props.html_code} filename="hello_world.zx" />
            <div class="callout note">
                <strong>Note:</strong>
                 Every component needs an allocator for memory management. The 
                <code>@allocator</code>
                 attribute must be set on the root element of each component. Child components inherit the allocator from their parent. See the <a href="/reference#allocator">@allocator documentation</a> for details.
            </div>
        </section>
    );
}

const WritingMarkupProps = struct {
    zx_code: []const u8,
    zig_code: []const u8,
    html_code: []const u8,
};

fn WritingMarkup(allocator: zx.Allocator, props: WritingMarkupProps) zx.Component {
    return (
        <section id="writing-markup" class="section" @allocator={allocator}>
            <h2>Writing markup with ZX</h2>
            <p>The markup syntax is called <em>ZX</em> - it's similar to JSX but designed for Zig. ZX files use the <code>.zx</code> extension and are transpiled to efficient Zig code.</p>
            <p>ZX is stricter than HTML. You have to close all tags, including self-closing ones like <code>{"<br />"}</code>:</p>
            <ExampleBlock id="markup" zx_code={props.zx_code} zig_code={props.zig_code} html_code={props.html_code} filename="about_section.zx" />
            <p>CSS classes are specified with the <code>class</code> attribute, same as HTML. Write your CSS in separate files and include them in your layout.</p>
            <p>ZX automatically escapes HTML content for security. If you need to render raw HTML, see the <a href="/reference#escaping">@escaping documentation</a>.</p>
        </section>
    );
}

const FragmentsProps = struct {
    zx_code: []const u8,
    zig_code: []const u8,
    html_code: []const u8,
};

fn Fragments(allocator: zx.Allocator, props: FragmentsProps) zx.Component {
    return (
        <section id="fragments" class="section" @allocator={allocator}>
            <h2>Fragments</h2>
            <p>Sometimes you want to return multiple elements from a component without adding an extra wrapper. Use the empty tag syntax <code>{"<>"}...{"</>"}</code>:</p>
            <ExampleBlock id="fragment" zx_code={props.zx_code} zig_code={props.zig_code} html_code={props.html_code} filename="fragment_demo.zx" />
            <p>Fragments are useful when you need to group elements but don't want to add extra DOM nodes. The children are rendered directly without any wrapper element. Learn more in the <a href="/reference#fragments">Fragments documentation</a>.</p>
        </section>
    );
}

const DisplayingDataProps = struct {
    zx_text: []const u8,
    zig_text: []const u8,
    html_text: []const u8,
    zx_format: []const u8,
    zig_format: []const u8,
    html_format: []const u8,
};

fn DisplayingData(allocator: zx.Allocator, props: DisplayingDataProps) zx.Component {
    return (
        <section id="displaying-data" class="section" @allocator={allocator}>
            <h2>Displaying data</h2>
            <p>ZX lets you embed dynamic content using curly braces <code>{"{expression}"}</code>. Expressions are automatically formatted based on their type:</p>
            <ul>
                <li><strong>Strings</strong> — displayed as text (HTML-escaped for safety)</li>
                <li><strong>Numbers</strong> — formatted as decimal</li>
                <li><strong>Booleans</strong> — displayed as "true" or "false"</li>
                <li><strong>Enums</strong> — displayed as the tag name</li>
                <li><strong>Optionals</strong> — unwrapped if present, otherwise renders nothing</li>
            </ul>
            <ExampleBlock id="text-expr" zx_code={props.zx_text} zig_code={props.zig_text} html_code={props.html_text} filename="user_greeting.zx" />
            <p>Different types are automatically handled:</p>
            <ExampleBlock id="format-expr" zx_code={props.zx_format} zig_code={props.zig_format} html_code={props.html_format} filename="product_info.zx" />
            <p>See the <a href="/reference#expressions">Expressions documentation</a> for detailed information on all supported types including components and component arrays.</p>
        </section>
    );
}

const DynamicAttributesProps = struct {
    zx_code: []const u8,
    zig_code: []const u8,
    html_code: []const u8,
};

fn DynamicAttributes(allocator: zx.Allocator, props: DynamicAttributesProps) zx.Component {
    const spread_example =
        \\const attrs = .{ .class = "btn", .disabled = true };
        \\...
        \\(<button {..attrs}>Click</button>)
    ;
    const template_example =
        \\const id = 42;
        \\...
        \\(<a href=`/users/{id}/profile`>Profile</a>)
    ;

    return (
        <section id="dynamic-attributes" class="section" @allocator={allocator}>
            <h2>Dynamic attributes</h2>
            <p>Use curly braces to pass dynamic values to HTML attributes:</p>
            <ExampleBlock id="dynamic-attr" zx_code={props.zx_code} zig_code={props.zig_code} html_code={props.html_code} filename="dynamic_attrs.zx" />
            <p>You can use any expression, including conditionals, to compute attribute values dynamically.</p>

            <h3>Template strings</h3>
            <p>Use backticks for string interpolation in attributes:</p>
            <CodeBlock code={template_example} />

            <h3>Spread and shorthand</h3>
            <p>Use <code>{"{..struct}"}</code> to spread struct fields as attributes, or <code>{"{variable}"}</code> as shorthand when the attribute name matches the variable:</p>
            <CodeBlock code={spread_example} />
            <p>See the <a href="/reference#attribute-syntax">Attribute Syntax documentation</a> for more details. ZX also provides special <a href="/reference#builtin-attributes">builtin attributes</a> like <code>@allocator</code>, <code>@escaping</code>, and <code>@rendering</code>.</p>
        </section>
    );
}

const ConditionalRenderingProps = struct {
    zx_conditional: []const u8,
    zig_conditional: []const u8,
    html_conditional: []const u8,
    zx_switch: []const u8,
    zig_switch: []const u8,
    html_switch: []const u8,
};

fn ConditionalRendering(allocator: zx.Allocator, props: ConditionalRenderingProps) zx.Component {
    return (
        <section id="conditional-rendering" class="section" @allocator={allocator}>
            <h2>Conditional rendering</h2>
            <p>Use Zig's <code>if</code> expressions to conditionally render content:</p>
            <ExampleBlock id="conditional" zx_code={props.zx_conditional} zig_code={props.zig_conditional} html_code={props.html_conditional} filename="user_status.zx" />

            <h3>Switch expressions</h3>
            <p>Use <code>switch</code> expressions to match against enum values. Each case can return text or a component:</p>
            <ExampleBlock id="switch-expr" zx_code={props.zx_switch} zig_code={props.zig_switch} html_code={props.html_switch} filename="role_badge.zx" />
            <p>ZX also supports <code>while</code> loops for conditional iteration. See the <a href="/reference#control-flow">Control Flow documentation</a> for all patterns.</p>
        </section>
    );
}

const RenderingListsProps = struct {
    zx_code: []const u8,
    zig_code: []const u8,
    html_code: []const u8,
};

fn RenderingLists(allocator: zx.Allocator, props: RenderingListsProps) zx.Component {
    return (
        <section id="rendering-lists" class="section" @allocator={allocator}>
            <h2>Rendering lists</h2>
            <p>Use <code>for</code> loops to iterate over arrays and render a component for each item:</p>
            <ExampleBlock id="list" zx_code={props.zx_code} zig_code={props.zig_code} html_code={props.html_code} filename="product_list.zx" />
            <p>The loop variable can be used within the component body to display item-specific content. See the <a href="/reference#for-loops">For Loops documentation</a> for more examples.</p>
        </section>
    );
}

const PassingPropsProps = struct {
    zx_code: []const u8,
    zig_code: []const u8,
    html_code: []const u8,
};

fn PassingProps(allocator: zx.Allocator, props: PassingPropsProps) zx.Component {
    return (
        <section id="passing-props" class="section" @allocator={allocator}>
            <h2>Passing props to components</h2>
            <p>Components can accept <em>props</em> (properties) to customize their behavior. Define a props struct as the second parameter:</p>
            <ExampleBlock id="props" zx_code={props.zx_code} zig_code={props.zig_code} html_code={props.html_code} filename="button_demo.zx" />
            <p>ZX automatically coerces attributes to the props struct. Fields with default values are optional. See the <a href="/reference#components">Components documentation</a> for more on props coercion.</p>
            <h3>Component signatures</h3>
            <ul>
                <li><strong>Allocator only:</strong><code>fn Component(allocator: zx.Allocator) zx.Component</code></li>
                <li><strong>With props:</strong><code>fn Component(allocator: zx.Allocator, props: Props) zx.Component</code></li>
            </ul>
        </section>
    );
}

const ChildrenPropsProps = struct {
    zx_code: []const u8,
    zig_code: []const u8,
    html_code: []const u8,
};

fn ChildrenProps(allocator: zx.Allocator, props: ChildrenPropsProps) zx.Component {
    return (
        <section id="children" class="section" @allocator={allocator}>
            <h2>Passing children to components</h2>
            <p>Components can accept <em>children</em> — content passed between opening and closing tags. Add a <code>children: zx.Component</code> field to your props:</p>
            <ExampleBlock id="children" zx_code={props.zx_code} zig_code={props.zig_code} html_code={props.html_code} filename="card_demo.zx" />
            <p>This pattern is useful for creating wrapper components like cards, modals, or layout containers. See the <a href="/reference#children-props">Children Props documentation</a> for more details.</p>
        </section>
    );
}

const PagesAndLayoutsProps = struct {
    zx_page: []const u8,
    zig_page: []const u8,
    html_page: []const u8,
    zx_layout: []const u8,
    zx_dynamic: []const u8,
    zig_dynamic: []const u8,
    html_dynamic: []const u8,
};

fn PagesAndLayouts(allocator: zx.Allocator, props: PagesAndLayoutsProps) zx.Component {
    const layout_code = @embedFile("./examples/layout_example.zx");
    const layout_html =
        \\<html><head><title>My App</title></head><body><nav><a href="/">Home</a> <a href="/about">About</a></nav><main><h1>About Us</h1><p>Welcome!</p></main><footer>© 2025 My App</footer></body></html>
    ;

    return (
        <section id="pages-layouts" class="section" @allocator={allocator}>
            <h2>Pages and Layouts</h2>
            <p>ZX uses file-based routing. Create <code>page.zx</code> files in the <code>app/pages/</code> directory:</p>
            <ExampleBlock id="page-example" zx_code={props.zx_page} zig_code={props.zig_page} html_code={props.html_page} filename="page.zx" />
            <p>The file path determines the URL: <code>app/pages/about/page.zx</code> → <code>/about</code></p>

            <h3>Dynamic routes</h3>
            <p>Use brackets <code>[param]</code> in folder names to create dynamic segments:</p>
            <ul>
                <li><code>app/pages/user/[id]/page.zx</code> → <code>/user/:id</code></li>
                <li><code>app/pages/blog/[slug]/page.zx</code> → <code>/blog/:slug</code></li>
            </ul>
            <p>Access the parameter value using <code>ctx.request.params.get("name")</code>:</p>
            <ExampleBlock id="dynamic-route" zx_code={props.zx_dynamic} zig_code={props.zig_dynamic} html_code={props.html_dynamic} filename="user/[id]/user_profile.zx" />

            <h3>Creating layouts</h3>
            <p>Layouts wrap pages with common UI. Create a <code>layout.zx</code> file:</p>
            <ExampleBlock id="layout-example" files={layoutFiles(allocator, layout_code, props.zx_page)} zig_code={layout_code} html_code={layout_html} />

            <h3>PageContext and LayoutContext</h3>
            <p>Both contexts provide:</p>
            <ul>
                <li><code>request</code> — HTTP request with headers, query params, body</li>
                <li><code>response</code> — HTTP response for setting headers</li>
                <li><code>arena</code> — Request-scoped allocator (recommended)</li>
                <li><code>allocator</code> — Global allocator for persistent allocations</li>
            </ul>
            <div class="callout tip">
                <strong>Best practice:</strong>
                 Use 
                <code>ctx.arena</code>
                 for allocations - it's automatically freed after the request.
            </div>
            <p>See the <a href="/reference#routing">Routing documentation</a> for detailed information on pages, layouts, and dynamic routes.</p>
        </section>
    );
}

const APIRoutesProps = struct {
    zig_code: []const u8,
};

fn APIRoutes(allocator: zx.Allocator, props: APIRoutesProps) zx.Component {
    return (
        <section id="api-routes" class="section" @allocator={allocator}>
            <h2>API Routes</h2>
            <p>ZX makes it easy to create APIs by adding <code>route.zig</code> files to your <code>app/pages/</code> directory. These files handle HTTP methods like GET, POST, and more.</p>
            <p>Create a <code>route.zig</code> file to handle API requests:</p>
            <CodeBlock code={props.zig_code} filename="route.zig" />
            <p>API routes have access to <code>zx.RouteContext</code>, which provides the request, response, and even WebSocket support. Learn more in the <a href="/reference#api-routes">API documentation</a>.</p>
        </section>
    );
}

fn Plugins(allocator: zx.Allocator) zx.Component {
    const tailwind_example = @embedFile("./examples/tailwind_plugin.zig");
    const esbuild_example = @embedFile("./examples/esbuild_plugin.zig");
    const link_css_example = "<link rel=\"stylesheet\" href=\"/assets/styles.css\" />";
    const link_js_example = "<script src=\"/assets/main.js\"></script>";

    return (
        <section id="plugins" class="section" @allocator={allocator}>
            <h2>Using Plugins</h2>
            <p>ZX provides a plugin system to extend your build process. Plugins run as additional build steps and integrate with tools like Tailwind CSS and esbuild.</p>

            <h3>Builtin Plugins</h3>
            <p>ZX ships with the following builtin plugins available via <code>zx.plugins</code>:</p>
            <ul>
                <li><strong><code>zx.plugins.tailwind</code></strong> — Compile Tailwind CSS styles</li>
                <li><strong><code>zx.plugins.esbuild</code></strong> — Bundle TypeScript/JavaScript for client-side code</li>
            </ul>

            <h3>Tailwind CSS Plugin</h3>
            <p>The Tailwind builtin plugin compiles your CSS using the Tailwind CLI. Add it to your <code>build.zig</code>:</p>
            <CodeBlock code={tailwind_example} filename="build.zig" />
            <p>Then link the compiled CSS in your layout:</p>
            <CodeBlock code={link_css_example} />
            <div class="callout note">
                <strong>Prerequisites:</strong>
                 Install the required CLI tools before using builtin plugins:
                <code>npm install tailwindcss @tailwindcss/cli</code>
            </div>

            <h3>esbuild Plugin</h3>
            <p>The esbuild builtin plugin bundles TypeScript or JavaScript for client-side interactivity:</p>
            <CodeBlock code={esbuild_example} filename="build.zig" />
            <p>Then include the bundled script in your layout:</p>
            <CodeBlock code={link_js_example} />
            <div class="callout note">
                <strong>Prerequisites:</strong>
                 Install the required CLI tools before using builtin plugins:
                <code>npm install esbuild</code>
            </div>

            <p>See the <a href="/reference#plugins">Plugins documentation</a> for all available options and how to create your own custom plugins.</p>
        </section>
    );
}

fn NextSteps(allocator: zx.Allocator) zx.Component {
    return (
        <section id="next-steps" class="section" @allocator={allocator}>
            <h2>Next Steps</h2>
            <p>You now know the basics of ZX! Here's what to explore next:</p>
            <div class="next-steps-grid">
                <a href="/reference" class="next-step-card">
                    <h3>Documentation</h3>
                    <p>Deep dive into all ZX features with detailed examples.</p>
                </a>
                <a href="/reference#cli" class="next-step-card">
                    <h3>CLI Reference</h3>
                    <p>Learn about the ZX command-line tools.</p>
                </a>
                <a href="/examples" class="next-step-card">
                    <h3>Examples</h3>
                    <p>Explore working code examples and patterns.</p>
                </a>
            </div>
        </section>
    );
}

const zx = @import("zx");
const std = @import("std");
const example_block = @import("../components/example_block.zx");
const ExampleBlock = example_block.ExampleBlock;
const File = example_block.File;
const CodeBlock = @import("../components/code_block.zx").CodeBlock;
const ProjectTree = @import("../components/project_tree.zx").ProjectTree;
const InstallCLI = @import("../components/install_guide.zx").InstallCLI;
const InstallZig = @import("../components/install_guide.zx").InstallZig;

// Helper to allocate files on heap to avoid stack lifetime issues
fn layoutFiles(allocator: zx.Allocator, layout_code: []const u8, page_code: []const u8) []const File {
    const files = allocator.alloc(File, 2) catch unreachable;
    files[0] = .{ .filename = "layout.zx", .code = layout_code };
    files[1] = .{ .filename = "page.zx", .code = page_code };
    return files;
}
