├── apps ├── web │ ├── public │ │ ├── demo.gif │ │ ├── favicon.ico │ │ ├── _routes.json │ │ └── _headers │ ├── .gitignore │ ├── resources │ │ ├── screenshot.jpg │ │ ├── tiktoken_bg.wasm │ │ └── gitmojis.json │ ├── postcss.config.js │ ├── functions │ │ └── [[path]].ts │ ├── components.json │ ├── app │ │ ├── entry.client.tsx │ │ ├── routes │ │ │ ├── sitemap[.]xml.ts │ │ │ ├── robots[.]txt.ts │ │ │ └── _index.tsx │ │ ├── components │ │ │ └── ui │ │ │ │ ├── textarea.tsx │ │ │ │ ├── separator.tsx │ │ │ │ ├── button.tsx │ │ │ │ └── select.tsx │ │ ├── entry.server.tsx │ │ ├── tailwind.css │ │ └── root.tsx │ ├── load-context.ts │ ├── vite.config.ts │ ├── tsconfig.json │ ├── lib │ │ └── utils.ts │ ├── package.json │ ├── .eslintrc.cjs │ └── tailwind.config.ts └── cli │ ├── package.json │ ├── Makefile │ ├── go.mod │ ├── emoji.go │ ├── genmoji.go │ ├── main.go │ ├── prompt.go │ ├── client.go │ └── go.sum ├── demo.tape ├── turbo.json ├── package.json ├── .editorconfig ├── .gitignore ├── README.md ├── scripts └── install.sh └── .github └── workflows └── ci.yml /apps/web/public/demo.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/segersniels/genmoji/HEAD/apps/web/public/demo.gif -------------------------------------------------------------------------------- /apps/web/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | 3 | /.cache 4 | /build 5 | .env 6 | .dev.vars 7 | 8 | .wrangler 9 | -------------------------------------------------------------------------------- /apps/cli/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cli", 3 | "scripts": { 4 | "build": "make build" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /apps/web/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/segersniels/genmoji/HEAD/apps/web/public/favicon.ico -------------------------------------------------------------------------------- /apps/web/resources/screenshot.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/segersniels/genmoji/HEAD/apps/web/resources/screenshot.jpg -------------------------------------------------------------------------------- /apps/web/resources/tiktoken_bg.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/segersniels/genmoji/HEAD/apps/web/resources/tiktoken_bg.wasm -------------------------------------------------------------------------------- /apps/web/postcss.config.js: -------------------------------------------------------------------------------- 1 | export default { 2 | plugins: { 3 | tailwindcss: {}, 4 | autoprefixer: {}, 5 | }, 6 | }; 7 | -------------------------------------------------------------------------------- /apps/web/public/_routes.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 1, 3 | "include": ["/*"], 4 | "exclude": ["/favicon.ico", "/assets/*"] 5 | } 6 | -------------------------------------------------------------------------------- /demo.tape: -------------------------------------------------------------------------------- 1 | Output demo.gif 2 | 3 | Require echo 4 | 5 | Set Shell "bash" 6 | Set FontSize 16 7 | Set Width 800 8 | Set Height 400 9 | 10 | Type `genmoji commit` Sleep 500ms Enter 11 | Sleep 5s Enter 12 | Sleep 5s Left Sleep 500ms Enter 13 | Sleep 1s 14 | -------------------------------------------------------------------------------- /apps/web/public/_headers: -------------------------------------------------------------------------------- 1 | https://:project.pages.dev/* 2 | X-Robots-Tag: noindex 3 | 4 | /demo.gif 5 | Cache-Control: public, max-age=2592000, s-maxage=2592000 6 | /favicon.ico 7 | Cache-Control: public, max-age=3600, s-maxage=3600 8 | /assets/* 9 | Cache-Control: public, max-age=31536000, immutable 10 | -------------------------------------------------------------------------------- /apps/web/functions/[[path]].ts: -------------------------------------------------------------------------------- 1 | import { createPagesFunctionHandler } from "@remix-run/cloudflare-pages"; 2 | 3 | // eslint-disable-next-line @typescript-eslint/ban-ts-comment 4 | // @ts-ignore - the server build file is generated by `remix vite:build` 5 | // eslint-disable-next-line import/no-unresolved 6 | import * as build from "../build/server"; 7 | 8 | export const onRequest = createPagesFunctionHandler({ build }); 9 | -------------------------------------------------------------------------------- /turbo.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://turbo.build/schema.json", 3 | "pipeline": { 4 | "build": { 5 | "dependsOn": ["^build"], 6 | "outputs": ["dist/**", ".next/**", "zig-cache/**", "zig-out/**"] 7 | }, 8 | "build:ci": { 9 | "dependsOn": ["^build:ci"], 10 | "outputs": ["dist/**", ".next/**", "zig-cache/**", "zig-out/**"] 11 | }, 12 | "lint": {}, 13 | "lint:fix": {} 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /apps/web/components.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://ui.shadcn.com/schema.json", 3 | "style": "new-york", 4 | "rsc": false, 5 | "tsx": true, 6 | "tailwind": { 7 | "config": "tailwind.config.ts", 8 | "css": "app/tailwind.css", 9 | "baseColor": "stone", 10 | "cssVariables": true, 11 | "prefix": "" 12 | }, 13 | "aliases": { 14 | "components": "components", 15 | "utils": "lib/utils" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "genmoji", 3 | "version": "0.1.0", 4 | "private": true, 5 | "scripts": { 6 | "dev": "npm run dev --workspace web", 7 | "build": "turbo build", 8 | "build:ci": "turbo build:ci", 9 | "lint": "turbo lint", 10 | "lint:fix": "turbo lint:fix" 11 | }, 12 | "devDependencies": { 13 | "turbo": "^1.13.0" 14 | }, 15 | "workspaces": [ 16 | "apps/*", 17 | "packages/*" 18 | ] 19 | } 20 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig is awesome: http://EditorConfig.org 2 | 3 | # top-most EditorConfig file 4 | root = true 5 | 6 | # Default ruleset for all files 7 | [*] 8 | end_of_line = lf 9 | insert_final_newline = true 10 | trim_trailing_whitespace = true 11 | charset = utf-8 12 | indent_style = space 13 | indent_size = 2 14 | quote_type = single 15 | 16 | # Zig ruleset 17 | [*.zig] 18 | indent_size = 4 19 | 20 | # Makefile 21 | [Makefile] 22 | indent_style = tab 23 | indent_size = 4 24 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # next.js 12 | .next 13 | out 14 | 15 | # production 16 | /build 17 | 18 | # misc 19 | .DS_Store 20 | *.pem 21 | 22 | # debug 23 | npm-debug.log* 24 | yarn-debug.log* 25 | yarn-error.log* 26 | .pnpm-debug.log* 27 | 28 | # local env files 29 | .env*.local 30 | 31 | # vercel 32 | .vercel 33 | 34 | # typescript 35 | *.tsbuildinfo 36 | next-env.d.ts 37 | 38 | # turbo 39 | .turbo 40 | 41 | # zig 42 | zig-cache/ 43 | zig-out/ 44 | bin/ 45 | -------------------------------------------------------------------------------- /apps/web/app/entry.client.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * By default, Remix will handle hydrating your app on the client for you. 3 | * You are free to delete this file if you'd like to, but if you ever want it revealed again, you can run `npx remix reveal` ✨ 4 | * For more information, see https://remix.run/file-conventions/entry.client 5 | */ 6 | 7 | import { RemixBrowser } from "@remix-run/react"; 8 | import { startTransition, StrictMode } from "react"; 9 | import { hydrateRoot } from "react-dom/client"; 10 | 11 | startTransition(() => { 12 | hydrateRoot( 13 | document, 14 | 15 | 16 | 17 | ); 18 | }); 19 | -------------------------------------------------------------------------------- /apps/web/load-context.ts: -------------------------------------------------------------------------------- 1 | import { type PlatformProxy } from 'wrangler'; 2 | 3 | // When using `wrangler.toml` to configure bindings, 4 | // `wrangler types` will generate types for those bindings 5 | // into the global `Env` interface. 6 | // Need this empty interface so that typechecking passes 7 | // even if no `wrangler.toml` exists. 8 | // eslint-disable-next-line @typescript-eslint/no-empty-interface 9 | interface Env { 10 | OPENAI_API_KEY: string; 11 | } 12 | 13 | type Cloudflare = Omit, 'dispose'>; 14 | 15 | declare module '@remix-run/cloudflare' { 16 | interface AppLoadContext { 17 | cloudflare: Cloudflare; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /apps/web/vite.config.ts: -------------------------------------------------------------------------------- 1 | import { 2 | vitePlugin as remix, 3 | cloudflareDevProxyVitePlugin as remixCloudflareDevProxy, 4 | } from '@remix-run/dev'; 5 | import { defineConfig } from 'vite'; 6 | import tsconfigPaths from 'vite-tsconfig-paths'; 7 | 8 | export default defineConfig({ 9 | server: { 10 | port: 3000, 11 | }, 12 | plugins: [ 13 | remixCloudflareDevProxy(), 14 | remix({ 15 | future: { 16 | v3_fetcherPersist: true, 17 | v3_relativeSplatPath: true, 18 | v3_throwAbortReason: true, 19 | unstable_singleFetch: true, 20 | unstable_lazyRouteDiscovery: true, 21 | }, 22 | }), 23 | tsconfigPaths(), 24 | ], 25 | }); 26 | -------------------------------------------------------------------------------- /apps/cli/Makefile: -------------------------------------------------------------------------------- 1 | .PHONY: build clean dev version demo $(TARGETS) 2 | 3 | BINARY_NAME := genmoji 4 | VERSION := 1.2.0 5 | BUILD_DIR := bin 6 | 7 | TARGETS := darwin-arm64 darwin-amd64 linux-arm64 linux-amd64 8 | LDFLAGS := -w -s -X main.AppVersion=$(VERSION) -X main.AppName=$(BINARY_NAME) 9 | 10 | build: $(TARGETS) 11 | 12 | $(TARGETS): 13 | GOOS=$(word 1,$(subst -, ,$@)) GOARCH=$(word 2,$(subst -, ,$@)) go build -o $(BUILD_DIR)/$(BINARY_NAME)-$@ -ldflags "$(LDFLAGS)" 14 | 15 | clean: 16 | rm -rf $(BUILD_DIR) 17 | 18 | dev: 19 | go build -o $(BUILD_DIR)/$(BINARY_NAME) -ldflags "$(LDFLAGS)" 20 | 21 | version: 22 | @echo $(VERSION) 23 | 24 | demo: 25 | @vhs ../../demo.tape -o ../web/public/demo.gif 26 | -------------------------------------------------------------------------------- /apps/web/app/routes/sitemap[.]xml.ts: -------------------------------------------------------------------------------- 1 | import { LoaderFunctionArgs } from '@remix-run/cloudflare'; 2 | 3 | export async function loader({ request }: LoaderFunctionArgs) { 4 | const url = new URL(request.url); 5 | const baseUrl = `${url.protocol}//${url.host}`; 6 | 7 | const sitemap = ` 8 | 9 | ${baseUrl} 10 | ${baseUrl}/web 11 | 12 | `; 13 | 14 | return new Response(sitemap, { 15 | status: 200, 16 | headers: { 17 | 'Content-Type': 'application/xml', 18 | 'Cache-Control': 'public, max-age=86400, must-revalidate', 19 | }, 20 | }); 21 | } 22 | -------------------------------------------------------------------------------- /apps/web/app/components/ui/textarea.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | 3 | import { cn } from 'lib/utils'; 4 | 5 | export interface TextareaProps 6 | extends React.TextareaHTMLAttributes {} 7 | 8 | const Textarea = React.forwardRef( 9 | ({ className, ...props }, ref) => { 10 | return ( 11 |