Tajreed: designing and shipping a bilingual asset library by Reem MagdiTajreed: designing and shipping a bilingual asset library by Reem Magdi

Tajreed: designing and shipping a bilingual asset library

Reem Magdi

Reem Magdi

Tajreed (تجريد) is a library of 1,346 Arabic design assets: 3D objects, illustrations, cultural and seasonal pieces, free to download, in Arabic and English. I designed it, built it, and run it. This is what that took.

Why it left Framer

Framer got Tajreed online fast, and for a first version that was the right trade. But the library outgrew it. I needed real search across 1,346 records, accounts with download limits, per-asset pages that Google could actually index, and full control over how Arabic renders. Framer was not going to give me those, and I was paying monthly for the privilege of not having them.
So I rebuilt the front end in Next.js on Vercel, kept the Supabase database and the Dropbox file store exactly as they were, and moved the domain across without a minute of downtime or a single lost email.

Arabic first, not Arabic translated

Most bilingual sites are an English site with Arabic poured into it. Tajreed is the other way round: Arabic is the default, English is the alternate, and the layout is genuinely mirrored rather than flipped.
That distinction shows up in small, unglamorous places. When someone switches language mid-session, the page does not reload, so the document direction has to be reapplied on navigation, or Arabic silently renders left-to-right and everything looks subtly wrong. Arabic and Latin needed separate font stacks with weights chosen per script, not one family stretched across both.
My favourite one: the download counter. It reads ٥ من ١٠ (five of ten). Written as ٥ / ١٠ it renders backwards, because the bidirectional algorithm reorders the numbers around the slash. I tried the standard fixes like directional isolates and explicit direction attributes, and measured the character positions to confirm each one had failed. The fix in the end was not technical at all. I used the Arabic word for "of" instead of a slash, and the ambiguity disappeared.
Side-by-side of the Arabic and English gallery, same scroll position, showing the mirrored layout.
Side-by-side of the Arabic and English gallery, same scroll position, showing the mirrored layout.

Search that understands Arabic

Arabic search breaks if you treat it like English. The same word can be written with or without diacritics, with a stretched connector, with any of three forms of alef, or with ي or ى at the end. A designer typing رمضان should find an asset tagged رَمَضان.
So every searchable string is normalized on the way into the index and on the way in from the search box: diacritics stripped, connectors removed, letter forms folded together. Titles are weighted above tags, tags above descriptions, so relevance ranking means something. Results filter live as you type, debounced, with stale responses discarded so a slow query can never overwrite a newer one.

One architecture decision I'd defend

Clicking an asset opens it in an overlay; opening the same URL directly gives you a full page. That is built with Next.js parallel and intercepting routes, and it is the interaction the whole library hangs on because browsing a grid should not cost you your place in it.
Partway through I added static pre-rendering to all 1,346 asset pages for SEO. The pages got faster. The overlay stopped working because pre-rendering bypasses the intercepting route entirely. I found out because I was clicking around the site, not because a test failed.

I took the overlay out of the SEO plan, not the plan out of the overlay. The pages render on demand with a ten-minute cache instead: slightly slower, and the product still behaves the way I designed it.

Everything that could be static is: the about page, the forms, the sitemap. Getting there meant restructuring the app so that reading a login cookie (which forces every page to render per-request) happens in one small client component instead of in the shared layout. Personalisation is one component's job; the other 1,346 pages are public and cacheable.

The half nobody puts in a portfolio

A product is not finished when the interface is. Tajreed also needed passwordless sign-in with emailed codes, a per-account download limit enforced on the server rather than suggested in the browser, short-lived download links so file paths never reach the client, transactional email that actually lands in inboxes, and a domain migration that moved the website without touching the mail records sitting on the same domain.
I also ran a security pass over the database before calling it done, found a way a signed-in user could have lifted their own download limit, and closed it. Nobody would have thanked me for it. It would have quietly cost me the entire library.

Building with AI, honestly

I built this with an AI collaborator, and I would rather describe that accurately than either hide it or oversell it.
A large share of the code was AI-written. What that changed was throughput, not judgment. The decisions stayed mine: that Arabic is the default and not the translation, that the overlay was worth losing pre-rendering for, that a counter reading backwards is a real bug and not a rounding error. The pre-rendering regression I mentioned came from an AI suggestion that was correct in general and wrong for this product, and it got caught because I use the thing I am building.
That is the working relationship I bring to a client project: fast execution, with someone who knows which of the fast answers to keep.

Where it landed

1,346 assets, live at tajreed.co, in Arabic and English
57 indexable pages plus a per-asset page for every item, with structured data for image licensing
Previews average 29 KB against source files averaging around 10 MB: the grid stays fast and the assets stay behind the account wall
Off Framer entirely, on infrastructure I control

If you're hiring for this

What I'm useful for is the span: I can take something from a Figma file to a live product without a handoff in the middle, and I'm as comfortable in a Postgres policy or a DNS record as in a type scale. That's worth most on small teams, on bilingual or Arabic-market products, and on projects where the gap between "designed" and "shipped" is where things usually stall.
Tajreed is the long version of my answer. Happy to walk through any part of it.
Like this project

Posted Aug 28, 2026

An Arabic-first library of 1,346 design assets moved off Framer and rebuilt as a real product. Design, front end, database, auth, email and deployment, by me.