Install
$ agentstack add skill-sabahattink-antigravity-fullstack-hq-docx-official ✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ✓ Network access No
- ● Filesystem access Used
- ✓ Shell / process execution No
- ✓ Environment & secrets No
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
Verified badge
Passed review? Show it. Paste this badge into your README, it links to the public security report.
Reliability & compatibility
Declared compatibility
Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.
We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.
How agent discovery & health will work →About
Generating Word Documents with docx
Installation
npm install docx
# or
pnpm add docx
Basic Document
import {
Document, Packer, Paragraph, TextRun,
HeadingLevel, AlignmentType, BorderStyle,
} from 'docx'
async function generateReport(data: ReportData): Promise {
const doc = new Document({
creator: 'Antigravity HQ',
title: data.title,
description: data.description,
styles: {
default: {
document: {
run: {
font: 'Calibri',
size: 24, // half-points (24 = 12pt)
color: '333333',
},
},
},
},
sections: [
{
properties: {},
children: [
new Paragraph({
text: data.title,
heading: HeadingLevel.HEADING_1,
spacing: { after: 200 },
}),
new Paragraph({
children: [
new TextRun({ text: 'Generated: ', bold: true }),
new TextRun({ text: new Date().toLocaleDateString() }),
],
spacing: { after: 400 },
}),
...data.paragraphs.map(text =>
new Paragraph({
text,
spacing: { after: 160 },
alignment: AlignmentType.JUSTIFIED,
})
),
],
},
],
})
return Packer.toBuffer(doc)
}
Tables
import { Table, TableRow, TableCell, WidthType, ShadingType } from 'docx'
function createDataTable(headers: string[], rows: string[][]): Table {
return new Table({
width: { size: 100, type: WidthType.PERCENTAGE },
rows: [
// Header row
new TableRow({
tableHeader: true,
children: headers.map(header =>
new TableCell({
shading: { type: ShadingType.SOLID, color: '2563EB' },
children: [
new Paragraph({
children: [new TextRun({ text: header, bold: true, color: 'FFFFFF' })],
}),
],
})
),
}),
// Data rows
...rows.map((row, rowIndex) =>
new TableRow({
children: row.map(cell =>
new TableCell({
shading: rowIndex % 2 === 0
? { type: ShadingType.SOLID, color: 'F8FAFC' }
: undefined,
children: [
new Paragraph({ text: cell }),
],
})
),
})
),
],
})
}
Headers & Footers
import { Header, Footer, PageNumber, NumberFormat } from 'docx'
const doc = new Document({
sections: [
{
properties: {
page: {
size: { width: 12240, height: 15840 }, // Letter size in twips
margin: { top: 1440, right: 1440, bottom: 1440, left: 1440 },
},
pageNumberStart: 1,
pageNumberFormatType: NumberFormat.DECIMAL,
},
headers: {
default: new Header({
children: [
new Paragraph({
children: [
new TextRun({ text: 'Antigravity HQ — Confidential', color: '6B7280', size: 18 }),
],
border: {
bottom: { style: BorderStyle.SINGLE, size: 1, color: 'E5E7EB' },
},
}),
],
}),
},
footers: {
default: new Footer({
children: [
new Paragraph({
children: [
new TextRun({ text: 'Page ' }),
new TextRun({ children: [PageNumber.CURRENT] }),
new TextRun({ text: ' of ' }),
new TextRun({ children: [PageNumber.TOTAL_PAGES] }),
],
alignment: AlignmentType.CENTER,
}),
],
}),
},
children: [/* document content */],
},
],
})
Lists
import { LevelFormat } from 'docx'
const doc = new Document({
numbering: {
config: [
{
reference: 'bullet-list',
levels: [
{
level: 0,
format: LevelFormat.BULLET,
text: '•',
alignment: AlignmentType.LEFT,
style: { paragraph: { indent: { left: 720, hanging: 360 } } },
},
],
},
{
reference: 'numbered-list',
levels: [
{
level: 0,
format: LevelFormat.DECIMAL,
text: '%1.',
alignment: AlignmentType.LEFT,
style: { paragraph: { indent: { left: 720, hanging: 360 } } },
},
],
},
],
},
sections: [
{
children: [
...[
'First item',
'Second item',
'Third item',
].map(text =>
new Paragraph({
text,
numbering: { reference: 'bullet-list', level: 0 },
})
),
],
},
],
})
Images
import { ImageRun } from 'docx'
import * as fs from 'fs'
const imageBuffer = fs.readFileSync('./logo.png')
const paragraph = new Paragraph({
children: [
new ImageRun({
data: imageBuffer,
transformation: {
width: 150,
height: 50,
},
}),
],
})
NestJS Service
// documents/documents.service.ts
@Injectable()
export class DocumentsService {
async generateInvoice(invoice: Invoice): Promise {
const doc = new Document({
sections: [
{
children: [
new Paragraph({ text: 'INVOICE', heading: HeadingLevel.HEADING_1 }),
new Paragraph({ text: `Invoice #${invoice.number}` }),
new Paragraph({ text: `Date: ${invoice.date.toLocaleDateString()}` }),
new Paragraph({ text: '' }),
createDataTable(
['Description', 'Qty', 'Unit Price', 'Total'],
invoice.items.map(item => [
item.description,
String(item.quantity),
`$${item.unitPrice.toFixed(2)}`,
`$${(item.quantity * item.unitPrice).toFixed(2)}`,
])
),
new Paragraph({ text: '' }),
new Paragraph({
children: [
new TextRun({ text: 'Total: ', bold: true }),
new TextRun({ text: `$${invoice.total.toFixed(2)}`, bold: true, size: 28 }),
],
alignment: AlignmentType.RIGHT,
}),
],
},
],
})
return Packer.toBuffer(doc)
}
}
// documents/documents.controller.ts
@Get('invoice/:id/download')
@UseGuards(JwtAuthGuard)
async downloadInvoice(
@Param('id') id: string,
@Res() res: Response,
) {
const invoice = await this.invoiceService.findOneOrFail(id)
const buffer = await this.documentsService.generateInvoice(invoice)
res.set({
'Content-Type': 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
'Content-Disposition': `attachment; filename="invoice-${invoice.number}.docx"`,
'Content-Length': buffer.length,
})
res.end(buffer)
}
Forbidden Patterns
- Never use
Packer.toBuffersynchronously and block the event loop on large documents — use async streaming for huge files - Never construct file paths from user input without sanitization
- Never trust user-provided content without sanitizing HTML/special characters
- Never include sensitive data (passwords, secrets) in generated documents
Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: sabahattink
- Source: sabahattink/antigravity-fullstack-hq
- License: MIT
- Homepage: https://github.com/sabahattink/antigravity-fullstack-hq
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet, be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.