{"id":23792099,"url":"https://github.com/quadnucyard/ourchat-typ","last_synced_at":"2026-03-04T23:03:19.530Z","repository":{"id":269721219,"uuid":"889106343","full_name":"QuadnucYard/ourchat-typ","owner":"QuadnucYard","description":"Forge wonderful chat messages in typst","archived":false,"fork":false,"pushed_at":"2025-12-16T15:00:06.000Z","size":5922,"stargazers_count":94,"open_issues_count":1,"forks_count":5,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-12-20T05:06:18.270Z","etag":null,"topics":["discord","qqnt","typst","wechat"],"latest_commit_sha":null,"homepage":"https://quadnucyard.github.io/ourchat-typ/","language":"Typst","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/QuadnucYard.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2024-11-15T16:12:12.000Z","updated_at":"2025-12-18T23:12:33.000Z","dependencies_parsed_at":"2024-12-25T16:27:28.480Z","dependency_job_id":"0008a090-00fd-4221-82da-49c33825b6a9","html_url":"https://github.com/QuadnucYard/ourchat-typ","commit_stats":null,"previous_names":["quadnucyard/ourchat-typ"],"tags_count":3,"template":false,"template_full_name":null,"purl":"pkg:github/QuadnucYard/ourchat-typ","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/QuadnucYard%2Fourchat-typ","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/QuadnucYard%2Fourchat-typ/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/QuadnucYard%2Fourchat-typ/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/QuadnucYard%2Fourchat-typ/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/QuadnucYard","download_url":"https://codeload.github.com/QuadnucYard/ourchat-typ/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/QuadnucYard%2Fourchat-typ/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30098108,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-04T22:49:54.894Z","status":"ssl_error","status_checked_at":"2026-03-04T22:49:48.883Z","response_time":59,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["discord","qqnt","typst","wechat"],"created_at":"2025-01-01T18:27:24.053Z","updated_at":"2026-03-04T23:03:19.522Z","avatar_url":"https://github.com/QuadnucYard.png","language":"Typst","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003ch1\u003e\n\nOurchat\n\n\u003c/h1\u003e\n\n\u003ca href=\"https://typst.app/universe/package/ourchat\"\u003e\n\n\u003cimg src=\"https://img.shields.io/badge/dynamic/xml?url=https%3A%2F%2Ftypst.app%2Funiverse%2Fpackage%2Fourchat\u0026amp;query=%2Fhtml%2Fbody%2Fdiv%2Fmain%2Fdiv%5B2%5D%2Faside%2Fsection%5B2%5D%2Fdl%2Fdd%5B3%5D\u0026amp;logo=typst\u0026amp;label=Universe\u0026amp;color=%2339cccc\" alt=\"Universe\" /\u003e\n\n\u003c/a\u003e \u003ca href=\"https://github.com/QuadnucYard/ourchat-typ\"\u003e\n\n\u003cimg src=\"https://img.shields.io/badge/dynamic/toml?url=https%3A%2F%2Fraw.githubusercontent.com%2FQuadnucYard%2Fourchat-typ%2Frefs%2Fheads%2Fmain%2Ftypst.toml\u0026amp;query=package.version\u0026amp;logo=GitHub\u0026amp;label=GitHub\" alt=\"GitHub\" /\u003e\n\n\u003c/a\u003e\n\n_Create chat interfaces in Typst with ease_\n\nOurchat is a [Typst](https://typst.app/) package for building chat UI mockups. It helps you document software features, create presentations, or prototype chat interfaces with themes for popular platforms like WeChat, Discord, and QQ.\n\n![typst-frame](assets/frame_0.svg)\n\n```typst\n#let yau = wechat.default-user(name: [丘成桐（囯內）])\n\n#wechat.chat(\n  theme: \"dark\",\n  ..oc.with-side-user(\n    left,\n    yau,\n    oc.time[5月16日 上午10:23],\n    oc.free-message[\n      已經到了無恥的地步。\n    ],\n    oc.time[6月18日 凌晨00:06],\n    oc.free-message[\n      我宣布他已經不是我的學生了\n    ],\n    oc.time[14:00],\n    oc.free-message[\n      這種成績，使人汗顏！如此成績，如何招生？\n    ],\n  ),\n  oc.message(right, yau)[\n    我沒有説過這種話！\n\n    ——發自我的手機\n  ],\n)\n```\n\n## Features\n\n- **Out-of-the-box themes**: WeChat, Discord, QQNT theme support\n- **Simple API**: Easy-to-use, declarative interface\n- **Customizable styling**: Colors, avatars, layouts, and typography\n- **Just do it**: Write anything inside messages—Code blocks, tables, mathematical equations…\n\n## Quick Start\n\nFirst, import the package in your Typst document:\n\n```typst\n#import \"@preview/ourchat:0.2.1\" as oc\n#import oc.themes: *\n```\n\nThen create your first chat:\n\n```typst\n#let alice = wechat.user(name: [Alice], avatar: circle(fill: blue, text(white)[A]))\n#let bob = wechat.user(name: [Bob], avatar: circle(fill: green, text(white)[B]))\n\n#wechat.chat(\n  oc.time[Today 14:30],\n\n  oc.message(left, alice)[\n    Hey! How's the new project going?\n  ],\n\n  oc.message(right, bob)[\n    Great! Just finished the API integration.\n    The performance improvements are impressive! 🚀\n  ],\n)\n```\n\n![typst-frame](assets/frame_1.svg)\n\n## Builtin Themes\n\n### WeChat Theme\n\n```typst\n#let user1 = wechat.user(name: [Alice], avatar: circle(fill: blue, text(white)[A]))\n#let user2 = wechat.user(name: [Bob], avatar: circle(fill: green, text(white)[B]))\n\n#wechat.chat(\n  theme: \"light\",  // or \"dark\"\n  layout: (\n    bubble-radius: 8pt,\n  ),\n  width: 400pt,\n\n  oc.time[Monday 9:00 AM],\n  oc.message(left, user1)[Hello world!],\n  oc.message(right, user2)[Hi there! 👋],\n)\n```\n\n![typst-frame](assets/frame_2.svg)\n\n### Discord Theme\n\n````typst\n#set text(font: (\"gg sans\", \"IBM Plex Sans SC\"))\n\n#let developer = discord.user(\n  name: [Dev],\n  avatar: circle(fill: purple, text(white)[D])\n)\n#let admin = discord.user(\n  name: [Admin],\n  avatar: circle(fill: red, text(white)[A])\n)\n\n#discord.chat(\n  oc.time[Today at 2:14 PM],\n\n  oc.message(left, developer)[\n```python\ndef optimize_query():\n    return cache_strategy.redis_cluster()\n```\n    What do you think about this approach? @admin\n  ],\n\n  oc.message(right, admin)[\n    @developer Looks good! The Redis cluster should handle the load well.\n  ],\n)\n````\n\n![typst-frame](assets/frame_3.svg)\n\n### QQNT Theme\n\n```typst\n#let student = qqnt.user(\n  name: [Student],\n  avatar: circle(fill: orange, text(white)[S])\n)\n#let expert = qqnt.user(\n  name: [Expert],\n  avatar: circle(fill: teal, text(white)[E])\n)\n\n#qqnt.chat(\n  theme: (\n    inherit: \"light\",\n    bubble-left: rgb(\"#F0F8FF\"),\n    bubble-right: rgb(\"#E8F5E8\"),\n    text-right: rgb(\"#111111\"),\n  ),\n\n  oc.message(left, student)[\n    Can someone explain Rust ownership?\n  ],\n\n  oc.message(right, expert)[\n    Sure! Ownership prevents data races at compile time...\n  ],\n)\n```\n\n![typst-frame](assets/frame_4.svg)\n\n## Advanced Usage\n\n### Convenience Functions\n\nFor multiple messages from the same user, use `with-side-user` to avoid repetition:\n\n```typst\n#set text(font: (\"gg sans\", \"IBM Plex Sans SC\"))\n\n#let admin = oc.user(\n  name: [System Admin],\n  avatar: circle(fill: red.darken(20%), text(white, weight: \"bold\")[⚡])\n)\n\n#discord.chat(\n  oc.time[Today at 3:45 PM],\n\n  // Instead of repeating the user for each message:\n  // oc.message(left, admin)[Server maintenance scheduled],\n  // oc.message(left, admin)[Downtime: 30 minutes max],\n  // oc.message(left, admin)[Please save your work],\n\n  // Use with-side-user for cleaner code:\n  ..oc.with-side-user(\n    left,\n    admin,\n    oc.free-message[🚨 *URGENT: Server Maintenance Alert*],\n    oc.free-message[Scheduled downtime: Tonight 11 PM - 11:30 PM],\n    oc.free-message[All services will be temporarily unavailable],\n    oc.free-message[Please save your work and plan accordingly],\n  ),\n)\n```\n\n![typst-frame](assets/frame_5.svg)\n\n### Custom User Avatars\n\nCreate distinctive user profiles:\n\n```typst\n#let ceo = oc.user(\n  name: [Sarah Chen],\n  badge: qqnt.badge(text-color: purple, bg-color: purple.transparentize(80%))[#text(stroke: 0.05em + purple)[CEO]],\n  avatar: rect(\n    fill: blue.darken(20%),\n    radius: 4pt,\n    inset: 6pt,\n    text(white, weight: \"bold\")[SC]\n  )\n)\n\n#qqnt.chat(\n  oc.message(left, ceo)[\n    Hi team! Ready for the quarterly review?\n  ],\n)\n```\n\n![typst-frame](assets/frame_6.svg)\n\n### Rich Content Support\n\nInclude tables, code blocks, and visual elements:\n\n```typst\n#let analyst = wechat.user(\n  name: [Data Analyst],\n  avatar: circle(fill: green.darken(10%), text(white)[📊])\n)\n\n#wechat.chat(\n  oc.message(left, analyst)[\n    Here's our performance analysis:\n\n    #table(\n      columns: (auto, auto, auto),\n      [*Metric*], [*Before*], [*After*],\n      [Response Time], [250ms], [120ms],\n      [Throughput], [1000 RPS], [2500 RPS],\n    )\n\n    The optimization yielded 58% improvement! 📊\n  ]\n)\n```\n\n![typst-frame](assets/frame_7.svg)\n\n### Theme Customization\n\nModify existing themes or create your own:\n\n```typst\n#let custom_theme = (\n  inherit: \"light\",\n  background: rgb(\"#F5F5F5\"),\n  bubble-left: rgb(\"#E3F2FD\"),\n  bubble-right: rgb(\"#C8E6C9\"),\n  text-primary: rgb(\"#212121\"),\n  text-secondary: rgb(\"#757575\"),\n)\n\n#wechat.chat(theme: custom_theme, ...)\n```\n\n### Layout Control\n\nFine-tune spacing and dimensions:\n\n```typst\n#wechat.chat(\n  layout: (\n    content-width: 350pt,\n    message-spacing: 0.8em,\n    avatar-size: 32pt,\n    bubble-padding: 12pt,\n  ),\n  ...\n)\n```\n\n## Examples Gallery\n\nExplore our comprehensive example collection: [https://quadnucyard.github.io/ourchat-typ](https://quadnucyard.github.io/ourchat-typ)\n\nThe source codes for these example are located at `./examples`.\n\n## Architecture \u0026 Design\n\n### API Design Philosophy\n\nOurchat follows a unified component architecture where `oc` provides the core building blocks:\n\n- `oc.message()`, `oc.user()`, `oc.time()` - Universal components that work across all themes\n- Built-in themes (`wechat`, `discord`, `qqnt`) import all common components but may override them for platform-specific features\n  - For example, `qqnt.user()` extends the base user component with `badge` support for role badges\n- Uses `chat` as the rendering function of messages, which is defined in individual themes. Styling is decided here.\n\n```typst\n// Universal approach - works with any theme\n#let user = oc.user(name: [Alice])\n\n// Theme-specific approach - leverages extended features\n#let qqnt_user = qqnt.user(\n  name: [Alice],\n  badge: qqnt.badge()[Admin]  // QQNT specific feature\n)\n```\n\n### Theme Customization Scope\n\nBuilt-in themes provide a solid foundation but don’t cover every possible customization. You’re encouraged to:\n\n- Extend existing themes for minor modifications using `theme` and `layout` parameters.\n- Create entirely new themes for different platforms or unique designs with basic blocks. Refer to the source code of built-in themes as implementation guides\n\n## API Reference\n\nHere only lists exported functions and variables. Please refer to the documentation comments of each function for details\n\n### Common Components\n\n- `oc.user(name, avatar, badge)`: Create universal user profiles\n- `oc.message(side, user, body, time, merge)`: Add chat messages (`left` or `right`)\n- `oc.time(body)`: Insert timestamp dividers\n- `oc.with-side-user(side, user, ..messages)`: Convenience for multiple messages from same user\n- `oc.free-message(body, time, merge)`: Create message without specific user or side\n- `oc.plain(side, user, body)`: Create plain item without padding\n\nNote: These are just helper functions for data wrapping. You can directly create data structures if you like.\n\n### Theme Collections\n\n#### `oc.themes.wechat`\n\nWeChat layout and color schemes (`light`, `dark`)\n\n- `wechat.chat(theme, layout, width, validate, ..messages)`: WeChat-style interface\n- `wechat.default-user`: Pre-configured user with WeChat avatar\n\n#### `oc.themes.qqnt`\n\nQQNT layout and color schemes (`light`, `dark`)\n\n- `qqnt.chat(theme, layout, width, validate, ..messages)`: QQNT-style interface\n- `qqnt.user` (uses `oc.user` with badge support): QQNT user with role support\n- `qqnt.badge(body, text-color, bg-color)`: Create role badges\n\n#### `oc.themes.discord`\n\nDiscord layout and color schemes\n\n- `discord.newbie-user`: Pre-configured user with newbie badge\n- `discord.mention(body)`: Create Discord-style mention element\n- `discord.chat(theme, layout, width, validate, auto-mention, ..messages)`: Discord-style interface\n\n### Utilities (`oc.utils`)\n\n- `validate-theme(theme, reference, field-type)`: Validate theme dictionary fields\n- `validate-layout(layout, reference)`: Validate layout dictionary fields\n- `resolve-theme(themes, theme, default, validate)`: Resolve theme with inheritance support\n- `resolve-layout(layout, default-layout, validate)`: Merge and validate layout settings\n- `stretch-cover(item)`: Scale content to cover its container\n- `auto-mention-rule(auto-mention, styler)`: Create show rule for automatic mention styling\n\n## Contributing\n\nWe welcome contributions! Please check our GitHub repository for:\n\n- Bug reports and feature requests\n- Code contributions and improvements\n- Documentation updates\n- New theme proposals and existing theme improvements\n\n## License\n\nMIT License - see [LICENSE](LICENSE) file for details.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fquadnucyard%2Fourchat-typ","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fquadnucyard%2Fourchat-typ","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fquadnucyard%2Fourchat-typ/lists"}