Mehmet Enes
Change language
Contact

One Rule: Never Hardcode a Number You Could Count

This site is held together by a single constraint. If a figure can be derived from content that already exists, it is never typed into a template. The home page does not report a project count because I wrote a number into a heading. It reports whatever the projects collection contains, counted from that collection at build time.

The rule sounds trivial. It is the reason every other decision here looks the way it does.

A portfolio is a set of claims about a person, and claims drift. You add an entry and forget the summary line above it. You mark something archived and the total keeps including it. Nothing crashes. The build is green. The page is simply wrong, in the quietest possible way — wrong because it used to be right and nobody re-read it. That failure does not announce itself, and it compounds. After two years of small edits you no longer trust any number on the page, so you stop maintaining them, so they get worse.

Deriving the figure removes the whole class of error. There is no second place to update, so there is no second place to forget. The number cannot disagree with reality, because it has no existence independent of the content.

Typed Content Collections as the Only Source of Truth

The site is built with Astro 7 and TypeScript. Everything that is a fact about me lives in a typed content collection: projects, awards, certifications, patents, blog, milestones. Each collection has a schema. Each entry is a Markdown file with YAML frontmatter that the schema validates before anything renders.

This is the part that pays off over years rather than weeks. A schema is an agreement with your future self about what an entry must contain. When I add a field — a status, a category, a competition name — the schema forces every existing entry to account for it, and the build fails loudly at the moment of change rather than silently at the moment of viewing. Validation errors during a build are cheap. Wrong pages in production are not.

Typing also makes aggregation safe. Because the shape of every entry is known, a page can ask real questions of the content: how many projects sit in a given category, which awards are international, where the earliest and latest dates in the timeline fall. Those are ordinary TypeScript queries over a typed array, checked by the compiler. Nothing about them is fragile, so nothing about them needs supervision.

Controlled vocabularies do the same job one level down. Categories, award types and project statuses come from fixed lists rather than free text. That is not bureaucracy for its own sake — it is what makes filtering, grouping and cross-referencing work without a database. A typo in a free-text category creates a silent orphan. A typo in a controlled vocabulary fails the build.

Two Locales, One Set of Slugs

The site is bilingual, and the rule there is the same rule in a different costume: structure once, content twice.

Each collection has one directory per locale, and the same entry keeps the same slug in both. The English file and the Turkish file are the same thing said in two languages. Nothing maps English identifiers onto Turkish ones, because an identifier is not language. Cross-references between entries — a project pointing at an award, a post pointing at another post — are slugs, so they resolve identically in either locale.

When a translation does not exist yet, the site falls back to English rather than rendering a gap or a dead link. This matters more than it sounds. Without a fallback, bilingual sites decay asymmetrically: one language stays current, the other quietly rots, and you find out from a reader. With a fallback, a missing translation shows up as an English page in a Turkish context — obvious, slightly embarrassing, and therefore fixed.

A Design System With No Framework

The visual layer is hand-written CSS custom properties. Spacing, type scale, radii and colour all live in one place as tokens, and components consume tokens rather than raw values.

Light and dark are handled by the CSS light-dark() function. Both values sit next to each other in the token definition, which means there is no parallel dark theme to keep in sync and no class toggle threaded through the markup. A theme becomes one declaration instead of a second stylesheet. When I change a colour I change it once, and both modes stay correct by construction.

There is no UI framework, so almost no JavaScript ships. That is a maintenance decision as much as a performance one. A framework is a dependency with opinions and a release cadence, and a portfolio is a document that should still build in five years without a migration weekend. Plain HTML, CSS and Markdown do not have a version I need to keep up with.

What the Constraint Actually Buys

The point of all this is not elegance. It is that the site stays true without effort.

Adding an award means writing one Markdown file. The listing picks it up, the counts move, the timeline places it, the related entries find it. I do not touch a template. I do not update a total. I do not audit the home page afterwards to check whether a number I typed two years ago is still accurate, because I never typed one.

A portfolio that requires vigilance will not get it. The only version that survives ten years of edits is the one where being correct is the path of least resistance — where the honest thing and the lazy thing are the same thing. “Never hardcode a number you could count” is the shortest way I know to describe that arrangement.

  • Research5 min read

    From Idea to Patent: What the Process Actually Involves

    A plain account of how a Turkish patent application actually works: prior art, claims, examination at Türk Patent ve Marka Kurumu, and the 20-year term.

  • Engineering5 min read

    Notes on Reaching a TEKNOFEST Final

    What a TEKNOFEST final actually demands: written reports that gate the on-site stage, a fixed schedule, and integration time nobody budgets for.

Let's build something

Open to research collaborations, engineering teams and competition partnerships.