type: decision
status: active
timestamp: 2026-06-21
tags: [architecture, apps, scaffold, ci-cd, sidebar, pages]

Per-app contents specification — sidebar + pages + CI/CD

Every app follows contents spec. 4-config structure split (site/nav/sidebar/footer) lives in src/config/. Common pages (landing, about, changelog, admin) + per-tool pages + 24 legal pages from astro-chrome. CI/CD via reusable workflow from astro-shell-npm-pkg + separate test.yml.

Per-app contents specification

Decision

Every *-app repo in the chirag127 family follows this contents template.

Folder structure per app

<repo>/
+-- .github/workflows/
¦   +-- deploy.yml             # uses chirag127/astro-shell-npm-pkg/.github/workflows/deploy.yml@main
¦   +-- test.yml               # vitest + playwright + lighthouse a11y/perf gate on every PR
+-- src/
¦   +-- config/                # 4-config split per chrome-config-contract
¦   ¦   +-- site.ts            # brand, subdomain, jurisdiction
¦   ¦   +-- nav.ts             # header actions
¦   ¦   +-- sidebar.ts         # 3-level tree (Section ? Group ? Leaf)
¦   ¦   +-- footer.ts          # columns + family directory
¦   +-- pages/
¦   ¦   +-- index.astro        # landing page (ToolGrid for tool apps; hero for content apps)
¦   ¦   +-- about.astro        # one-paragraph about + family link
¦   ¦   +-- changelog.astro    # auto-generated from git-cliff or CHANGELOG.md
¦   ¦   +-- admin.astro        # auth-gated analytics dashboard widget
¦   ¦   +-- <tool-or-content-pages>  # one page per tool/post/entry
¦   +-- components/            # app-specific React/Astro components
¦   +-- styles.css             # @chirag127/astro-chrome tokens + per-app overrides
¦   +-- env.d.ts
+-- public/
¦   +-- manifest.json          # PWA manifest derived from src/config/site.ts
¦   +-- robots.txt             # per multi-target-build § Robots.txt
¦   +-- sitemap.xml            # generated by @astrojs/sitemap
¦   +-- favicon.svg            # Stamp signature SVG (or rendered version)
+-- tests/
¦   +-- smoke.test.ts          # vitest — every page module has default export
¦   +-- e2e/<page>.spec.ts     # playwright — one test per critical page
+-- astro.config.ts            # re-exports @chirag127/astro-shell-npm-pkg config + site URL
+-- package.json               # workspace deps, scripts: dev/build/preview/lint/test/typecheck
+-- tsconfig.json              # extends @chirag127/astro-config-npm-pkg/tsconfig.json
+-- biome.json                 # extends @chirag127/astro-config-npm-pkg/biome.json
+-- tailwind.config.js         # imports @chirag127/astro-config-npm-pkg/tailwind.preset
+-- .gitignore                 # standard Node + Astro
+-- LICENSE                    # source-available, all rights reserved
+-- README.md                  # product brand explanation + stack + live URL

Page structure

Tool apps (15 repos)

PathPurpose
/ToolGrid: every tool as a card. Hero with Stamp + tagline.
/<tool-slug>One page per tool. Uses ToolPage from astro-tools-npm-pkg.
/aboutOne paragraph about the app + product-brand-explanation + family link.
/changelogAuto-generated from git-cliff or repo’s CHANGELOG.md.
/adminAuth-gated. Embed of family analytics dashboard widget.
24 legal routesRe-exported from @chirag127/astro-chrome-npm-pkg/legal/*. Slugs: /privacy, /terms, /cookies, /imprint, /refund, /sub-processors, /dpa, /gdpr-rights, /ccpa-rights, /dpdp-rights, /accessibility, /security, /vulnerability, /dmca, /trademark, /attribution, /community, /takedown, /age-gating, /affiliate-disclosure, /ad-disclosure, /sponsored, /changelog (overrides app’s /changelog), /status.

Page count per tool app: N tools + 4 common + 24 legal = N + 28.

Content apps (6 repos: blog, journal, lore, ncert, cards, post)

PathPurpose
/Hero + recent-N grid + tag/category nav.
/<slug>Individual post / entry / card.
/tags/<tag>Tag archive.
/about, /changelog, /adminSame as tool apps.
24 legal routesSame.

Hub + personal apps (home + me)

Per the v6 chrome-config-contract: every app has src/config/sidebar.ts exporting a typed 3-level tree (Section ? Group ? Leaf). Astro-chrome’s <Sidebar> component renders it.

Examples:

oriz-slice-pdf-tools-app/src/config/sidebar.ts:

import type { SidebarNode } from "@chirag127/astro-chrome-npm-pkg/types";

export const sidebarTree: SidebarNode[] = [
  { type: "section", label: "TOOLS", children: [
    { type: "group", label: "Combine", href: "/combine/", children: [
      { type: "leaf", label: "merge", href: "/combine/merge" },
      { type: "leaf", label: "split", href: "/combine/split" },
      { type: "leaf", label: "reorder", href: "/combine/reorder" },
    ]},
    { type: "group", label: "Compress", href: "/compress/", children: [
      { type: "leaf", label: "shrink", href: "/compress/shrink" },
      { type: "leaf", label: "optimize", href: "/compress/optimize" },
    ]},
    // ... more groups
  ]},
];

Each app authors its own. Defaults via astro-chrome-npm-pkg if not set.

CI/CD per app

.github/workflows/deploy.yml

Uses the reusable workflow from astro-shell-npm-pkg:

name: Deploy to Cloudflare Pages
on:
  push:
    branches: [main]
  pull_request:
    types: [opened, synchronize]
  workflow_dispatch:
jobs:
  deploy:
    uses: chirag127/astro-shell-npm-pkg/.github/workflows/deploy.yml@main
    with:
      project-name: <repo-slug>
      build-output-directory: dist
    secrets:
      CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}
      CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}

Triggers (per multi-target-build.md):

Branch / eventTarget
Push to mainCloudflare Pages production
Pull requestCloudflare Pages preview at <pr>.<subdomain>.oriz.in
Tag v*.*.*Production + APK + EXE build via PWABuilder

.github/workflows/test.yml

Separate workflow runs on every PR + push to main:

name: Test
on:
  pull_request:
  push:
    branches: [main]
jobs:
  unit:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v5
      - uses: pnpm/action-setup@v4
      - uses: actions/setup-node@v5
        with: { node-version: 22, cache: pnpm }
      - run: pnpm install --frozen-lockfile
      - run: pnpm typecheck
      - run: pnpm lint
      - run: pnpm test            # vitest
  e2e:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v5
      - uses: pnpm/action-setup@v4
      - uses: actions/setup-node@v5
        with: { node-version: 22, cache: pnpm }
      - run: pnpm install --frozen-lockfile
      - run: pnpm exec playwright install --with-deps chromium
      - run: pnpm build
      - run: pnpm test:e2e        # playwright
  lighthouse:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v5
      - uses: actions/setup-node@v5
        with: { node-version: 22 }
      - run: npx lhci autorun     # WCAG 2.2 AA + a11y >= 95 + perf >= 80 gates

Local submodule path = full brand slug

Local submodule disk paths mirror the full GitHub slug. Apps and APIs live under repos/oriz/own/prod/apps/ and repos/oriz/own/svc/api/:

Local path
repos/c127/own/prod/apps/personal/cs-me-app
repos/oriz/own/prod/apps/content/oriz-pages-blog-app
repos/oriz/own/prod/apps/content/oriz-roam-journal-app
repos/oriz/own/prod/apps/content/oriz-lore-app
repos/oriz/own/prod/apps/content/oriz-financial-cards-app
repos/oriz/own/prod/apps/content/oriz-omni-post-app
repos/oriz/own/prod/apps/content/oriz-ncert-app
repos/oriz/own/prod/apps/content/oriz-janaushdhi-app
repos/oriz/own/prod/apps/tools/oriz-slice-pdf-tools-app
repos/oriz/own/prod/apps/tools/oriz-pixie-image-tools-app
repos/oriz/own/prod/apps/tools/oriz-paisa-finance-tools-app
repos/oriz/own/prod/apps/tools/oriz-forge-dev-tools-app
repos/oriz/own/prod/apps/tools/oriz-scribe-text-tools-app
repos/oriz/own/prod/apps/tools/oriz-shift-convert-tools-app
repos/oriz/own/prod/apps/tools/oriz-grid-qr-tools-app
repos/oriz/own/prod/apps/tools/oriz-pivot-data-tools-app
repos/oriz/own/prod/apps/tools/oriz-echo-audio-tools-app
repos/oriz/own/prod/apps/tools/oriz-reel-video-tools-app
repos/oriz/own/prod/apps/tools/oriz-rank-seo-tools-app
repos/oriz/own/prod/apps/tools/oriz-cipher-crypto-tools-app
repos/oriz/own/prod/apps/tools/oriz-vitals-health-tools-app
repos/oriz/own/prod/apps/tools/oriz-dice-random-tools-app
repos/oriz/own/prod/apps/tools/oriz-paper-print-tools-app
repos/oriz/own/svc/api/oriz-mmi-tickertape-mmi-api
repos/oriz/own/svc/api/oriz-flow-fii-dii-activity-api

Kept short (vendor-convention or category-IS-brand):

Cross-refs


Edit on GitHub · Back to index