1. Start
  2. An entity
  3. A source
  4. A rule
  5. A port
  6. A link
  7. A fact
  8. An app
  9. Split

A page, and nothing declared twice

We add a Nuxt app in apps/nuxt with the @fougere/nuxt module and write a page. The page calls the blog by its name, and the fronds run inside Nuxt.

Install
$ npm create nuxt@latest apps/nuxt && cd apps/nuxt && npm install @fougere/nuxt
apps/nuxt/app/pages/posts.vue
1<script setup lang="ts">
2import { post } from '@fronds/facade';
3import Post from '@fronds/blog/entities/Post.js';
4
5const { items } = await useQuery(post, 'list');a
6const { fields, values, errors, submit } = useFormFor(Post);b
7const publish = useCommand(post, 'publish');d
8</script>
9
10<template>
11 <form novalidate @submit.prevent="submit">
12 <template v-for="field in fields" :key="field.name">
13 <input v-model="values[field.name]" v-bind="field.attrs" :placeholder="field.label" />
14 <small v-if="errors[field.name]">{{ errors[field.name] }}</small>
15 </template>
16 <button>Write a draft</button>
17 </form>
18
19 <ul>
20 <li v-for="row in items" :key="row.id">
21 {{ row.title }} — {{ row.status }}
22 <button v-if="row.status === 'draft'" @click="publish.execute({ params: { id: row.id } })">Publish</button>
23 </li>
24 </ul>
25 <p v-if="publish.error.value">{{ publish.error.value.message }}</p>
26</template>

point at a lettered line, or tap it, to see what grows from it

0 line changed under fronds/

The page names post and an operation. Its rows, its form and its refusals are read from what you already wrote.

Try it
$ cd apps/nuxt && npm run dev   # then open localhost:3000/posts
a form with one field, title — and the posts, each with Publish

Publish twice from two tabs: the second click shows Already published, the CONFLICT the handler throws.

Built with Fougere and Nuxt, hosted on GitHub Pages.