Communitygithub.com

Portfolio One Shot

Generate a verifiable, zero-fabrication portfolio from a folder of real work in one command.

What is Portfolio One Shot?

Portfolio One Shot is a developer tool that transforms a directory of real project files into a tangible, honest portfolio without any AI-invented content. It is designed to eliminate the common problem of AI agents fabricating project names, roles, metrics, or descriptions when asked to create a portfolio. The tool works by scanning a source folder, building a responsive offline HTML portfolio alongside an ATS-readable plain-text version, and then running a strict verifier that lists missing fields as visible gaps rather than silently filling them in. It supports two modes: `case_study` for narrative-heavy work (UX, design, engineering) and `gallery` for visual work (art, photography). The core invariants are zero fabrication, independent verification, and a single command workflow (`all`). It is intended for use in Claude Code, Cursor, Codex, and similar AI agent environments where a user hands over a folder of real work and wants a portfolio generated without any made-up content.

Works with~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/CatsMansion/portfolio-one-shot/tree/HEAD

Ask in your favorite AI

Open a new chat with this agent skill pre-loaded.

Documentation

What does Portfolio One Shot do?

Purpose

Turn a directory of real work into a portfolio that can be opened, read by machines, and independently checked — without the model writing a single line of fictional project copy.

The three invariants, in priority order:

  1. Zero fabrication. Every displayed fact must trace back to a file, a README excerpt, or a value the user supplied. Missing fields render as visible gaps. Never invent project names, roles, metrics, clients, quotes, results, or images.
  2. Independent verification. Run the verifier on the output before reporting success. List failures first, passes second. Never present a green criteria list as proof that the portfolio looks good — visual judgement belongs to the user, by eye.
  3. One command. all performs scan → config → build → verify. A second command is a defect, not a workflow.

When to use

  • The user says 一键生成作品集 / 做个作品集 / 把我的项目做成作品集 / build a portfolio from this folder.
  • The user hands over a directory of images, videos, or project folders and wants them presented.
  • The user wants to regenerate a portfolio after adding or removing work.
  • The user wants to check whether an existing portfolio has missing evidence.

Do not use when the user wants a decorative demo site with made-up content, a specific art-directed visual style, or a hosted platform integration. Those are different jobs. Do not silently switch to this skill's zero-fabrication rules in that case — say the difference out loud.

The one command

python scripts/portfolio.py all <SOURCE_DIR> --out <OUTPUT_DIR> --mode <case_study|gallery>

Example:

python scripts/portfolio.py all "C:/work/my-projects" --out "C:/work/portfolio-dist" --mode gallery

The command writes index.html, portfolio.txt, portfolio.md, projects.json, assets/, build-report.json, and verify-report.md into the output directory, then prints the verifier verdict. Open index.html for the user with the file-presentation tool. Put the visual deliverable first in the list.

To rebuild after the user edits projects.json, run build and verify only:

python scripts/portfolio.py build <OUTPUT_DIR>/projects.json --out <OUTPUT_DIR> --mode gallery
python scripts/portfolio.py verify <OUTPUT_DIR>

Workflow

Phase 0 · Decide the mode, do not guess silently

Two modes exist because the source research found the two domains demand opposite things (see references/content-spec.md §Domain split).

ModeForText densityLayout
case_studyUX, product, design, engineering, researchLong narrative; seven required field groupsOne project per section, images interleaved
galleryGame art, illustration, concept art, photography, animationMinimal words; let the work speakImage-forward grid, lightbox on click

If the user has not chosen, infer from the material and say the inference in one sentence before running — then let one word from the user override it. Never hard-code a default into someone's portfolio.

Phase 1 · Scan real material

scan enumerates subdirectories as projects. For each project it records:

  • Directory name as the project title candidate (a fact, not an invention).
  • Every image and video file with byte size, SHA-256 prefix, and pixel dimensions.
  • The first paragraph of README.md / project.md / about.md as a verbatim summary candidate, with a _sources entry naming the file and line range.
  • A missing list of fields no file could supply.

Files with unknown extensions stay in manifest.json as unclassified rather than being dropped. Never delete, rename, move, or resize source files. Write only into the output directory.

Phase 2 · Build

build reads projects.json (schema in references/config-schema.md) and renders:

  • index.html — light theme, responsive, system font stack, no CDN dependencies, no flashy template. Every <img> carries alt, width, height, loading="lazy". Images use relative paths under assets/.
  • portfolio.txt — plain-text project summary for ATS parsing and copy-paste into a resume.
  • portfolio.md — the same facts as Markdown for README or email.
  • A visible warning banner stating exactly how many fields are missing, so a skeleton can never be mistaken for a finished portfolio.

When --embed is set, inline only images under 10 KB as base64 and keep larger ones external; print a warning for every file that would have exceeded the threshold. Base64 grows payload by about 33 percent and cannot be lazy-loaded — see references/content-spec.md §Image policy.

Phase 3 · Verify before reporting

verify checks field completeness, image existence and decodability, meaningful alt text, absence of placeholder-image hosts, link shape, HTML structure, and plain-text parity. It writes verify-report.md with Failures first, Passes second, then Limitations / unverified.

Exit code 1 means red items exist. Report that honestly. Do not edit the criteria to make them pass, do not retry a failing generation channel, and do not hide a limitation.

For a positive/negative control, run python scripts/portfolio.py verify <dir> --self-test — it constructs one deliberately broken project and one complete project in memory and confirms the verifier flags the first and clears the second. If the negative control passes green, the verifier is broken; fix the verifier, not the fixture.

Phase 4 · Hand off

Present index.html first so the user can open it, then verify-report.md, then projects.json. In the text reply: give the verdict, the exact number of missing fields, and the single next action (fill projects.json). Do not claim the portfolio looks good. Do not claim it is ready to send while the warning banner is present.

Zero-fabrication contract

Hard rules, all derived from documented failure modes in references/content-spec.md:

  • Never write project prose, captions, roles, metrics, outcomes, credits, or client names that are absent from the input. A missing field renders as [MISSING: field] — conspicuous, never silently blank, never paraphrased into a plausible sentence.
  • Never use placeholder image hosts (picsum.photos, placehold.co, lorem, stock URLs) as stand-ins for real work. A project with no images renders an explicit empty-media block.
  • Never quote a metric without a _sources entry. If the user supplies a metric, record source: "user-supplied"; do not upgrade it to "verified".
  • Never invent a studio name, personal bio, or contact details. Leave them empty and list them as failures.
  • When a README is used, copy the paragraph verbatim and record its file and line range. Do not polish, shorten, or rewrite it.
  • Do not present AI-assisted wording as the user's own decision-making. Process and reflection fields stay empty until the user supplies them.

Multi-version output

The same projects.json supports targeted versions. Add a select list of project ids, or pass --only id1,id2 to build, to produce a version aimed at one audience. Reordering is a config change, never an automatic rewrite. This follows the documented split between a website for discovery and a PDF or deck for applications.

Gotchas

  • Do not judge from a fragment. Read the whole README, the whole projects.json, and the whole verifier report before concluding anything is complete or broken.
  • Criteria passing is not quality. A green verifier means the file structure is sound. Aesthetics require the user's eyes.
  • Do not fill gaps to make the page look finished. A visibly incomplete page is the correct output when the user has not supplied the facts.
  • Do not touch personal directories. Scan is read-only on the source. All writes go to the output directory.
  • Do not scope-creep into PDF generation, hosting, or GitHub API access. Those need an explicit decision from the user.
  • Image dimensions matter. Emitting width and height prevents layout shift. If Pillow is unavailable, fall back to header parsing and print a visible warning; never silently degrade.
  • One folder is one project. If the user's material is flat, ask for a grouping or use --flat to make one project containing all media. Do not invent groupings.

Resources

PathRole
scripts/portfolio.pySingle CLI: scan, build, verify, all, --self-test. Standard library plus optional Pillow.
references/content-spec.mdResearch-backed content rules, domain split, image policy, and source URLs. Load before changing field definitions or templates.
references/config-schema.mdFull projects.json schema, field meanings, and what counts as a source.
assets/template.htmlLight-theme responsive template with both modes. Replace {{TOKEN}} placeholders only; do not rewrite the CSS to chase a look.
assets/projects.sample.jsonA clearly labelled DEMO config. Never ship it as the user's real portfolio.

Related Skills