Library / SDK
suyalcinkaya/onur.dev avatar
suyalcinkaya/onur.dev

onur.dev: a personal site that documents its own five rewrites

✦ My personal website built using Next.js, Tailwind CSS, shadcn/ui, Contentful, Raindrop, Supabase and deployed on Vercel.

2,312 stars194 forksJavaScriptNOASSERTION

At a glance

What is it?
A Next.js personal website pulling writing from Contentful and bookmarks from Raindrop, with a dependency list that hints at what the site actually does. Its three-line licence is the most opinionated file in the repository.
Who is it for?
The interesting part of onur.dev is not the site, it is the record. A personal website that has been rewritten five times, with each generation named in the README, is a more honest artefact than most portfolio projects, because it shows what survived and what did not.
Can I use it commercially?
Check first. The repository uses a licence we do not classify automatically, so read its LICENSE file before any commercial use.
Is it still maintained?
Yes. The repository last received commits 12 days ago.
What is it written in?
Mainly JavaScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 28, 2026, and from our analysis. They are not legal advice.

Editorial analysis

A README that opens with the site's own history

The README for onur.dev does not describe features. It starts with a sentence about evolution: the personal website has changed over the years from a simple static HTML page, to Create React App, to Gatsby, then to Next.js with Chakra UI and MDX, and finally to Next.js with Tailwind CSS and Contentful.

That is four named rewrites after the original, and it is the most useful paragraph in the file. Each generation represents a different answer to the question a personal site has to answer, which is where content comes from. Static HTML had no content layer at all. Gatsby was built around pulling content at build time. Next.js with Chakra and MDX moved to a hybrid model where some content is authored in the repository and some is not. The current version separates the two cleanly: writing lives in Contentful, static pages live in Contentful, and bookmarks come from Raindrop.

The site is described as an app-like-web platform for the author's writings, journey and bookmarks. That framing is slightly grander than a blog, and the routing table supports it, since there is no single post index. The journey and workspace pages are separate, and the bookmarks section has both an index and per-item pages.

It is worth remembering what this repository is when judging it: one person's website, built by one person, published because the code was interesting enough to share. The 2,312 stars are people who recognise that a well-built personal site is a useful reference, not people who depend on it as infrastructure.

The route table explains the content model

The README lists the routes, and the list is short enough to hold in your head while reading the source.

/ is the home page. /[slug] is a set of static pre-rendered pages sourced from Contentful, with the README giving /stack as the example. /writing is the writing index, and /writing/[slug] holds the individual writing pages, also static and also from Contentful. /journey and /workspace are their own pages. /bookmarks is the index, /bookmarks/[slug] holds individual bookmark pages sourced from Raindrop, /bookmarks.xml is an XML feed of the bookmarks, and /api is the API routes area.

Three things are worth drawing out of that. First, the whole content layer is external, with Contentful for anything authored as prose and Raindrop for anything saved from elsewhere. Nothing in the repository holds content, which is what makes the site editable from a browser rather than a text editor. Second, everything user-facing is statically pre-rendered, which is the right call for content that changes on a schedule rather than per request. Third, there is an XML feed, which means the bookmarks are readable by any feed reader rather than only through the site.

The API routes are the one part the README does not explain, and they are where the interesting infrastructure sits. The presence of an on-demand revalidation secret in the environment file implies the routes trigger cache invalidation, which is how a Contentful edit reaches a statically rendered page without a full rebuild.

Contentful, Raindrop, Supabase and three data stores you did not expect

The .env.example is more revealing than the tech stack list, because it names variables rather than services.

Contentful takes a space id, an access token, a preview access token and a preview secret. Having a separate preview token and preview secret is the standard pattern for a drafts-enabled Contentful setup, where editors see unpublished entries on a preview domain and the public site never does.

Supabase takes four variables, and the split matters: a SUPABASE_URL and SUPABASE_SERVICE_ROLE_KEY, plus a NEXT_PUBLIC_SUPABASE_URL and NEXT_PUBLIC_SUPABASE_ANON_KEY. The service role key bypasses row level security and must never reach the browser, while the anon key is public and protected by your policies. The naming convention here is right, and the presence of the server-only package in the dependency list suggests the code is careful about which one it imports where.

Raindrop takes a single NEXT_PUBLIC_RAINDROP_ACCESS_TOKEN, and the README says bookmark pages are statically pre-rendered from it. A public-prefixed variable holding an access token is worth a second look, since anything in a NEXT_PUBLIC_ name is bundled into the client. Raindrop's own API design has public tokens for bookmark feeds, which makes this consistent with how that service is meant to be used, but it is still the variable to check first if you fork this.

Then there are three services the tech stack list does not mention. Tinybird has a NEXT_PUBLIC_TINYBIRD_TOKEN, which is analytics. Airtable has a personal access token, a base id and a BOOKMARKS_TABLE_ID specifically, which suggests bookmarks passed through Airtable at some point in the site's history. And NEXT_REVALIDATE_SECRET is the on-demand revalidation hook.

Three bookmark-related sources in one environment file, with Raindrop current and Airtable carrying a bookmarks table id, is the residue of the site's rewrites. That is normal for a long-lived project and worth knowing before you assume each variable is load-bearing.

The dependency list is a description of the site

For a personal website, the package manifest reads better than a feature list, because every dependency corresponds to something visible on screen.

The framework layer is current: next at 16.2.1, react and react-dom at 19.2.0, and Tailwind at the 4.1 generation with the PostCSS plugin. The engines field pins Node to 20.x, which is worth flagging because the README tells you to install with bun. Bun ignores the engines field, so this is not a conflict in practice, but a contributor using Node will be held to 20.

The component layer is shadcn/ui, which means Radix primitives plus Tailwind: react-dialog, react-label, react-select and react-slot, with class-variance-authority, tailwind-merge and classix for styling. The components.json file in the tree is what makes that visible, since it is the shadcn configuration file. If you have used shadcn in your own project you know the shape, and it is a sensible default for a personal site because the components end up in the repository rather than in a dependency.

The interaction layer is more distinctive. framer-motion at 12.4.7 for animation, vaul for drawer components built on Radix dialog, and embla-carousel-react for carousels. react-intersection-observer suggests scroll-triggered reveals, and framer-motion with a carousel and a drawer is the shape of a site with a portfolio section and a mobile navigation that slides.

Content rendering is handled by @contentful/rich-text-react-renderer for Contentful entries, markdown-to-jsx for anything authored in Markdown, sugar-high for syntax highlighting rather than the usual Prism or Shiki, and react-tweet for embedding posts from X. Also present: sonner for toasts, zod with @hookform/resolvers and react-hook-form for forms, lru-cache and lodash.throttle for rate limiting on the client, @arcjet/ip for IP handling, server-only as a guard against importing server code into the browser, isbot for user-agent checks, and the Geist font package.

Two entries suggest the site handles visitors rather than only serving pages. lru-cache with lodash.throttle is the standard client-side combination for deduplicating expensive lookups, and @arcjet/ip points at identifying or geolocating visitors, probably for the analytics side rather than for accounts.

Running it locally, and the two package managers in the story

The README's local instructions are four commands:

bash
$ git clone https://github.com/suyalcinkaya/onur.dev.git
$ cd onur.dev
$ bun i
$ bun dev

Then you create a .env file based on .env.example, which is the step the README gets right by linking rather than pasting, since there are a dozen variables and none of them have defaults.

The shell prompt markers in the block are worth noting. Most READMEs write these commands without the leading dollar sign, which makes them harder to paste. This one includes it, and the build's code checker had to strip it before matching, which is a small sign that the project has automated checks on its own README examples.

The tree confirms bun rather than npm or pnpm. There is a bun.lockb, a binary lockfile, and no package-lock.json or yarn.lock. The package.json is consistent with that: the outdated script runs bun outdated rather than npm outdated, which means the author uses bun day to day rather than only for the initial install.

The rest of the scripts are plain Next.js plus a few quality tools. dev, build and start are the standard next commands. prettier covers html, js, jsx, json, md, mdx and mjs. lint runs eslint, with lint:fix to write changes. There is a clear-cache script that removes .next, an unused script running next-unused to find unused exports and dependencies, and an outdated script for dependency drift.

next-unused is the one worth calling out. It is the kind of check that keeps a personal site's dependency list from growing without bound, and it is the direct answer to the question of why this manifest is not larger. The eslint configuration is the flat-config style in an eslint.config.mjs file, with the compat and js packages present, and prettier.config.mjs and postcss.config.mjs sit alongside jsconfig.json and next.config.mjs.

The repository also has a renovate.json, so dependency updates are automated rather than manual. For a site like this that is the difference between a build that works and one that broke six months ago and nobody noticed.

A licence that is three sentences and a tool

The License section of this README is unusual enough to be the reason someone stars the repository.

GitHub's metadata records NOASSERTION for the license, meaning it could not be classified automatically. The file in the tree is named LICENSE.txt rather than LICENSE, and it does not begin with an SPDX identifier. Instead the README states three rules: feel free to take inspiration from the code, avoid copying it directly, and crediting the author is appreciated. Then comes the line that makes it memorable: no complicated licensing, be kind and help others learn.

That is a real licence in the ordinary sense of the word, but it is not a standard one, which creates genuine ambiguity. Whether a copyleft obligation applies, whether redistribution is permitted, and whether commercial use is allowed are all undefined. If you are considering reusing code from this repository, you have no clear rights and a vague request, which is the worst of both worlds. The safe assumption is that you may read it and learn from it and should write your own code.

The last part of the section is the practical bit. It recommends a tool called lice for reading licences in a readable form, and gives the two commands:

bash
$ npm install -g lice
$ lice -l onur_dev

That is a small piece of advocacy for a different way of doing things, and it reframes the section: rather than inventing a licence, the author is nudging people toward licences that are human-readable in the first place. If your objection to open source licensing is that SPDX identifiers are machine syntax for lawyers, lice is an argument with a working implementation.

For a personal website repository, this is a defensible position, and the README's framing is honest about it. It is not a licence you should rely on though, and if you fork this project for commercial use you should replace it with a real one.

Project state, and what makes this worth reading

The repository has 2,312 stars and 194 forks, with 11 open issues. The last push was 2026-09-25. The homepage is onur.dev, the default branch is master rather than main, and the language is recorded as JavaScript even though the project is TypeScript in practice, with a jsconfig.json and no separate build step for types. There are no GitHub releases, which is correct for a site deployed from the default branch.

Eleven open issues is a small number for a repository this size, and the fork count is proportionally high, close to one fork for every twelve stars. For a personal site that pattern suggests people copying it as a starting point rather than contributing to it, which is exactly the use the licence section anticipates.

The README also embeds a Repobeats analytics image for repository activity, which is a minor but telling detail. It is there because the author cares about the repository's own metrics, which is a hobbyist habit rather than a professional one.

What makes the repository worth your time has little to do with the code quality of a personal website, which is unremarkable in the best possible way. It is the combination of three things: an unusually current dependency set, meaning the README's tech stack claims are backed by a manifest that reflects the state of Next.js and Tailwind rather than a snapshot from two years ago; a content architecture that separates prose, bookmarks and analytics into three different services with a clear reason for each; and a licence section that argues for a position rather than defaulting to MIT.

If you are building a personal site with an external CMS, the routing table and the Contentful plus Raindrop split are worth copying. If you are looking for a Next.js starter kit, the components.json and Tailwind 4 setup will save you some setup work. If you want to argue about open source licensing, the License section is a better starting point than most, because at least it says something.

The site's own description calls it a personal website built with Next.js, Tailwind CSS, shadcn/ui, Contentful, Raindrop, Supabase and Vercel. That list is accurate, and it is also the honest summary: a well-chosen set of tools, assembled by someone who knew why each one was there.

Editorial conclusion

The interesting part of onur.dev is not the site, it is the record. A personal website that has been rewritten five times, with each generation named in the README, is a more honest artefact than most portfolio projects, because it shows what survived and what did not. The current build is a Next.js 16 application with React 19 and Tailwind 4, shadcn/ui for components, Contentful for writing and static pages, Raindrop for bookmarks exported as an XML feed, and Supabase with the service role key reserved for on-demand revalidation, which is the detail that tells you what the database is really for. The dependency list is the honest description of the site: framer-motion, vaul and embla for drawers and carousels, react-tweet for embedded posts, sugar-high for syntax highlighting, and isbot for user-agent checks. Read the three-line licence before reusing anything. It asks for inspiration rather than copying, and points at a tool called lice for reading licences in a readable form, which is a better answer than most projects manage. If you are building a personal site with the same shape, the routing table is the useful part: static slug pages, a writing section, and a bookmark feed you can read from any reader.

Frequently asked questions

What is onur.dev?

It is a personal website built with Next.js, Tailwind CSS, shadcn/ui, Contentful, Raindrop, Supabase and deployed on Vercel. The repository describes it as an app-like web platform for writing, a journey page, a workspace page and a bookmarks section, and it has been rewritten several times over the years.

How do I run onur.dev locally?

Clone the repository, change into the directory, then run bun i and bun dev. You also need a .env file based on .env.example, since the site depends on Contentful, Supabase, Raindrop and several other services with no default values. The lockfile is a bun.lockb, so bun is the intended package manager.

Where does the content come from?

Writing pages and static slug pages such as /stack are statically pre-rendered from Contentful, which also supplies a preview token and preview secret for draft viewing. Individual bookmark pages are statically pre-rendered from Raindrop, and there is a /bookmarks.xml feed so the bookmarks can be read outside the site.

What license does onur.dev use?

It does not use a standard open source license. GitHub records it as NOASSERTION and the file is named LICENSE.txt. The README states three rules in plain language: take inspiration freely, avoid copying directly, and credit the author is appreciated. It recommends the lice tool for reading licenses in a readable form instead.

Can I fork this project for my own personal website?

The README invites inspiration, so read it, learn the structure and write your own code. If you want to reuse it directly, be aware the three rules are not a real license and leave your obligations undefined, so replacing them with a standard license such as MIT is the safer path.

What is Supabase used for in this project?

The environment file lists a SUPABASE_URL and SUPABASE_SERVICE_ROLE_KEY alongside the public NEXT_PUBLIC variants, and the README also documents an on-demand revalidation secret. Together these suggest the database backs server-side actions such as triggering cache invalidation after a Contentful edit, rather than holding the site's content.

Official sources

  1. Issues
  2. Project website
  3. README
  4. suyalcinkaya/onur.dev on GitHub
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/suyalcinkaya-onur-dev.svg)](https://hysenlabs.com/projects/suyalcinkaya-onur-dev)