Skip to content
Muslu Yüksektepe

gokhancoskun.com

The Python source code of gokhancoskun.com, including migrations, deploy scripts and an MCP server.

gokhancoskun.com is the personal website and blog I built for Gökhan Coşkun. It consists of server-rendered public pages, an admin panel running on a separate subdomain, and an MCP server that lets posts be written through Claude as well. A single FastAPI application serves all three.

Purpose

In his daily work Gökhan uses CNC machines and CAM software, Alphacam in particular. The project stands on two equal legs. The first is a fast, secure and easy-to-maintain site where he can present himself and his work. The second is turning the steps that keep repeating in his job into Alphacam macros and add-ins, and then sharing them as blog posts.

Our working loop goes like this: we turn a repetitive task into a macro together, Gökhan tests it on his own machine, and once he confirms it works, the macro becomes a blog post with a proper explanation and animated SVG drawings that show the motion. I use animation instead of screenshots because a still image cannot show how a toolpath progresses.

How it works

The public site serves the home page, the blog list, post pages, tag pages, static pages and a contact form, all rendered on the server with Jinja2 templates. The admin panel is part of the same application but is routed to its own subdomain at the Nginx level. Panel and login paths on the main domain redirect permanently to the panel, and the API path does not answer on the main domain at all.

Posts are written in Markdown, converted to HTML and then cleaned with the bleach library, which removes disallowed tags and attributes so no harmful code can slip into a post. For that reason animated SVGs are not embedded inline. They are uploaded as separate files and added to the post as images, so the CSS animation inside the SVG runs while any script inside it cannot.

Key features

  • From the panel you can add and edit posts, move them to draft, publish them and delete them. Static pages, profile details and the password are managed there as well.
  • Messages from the contact form are listed in the panel, can be marked as read and can be answered from the panel.
  • The panel can create and revoke scoped access keys so external tools can use the API.
  • Actions are recorded in an audit log that can be viewed in the panel.
  • The MCP server exposes 15 tools to Claude for creating, updating, listing, publishing, drafting and deleting posts, managing tags and pages, and updating the profile. MCP is a protocol that lets an AI assistant call tools in external systems in a controlled way.
  • Posts created through Claude start as drafts and are only published after Gökhan reads and approves them.
  • The blog has full-text search, and a post can also be found by a fragment of a word in its title.
  • The site supports light and dark themes, and the home page features an animated SVG drawing that illustrates CNC machining.

Technical stack

The application is written in Python 3.12 on FastAPI and runs as a systemd service with Gunicorn and Uvicorn workers. The database is PostgreSQL, accessed through SQLAlchemy's async layer and asyncpg, and every SQL query lives in a single repository module. Posts use a GIN index for full-text search, the pg_trgm extension speeds up partial matches in titles, and the unaccent extension makes search independent of Turkish characters. I added partial indexes for published and featured posts.

Valkey is used as the cache. Validation and settings use Pydantic, the panel session uses a signed cookie, and API access uses scoped Bearer keys. Sensitive data is protected with Fernet encryption, and there is a script for rotating the key.

Security headers are owned by Nginx. The content security policy is almost completely closed; the only exception is a tiny inline script that applies the theme before the page renders, and it is whitelisted by its SHA-256 hash. The site is also served over HTTP/3. I took care of small details too, such as stopping the layout from shifting sideways when the scrollbar disappears on short pages. Animations respect users who ask for reduced motion.

Privacy and security

I deliberately did not use reCAPTCHA on the contact form. An external script would have forced me to loosen the content security policy, would send visitor data to a third party, and visual puzzles cause accessibility problems. Instead, three layers work together. Submissions that fill a hidden trap field are treated as bots. The moment the form is shown is written into a signed token, and a submission that arrives too fast or too late is rejected. Finally, the form endpoint is rate limited to 5 requests per 10 minutes.

Messages are first written to the database and then also forwarded by email. Sending runs in the background, so a mail failure never loses a message. The sender address always stays the site's own address while the reply-to is set to the visitor, which keeps SPF and DKIM aligned and keeps messages out of the spam folder.

Use cases

  • It is a ready, lightweight personal site foundation for a professional who wants to present their work and share technical posts.
  • It is a knowledge source where macro and automation work in the CNC and CAM field is documented with explanations and animations.
  • It is a working example of a content flow where an AI assistant drafts posts through MCP and a human approves them before publishing.
  • It is a practical reference for bot protection without captchas, a strict content security policy and accessibility.
Category
Websites
Year
2026

Technologies

  • Python
  • MCP
  • PostgreSQL

Links

  • GitHub https://github.com/muslu/gokhancoskuncom

Back to all projects