feat: embeddable CompanyGame with loader, poster, no-WebGL fallback and SEO
CI/CD / test (push) Successful in 1m10s
CI/CD / publish (push) Successful in 1m20s
CI/CD / deploy (push) Successful in 6s

- CompanyGame bundles the store, a branded loader with start-up progress, an optional
  light poster (Enter the game) and a company-info fallback when WebGL is missing.
- startMode prop and ?mode= start straight in a mode; ?poster shows the poster first.
- Pixel ratio capped at 1.5 on touch devices and 1.75 on desktop (constants/graphics.js).
- Build writes the title, description, Organization JSON-LD and a hidden Persian
  summary into index.html from the company config.
- README explains iframe and component embedding.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-31 13:26:30 +03:00
co-authored by Claude Opus 5.5
parent 53caa0a208
commit bc6f472f08
19 changed files with 423 additions and 40 deletions
+25
View File
@@ -0,0 +1,25 @@
import test from 'node:test';
import assert from 'node:assert/strict';
import { COMPANY } from '../src/config/company.js';
import { seoHead, seoStructuredData, seoSummary } from '../src/utils/seoSummary.js';
test('The page head carries the company title and description', () => {
const head = seoHead();
assert.ok(head.includes(`<title>${COMPANY.name}`));
assert.match(head, /<meta name="description" content="[^"]+"/);
});
test('The hidden summary lists the company, every product and the contact details', () => {
const summary = seoSummary();
assert.ok(summary.startsWith('<section class="sr-only"'));
for (const product of COMPANY.products) assert.ok(summary.includes(product.name));
assert.ok(summary.includes(COMPANY.contact.email));
});
test('Structured data is valid JSON-LD for the organization', () => {
const json = seoStructuredData().replace(/^<script[^>]*>|<\/script>$/g, '');
const data = JSON.parse(json);
assert.equal(data['@type'], 'Organization');
assert.equal(data.name, COMPANY.name);
assert.equal(data.address.addressLocality, COMPANY.contact.city);
});