Skip to content

Homepage Counter examples: Vue Vapor should use SFC template, Octane should use TSRX #244

Description

@ywenhao

Summary

The homepage code switcher in the "Familiar code, native machinery" section (site/home.html) shows misleading examples for the Vue Vapor and Octane tabs. Both tabs currently display Counter.tsx with TSX-style functional components, which does not reflect the idiomatic authoring models for those frameworks.

Current behavior

All three tabs label the file as Counter.tsx and use the same TSX functional-component shape:

  • Solid — looks correct (createSignal + JSX).
  • Vue Vapor — shows TSX with ref from vue and a return (...) JSX tree.
  • Octane — shows plain TSX with useState from octane.

Expected behavior

Vue Vapor → Vue SFC (Counter.vue)

PocketJS supports (and documents via real apps) the <script setup> + <template> authoring model for Vue Vapor, not only TSX.

Canonical in-repo examples:

  • apps/hero-vue-sfc/app.vue
  • apps/vue-sfc-lab/app.vue (described as "official template syntax • PocketJS Vapor")

A minimal Counter example should look more like:

<script setup lang="ts">
import { ref } from "vue";
import { Text, View } from "@pocketjs/framework/vue-vapor/components";

const n = ref(0);
</script>

<template>
  <View class="flex-col items-center gap-4 p-6 bg-slate-950">
    <Text class="text-2xl text-slate-50 font-bold">Count: {{ n }}</Text>
    <View
      class="px-4 py-2 rounded-xl bg-slate-700 focus:bg-slate-500"
      focusable
      @press="n++"
    >
      <Text class="text-base text-slate-50 font-bold">Press Circle</Text>
    </View>
  </View>
</template>

The tab label / filename in the card should probably be Counter.vue, not Counter.tsx.

Octane → TSRX (Counter.tsrx)

Octane's idiomatic dialect is TSRX (.tsrx), which uses the @{ ... } shorthand so setup logic sits next to the JSX output. Plain .tsx works, but the homepage should showcase TSRX since that is Octane's distinguishing authoring format.

Reference: Octane TSRX basics

A minimal Counter example should look more like:

import { Text, View } from "@pocketjs/framework/octane/components";
import { useState } from "octane";

export function Counter() @{
  const [n, setN] = useState(0);

  <View class="flex-col items-center gap-4 p-6 bg-slate-950">
    <Text class="text-2xl text-slate-50 font-bold">{`Count: ${n}`}</Text>
    <View
      class="px-4 py-2 rounded-xl bg-slate-700 focus:bg-slate-500"
      focusable
      onPress={() => setN(n + 1)}
    >
      <Text class="text-base text-slate-50 font-bold">Press Circle</Text>
    </View>
  </View>
}

The tab label / filename in the card should probably be Counter.tsrx, not Counter.tsx.

Suggested fix

  1. Update the Vue Vapor panel in site/home.html to show a Vue SFC example (<script setup> + <template>).
  2. Update the Octane panel to show TSRX (@{ ... }) syntax.
  3. Consider updating the displayed filename per tab (Counter.tsx / Counter.vue / Counter.tsrx), or make it dynamic when switching tabs.
  4. Optionally align site/content/docs/frameworks.md and site/content/docs/getting-started.md if the goal is to present SFC + TSRX as the primary onboarding examples (those docs still show TSX for Vue Vapor and Octane).

Why this matters

The homepage is the first place new visitors learn what "familiar code" means for each framework. Showing TSX for Vue Vapor and plain TSX for Octane understates PocketJS's Vue SFC pipeline and Octane's TSRX dialect, which are important differentiators.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions