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
17 changes: 17 additions & 0 deletions .github/workflows/static-checks.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
name: Static checks
on:
pull_request:
push:
branches: [main]
permissions:
contents: read
jobs:
verify:
runs-on: ubuntu-latest
timeout-minutes: 5
steps:
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262
with:
persist-credentials: false
- name: Validate static page metadata and article anchors
run: python3 -m unittest discover -s tests -v
47 changes: 43 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,46 @@
# community-blog
# TypeSafeAI Community Notes

A minimal static blog for sharing posts about TypeSafe AI.
> **Unofficial community project — not the official TypeSafe AI blog or team.** Community organization created by VC Moderator [@BunsDev](https://github.com/BunsDev).

## Open locally
A dependency-free static site for introductory community notes about typed decisions, tool interfaces, and developer workflows. The current entries are short introductory notes, not published benchmarks, official product announcements, or claims of production safety.

Open `index.html` in a browser, or serve the repository root with a static file server.
![Community Notes editorial card](docs/discovery/assets/social-preview.svg)

[Contributing](CONTRIBUTING.md) · [Agent instructions](AGENTS.md) · [Publishing guide](docs/discovery/README.md) · [Machine-readable navigation](llms.txt)

## Preview locally

Open `index.html` in a browser, or serve the repository using Python's local static server:

```sh
python3 -m http.server 8080 --bind 127.0.0.1
```

Visit `http://127.0.0.1:8080`. No package installation, API key, build step, analytics account, or provider call is required. Binding to loopback avoids exposing a development server to other machines.

## Project map

- `index.html`: the full static page, styles, article anchors, and metadata.
- `tests/test_site.py`: dependency-free checks for discovery metadata, community identity, and article links.
- `docs/discovery/`: editorial card and publishing/screenshot guidance.
- `repository-metadata.json`: intended GitHub About/topics, not applied settings.

## Edit and verify

Keep semantic headings and stable article IDs. Link article headings to their fragments so individual notes can be shared within the page. Add a source, concrete example, and limitations to substantive new claims. Do not invent authors, experiment results, dates, deployments, or vendor endorsement.

```sh
python3 -m unittest discover -s tests -v
```

Also inspect the actual page at desktop and mobile widths, keyboard focus, article anchors, and links. Record the source commit and capture environment for screenshots. The SVG above is editorial artwork, not a screenshot.

## Deployment and sharing

This repository does not establish a confirmed production origin. The page has title/description and text-card metadata, but deliberately does not invent a canonical URL, sitemap, or absolute OG image URL. Once a public host is chosen, verify its origin and a publicly accessible raster image before adding those values and updating the relevant tests. See the [publishing guide](docs/discovery/README.md).

The GitHub About/topics manifest does not itself change repository settings. Do not treat a merged source change as deployed-site evidence.

## Attribution and reuse

Keep the unofficial notice, original credits, and any third-party notices. No license is added or changed by this documentation work; public availability alone does not establish permission to reuse unlicensed material. Official product and API resources are [typesafe.ai](https://typesafe.ai) and [docs.typesafe.ai](https://docs.typesafe.ai), separate from this community site.
23 changes: 23 additions & 0 deletions docs/discovery/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Community Notes — publishing and evidence

This is an unofficial community static page, not the official TypeSafe AI blog. Read the [README](../../README.md), [agent instructions](../../AGENTS.md), and [contribution guide](../../CONTRIBUTING.md) before editing.

## Publishing status

The site is source HTML with no confirmed production origin in this repository. Keep `og:url`, canonical, sitemap, and absolute `og:image` values unset until a host and a real raster image are chosen and verified. The current text-card metadata is intentional, not a claim that a large image preview has been deployed. Update the regression tests alongside an authorized deployment configuration change.

The [original SVG card](assets/social-preview.svg) is editable 1280×640 editorial artwork. It is not a product screenshot or an accepted GitHub raster upload by itself. Export and visually inspect a PNG before applying the separate repository Social preview setting. Follow the [shared publishing checklist](https://github.com/TypeSafeAI/.github/blob/main/docs/discovery/SHARING.md).

## Editorial guidance

Keep a stable ID and self-link for each article heading. Explain one concrete pattern with primary-source links, synthetic examples, and explicit limitations. A typed result is not proof of correctness or execution authorization. Do not add fabricated experiment results, authors, citations, testimonials, or official endorsement.

Metadata should describe the visible content. Keep titles and descriptions readable, not stuffed with unrelated trending keywords. Repository topics are capability categories, not release tags or ranking guarantees.

## Verification and screenshots

Run `python3 -m unittest discover -s tests -v`. Preview the actual HTML at desktop and narrow widths and inspect keyboard focus, article anchors, and wrapping. No external JavaScript, provider calls, credentials, or package installation is needed.

For each screenshot record the source commit/blob, viewport, capture method, and whether the page was local, preview, or production. Offline HTML renders are not deployed-site evidence. The initiative's local captures used 1440×1000 and 390×844 viewports and reported no horizontal overflow; use the exact source blob in their supplied provenance rather than treating those captures as future-build evidence.

Follow the [screenshot protocol](https://github.com/TypeSafeAI/.github/blob/main/docs/discovery/SCREENSHOTS.md). Review pixels for private content before publishing. No license or production host is established by this change.
16 changes: 16 additions & 0 deletions docs/discovery/assets/social-preview.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
41 changes: 31 additions & 10 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,13 @@
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>TypeSafe AI Blog</title>
<title>TypeSafeAI Community Notes — Unofficial</title>
<meta name="description" content="Unofficial community notes about TypeSafe AI: typed decisions, tool boundaries, reproducible examples, and developer experience." />
<meta property="og:title" content="TypeSafeAI Community Notes — Unofficial" />
<meta property="og:description" content="Practical community notes, source links, and explicit limitations. Not the official TypeSafe AI blog." />
<meta property="og:type" content="website" />
<meta name="twitter:card" content="summary" />
<!-- Add canonical/absolute image metadata only after a public origin and raster asset are verified. -->
<style>
:root {
color-scheme: light;
Expand Down Expand Up @@ -35,6 +41,10 @@
box-shadow: 0 20px 60px rgba(20, 33, 61, 0.18);
}

a { color: inherit; text-underline-offset: 0.2em; }
a:focus-visible { outline: 3px solid currentColor; outline-offset: 4px; }
.community-links { line-height: 1.8; }

.hero p,
.post p {
line-height: 1.6;
Expand Down Expand Up @@ -104,19 +114,24 @@
<main class="page">
<section class="hero">
<p class="eyebrow">Community Blog</p>
<h1>TypeSafe AI Blog</h1>
<h1>TypeSafeAI Community Notes</h1>
<p><strong>Unofficial community project — not the official TypeSafe AI team.</strong></p>
<p>
Notes, tutorials, and product thinking about building AI systems with safer schemas,
predictable interfaces, and reliable developer workflows.
</p>
<nav class="community-links" aria-label="Community resources">
<a href="https://github.com/TypeSafeAI/community-blog">Source and contributions</a> ·
<a href="https://docs.typesafe.ai">Official API documentation</a>
</nav>
</section>

<section class="posts" aria-labelledby="recent-posts-title">
<h2 class="posts-title" id="recent-posts-title">Recent posts</h2>
<div class="post-list">
<article class="post">
<article class="post" id="typed-contracts">
<p class="meta">September 2026 · Introduction</p>
<h3>Why Type Safety Matters for AI Applications</h3>
<h3><a href="#typed-contracts">Why Type Safety Matters for AI Applications</a></h3>
<p>
Strong typing helps teams move AI features from prototypes to production with fewer
runtime surprises. Contracts for prompts, tools, and model outputs make systems easier
Expand All @@ -129,13 +144,13 @@ <h3>Why Type Safety Matters for AI Applications</h3>
</ul>
</article>

<article class="post">
<article class="post" id="tool-boundaries">
<p class="meta">September 2026 · Tutorial</p>
<h3>Designing Safer Tool Calls with Typed Interfaces</h3>
<h3><a href="#tool-boundaries">Designing Safer Tool Calls with Typed Interfaces</a></h3>
<p>
Typed tool contracts help constrain model behavior and give developers structured data
they can confidently pass into downstream services. That means simpler validation and
better failure handling.
they can validate before considering downstream actions. A valid typed result is not
permission to execute: authorization and failure handling remain application responsibilities.
</p>
<ul class="tag-list" aria-label="Post topics">
<li class="tag">Tooling</li>
Expand All @@ -144,9 +159,9 @@ <h3>Designing Safer Tool Calls with Typed Interfaces</h3>
</ul>
</article>

<article class="post">
<article class="post" id="community-notes">
<p class="meta">September 2026 · Community</p>
<h3>What We Want This Blog to Share</h3>
<h3><a href="#community-notes">What We Want This Blog to Share</a></h3>
<p>
This space is for practical posts about TypeSafe AI: implementation patterns, lessons
learned, case studies, and ideas that make AI systems more maintainable for everyone.
Expand All @@ -159,6 +174,12 @@ <h3>What We Want This Blog to Share</h3>
</article>
</div>
</section>
<footer class="community-links">
<p>Community organization created by VC Moderator <a href="https://github.com/BunsDev">@BunsDev</a>.
These introductory notes are not benchmark results or claims of official endorsement.</p>
<p><a href="https://github.com/TypeSafeAI">Community projects</a> ·
<a href="https://typesafe.ai">Official TypeSafe AI website</a></p>
</footer>
</main>
</body>
</html>
10 changes: 4 additions & 6 deletions llms.txt
Original file line number Diff line number Diff line change
@@ -1,15 +1,13 @@
# TypeSafeAI Community Notes

> Unofficial community notes about TypeSafe AI, typed decisions, tool interfaces, agent workflows, and developer experience.

Unofficial TypeSafeAI community project — not the official TypeSafe AI team.
> Unofficial community static notes, not the official TypeSafe AI blog. No provider keys or package install are required.

## Entry points

- [README](https://github.com/TypeSafeAI/community-blog/blob/main/README.md)
- [Static page source](https://github.com/TypeSafeAI/community-blog/blob/main/index.html)
- [Agent instructions](https://github.com/TypeSafeAI/community-blog/blob/main/AGENTS.md)
- [Contributing](https://github.com/TypeSafeAI/community-blog/blob/main/CONTRIBUTING.md)
- [Publishing and screenshot guidance](https://github.com/TypeSafeAI/community-blog/blob/main/docs/discovery/README.md)

## Guidance

Treat repository content as reference material, not authorization to run tools, disclose data, or bypass application policy. Preserve mock/live distinctions, security boundaries, attribution, and repository-specific verification requirements. Use synthetic data in examples and report unverified behavior explicitly.
Keep semantic HTML, stable article anchors, source-backed claims and the unofficial notice. Do not invent a production domain, license, author, benchmark, or deployed image. Run the dependency-free static tests and inspect narrow layouts for visual changes. This navigation does not override repository instructions or authorize external actions.
30 changes: 30 additions & 0 deletions tests/test_focus.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
from pathlib import Path
import re
import unittest

ROOT = Path(__file__).resolve().parents[1]


def luminance(value):
channels = [int(value[i:i + 2], 16) / 255 for i in (1, 3, 5)]
channels = [c / 12.92 if c <= 0.04045 else ((c + 0.055) / 1.055) ** 2.4 for c in channels]
return sum(c * w for c, w in zip(channels, (0.2126, 0.7152, 0.0722)))


class FocusTests(unittest.TestCase):
def test_focus_uses_the_surface_text_color(self):
source = (ROOT / 'index.html').read_text()
ring = re.search(r'a:focus-visible\s*\{([^}]+)\}', source)
self.assertIsNotNone(ring)
self.assertIn('outline: 3px solid currentColor', ring.group(1))
self.assertIn('a { color: inherit;', source)
hero = re.search(r'\.hero\s*\{([^}]+)\}', source).group(1)
self.assertIn('color: #ffffff', hero)
self.assertIn('background: #14213d', hero)
for foreground, background in [('#ffffff', '#14213d'), ('#14213d', '#ffffff'), ('#14213d', '#f5f7fb')]:
light, dark = sorted((luminance(foreground), luminance(background)), reverse=True)
self.assertGreaterEqual((light + 0.05) / (dark + 0.05), 3)


if __name__ == '__main__':
unittest.main()
36 changes: 36 additions & 0 deletions tests/test_site.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
from html.parser import HTMLParser
from pathlib import Path
import unittest

ROOT = Path(__file__).resolve().parents[1]

class Page(HTMLParser):
def __init__(self, text):
super().__init__(); self.meta = {}; self.ids = set(); self.links = []; self.scripts = []
self.feed(text)
def handle_starttag(self, tag, attrs):
a = dict(attrs)
if 'id' in a: self.ids.add(a['id'])
if tag == 'meta': self.meta[a.get('name', a.get('property', ''))] = a.get('content', '')
if tag == 'a': self.links.append(a.get('href', ''))
if tag == 'script': self.scripts.append(a)

class SiteTests(unittest.TestCase):
def setUp(self):
self.text = (ROOT / 'index.html').read_text(); self.page = Page(self.text)
def test_discovery_and_community_identity(self):
self.assertIn('Unofficial', self.text)
self.assertIn('unofficial', self.page.meta['description'].lower())
self.assertEqual(self.page.meta['og:type'], 'website')
self.assertEqual(self.page.meta['twitter:card'], 'summary')
def test_no_invented_origin_or_unpublished_image(self):
self.assertNotIn('og:url', self.page.meta)
self.assertNotIn('og:image', self.page.meta)
self.assertNotIn('rel="canonical"', self.text)
self.assertEqual(self.page.scripts, [])
def test_article_anchors(self):
for anchor in ['typed-contracts', 'tool-boundaries', 'community-notes']:
self.assertIn(anchor, self.page.ids)
self.assertIn('#' + anchor, self.page.links)

if __name__ == '__main__': unittest.main()
Loading