On this page
1 — Install 2 — Write a component 3 — Create an engine 4 — Render with props 5 — Use slots Component system Go API reference How-to guidesTutorial
Build your first htmlc component from scratch. This walkthrough takes you from installation to rendering a component with props and slots in about five minutes.
Step 1 — Install htmlc
Add the package to your Go module:
go get github.com/dhamidi/htmlc
The CLI is optional but handy for testing components without writing Go code:
go install github.com/dhamidi/htmlc/cmd/htmlc@latest
Step 2 — Write a component
Create a directory called components/ and add a file named Card.vue:
<!-- components/Card.vue --> <template> <div class="card"> <h2>{{ title }}</h2> <slot>No content provided.</slot> </div> </template> <style scoped> .card { border: 1px solid #ccc; border-radius: 8px; padding: 1rem; } </style>
The {{ title }} interpolation reads the title prop. The <slot> element is a placeholder for content supplied by a parent component; its children are the fallback rendered when no content is provided.
Step 3 — Create an engine
Call htmlc.New with the directory that contains your .vue files. The engine discovers and registers every component automatically.
package main import ( "log" "github.com/dhamidi/htmlc" ) func main() { engine, err := htmlc.New(htmlc.Options{ ComponentDir: "./components", }) if err != nil { log.Fatal(err) } _ = engine }
Step 4 — Render with props
Call RenderFragmentString to render a component to a string. Pass props as a map[string]any.
html, err := engine.RenderFragmentString("Card", map[string]any{ "title": "Hello, htmlc!", }) if err != nil { log.Fatal(err) } fmt.Println(html)
Expected output (style block prepended by the engine):
<style> .card[data-v-…]{border:1px solid #ccc;border-radius:8px;padding:1rem} </style> <div class="card" data-v-…> <h2>Hello, htmlc!</h2> No content provided. </div>
The fallback text "No content provided." is rendered because no slot content was passed. Step 5 shows how to supply it.
Step 5 — Use slots
Slot content is supplied through component composition in a .vue template. There is no $slots key in the Go props map; htmlc does not support injecting raw HTML into slots via the data map.
Create a wrapper component that uses Card with slot content:
<!-- components/WelcomeCard.vue --> <template> <Card title="Welcome"> <p>This paragraph is rendered inside the Card's slot.</p> </Card> </template>
Then render the wrapper from Go:
html, err := engine.RenderFragmentString("WelcomeCard", nil) if err != nil { log.Fatal(err) } fmt.Println(html)
Expected output:
<div class="card" data-v-…> <h2>Welcome</h2> <p>This paragraph is rendered inside the Card's slot.</p> </div>
The same pattern applies to named and scoped slots — the parent component uses <template #name> syntax in the .vue file to target specific slots. See the component system reference for named and scoped slot examples.
Dynamic slot content from Go
If you need to inject a dynamic HTML string into a component from Go, use a regular prop with v-html instead of a slot:
<!-- components/Card.vue --> <div class="card"> <h2>{{ title }}</h2> <div v-html="body"></div> </div>
html, err := engine.RenderFragmentString("Card", map[string]any{ "title": "Hello", "body": "<p>Dynamic content from Go</p>", })