
Research
2025 Report: Destructive Malware in Open Source Packages
Destructive malware is rising across open source registries, using delays and kill switches to wipe code, break builds, and disrupt CI/CD.
@lightningrodlabs/attachments
Advanced tools
This package contains the interfaces and contracts that a UI module needs to implement in order to become a We Applet.
This package contains the interfaces and contracts that a UI module needs to implement in order to become a We Applet.
We applets don't have an index.html file as their entrypoint, but an index.js. This index.js must have a default export that implements the interface defined by the WeApplet type.
To implement the UI for your applet, import the WeApplet type from @lightningrodlabs/we-applet, create an object that implements it, and have that be the default export in your file:
index.ts.
import { DnaHash, EntryHash, AppAgentClient } from "@holochain/client";
import { WeApplet, GroupServices, WeServices, Hrl } from "@lightningrodlabs/we-applet";
function groupViews(
client: AppAgentClient, // The client for this applet, already set up
groupId: DnaHash, // The group id that this applet is installed in, usually used when opening views
appletId: EntryHash, // The applet instance id, usually used when opening views
groupServices: GroupServices, // The services that this group offers, like the group's profile or the ProfilesClient for the agents
weServices: WeServices // The services that "we" offers to this applet, to enable attachments, open views, search...
): GroupViews {
return {
main: (element: HTMLElement) => element.innerHTML = "<span>This is the main view for this applet, which is going to be opened when the user clicks on the applet's icon</span>",
blocks: {
my_block: (element: HTMLElement) => element.innerHTML = '<span>This is a block view for this applet, which can be opened from the main view</span>'
},
entries: {
my_role_name: {
my_integrity_zome_name: {
my_entry_type_name: {
view(element, hrl, context) {
const myEntry = await client.callZome({
cell_id: [hrl[0], client.myPubKey],
payload: hrl[1],
/** TODO: call the appropriate zome function in your app */
});
element.innerHTML = `<span>The title of this entry is ${myEntry.title}</span>`
},
async info(hrl: Hrl) { // The HRL is a [DnaHash, ActionHash | EntryHash] pair, identifying the entry to retrieve
const myEntry = await client.callZome({
cell_id: [hrl[0], client.myPubKey],
payload: hrl[1],
/** TODO: call the appropriate zome function in your app */
});
if (!myEntry) return undefined;
return {
name: myEntry.title,
icon_src: /** Here you can use a SVG, maybe from the @mdi/js package */
}
},
}
}
}
}
}
}
const applet: WeApplet = {
groupViews,
crossGroupViews: (
appletsByGroup: ReadonlyMap<DnaHash, GroupWithApplets>, // Segmented by groupId
weServices: WeServices
) {
return {
main: element => {},
blocks: {}
}
},
attachmentTypes: async client => ({}),
search: async () => [],
};
export default applet;
Use rollup to build a fully bundled javascript file that doesn't have any external imports.
This is an example configuration for it:
rollup.config.js
import nodeResolve from "@rollup/plugin-node-resolve";
import commonjs from "@rollup/plugin-commonjs";
import typescript from "@rollup/plugin-typescript";
import babel from "@rollup/plugin-babel";
import { terser } from "rollup-plugin-terser";
export default {
input: "src/index.ts", // This needs to be pointing to the file that has the `WeApplet` default export
output: {
format: "es",
dir: 'dist',
},
watch: {
clearScreen: false,
},
plugins: [
/** Resolve bare module imports */
nodeResolve({
browser: true,
preferBuiltins: false,
}),
commonjs({}),
typescript(),
/** Minify JS */
terser(),
/** Compile JS to a lower language target */
babel({
exclude: /node_modules/,
babelHelpers: "bundled",
presets: [
[
require.resolve("@babel/preset-env"),
{
targets: [
"last 3 Chrome major versions",
"last 3 Firefox major versions",
"last 3 Edge major versions",
"last 3 Safari major versions",
],
modules: false,
bugfixes: true,
},
],
],
}),
],
};
Now you have it! You can use the generated .js file as a We Applet UI file.
FAQs
This package contains store and elements for implementing UI for attachments in a We Applet based on the official attachments zome.
We found that @lightningrodlabs/attachments demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 5 open source maintainers collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Research
Destructive malware is rising across open source registries, using delays and kill switches to wipe code, break builds, and disrupt CI/CD.

Security News
Socket CTO Ahmad Nassri shares practical AI coding techniques, tools, and team workflows, plus what still feels noisy and why shipping remains human-led.

Research
/Security News
A five-month operation turned 27 npm packages into durable hosting for browser-run lures that mimic document-sharing portals and Microsoft sign-in, targeting 25 organizations across manufacturing, industrial automation, plastics, and healthcare for credential theft.