or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

index.mdplugin-configuration.mdpwa-info-assets.mdvirtual-modules.md

pwa-info-assets.mddocs/

0

# PWA Information and Assets

1

2

Virtual modules providing access to PWA information, generated assets, and metadata for integrations and custom implementations.

3

4

## Capabilities

5

6

### PWA Information Module

7

8

Access to PWA configuration and runtime information.

9

10

```typescript { .api }

11

// Virtual module: virtual:pwa-info

12

/**

13

* PWA information object containing web manifest and service worker data

14

* Available only when PWA is enabled and not in SSR builds

15

*/

16

const pwaInfo: PwaInfo | undefined;

17

18

interface PwaInfo {

19

/** Whether PWA is running in development environment */

20

pwaInDevEnvironment: boolean;

21

/** Web manifest information - always present when pwaInfo is available */

22

webManifest: {

23

/** URL to the web manifest file */

24

href: string;

25

/** Whether to use credentials for manifest requests */

26

useCredentials: boolean;

27

/** Complete link tag for the web manifest */

28

linkTag: string;

29

};

30

/** Service worker registration information - conditionally present */

31

registerSW?: {

32

/** @deprecated Use mode instead */

33

inline: boolean;

34

/** Registration mode - inline script or external script */

35

mode: 'inline' | 'script' | 'script-defer';

36

/** Path for inline service worker registration script */

37

inlinePath: string;

38

/** Path for external service worker registration script */

39

registerPath: string;

40

/** Service worker scope */

41

scope: string;

42

/** Service worker type */

43

type: 'classic' | 'module';

44

/** Complete script tag for service worker registration */

45

scriptTag?: string;

46

};

47

}

48

```

49

50

**Usage Example:**

51

52

```typescript

53

import { pwaInfo } from "virtual:pwa-info";

54

55

// Use in framework integrations or custom implementations

56

if (pwaInfo) {

57

console.log("PWA is enabled");

58

console.log("Manifest URL:", pwaInfo.webManifest.href);

59

60

// Add manifest link to head

61

document.head.insertAdjacentHTML("beforeend", pwaInfo.webManifest.linkTag);

62

63

// Handle service worker registration

64

if (pwaInfo.registerSW && pwaInfo.registerSW.scriptTag) {

65

document.head.insertAdjacentHTML("beforeend", pwaInfo.registerSW.scriptTag);

66

}

67

} else {

68

console.log("PWA is disabled or in SSR mode");

69

}

70

71

// Framework integration example

72

function usePWAInfo() {

73

return {

74

isPWAEnabled: !!pwaInfo,

75

isDevEnvironment: pwaInfo?.pwaInDevEnvironment ?? false,

76

manifestUrl: pwaInfo?.webManifest.href,

77

hasServiceWorker: !!pwaInfo?.registerSW,

78

};

79

}

80

```

81

82

### PWA Assets Head Module

83

84

Access to generated PWA assets for HTML head injection.

85

86

```typescript { .api }

87

// Virtual module: virtual:pwa-assets/head

88

/**

89

* PWA assets head configuration with links and theme color

90

* Available when PWA assets generation is enabled

91

*/

92

const pwaAssetsHead: PWAAssetsHead;

93

94

interface PWAAssetsHead {

95

/** Array of head link elements for PWA assets */

96

links: PWAAssetHeadLink[];

97

/** Theme color meta tag configuration */

98

themeColor?: ColorSchemeMeta;

99

}

100

101

interface PWAAssetHeadLink {

102

/** Optional link ID for targeting */

103

id?: string;

104

/** Link relationship type */

105

rel: 'apple-touch-startup-image' | 'apple-touch-icon' | 'icon';

106

/** Asset URL */

107

href: string;

108

/** Media query for responsive assets */

109

media?: string;

110

/** Icon sizes specification */

111

sizes?: string;

112

/** MIME type of the asset */

113

type?: string;

114

}

115

116

interface ColorSchemeMeta {

117

/** Meta tag name attribute */

118

name: string;

119

/** Meta tag content attribute */

120

content: string;

121

}

122

```

123

124

**Usage Example:**

125

126

```typescript

127

import { pwaAssetsHead } from "virtual:pwa-assets/head";

128

129

// Inject PWA assets into HTML head

130

function injectPWAAssets() {

131

const head = document.head;

132

133

// Inject icon and splash screen links

134

pwaAssetsHead.links.forEach((link) => {

135

const linkElement = document.createElement("link");

136

linkElement.rel = link.rel;

137

linkElement.href = link.href;

138

139

if (link.id) linkElement.id = link.id;

140

if (link.sizes) linkElement.setAttribute("sizes", link.sizes);

141

if (link.type) linkElement.type = link.type;

142

if (link.media) linkElement.media = link.media;

143

144

head.appendChild(linkElement);

145

});

146

147

// Inject theme color meta tag

148

if (pwaAssetsHead.themeColor) {

149

const metaElement = document.createElement("meta");

150

metaElement.name = pwaAssetsHead.themeColor.name;

151

metaElement.content = pwaAssetsHead.themeColor.content;

152

head.appendChild(metaElement);

153

}

154

}

155

156

// Framework integration example (React)

157

function PWAHeadAssets() {

158

return (

159

<>

160

{pwaAssetsHead.links.map((link, index) => (

161

<link

162

key={link.id || index}

163

rel={link.rel}

164

href={link.href}

165

{...(link.sizes && { sizes: link.sizes })}

166

{...(link.type && { type: link.type })}

167

{...(link.media && { media: link.media })}

168

/>

169

))}

170

{pwaAssetsHead.themeColor && (

171

<meta

172

name={pwaAssetsHead.themeColor.name}

173

content={pwaAssetsHead.themeColor.content}

174

/>

175

)}

176

</>

177

);

178

}

179

```

180

181

### PWA Assets Icons Module

182

183

Access to generated PWA icon assets organized by type and purpose.

184

185

```typescript { .api }

186

// Virtual module: virtual:pwa-assets/icons

187

/**

188

* PWA assets icons collection organized by type

189

* Available when PWA assets generation is enabled

190

*/

191

const pwaAssetsIcons: PWAAssetsIcons;

192

193

interface PWAAssetsIcons {

194

/** Favicon icons for browser tabs */

195

favicon: Record<string, PWAAssetIcon<FaviconLink>>;

196

/** Transparent background icons */

197

transparent: Record<string, PWAAssetIcon<HtmlLink>>;

198

/** Maskable icons for adaptive icon support */

199

maskable: Record<string, PWAAssetIcon<HtmlLink>>;

200

/** Apple-specific touch icons */

201

apple: Record<string, PWAAssetIcon<HtmlLink>>;

202

/** Apple splash screen images */

203

appleSplashScreen: Record<string, PWAAssetIcon<AppleSplashScreenLink>>;

204

}

205

206

type PWAAssetIcon<T extends HtmlLink> = Omit<IconAsset<T>, 'buffer'>;

207

208

interface IconAsset<T extends HtmlLink> {

209

/** Asset name/identifier */

210

name: string;

211

/** Asset file path */

212

src: string;

213

/** Icon dimensions */

214

size: { width: number; height: number };

215

/** HTML link configuration */

216

htmlLink: T;

217

}

218

219

interface HtmlLink {

220

rel: string;

221

href: string;

222

sizes?: string;

223

type?: string;

224

}

225

226

interface FaviconLink extends HtmlLink {

227

rel: 'icon';

228

}

229

230

interface AppleSplashScreenLink extends HtmlLink {

231

rel: 'apple-touch-startup-image';

232

media: string;

233

}

234

```

235

236

**Usage Example:**

237

238

```typescript

239

import { pwaAssetsIcons } from "virtual:pwa-assets/icons";

240

241

// Access different icon types

242

function logIconAssets() {

243

console.log("Favicon icons:", Object.keys(pwaAssetsIcons.favicon));

244

console.log("Transparent icons:", Object.keys(pwaAssetsIcons.transparent));

245

console.log("Maskable icons:", Object.keys(pwaAssetsIcons.maskable));

246

console.log("Apple icons:", Object.keys(pwaAssetsIcons.apple));

247

console.log("Apple splash screens:", Object.keys(pwaAssetsIcons.appleSplashScreen));

248

}

249

250

// Create manifest icons from generated assets

251

function createManifestIcons() {

252

const icons = [];

253

254

// Add transparent icons to manifest

255

Object.values(pwaAssetsIcons.transparent).forEach((icon) => {

256

icons.push({

257

src: icon.src,

258

sizes: `${icon.size.width}x${icon.size.height}`,

259

type: icon.htmlLink.type || "image/png",

260

purpose: "any",

261

});

262

});

263

264

// Add maskable icons to manifest

265

Object.values(pwaAssetsIcons.maskable).forEach((icon) => {

266

icons.push({

267

src: icon.src,

268

sizes: `${icon.size.width}x${icon.size.height}`,

269

type: icon.htmlLink.type || "image/png",

270

purpose: "maskable",

271

});

272

});

273

274

return icons;

275

}

276

277

// Framework integration example (Vue)

278

function usePWAIcons() {

279

return {

280

favicon: computed(() => pwaAssetsIcons.favicon),

281

transparent: computed(() => pwaAssetsIcons.transparent),

282

maskable: computed(() => pwaAssetsIcons.maskable),

283

apple: computed(() => pwaAssetsIcons.apple),

284

appleSplashScreen: computed(() => pwaAssetsIcons.appleSplashScreen),

285

286

// Helper to get icon by size

287

getIconBySize: (type: keyof PWAAssetsIcons, size: string) => {

288

const icons = pwaAssetsIcons[type];

289

return Object.values(icons).find(

290

(icon) => `${icon.size.width}x${icon.size.height}` === size

291

);

292

},

293

294

// Helper to create HTML links

295

createHtmlLinks: (type: keyof PWAAssetsIcons) => {

296

return Object.values(pwaAssetsIcons[type]).map((icon) => icon.htmlLink);

297

},

298

};

299

}

300

```

301

302

## Integration Patterns

303

304

### Server-Side Rendering (SSR)

305

306

Handle PWA info and assets in SSR environments:

307

308

```typescript

309

// Check availability before use

310

function getSSRPWAInfo() {

311

try {

312

const info = pwaInfo;

313

return info || null;

314

} catch {

315

// Module not available in SSR

316

return null;

317

}

318

}

319

320

// Conditional asset injection

321

function injectPWAAssetsSSR() {

322

try {

323

const assets = pwaAssetsHead;

324

return assets.links.map(link =>

325

`<link rel="${link.rel}" href="${link.href}"${

326

link.sizes ? ` sizes="${link.sizes}"` : ''

327

}${link.type ? ` type="${link.type}"` : ''}${

328

link.media ? ` media="${link.media}"` : ''

329

}>`

330

).join('\n');

331

} catch {

332

return '';

333

}

334

}

335

```

336

337

### Meta Framework Integration

338

339

Integration patterns for popular meta-frameworks:

340

341

```typescript

342

// Next.js Head component integration

343

import Head from "next/head";

344

import { pwaAssetsHead } from "virtual:pwa-assets/head";

345

346

function PWAHead() {

347

return (

348

<Head>

349

{pwaAssetsHead.links.map((link, index) => (

350

<link

351

key={index}

352

rel={link.rel}

353

href={link.href}

354

sizes={link.sizes}

355

type={link.type}

356

media={link.media}

357

/>

358

))}

359

{pwaAssetsHead.themeColor && (

360

<meta

361

name={pwaAssetsHead.themeColor.name}

362

content={pwaAssetsHead.themeColor.content}

363

/>

364

)}

365

</Head>

366

);

367

}

368

369

// Nuxt.js useHead integration

370

import { useHead } from "@vueuse/head";

371

import { pwaAssetsHead } from "virtual:pwa-assets/head";

372

373

function usePWAHead() {

374

useHead({

375

link: pwaAssetsHead.links,

376

meta: pwaAssetsHead.themeColor ? [pwaAssetsHead.themeColor] : [],

377

});

378

}

379

```

380

381

### Dynamic Asset Loading

382

383

Load PWA assets dynamically based on conditions:

384

385

```typescript

386

import { pwaAssetsIcons } from "virtual:pwa-assets/icons";

387

388

async function loadOptimalIcon(preferredSize = "192x192") {

389

// Try to find icon with preferred size

390

const transparent = Object.values(pwaAssetsIcons.transparent);

391

let icon = transparent.find(

392

(icon) => `${icon.size.width}x${icon.size.height}` === preferredSize

393

);

394

395

// Fall back to first available icon

396

if (!icon && transparent.length > 0) {

397

icon = transparent[0];

398

}

399

400

if (icon) {

401

// Preload the icon

402

const link = document.createElement("link");

403

link.rel = "preload";

404

link.as = "image";

405

link.href = icon.src;

406

document.head.appendChild(link);

407

408

return icon;

409

}

410

411

return null;

412

}

413

```