Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions apps/logicsrc-web/contract/logicsrc-web.contract.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";

import { proxy } from "../src/proxy";
import { renderPageMarkup } from "@/lib/page-markup";
import { siteFooterHtml } from "@/lib/site-footer";
import { choosePaymentRail, signSession, verifyCoinPayWebhook, verifySession } from "@/lib/coinpay";
import { POST as coinpayCheckout } from "@/app/api/hire-us/coinpay-checkout/route";
import { POST as projectRequest } from "@/app/api/hire-us/project-request/route";
Expand Down Expand Up @@ -91,8 +92,10 @@ describe("server-rendered page markup", () => {
expect(markup).toContain('id="project-request-form"');
});

it("carries the Profullstack webring links (the ring verifier reads the homepage)", () => {
const markup = renderPageMarkup();
it("carries the Profullstack webring links (the ring verifier reads the homepage)", async () => {
process.env.PROFULLSTACK_FOOTER_OFFLINE = "1";
const markup = renderPageMarkup("/", await siteFooterHtml());
expect(markup).toContain("data-pfs-footer");
const from = "from=https%3A%2F%2Flogicsrc.com%2F";
for (const hop of ["previous", "next", "random"]) {
expect(markup).toContain(`https://rssamplifier.com/ring/profullstack/${hop}?${from}`);
Expand Down
1 change: 1 addition & 0 deletions apps/logicsrc-web/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
"@logicsrc/openontology": "file:../../packages/openontology",
"@logicsrc/openprd": "file:../../packages/openprd",
"@profullstack/autoblog": "github:profullstack/autoblog#75e54af",
"@profullstack/footer": "latest",
"@profullstack/stack": "^0.1.3",
"@profullstack/x402-gateway": "^0.7.0",
"@supabase/supabase-js": "^2.105.4",
Expand Down
4 changes: 3 additions & 1 deletion apps/logicsrc-web/src/app/[[...slug]]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import { renderPageMarkup } from "@/lib/page-markup";
import { pageMetadata, specMetadata } from "@/lib/page-meta";
import { HomeInteractivity } from "@/components/home-interactivity";
import { siteFooterHtml } from "@/lib/site-footer";

// The legacy SPA served the same single page for every top-level path and just
// scrolled to the matching section. We preserve those URLs (they are canonical
Expand Down Expand Up @@ -50,9 +51,10 @@
}
}

const footer = await siteFooterHtml();
return (
<>
<div id="app" dangerouslySetInnerHTML={{ __html: renderPageMarkup(slug?.[0] ? `/${slug[0]}` : "/") }} />
<div id="app" dangerouslySetInnerHTML={{ __html: renderPageMarkup(slug?.[0] ? `/${slug[0]}` : "/", footer) }} />
<HomeInteractivity />
</>
);
Expand Down
36 changes: 5 additions & 31 deletions apps/logicsrc-web/src/components/site-shell.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ import type { ReactNode } from "react";
import { renderInstallCommand } from "@/lib/install-command";
import { Breadcrumbs } from "@/components/breadcrumbs";
import { SideNav } from "@/components/side-nav";
import { Footer } from "@profullstack/footer/react";
import { SITE_FOOTER, SITE_FOOTER_COLOR } from "@/lib/site-footer";

/**
* The site chrome for every standalone route: the sidebar that unfolds to
Expand Down Expand Up @@ -37,37 +39,9 @@ export function SiteShell({
<section className="workspace">
<Breadcrumbs leaf={crumbTitle} />
{children}
<footer
style={{
maxWidth: "72rem",
margin: "2rem auto 0",
padding: "1.25rem 0",
borderTop: "1px solid #d9ded4",
display: "flex",
flexWrap: "wrap",
gap: "0.75rem",
justifyContent: "space-between",
fontSize: "0.85rem",
color: "#5b6b7a",
}}
>
<span>© {new Date().getFullYear()} Profullstack, Inc. · LogicSRC</span>
<span style={{ display: "flex", gap: "0.75rem" }}>
<a href="/specs" style={{ color: "inherit" }}>Specs</a>
<a href="/docs" style={{ color: "inherit" }}>Docs</a>
<a href="/blog/rss.xml" style={{ color: "inherit" }}>RSS</a>
<a href="/llms.txt" style={{ color: "inherit" }}>llms.txt</a>
<a href="/terms" style={{ color: "inherit" }}>Terms</a>
<a href="/privacy" style={{ color: "inherit" }}>Privacy</a>
</span>
{/* Member of the Profullstack OpenWebring (/openwebring): the ring reads these links. */}
<span style={{ display: "flex", gap: "0.75rem", width: "100%" }}>
<a href="https://rssamplifier.com/ring/profullstack/previous?from=https%3A%2F%2Flogicsrc.com%2F" rel="prev" title="Previous site" style={{ color: "inherit" }}>{"<<"}</a>
<a href="https://rssamplifier.com/ring/profullstack" style={{ color: "inherit" }}>Profullstack</a>
<a href="https://rssamplifier.com/ring/profullstack/next?from=https%3A%2F%2Flogicsrc.com%2F" rel="next" title="Next site" style={{ color: "inherit" }}>{">>"}</a>
<a href="https://rssamplifier.com/ring/profullstack/random?from=https%3A%2F%2Flogicsrc.com%2F" title="Random site" aria-label="Random site" style={{ color: "inherit" }}>{"⚄"}</a>
</span>
</footer>
<div style={{ color: SITE_FOOTER_COLOR, marginTop: "2rem" }}>
<Footer {...SITE_FOOTER} />
</div>
</section>
</main>
);
Expand Down
19 changes: 7 additions & 12 deletions apps/logicsrc-web/src/lib/page-markup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,12 @@ const comparisonRows = [
}
];

export function renderPageMarkup(path = "/"): string {
/**
* `footer` is the site footer's HTML (lib/site-footer.ts, @profullstack/footer), placed
* at the end of the workspace. The page route passes it; it is server-rendered, which
* the Profullstack ring's verifier needs.
*/
export function renderPageMarkup(path = "/", footer = ""): string {
return `
<main class="shell">
<aside class="rail">
Expand Down Expand Up @@ -431,17 +436,7 @@ COINPAY_STATUS=pending_acceptance</code></pre>
`).join("")}
</div>
</section>
<!-- Member of the Profullstack OpenWebring (/openwebring). The homepage is this
markup, not SiteShell, so it carries its own copy of the shell's ring footer:
the ring's verifier reads these links from the server-rendered homepage. -->
<footer style="max-width:72rem;margin:2rem auto 0;padding:1.25rem 0;border-top:1px solid #d9ded4;font-size:0.85rem;color:#5b6b7a">
<nav class="webring" aria-label="Profullstack webring" style="display:flex;gap:0.75rem;justify-content:center">
<a href="https://rssamplifier.com/ring/profullstack/previous?from=https%3A%2F%2Flogicsrc.com%2F" rel="prev" title="Previous site" style="color:inherit">&lt;&lt;</a>
<a href="https://rssamplifier.com/ring/profullstack" style="color:inherit">Profullstack</a>
<a href="https://rssamplifier.com/ring/profullstack/next?from=https%3A%2F%2Flogicsrc.com%2F" rel="next" title="Next site" style="color:inherit">&gt;&gt;</a>
<a href="https://rssamplifier.com/ring/profullstack/random?from=https%3A%2F%2Flogicsrc.com%2F" title="Random site" aria-label="Random site" style="color:inherit">&#x2684;</a>
</nav>
</footer>
<div style="color:#5b6b7a">${footer}</div>
</section>
</main>
`;
Expand Down
26 changes: 26 additions & 0 deletions apps/logicsrc-web/src/lib/site-footer.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { footerHtml, type FooterOptions } from "@profullstack/footer";

/**
* The site footer: @profullstack/footer (links, copyright and the Profullstack
* webring). SiteShell renders it as the package's React server component; the
* homepage, which is the legacy markup string (lib/page-markup.ts), gets the same
* footer as HTML. Both render on the server, which is what the ring's verifier reads.
*/
export const SITE_FOOTER: FooterOptions = {
site: "https://logicsrc.com/",
links: [
{ label: "Specs", href: "/specs" },
{ label: "Docs", href: "/docs" },
{ label: "RSS", href: "/blog/rss.xml" },
{ label: "llms.txt", href: "/llms.txt" },
{ label: "Terms", href: "/terms" },
{ label: "Privacy", href: "/privacy" },
],
};

/** Muted text, as the old footer had; the package inherits `color`. */
export const SITE_FOOTER_COLOR = "#5b6b7a";

export function siteFooterHtml(): Promise<string> {
return footerHtml(SITE_FOOTER);
}
3 changes: 3 additions & 0 deletions bun.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading