Commit Graph
539 Commits
Author SHA1 Message Date
tiennm99 94500a8e3d feat: initial theme scaffold
- Repo metadata: theme.toml, README, Apache-2.0 license
- Hugo defaults: vi language, post permalinks, taxonomies, paginate, TOC config
- exampleSite skeleton with themesDir wiring
- CI: Hugo build + Pagefind index + Pages deploy
- Pagefind devDependency in package.json (Dependabot weekly)
- vi i18n strings, default archetype
- Empty layouts/_partials/_markup/_shortcodes directories ready for Phase 3
2026-05-07 20:27:07 +07:00
tiennm99 5d36f5966c Initial commit 2026-05-07 20:25:16 +07:00
github-actions[bot] c083129bc9 chore(projects): refresh projects list 2026-10-04 02:34:26 +07:00
tiennm99 93798350bc docs(referral): add Hermes Agent Cloud referral 2026-10-03 09:30:40 +07:00
github-actions[bot] 8eb701f110 chore(projects): refresh projects list 2026-10-03 04:04:47 +07:00
tiennm99 c5efe95cac docs(referral): refresh current deals and offers 2026-10-02 10:45:26 +07:00
tiennm99 d464b5df8e docs(referral): remove ended OpenCode Go referral 2026-10-02 09:57:16 +07:00
tiennm99 b5a80e3ab6 docs(referral): remove BigModel.cn and Claude Code guest pass entries 2026-10-02 09:00:02 +07:00
github-actions[bot] afd1d56ca1 chore(projects): refresh projects list 2026-10-02 04:30:01 +07:00
github-actions[bot] 2550fbe79d chore(projects): refresh projects list 2026-10-01 04:04:46 +07:00
github-actions[bot] 58261a01cb chore(projects): refresh projects list 2026-09-30 17:07:37 +07:00
github-actions[bot] 1a68d064d5 chore(projects): refresh projects list 2026-09-30 16:58:10 +07:00
github-actions[bot] 470b0a143d chore(projects): refresh projects list 2026-09-30 16:37:51 +07:00
github-actions[bot] c1cb997311 chore(projects): refresh projects list 2026-09-30 16:22:09 +07:00
github-actions[bot] f03bb0f287 chore(projects): refresh projects list 2026-09-30 04:07:31 +07:00
github-actions[bot] b1174df458 chore(projects): refresh projects list 2026-09-29 05:18:57 +07:00
tiennm99 318098d384 docs(newsletter): restore original source titles on article headings 2026-09-28 09:33:15 +07:00
tiennm99 8574eee45e docs(newsletter): mark dead links, fix headings and tags 2026-09-28 09:25:58 +07:00
github-actions[bot] c84fccf0e3 chore(projects): refresh projects list 2026-09-28 02:54:30 +07:00
tiennm99 c0ddcb17b8 docs(newsletter): rewrite newsletters with Opus 5.5 2026-09-27 21:47:31 +07:00
tiennm99 574a830e03 feat(newsletter): protect code, verdicts and author notes in rewrites
protected-lines now keeps fenced code blocks (re-indent allowed) and
**Đánh giá:** verdict lines, and leaves summary sub-headings and short
italic key-point labels rewritable. The rewrite skill skips posts
without the AI-Assisted tag.
2026-09-27 21:47:31 +07:00
tiennm99 5804366438 feat(newsletter): add mt-rewrite-newsletter skill and protected-lines guard 2026-09-27 21:47:30 +07:00
github-actions[bot] 4710af385f chore(projects): refresh projects list 2026-09-27 02:29:20 +07:00
github-actions[bot] a53a9f5e07 chore(projects): refresh projects list 2026-09-26 03:10:28 +07:00
github-actions[bot] ba76a170fc chore(projects): refresh projects list 2026-09-25 03:12:20 +07:00
github-actions[bot] 5e6a84b9a4 chore(projects): refresh projects list 2026-09-24 02:54:13 +07:00
github-actions[bot] 21dcce6067 chore(projects): refresh projects list 2026-09-23 02:57:16 +07:00
github-actions[bot] e5f28ef941 chore(projects): refresh projects list 2026-09-22 03:41:18 +07:00
github-actions[bot] 76dd8c9622 chore(projects): refresh projects list 2026-09-21 02:09:31 +07:00
github-actions[bot] 20c4e27dc2 chore(projects): refresh projects list 2026-09-20 02:02:07 +07:00
github-actions[bot] 377b2dab6a chore(projects): refresh projects list 2026-09-19 02:16:08 +07:00
tiennm99 50ef688ce8 chore: drop Netlify
The site is built and deployed to Cloudflare Pages by hugo.yml and served by
Cloudflare; netlify.toml was referenced nowhere else and no Netlify build runs,
so the file only pinned toolchain versions for a deploy path that no longer
exists. No _redirects or _headers accompanied it.
2026-09-18 16:34:13 +07:00
tiennm99 20301d2d88 chore: check out LF line endings everywhere
The repository normalises to LF in the index either way; the working tree was
being converted to CRLF on checkout, which is wrong for a repo worked on from
Linux. It also silently breaks the newsletter parity suite, which compares
committed golden files byte for byte against engine stdout — the reason
scripts/newsletter needed an explicit LF override until now. That override and
the *.sh one are both redundant against an LF default.
2026-09-18 16:33:41 +07:00
tiennm99 7588c6566f docs(plans): record the post-push verification results
Actions deploy and the projects workflow both pass without Go. Netlify is
recorded as not applicable: the site deploys to Cloudflare Pages and netlify.toml
is referenced nowhere else, so no Netlify build exists to observe.
2026-09-18 16:28:07 +07:00
github-actions[bot] 486732d78c chore(projects): refresh projects list 2026-09-18 16:27:11 +07:00
tiennm99 19e297d25d docs(plans): record the JavaScript migration, parity, and review
Adds the migration plan and its phase files, the parity report, and the code
review.

Annotates the two records this work supersedes rather than rewriting them: the
2026-09-18 language-choice research, whose first recommendation was to keep the
engine in Go and was overridden the same day, and the 2026-08-18 plan that
produced that engine. Both bodies are left as written, since erasing them would
destroy the reasoning a future reader needs.

Six success criteria stay unticked with the reason inline: they need a push, a
GitHub token, or a Codex run to verify.
2026-09-18 16:24:56 +07:00
tiennm99 a95dfe3d05 ci: drop the Go toolchain from Actions and Netlify
Nothing in the repository needs Go any more. Kept as its own commit so a bisect
can attribute a Hugo build break to this change rather than to the engine
deletion.

Node setup and the conditional npm ci stay: the lockfile exists, so the
dependencies the engine now needs are installed if a workflow ever invokes it.
2026-09-18 16:24:49 +07:00
tiennm99 a56168b119 chore(newsletter): delete the Go engine
Parity is proven and every call site now invokes the JavaScript engine, so the
Go implementation has no callers. It remains recoverable from history.

The newsletter engine was Go's only consumer here: the Hugo theme is vendored
under themes/ and the site configuration declares no module block, so nothing
else needs a toolchain. Dropping go.mod also disposes of a latent defect, since
it declared a newer Go version than either build environment pinned and only
worked because the toolchain was fetched on demand.

The Go patterns in .gitignore go with it.
2026-09-18 16:24:42 +07:00
tiennm99 d0bf8bd347 refactor(skills): invoke the Node engine and centralise the command reference
Switches every call site to `node scripts/newsletter` and, in the same pass,
fixes three structural problems in the skill layer.

The seven subcommands were spelled out in five files; they are now enumerated
once in docs/newsletter/engine-commands.md, and every other mention is a link
except where a skill inlines the one or two commands it actually invokes. The
shared post mechanics move out of mt-add-url's directory into docs/newsletter/,
so no skill owns another skill's documentation and both runtimes reach it by a
repository-relative path. The Codex adapters become symlinks to their canonical
counterparts, which removes the parallel frontmatter that could drift.

Two skills are renamed for a uniform mt-<verb>-<object> scheme: mt-add-post
becomes mt-add-article, since it adds an article to a post, and mt-webfetch
becomes mt-fetch-url. The other four already conformed. Note that $mt-add-post
and mt-webfetch no longer resolve; no alias directories are left behind, because
two names for one skill is the duplication this change removes.

Trigger wording in the frontmatter descriptions is left alone apart from the
renamed tokens and the corrected fetch-tier summary: those strings are how the
runtimes decide whether to invoke a skill.

Setup documentation now states the npm ci prerequisite. The engine has
dependencies, so unlike its predecessor it does not run on a bare clone.
2026-09-18 16:24:34 +07:00
tiennm99 d07f48d69e test(newsletter): add a golden-output parity suite
Captures the Go engine's stdout for 26 deterministic cases, commits those
outputs as fixtures, and asserts the JavaScript engine reproduces them through
the real CLI surface, exit codes included. This is both the migration's proof of
correctness and the regression net the engine never had.

Every fixture was generated from the Go engine rather than written by hand, and
reviewed before commit so no existing bug became a permanent contract. Each
behaviour that a JavaScript-idiomatic rewrite would silently break has a case
that goes red when the naive implementation is reintroduced; verified by
mutating the engine and re-running.

Content-scanning commands are pointed at a fixture tree through the subprocess
working directory. Both engines already resolve content/post from the process
CWD, so neither needed a test-only configuration knob, and the suite is proven
isolated from the real content by renaming it away and re-running.

Cases that depend on live upstreams are opt-in behind NEWSLETTER_NET=1: a
publication's feed window moves, and a suite that goes red on someone else's
outage teaches people to ignore red. The deterministic tier reaches the network
only through .invalid hosts, which never resolve, so it runs offline in about
two seconds.

The golden files are compared byte for byte, so scripts/newsletter is pinned to
LF; the repository otherwise checks out CRLF, which would break every comparison
on a fresh clone.
2026-09-18 16:24:16 +07:00
tiennm99 fb292d444d feat(newsletter): port the engine to JavaScript
Translates the seven-subcommand engine to Node ESM, one module per former Go
file, invoked as `node scripts/newsletter <command>` from the repo root. The Go
implementation stays in place for now so parity can be measured against it.

Hand-rolled HTML and XML regexes give way to cheerio, which removes the manual
string surgery in caption extraction and covers RSS and sitemap XML through
xmlMode without a second parser. fetch-via-defuddle gains a local extraction
stage ahead of the defuddle.md proxy; the proxy stays, because fetching from a
third IP is the whole point when this machine's IP is the blocked one. Both
stages now emit the same YAML frontmatter plus body, and an extraction that
looks like a bot challenge counts as a local failure so the proxy still runs.

Behaviour is preserved where it is load-bearing rather than where it is merely
idiomatic: query strings are rebuilt by string surgery so surviving parameters
keep their original order and encoding, duplicate detection stays an index loop
with byte-offset boundary checks so a prefix of a stored URL is not a false
match, empty optional fields are omitted rather than emitted as "", a deep-crawl
miss reports cutoff as null rather than dropping the key, bullet filtering counts
code points, tag counts keep their six-column alignment, and a malformed percent
sequence falls back to the raw substring.

The printer lives in its own module so a command module never imports the
dispatcher: index.js runs main() at module scope, so that cycle would execute
the CLI as a side effect of any import. Missing dependencies report one
actionable line instead of a module-resolution stack trace, and a reader that
closes early exits quietly instead of raising EPIPE.
2026-09-18 16:23:58 +07:00
tiennm99 a396c1fb40 refactor(scripts): unify module extensions on .js
The root package.json already declares "type": "module", so a .js file here is
ESM and the .mjs suffix only restates what the manifest states. Renames the three
GitHub Actions scripts and follows every reference, including the six JSDoc
import("...") type annotations that would otherwise degrade to any without
throwing.
2026-09-18 16:23:36 +07:00
tiennm99 2d35361ddd feat(projects): drop in-development namespaces from the demo list 2026-09-18 13:21:41 +07:00
tiennm99 aa1834f1bc refactor(projects): rename the demo list identifiers to match the page 2026-09-18 13:18:37 +07:00
tiennm99 552ea60a65 docs(projects): reword section headings and intros 2026-09-18 13:13:13 +07:00
tiennm99 1350aea058 docs(projects): rewrite projects page intros in a lighter voice 2026-09-18 13:04:36 +07:00
github-actions[bot] 89707097bc chore(projects): refresh projects list 2026-09-18 12:58:43 +07:00
tiennm99 bbda4851a8 refactor(projects): build the projects list on the octokit SDK
Replace hand-rolled REST paging, GraphQL cursor loops and header plumbing with
octokit, which also brings request retry and rate-limit backoff. Introduces the
repo's first package.json, lockfile and ESLint flat config; the Hugo site build
itself still needs no Node step.

Output verified against the previous implementation: identical counts and rows
apart from live star drift on four upstream repos.
2026-09-18 12:28:11 +07:00
tiennm99 7e46fde418 docs(plans): record script language evaluation for repo scripts 2026-09-18 12:24:44 +07:00
tiennm99 4656fbed46 feat(projects): split projects page into starred, linked and contributed lists
Resolve owned namespaces from org memberships with the admin role instead of
assuming a fixed owner list, so repos under orgs I own are included.

- starred: owned public non-fork repos with at least one star, by stars then
  most recent push
- linked: owned public non-fork repos exposing a homepage or Pages URL, by most
  recent push
- contributed: public repos owned by others, by my merged PR count then most
  recent push

Private repos are excluded everywhere; forks are excluded from the owned lists
because their homepage belongs to upstream. Split the generator into API access
and rendering modules.
2026-09-18 12:24:44 +07:00