Skip to content

Commit 0b74780

Browse files
committed
Build customizable GitHub profile studio
1 parent b66f559 commit 0b74780

29 files changed

Lines changed: 8438 additions & 112 deletions

.github/workflows/ci.yml

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
name: CI
2+
3+
on:
4+
push:
5+
pull_request:
6+
7+
permissions:
8+
contents: read
9+
10+
jobs:
11+
verify:
12+
runs-on: ubuntu-latest
13+
steps:
14+
- name: Check out repository
15+
uses: actions/checkout@v4
16+
- name: Set up Node.js
17+
uses: actions/setup-node@v4
18+
with:
19+
node-version: 22
20+
cache: npm
21+
- name: Install dependencies
22+
run: npm ci
23+
- name: Type-check
24+
run: npm run typecheck
25+
- name: Test
26+
run: npm test
27+
- name: Build
28+
run: npm run build

.gitignore

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
node_modules/
2+
dist/
3+
coverage/
4+
*.tsbuildinfo
5+
.env
6+
.env.*
7+
!.env.example

.openai/hosting.json

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"project_id": "appgprj_6a9c1a5f4c388191a5df1f96fee36ec5",
3+
"static": {
4+
"directory": "dist"
5+
}
6+
}

README.md

Lines changed: 68 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -1,61 +1,82 @@
1-
<!-- TFQ0 / Quality Control. Upload this README and the assets directory together. -->
2-
<picture>
3-
<source media="(max-width: 600px) and (prefers-reduced-motion: reduce) and (prefers-color-scheme: dark)" srcset="./assets/tfq-control-center-mobile-dark-static.svg">
4-
<source media="(max-width: 600px) and (prefers-reduced-motion: reduce) and (prefers-color-scheme: light)" srcset="./assets/tfq-control-center-mobile-light-static.svg">
5-
<source media="(prefers-reduced-motion: reduce) and (prefers-color-scheme: dark)" srcset="./assets/tfq-control-center-dark-static.svg">
6-
<source media="(prefers-reduced-motion: reduce) and (prefers-color-scheme: light)" srcset="./assets/tfq-control-center-light-static.svg">
7-
<source media="(max-width: 600px) and (prefers-color-scheme: dark)" srcset="./assets/tfq-control-center-mobile-dark.svg">
8-
<source media="(max-width: 600px) and (prefers-color-scheme: light)" srcset="./assets/tfq-control-center-mobile-light.svg">
9-
<source media="(prefers-color-scheme: dark)" srcset="./assets/tfq-control-center-dark.svg">
10-
<source media="(prefers-color-scheme: light)" srcset="./assets/tfq-control-center-light.svg">
11-
<img alt="Talal Alqahs — Software Test Engineer and Independent Developer. Build it. Break it. Make it better. Animated QA terminal demonstration; not live test results." src="./assets/tfq-control-center-dark.svg" width="100%">
12-
</picture>
13-
14-
<p align="center">
15-
<a href="#selected-work">Selected work</a> &nbsp; / &nbsp;
16-
<a href="#toolbox">Toolbox</a> &nbsp; / &nbsp;
17-
<a href="#open-source">Open source</a>
18-
</p>
19-
20-
## Beyond the green checkmark.
21-
22-
I'm **Talal**, a Software Test Engineer and independent developer. I work across UI automation, API testing, and backend development—connecting how software is built with how it behaves in the real world.
23-
24-
I like reproducible bugs, useful automation, readable code, and tools that stay open.
1+
# Animated GitHub Profile Studio
252

26-
```text
27-
inspect → reproduce → automate → improve
3+
A browser-based editor for creating a personal GitHub profile README from one reusable configuration. Customize the text, animated terminal, featured repositories, skills, links, section order, colors, and motion settings, then export a ready-to-upload ZIP.
4+
5+
The built-in TFQ0 design remains the canonical example, but users no longer need to edit eight SVG files by hand.
6+
7+
## What it includes
8+
9+
- Live desktop and mobile preview in dark and light themes.
10+
- Animated and reduced-motion/static SVG variants.
11+
- Profile, hero, project, skill, link, palette, section, Markdown, and footer editing.
12+
- Optional public GitHub repository import with no login or token.
13+
- Local autosave of the last valid configuration.
14+
- Versioned `profile.config.json` import/export.
15+
- Deterministic ZIP generation containing `README.md`, setup guidance, the saved config, and all eight SVG assets.
16+
- Strict runtime validation, HTTPS-only generated links, contextual XML/Markdown escaping, and self-contained SVG output.
17+
- WebMCP tools for agents to read or stage the same configuration used by the visible editor.
18+
19+
## Use the studio
20+
21+
1. Open the app and choose **Start blank** or customize the TFQ0 example.
22+
2. Work through Profile, Hero, Projects, Skills, Links, Style, and Sections.
23+
3. Check the desktop/mobile, dark/light, and animated/static previews.
24+
4. Resolve validation errors and review any design warnings in Export.
25+
5. Download the complete ZIP.
26+
6. Upload its `README.md` and `assets/` directory to the public GitHub repository whose name exactly matches your username.
27+
28+
Keep the exported `profile.config.json`; importing it later restores an editable profile instead of requiring manual SVG changes.
29+
30+
## Local development
31+
32+
Requirements: Node.js `^22.13.0` or `>=24.0.0` and npm.
33+
34+
```bash
35+
npm ci
36+
npm run dev
2837
```
2938

30-
## Selected work
39+
The local app is served at `http://localhost:4173/`.
3140

32-
| Project | What it does | Focus |
33-
| :--- | :--- | :--- |
34-
| **[tfq0seo](https://github.com/TFQ0/tfq0seo)** | A command-line SEO analyzer with site crawling and report generation. | Python · CLI tooling |
35-
| **[tfq0tool](https://github.com/TFQ0/tfq0tool)** | Extracts text from documents, data files, and source code. | Python · Automation |
36-
| **[ksaa-api-tool](https://github.com/TFQ0/ksaa-api-tool)** | A browser-based interface for exploring Falak API endpoints. | API testing · Developer tooling |
41+
```bash
42+
npm run typecheck
43+
npm test
44+
npm run build
45+
```
3746

38-
<!-- Add other projects when their public repositories are ready to share. -->
47+
The production site is written to `dist/`. Vite uses relative asset URLs, so the build works at a root domain or a GitHub Pages project subpath.
3948

40-
## Toolbox
49+
## Architecture
4150

42-
**Testing**
43-
`Playwright` `Cypress` `Bruno` `Postman` `JMeter`
51+
```text
52+
src/
53+
├── domain/profile.ts # strict v1 config, template metadata, presets
54+
├── generator/
55+
│ ├── svg.ts # pure eight-variant SVG renderer
56+
│ ├── readme.ts # GitHub README renderer
57+
│ ├── escape.ts # XML/Markdown/URL safety boundaries
58+
│ └── artifacts.ts # deterministic file and ZIP assembly
59+
├── services/github.ts # optional public repository import
60+
├── components/ # editor fields and GitHub-like preview
61+
├── webmcp.ts # agent-facing read/stage actions
62+
└── App.tsx # editor state and workflows
63+
```
4464

45-
**Development**
46-
`Python` `TypeScript` `JavaScript` `FastAPI` `PostgreSQL`
65+
`ProfileConfig` is the single source of truth. The visible preview, README source, SVG files, saved config, and ZIP are all produced from the same validated object. Imported GitHub data becomes an editable snapshot; it is never a hidden dependency of later exports.
4766

48-
**Environment & delivery**
49-
`Git` `GitHub Actions` `Docker` `Linux`
67+
## Privacy and output safety
5068

51-
## Open source
69+
- The editor has no backend and requests no GitHub token.
70+
- Drafts and the short-lived public repository cache stay in browser storage.
71+
- Only public repository metadata is fetched directly from GitHub's public API.
72+
- Generated SVGs contain no scripts, event handlers, remote fonts, external images, tracking, or live CI claims.
73+
- Static fallbacks are generated for visitors who prefer reduced motion.
74+
- Custom Markdown blocks raw HTML and neutralizes non-HTTPS link destinations in generated output.
5275

53-
I enjoy understanding a project before changing it: reproduce the problem, trace the cause, make a focused change, and verify the result.
76+
## Legacy reference
5477

55-
[Pull requests](https://github.com/pulls?q=is%3Apr+author%3ATFQ0) &nbsp; / &nbsp; [Issues](https://github.com/issues?q=is%3Aissue+author%3ATFQ0) &nbsp; / &nbsp; [Repositories](https://github.com/TFQ0?tab=repositories)
78+
The original hand-authored TFQ0 SVGs, screenshots, GIF, and `preview.html` remain in `assets/` and `preview/` as visual references. They are not used by the Studio build. New custom profiles should be generated through the editor so all responsive, theme, and reduced-motion variants stay synchronized.
5679

57-
---
80+
## License
5881

59-
<p align="center">
60-
<sub><b>No monopoly. Yes to open source.</b><br>Build it. Break it. Test it. Improve it.</sub>
61-
</p>
82+
No license has been selected yet. Choose and add an appropriate license before inviting third parties to copy, modify, or redistribute the source.

SETUP.md

Lines changed: 25 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -1,81 +1,41 @@
1-
# TFQ0 // Quality Control
1+
# Project setup and release checks
22

3-
An animated GitHub profile for Talal Alqahs. The header is an original, self-contained SVG animation. The README contains a short introduction, public projects, a toolbox, and links to pull requests and issues.
3+
## Install and run
44

5-
## Preview first
5+
Use Node.js `^22.13.0` or `>=24.0.0`.
66

7-
Open `preview.html` in a browser after extracting this package. It is self-contained and works without an installation or internet connection. Use the Dark / Light, Desktop / Mobile, Pause, and Replay controls to inspect the design. Those controls are for this local preview only; they are not part of the GitHub profile.
8-
9-
`preview/animated-header.gif` shows one 16-second cycle. The GIF is for previewing, not the default README asset. The SVGs are sharper and smaller. The full-profile PNGs are local mockups, not screenshots of a deployed GitHub page; GitHub controls the surrounding Markdown styling.
10-
11-
## Publish to your existing profile repository
12-
13-
Your public `TFQ0/TFQ0` profile repository already exists. Use that repository rather than creating a different one.
14-
15-
1. Save a copy of your current README locally before replacing it.
16-
2. In `TFQ0/TFQ0`, choose **Add file → Upload files**. Upload the supplied `README.md` and the entire `assets` folder at the repository root. Do not upload the ZIP itself or nest the files inside a `tfq0-profile` folder.
17-
3. Review and commit the change to your default branch (`main` when checked). For an extra review step, commit to a new branch, review its README, and merge it through a pull request.
18-
4. Visit your profile and refresh. Confirm the header loads and the project links are correct.
19-
20-
The required repository layout is:
21-
22-
```text
23-
TFQ0/
24-
├── README.md
25-
└── assets/
26-
├── tfq-control-center-dark.svg
27-
├── tfq-control-center-light.svg
28-
├── tfq-control-center-mobile-dark.svg
29-
├── tfq-control-center-mobile-light.svg
30-
├── tfq-control-center-dark-static.svg
31-
├── tfq-control-center-light-static.svg
32-
├── tfq-control-center-mobile-dark-static.svg
33-
└── tfq-control-center-mobile-light-static.svg
7+
```bash
8+
npm ci
9+
npm run dev
3410
```
3511

36-
Only `README.md` and `assets/` are needed on GitHub. `SETUP.md`, `preview.html`, and `preview/` are optional reference files. Existing unrelated files in your repository do not need to be removed.
37-
38-
GitHub requires a public repository whose name matches your username, with a nonempty root `README.md`, to display it as a profile README. GitHub also supports the `<picture>` element and relative image paths used by this package. See the official references below.
39-
40-
## How the animation behaves
12+
Open `http://localhost:4173/`. Vite also prints network URLs when the development server starts.
4113

42-
The 16-second sequence types an illustrative command, advances through four demo checks, holds the completed state, and repeats. A small signal moves along the build / test / learn / repeat line. These are decorative demonstrations, not actual CI results, availability indicators, or live metrics. Nothing executes on your machine.
14+
## Verify a change
4315

44-
The README selects a compact, stacked header at viewport widths up to 600px. It includes dark and light variants selected through `prefers-color-scheme`. Theme selection depends on the rendering environment's media preferences; it is not a script that reads your GitHub theme setting.
45-
46-
Visitors requesting reduced motion are served dedicated static SVGs by the parent `<picture>` element. The animated SVGs also include their own motion preference handling. Keep the static sources first in the README. This avoids relying solely on propagation of media preferences into an embedded SVG.
47-
48-
The header uses no JavaScript, external fonts, embedded font files, remote badges, tracking pixels, GitHub Actions, access tokens, or third-party rendering services. The browser preview has local JavaScript only for its preview controls.
49-
50-
## Customize
51-
52-
Edit the wording, tools, and project links directly in `README.md`. The SVGs are editable text files: change `TALAL ALQAHS`, the role text, or the palette values in their `<style>` blocks. Apply matching content changes to the animated and static variants.
53-
54-
To change the loop duration, replace every `16s` in each animated SVG with the same new duration, such as `20s`. Do not change just one timeline or the typing and check states will become unsynchronized. The one-second cursor blink and four-second status pulse are independent accents.
16+
```bash
17+
npm run typecheck
18+
npm test
19+
npm run build
20+
```
5521

56-
The preview HTML embeds copies of the original SVGs. Editing an asset does not automatically update this preview; inspect the edited SVG in a browser or the README in your repository after making changes.
22+
These checks cover TypeScript, strict config parsing, all eight SVG variants, reduced-motion output, README-to-asset references, deterministic ZIP contents, unsafe input handling, public GitHub import errors, cache validation, and the WebMCP contract.
5723

58-
To use only the dark desktop header, replace the README's complete `<picture>...</picture>` block with this smaller version, retaining its reduced-motion fallback:
24+
For a release, also inspect representative long content in desktop/mobile and dark/light previews. Design warnings are advisory because fixed SVG artwork cannot measure browser font metrics during generation.
5925

60-
```html
61-
<picture>
62-
<source media="(prefers-reduced-motion: reduce)" srcset="./assets/tfq-control-center-dark-static.svg">
63-
<img src="./assets/tfq-control-center-dark.svg" width="100%" alt="Talal Alqahs — Software Test Engineer and Independent Developer. Animated QA demo, not live test results.">
64-
</picture>
65-
```
26+
## Production output
6627

67-
## Validation and limitations
28+
`npm run build` creates the static site in `dist/`. The build uses relative asset paths and can be hosted at a domain root or a project subpath.
6829

69-
The assets and local preview were checked in Chromium. Validation covered SVG XML parsing; animation in an actual `<img>` element; all eight light/dark, mobile/desktop, motion/reduced-motion image selections; stable static fallbacks; preview controls; absence of external resource requests; and a 390px-wide preview. See `preview/validation.txt` for the check record.
30+
The `.openai/hosting.json` file connects this repository to its Sites project. Publishing the Studio site and publishing a generated GitHub profile are separate operations.
7031

71-
The package has not been uploaded to your GitHub repository. Live GitHub rendering and other browser engines have not been tested. The preview is an approximation of the Markdown presentation; the SVG artwork itself is the supplied asset. A browser, accessibility preference, or renderer may display a static version instead of motion.
32+
## Publish a generated GitHub profile
7233

73-
## Public content and references
34+
The editor's ZIP contains its own profile-specific `SETUP.md`. In summary:
7435

75-
Project descriptions were checked against the public repository READMEs on 5 September 2026. No private project repository, personal email address, or unverified contact link is included.
36+
1. Create or open the public repository `<username>/<username>`.
37+
2. Upload the generated `README.md` and complete `assets/` directory at its root.
38+
3. Keep `profile.config.json` privately or in the repository if you want the profile to remain easy to edit.
39+
4. Commit, visit the GitHub profile, and verify links, text wrapping, theme selection, and reduced motion.
7640

77-
- [Your existing profile repository](https://github.com/TFQ0/TFQ0)
78-
- [tfq0seo](https://github.com/TFQ0/tfq0seo), [tfq0tool](https://github.com/TFQ0/tfq0tool), and [ksaa-api-tool](https://github.com/TFQ0/ksaa-api-tool)
79-
- [GitHub: Managing your profile README](https://docs.github.com/en/account-and-profile/how-tos/profile-customization/managing-your-profile-readme)
80-
- [GitHub: Basic writing and formatting syntax](https://docs.github.com/en/get-started/writing-on-github/getting-started-with-writing-and-formatting-on-github/basic-writing-and-formatting-syntax)
81-
- [MDN: SVG as an image and embedded-image restrictions](https://developer.mozilla.org/en-US/docs/Web/SVG/Guides/SVG_as_an_image)
41+
The animated terminal is decorative. It does not execute code or report live checks.

index.html

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<!doctype html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="UTF-8" />
5+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
6+
<meta
7+
name="description"
8+
content="Build and export a customizable animated GitHub profile README without sharing credentials."
9+
/>
10+
<meta name="theme-color" content="#091114" />
11+
<title>Animated GitHub Profile Studio</title>
12+
</head>
13+
<body>
14+
<div id="root"></div>
15+
<script type="module" src="/src/main.tsx"></script>
16+
</body>
17+
</html>

0 commit comments

Comments
 (0)