18 Commits
Author SHA1 Message Date
FernandoJVideira 8a11de5b0f Merge pull request 'Scaffold generated clients with @lucide/vue' (#11) from chore/lucide-vue into main
Reviewed-on: #11
2026-10-08 22:55:31 +00:00
FernandoJVideiraandClaude Sonnet 5.5 b7fe8f3f4e Scaffold generated clients with @lucide/vue
The template overlay now imports its icons from @lucide/vue (project-template#6),
so the scaffolder has to install that instead of the deprecated
lucide-vue-next: pnpm doesn't hoist the kit's own copy to the app, and a
fresh project would fail to resolve its icon imports. No version is pinned
here - these stay unpinned `pnpm add` calls, so the template remains the
version authority.

Submodule bumped to that commit.

Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
2026-10-08 23:54:00 +01:00
FernandoJVideira 0bd1550779 Merge pull request 'Generated clients: exclude vue-ui-kit from Vite pre-bundling, /signup route' (#10) from fix/generated-client-configs into main
Reviewed-on: #10
2026-09-16 12:58:56 +00:00
FernandoJVideiraandClaude Fable 5.1 1dcc135094 Generated clients: exclude vue-ui-kit from Vite pre-bundling, /signup route
Generated projects never got the optimizeDeps exclusion the template's
own configs carry - the Nuxt config is patched from nuxi's output and the
Vue one from create-vue's - so Vite bundled vue-ui-kit's index.ts with
reka-ui inlined while the kit's .vue files imported reka-ui from source.
Two module instances, mismatched provide/inject Symbols: a fresh Vue
client rendered a blank /login ("Injection Symbol(TabsRootContext) not
found") and a fresh Nuxt one crashed SSR on any page with a Dialog. Both
config patches now add the exclusion.

The Nuxt patch also adds the pages:extend hook that gives pages/login.vue
a second /signup record, matching the template's auth card whose tabs now
drive the URL (project-template#5). Submodule bumped to that commit.

Co-Authored-By: Claude Fable 5.1 <[email protected]>
2026-09-16 13:58:23 +01:00
FernandoJVideira 39678f3ea6 Merge pull request 'Make generated Vue monorepos buildable with docker compose' (#9) from fix/vue-monorepo-docker into main
Reviewed-on: #9
2026-09-16 12:27:07 +00:00
FernandoJVideiraandClaude Fable 5.1 230037c5f5 Make generated Vue monorepos buildable with docker compose
Running `draft new monorepo` with the Vue client and then
`docker compose build client` failed three separate ways, each found by
actually doing it:

- No Dockerfile: the Vue overlay never shipped one. The template now has
  an nginx-based image (project-template#4) and the client-vue sync job
  embeds it plus its nginx.conf.template, with the pnpm pin rewritten to
  the local version like the Nuxt overlay.
- Stale root lockfile: the Vue scaffold wrote a pnpm-workspace.yaml into
  apps/client (to approve vue-demi's build script), which made it its own
  workspace, so the installs updated a nested lockfile and the root one
  kept describing the template's Nuxt client - pnpm install
  --frozen-lockfile then refused it. The file is only written when the
  client isn't already inside a workspace (standalone `draft new client`).
- Missing component: the client-vue job listed components by name, so the
  AuthCard.vue that Login/Signup import was never embedded. It now embeds
  src/components/ as a whole.

Co-Authored-By: Claude Fable 5.1 <[email protected]>
2026-09-16 13:22:37 +01:00
FernandoJVideira 1195fdacb5 Merge pull request 'v0.2.0: ship the client Dockerfile with generated Nuxt apps' (#8) from chore/v0.2.0 into main
Reviewed-on: #8
2026-09-16 12:09:31 +00:00
FernandoJVideiraandClaude Fable 5.1 2f1ad93a74 Ship the client Dockerfile with generated Nuxt apps; bump to v0.2.0
A generated monorepo's docker-compose.yml already built apps/client from
apps/client/Dockerfile, but the client overlay only embedded app/ and
public/, so the file never existed and `docker compose build client`
failed on every fresh project. The client-nuxt sync job now embeds the
template's Dockerfile too, and the Nuxt scaffold rewrites its pnpm pin to
the locally detected version - the one that produces the generated
project's lockfile - the same way it already stamps packageManager.

Bumps the submodule to the template commit that mounts ~/.npmrc as a
build secret for the registry token, and the Makefile VERSION to v0.2.0
for the release.

Co-Authored-By: Claude Fable 5.1 <[email protected]>
2026-09-16 13:08:18 +01:00
FernandoJVideira b3ea1013bc Merge pull request 'Release: vue-ui-kit client scaffolding' (#7) from dev into main
Reviewed-on: #7
2026-09-16 11:57:52 +00:00
FernandoJVideira 35b88b4dcf Merge pull request 'Scaffold clients with vue-ui-kit; API/client/monorepo scaffolding fixes' (#6) from chore/refactor into dev
Reviewed-on: #6
2026-09-16 11:51:56 +00:00
FernandoJVideiraandClaude Fable 5.1 64c57f830b Bump project-template: tabbed auth card, single-tone page background
Co-Authored-By: Claude Fable 5.1 <[email protected]>
2026-09-16 12:41:39 +01:00
FernandoJVideiraandClaude Sonnet 5 d62383598c Bump project-template: redesign default pages, fix Nuxt Dialog/Select SSR
Co-Authored-By: Claude Sonnet 5 <[email protected]>
2026-09-16 11:33:59 +01:00
FernandoJVideiraandClaude Sonnet 5 650e811c84 Bump project-template: remove leftover shadcn-vue/Nuxt UI cruft
No change to draft's own generated output - this commit only touches
files outside what tools/sync_templates.go pulls into assets/embedded
(package.json, main.css, and the shadcn-vue-generated files it deletes
are all excluded from the client-vue/client-nuxt sync jobs already).
Keeps the reference project itself buildable and free of dead
dependencies now that both clients use vue-ui-kit.

Co-Authored-By: Claude Sonnet 5 <[email protected]>
2026-09-16 11:02:08 +01:00
FernandoJVideiraandClaude Sonnet 5 663ffb1c09 Scaffold clients with vue-ui-kit instead of Nuxt UI / shadcn-vue
Both `draft new client` and `draft new monorepo` (which reuses the same
client scaffolding for apps/client) now wire up @fernandojvideira/vue-ui-kit
as the component library on both frameworks, installed from its Gitea npm
registry.

Vue: drops the shadcn-vue init/add steps entirely - vue-ui-kit's theme.css
is imported directly instead of a generated one, and the overlay's one
shadcn Button usage now comes from vue-ui-kit.

Nuxt: switches the nuxi starter from "ui" (Nuxt UI) to "minimal", wiring
Tailwind v4 + vue-ui-kit by hand instead (mirrors vue-ui-kit's own Nuxt
INSTALL.md instructions). Needed one real fix: the "minimal" starter has
no typescript devDependency, and pnpm resolving it unpinned lands on
TypeScript 7, which breaks @vue/compiler-sfc's cross-file type resolution
that vue-ui-kit's components rely on - pinned to ~6.0.0 to match
create-vue's own default for the Vue flow.

The actual overlay content changes (token renames, icon swaps, a new
useToast() composable for Nuxt, etc.) live in the project-template
submodule, bumped here to its latest commit.

Verified end-to-end: both frameworks install, typecheck, and build clean
from a fresh `draft new client`, and were checked live in the browser.

Co-Authored-By: Claude Sonnet 5 <[email protected]>
2026-09-16 10:57:18 +01:00
FernandoJVideira 4806186ae6 Merge pull request 'Dev' (#5) from dev into main
Reviewed-on: #5
2026-08-25 21:03:41 +00:00
FernandoJVideira 7cec03d4c5 Merge pull request 'Chore/refactor' (#4) from chore/refactor into dev
Reviewed-on: #4
2026-08-25 21:03:22 +00:00
FernandoJVideira 145b3bb879 fix: duplicated binary built on makefile 2026-08-25 22:02:13 +01:00
FernandoJVideira 095a4c859a fix: changed help command 2026-08-25 21:52:07 +01:00
7 changed files with 171 additions and 89 deletions

No files matched your search

+1
View File
@@ -31,3 +31,4 @@ go.work.sum
# Binary
/draft*
prepare-embed-stamp
+22 -17
View File
@@ -1,25 +1,30 @@
PKG_NAME="git.fernandovideira.com/FernandoJVideira/draft"
PKG_NAME := git.fernandovideira.com/FernandoJVideira/draft
VERSION := v0.2.0
GO_SOURCES := $(shell find . -name '*.go' -not -path './assets/testdata/*')
.PHONY: version build windows win-arm linux mac prepare-embed clean
version:
@go run -ldflags "-X ${PKG_NAME}/cmd.version=v0.1.0" ./main.go version
@go run -ldflags "-X ${PKG_NAME}/cmd.version=${VERSION}" ./main.go version
build: prepare-embed
windows: ; @$(MAKE) build GOOS=windows GOARCH=amd64 OUTPUT=draft_windows_amd64.exe
win-arm: ; @$(MAKE) build GOOS=windows GOARCH=arm64 OUTPUT=draft_windows_arm64.exe
linux: ; @$(MAKE) build GOOS=linux GOARCH=amd64 OUTPUT=draft_linux_amd64
mac: ; @$(MAKE) build GOOS=darwin GOARCH=arm64 OUTPUT=draft_darwin_arm64
build: $(OUTPUT)
$(OUTPUT): prepare-embed-stamp $(GO_SOURCES)
@echo "Building for $(GOOS)/$(GOARCH)..."
@GOOS=$(GOOS) GOARCH=$(GOARCH) go build -ldflags "-X ${PKG_NAME}/cmd.version=v0.1.0" -o $(OUTPUT) ./main.go
@GOOS=$(GOOS) GOARCH=$(GOARCH) go build -ldflags "-X ${PKG_NAME}/cmd.version=${VERSION}" -o $(OUTPUT) ./main.go
windows:
@$(MAKE) build GOOS=windows GOARCH=amd64 OUTPUT=draft_windows_amd64.exe
win-arm:
@$(MAKE) build GOOS=windows GOARCH=arm64 OUTPUT=draft_windows_arm64.exe
linux:
@$(MAKE) build GOOS=linux GOARCH=amd64 OUTPUT=draft_linux_amd64
mac:
@$(MAKE) build GOOS=darwin GOARCH=arm64 OUTPUT=draft_darwin_arm64
prepare-embed:
prepare-embed-stamp:
@git submodule update --init --recursive
@mkdir -p assets/embedded
@GOOS="" GOARCH="" go run tools/sync_templates.go
@touch $@
prepare-embed: prepare-embed-stamp
clean:
@rm -f draft_windows_amd64.exe draft_windows_arm64.exe draft_linux_amd64 draft_darwin_arm64 prepare-embed-stamp
+2 -2
View File
@@ -82,10 +82,10 @@ draft new client
1. Prompts for a project name
2. Prompts you to pick a framework — **Nuxt** or **Vue**
3. Scaffolds the base app via the official tooling (`nuxi init` for Nuxt, `create-vue` + `shadcn-vue` for Vue), so the generated boilerplate, dependency versions, and lockfile are always current rather than pinned by Draft
3. Scaffolds the base app via the official tooling (`nuxi init` for Nuxt, `create-vue` for Vue), so the generated boilerplate, dependency versions, and lockfile are always current rather than pinned by Draft
4. Layers a Draft-maintained overlay on top: an auth store (login/logout/register/token refresh), route guards, API composable, and pages for login/signup/profile/organizations/email verification/invites — all wired up to talk to a Draft-generated API out of the box
Both frameworks produce a comparable app: Nuxt UI + Tailwind for Nuxt, shadcn-vue + Tailwind for Vue.
Both frameworks produce a comparable app: [`vue-ui-kit`](https://git.fernandovideira.com/FernandoJVideira/vue-ui-kit) (installed from its own Gitea npm registry - see its README for the one-time `.npmrc` token setup) + Tailwind, the same component library and theme tokens on either framework. Both clients ship with a Dockerfile that mounts that `~/.npmrc` as a build secret (wired up in the monorepo's `docker-compose.yml`), so container builds resolve the package without baking the token into the image - Nuxt runs its Nitro server, Vue is served by nginx with an SPA fallback and `/api/` proxied to the api container.
### Create a New Monorepo Project
+139 -64
View File
@@ -54,18 +54,29 @@ func genClient(cmd *cobra.Command, args []string) {
}
func scaffoldClientNuxt(projectDir, serviceName string) error {
// "minimal", not "ui" - the Nuxt UI starter is what we'd otherwise get
// for free, but this project uses vue-ui-kit as its component library
// instead, wired up by hand below (Tailwind v4 + the overlay's own
// app/assets/css/main.css already import it).
if err := runCommand("", "npx", "nuxi@latest", "init", projectDir,
"--no-install",
"--packageManager=pnpm",
"-t", "ui",
"-t", "minimal",
"--gitInit=false",
"-M", "@pinia/nuxt",
); err != nil {
return fmt.Errorf("error running nuxi init: %w", err)
}
version, err := pnpmVersion()
if err != nil {
return fmt.Errorf("error detecting pnpm version: %w", err)
}
replacements := map[string]string{
"App Template": serviceName,
// The overlay's Dockerfile pins the pnpm that produced the template's
// lockfile; the generated project's lockfile comes from the local pnpm.
"[email protected]": "pnpm@" + version,
}
if err := copyEmbeddedDir("embedded/client-nuxt", projectDir, replacements); err != nil {
return fmt.Errorf("error copying client overlay: %w", err)
@@ -76,7 +87,21 @@ func scaffoldClientNuxt(projectDir, serviceName string) error {
}
fmt.Println("📦 Installing dependencies...")
return runCommand(projectDir, "pnpm", "add", "pinia", "@pinia/nuxt")
if err := runCommand(projectDir, "pnpm", "add", "pinia", "@pinia/nuxt",
"@fernandojvideira/vue-ui-kit", "@lucide/vue",
); err != nil {
return fmt.Errorf("error installing dependencies: %w", err)
}
// typescript itself: the "minimal" starter (unlike "ui", and unlike
// create-vue's own output) doesn't include it, but @vue/compiler-sfc
// needs a real TypeScript install to resolve cross-file type extends -
// exactly what several vue-ui-kit components' Props interfaces do.
// Pinned below 7.x (matching create-vue's own "~6.0.0" default) since
// @vue/compiler-sfc's cross-file resolution isn't compatible with
// TypeScript 7 yet - it fails with "No fs option provided to
// compileScript in non-Node environment" on every extended interface.
return runCommand(projectDir, "pnpm", "add", "-D", "tailwindcss", "@tailwindcss/vite", "typescript@~6.0.0", "vue-tsc")
}
func patchNuxtConfig(projectDir, serviceName string) error {
@@ -86,7 +111,44 @@ func patchNuxtConfig(projectDir, serviceName string) error {
return fmt.Errorf("error reading nuxt.config.ts: %w", err)
}
// The "minimal" starter registers no Tailwind plugin and no CSS entry
// point on its own (the "ui" starter did both, bundled inside @nuxt/ui) -
// both are added explicitly here since the overlay's own main.css needs
// to actually run.
newContent := strings.Replace(string(content),
"// https://nuxt.com/docs/api/configuration/nuxt-config\n",
"// https://nuxt.com/docs/api/configuration/nuxt-config\nimport tailwindcss from '@tailwindcss/vite'\n\n",
1,
)
if newContent == string(content) {
return fmt.Errorf("could not find the file-header anchor in nuxt.config.ts")
}
insertion := fmt.Sprintf(`
css: ['~/assets/css/main.css'],
vite: {
plugins: [tailwindcss()],
// vue-ui-kit ships raw .vue/.ts source. Left to Vite's dependency
// pre-bundler, its index.ts gets bundled with reka-ui inlined while its
// .vue files import reka-ui from source - two module instances, so
// reka-ui's provide/inject contexts (Dialog, Tabs, Select...) can't find
// each other. Excluding it keeps every import on the one reka-ui.
optimizeDeps: {
exclude: ['@fernandojvideira/vue-ui-kit'],
},
},
hooks: {
// /login and /signup are the two tabs of one auth card, served by the
// same page file. A second route record (not an alias - the router
// would treat switching between a route and its alias as a duplicate
// navigation and drop it) lets the tab change the URL while NuxtPage
// keeps the same component instance thanks to the page's fixed key.
'pages:extend'(pages) {
const login = pages.find((page) => page.path === '/login')
if (login) pages.push({ ...login, name: 'signup', path: '/signup' })
},
},
app: {
head: {
title: %q,
@@ -102,12 +164,25 @@ func patchNuxtConfig(projectDir, serviceName string) error {
},
`, serviceName, serviceName)
newContent := strings.Replace(string(content), "defineNuxtConfig({", "defineNuxtConfig({"+insertion, 1)
if newContent == string(content) {
finalContent := strings.Replace(newContent, "defineNuxtConfig({", "defineNuxtConfig({"+insertion, 1)
if finalContent == newContent {
return fmt.Errorf("could not find defineNuxtConfig({ anchor in nuxt.config.ts")
}
return os.WriteFile(configPath, []byte(newContent), 0644)
return os.WriteFile(configPath, []byte(finalContent), 0644)
}
func insidePnpmWorkspace(dir string) bool {
for {
if _, err := os.Stat(filepath.Join(dir, "pnpm-workspace.yaml")); err == nil {
return true
}
parent := filepath.Dir(dir)
if parent == dir {
return false
}
dir = parent
}
}
func scaffoldClientVue(projectDir, serviceName string) error {
@@ -130,6 +205,12 @@ func scaffoldClientVue(projectDir, serviceName string) error {
return err
}
// A standalone client is its own workspace root and needs vue-demi's build
// script approved. Inside a monorepo the root pnpm-workspace.yaml already
// does that - and writing one here would make apps/client a separate
// workspace, so the installs below would update a nested lockfile and
// leave the root one describing the template's client instead of this one.
if !insidePnpmWorkspace(parentDir) {
if err := os.WriteFile(
filepath.Join(projectDir, "pnpm-workspace.yaml"),
[]byte("allowBuilds:\n vue-demi: true\n"),
@@ -137,6 +218,7 @@ func scaffoldClientVue(projectDir, serviceName string) error {
); err != nil {
return fmt.Errorf("error writing pnpm-workspace.yaml: %w", err)
}
}
fmt.Println("📦 Installing base dependencies...")
if err := runCommand(projectDir, "pnpm", "install"); err != nil {
@@ -151,8 +233,8 @@ func scaffoldClientVue(projectDir, serviceName string) error {
if err := os.MkdirAll(assetsDir, 0755); err != nil {
return fmt.Errorf("error creating src/assets: %w", err)
}
if err := os.WriteFile(filepath.Join(assetsDir, "main.css"), []byte("@import \"tailwindcss\";\n"), 0644); err != nil {
return fmt.Errorf("error writing main.css stub: %w", err)
if err := os.WriteFile(filepath.Join(assetsDir, "main.css"), []byte(vueUiKitMainCSS), 0644); err != nil {
return fmt.Errorf("error writing main.css: %w", err)
}
if err := patchViteConfigForTailwind(projectDir); err != nil {
@@ -161,38 +243,51 @@ func scaffoldClientVue(projectDir, serviceName string) error {
if err := patchTsconfigAlias(projectDir); err != nil {
return err
}
fmt.Println("🎨 Setting up shadcn-vue...")
if err := runCommand(projectDir, "pnpm", "dlx", "shadcn-vue@latest", "init",
"-t", "vite", "-b", "neutral", "--icon-library", "lucide", "-y", "-d",
); err != nil {
return fmt.Errorf("error running shadcn-vue init: %w", err)
}
if err := runCommand(projectDir, "pnpm", "dlx", "shadcn-vue@latest", "add",
"button", "input", "label", "select", "-y",
); err != nil {
return fmt.Errorf("error adding shadcn-vue components: %w", err)
}
if err := patchMainCssTokens(projectDir); err != nil {
return err
}
if err := patchEslintConfig(projectDir); err != nil {
return err
}
replacements := map[string]string{
"App Template": serviceName,
// The overlay's Dockerfile pins the pnpm that produced the template's
// lockfile; the generated project's lockfile comes from the local pnpm.
"[email protected]": "pnpm@" + version,
}
if err := copyEmbeddedDir("embedded/client-vue", projectDir, replacements); err != nil {
return fmt.Errorf("error copying client overlay: %w", err)
}
fmt.Println("📦 Installing remaining dependencies...")
return runCommand(projectDir, "pnpm", "add", "ofetch", "vue-sonner")
return runCommand(projectDir, "pnpm", "add", "ofetch", "@fernandojvideira/vue-ui-kit", "@lucide/vue")
}
// The library's theme brings its own tokens; --success/--warning are added on
// top the same way a consumer would (see vue-ui-kit's THEMING.md) since the
// base theme deliberately doesn't define them.
const vueUiKitMainCSS = `@import "tailwindcss";
@source "../../node_modules/@fernandojvideira/vue-ui-kit/src";
@import "@fernandojvideira/vue-ui-kit/theme.css";
:root {
--success: 142 71% 35%;
--success-foreground: 0 0% 98%;
--warning: 38 92% 40%;
--warning-foreground: 0 0% 98%;
}
.dark {
--success: 142 71% 45%;
--success-foreground: 0 0% 9%;
--warning: 38 92% 55%;
--warning-foreground: 0 0% 9%;
}
@theme inline {
--color-success: hsl(var(--success));
--color-success-foreground: hsl(var(--success-foreground));
--color-warning: hsl(var(--warning));
--color-warning-foreground: hsl(var(--warning-foreground));
}
`
func patchPackageManagerField(projectDir, version string) error {
pkgPath := filepath.Join(projectDir, "package.json")
content, err := os.ReadFile(pkgPath)
@@ -223,13 +318,31 @@ func patchViteConfigForTailwind(projectDir string) error {
)
newContent = strings.Replace(newContent, "vueDevTools(),", "vueDevTools(),\n tailwindcss(),", 1)
if newContent == string(content) {
// create-vue's config ends with the resolve.alias block; hang the
// optimizeDeps exclusion off its closing brace.
newContent = strings.Replace(newContent,
" '@': fileURLToPath(new URL('./src', import.meta.url)),\n },\n },\n})",
" '@': fileURLToPath(new URL('./src', import.meta.url)),\n },\n },\n"+viteOptimizeDepsExclude+"})",
1,
)
if newContent == string(content) || !strings.Contains(newContent, "optimizeDeps") {
return fmt.Errorf("could not find expected anchors in vite.config.ts")
}
return os.WriteFile(configPath, []byte(newContent), 0644)
}
// vue-ui-kit ships raw .vue/.ts source. Left to Vite's dependency pre-bundler,
// its index.ts gets bundled with reka-ui inlined while its .vue files import
// reka-ui from source - two module instances, so reka-ui's provide/inject
// contexts (Dialog, Tabs, Select...) can't find each other. Excluding it keeps
// every import on the one reka-ui.
const viteOptimizeDepsExclude = ` optimizeDeps: {
exclude: ['@fernandojvideira/vue-ui-kit'],
},
`
func patchTsconfigAlias(projectDir string) error {
configPath := filepath.Join(projectDir, "tsconfig.json")
content, err := os.ReadFile(configPath)
@@ -253,44 +366,6 @@ func patchTsconfigAlias(projectDir string) error {
return os.WriteFile(configPath, []byte(newContent), 0644)
}
func patchMainCssTokens(projectDir string) error {
cssPath := filepath.Join(projectDir, "src", "assets", "main.css")
content, err := os.ReadFile(cssPath)
if err != nil {
return fmt.Errorf("error reading main.css: %w", err)
}
s := string(content)
s2 := strings.Replace(s,
"--color-background: var(--background);",
"--color-background: var(--background);\n --color-success: var(--success);\n --color-success-foreground: var(--success-foreground);\n --color-warning: var(--warning);\n --color-warning-foreground: var(--warning-foreground);",
1,
)
if s2 == s {
return fmt.Errorf("could not find @theme anchor in main.css")
}
s3 := strings.Replace(s2,
"}\n\n.dark {",
" --success: oklch(0.6 0.15 145);\n --success-foreground: oklch(0.985 0 0);\n --warning: oklch(0.75 0.15 80);\n --warning-foreground: oklch(0.145 0 0);\n}\n\n.dark {",
1,
)
if s3 == s2 {
return fmt.Errorf("could not find :root close anchor in main.css")
}
s4 := strings.Replace(s3,
"}\n\n@layer base {",
" --success: oklch(0.65 0.15 145);\n --success-foreground: oklch(0.145 0 0);\n --warning: oklch(0.8 0.15 80);\n --warning-foreground: oklch(0.145 0 0);\n}\n\n@layer base {",
1,
)
if s4 == s3 {
return fmt.Errorf("could not find .dark close anchor in main.css")
}
return os.WriteFile(cssPath, []byte(s4), 0644)
}
func patchEslintConfig(projectDir string) error {
configPath := filepath.Join(projectDir, "eslint.config.ts")
content, err := os.ReadFile(configPath)
+2 -2
View File
@@ -9,8 +9,8 @@ import (
var rootCmd = &cobra.Command{
Use: "draft",
Short: "Draft is a CLI tool for bootstrapping Go APIs",
Long: `Draft is a CLI tool built by LKResuts for internal usage to bootstrap Go APIs`,
Short: "Draft is a CLI tool for bootstrapping Go APIs, clients, and monorepos",
Long: `Draft is a CLI tool built by LKResuts for internal usage to bootstrap Go APIs, Nuxt/Vue clients, and full-stack monorepos combining both`,
}
func Execute() {
+4 -3
View File
@@ -39,7 +39,7 @@ var jobs = []syncJob{
templateName: "client-nuxt",
sourceDir: "assets/testdata/template/apps/client",
targetDir: "assets/embedded/client-nuxt",
includePrefixes: []string{"app/", "public/"},
includePrefixes: []string{"app/", "public/", "Dockerfile"},
},
{
templateName: "client-vue",
@@ -52,11 +52,12 @@ var jobs = []syncJob{
"src/stores/",
"src/composables/",
"src/lib/api-client.ts",
"src/components/AppBrand.vue",
"src/components/AppLayout.vue",
"src/components/",
"src/views/",
"src/shared/",
".env.example",
"Dockerfile",
"nginx.conf.template",
},
},
}