# Render a post above the discovery-list-container-top Outlet

**URL:** https://meta.discourse.org/t/render-a-post-above-the-discovery-list-container-top-outlet/394270
**Category:** Development
**Created:** [January 24, 2026, 11:52pm UTC](https://meta.discourse.org/t/render-a-post-above-the-discovery-list-container-top-outlet/394270 "2026-01-24T23:52:57Z")
**Posts on this page:** 9
**Page:** 1

<div class="post-metadata">

### Author: ![Andrew\_Rowe](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/andrew_rowe/32/445877_2.png) [@Andrew\_Rowe](https://meta.discourse.org/u/Andrew_Rowe)
#### Post date: [January 24, 2026, 11:52pm UTC](https://meta.discourse.org/t/render-a-post-above-the-discovery-list-container-top-outlet/394270/1 "2026-01-24T23:52:57Z")

</div>

I’m a noob at this sorry

I used ask discourse to ask:

in a theme i want to render the first post from two topics above the topic list in the discovery-list-container-top Outlet

it gave me several versions which to my eyes looked like it should work. All are throwing an error in the preview. I ask discourse:

how would I put the sample code in the JS tab instead of files?

it gave me this version

```plaintext
import { apiInitializer } from "discourse/lib/api";
import Component from "@glimmer/component";
import { tracked } from "@glimmer/tracking";

class FirstPosts extends Component {
  @tracked posts = [];

  constructor() {
    super(...arguments);
    this.loadPosts();
  }

  async loadPosts() {
    let topicIds = [123, 456]; // change to your topic IDs
    let posts = [];
    for (let id of topicIds) {
      let res = await fetch(`/t/${id}.json`);
      let data = await res.json();
      if (data.post_stream && data.post_stream.posts.length > 0) {
        posts.push(data.post_stream.posts[0]);
      }
    }
    this.posts = posts;
  }

  static template = <template>
    {{#each this.posts as |post|}}
      <div class="first-post-preview">
        <h4>{{post.topic_title}}</h4>
        {{{post.cooked}}}
      </div>
    {{/each}}
  </template>;
}

export default apiInitializer("0.11.1", api => {
  api.renderInOutlet("discovery-list-container-top", FirstPosts);
});

```

and when I pasted the error code into ask discourse it gave me this version

```plaintext
import { apiInitializer } from "discourse/lib/api";

// Global data store (hacky, but works for the JS tab)
window.firstPostsData = [];

fetch("/t/123.json")
  .then(r => r.json())
  .then(data => window.firstPostsData.push(data.post_stream.posts[0]));

fetch("/t/456.json")
  .then(r => r.json())
  .then(data => window.firstPostsData.push(data.post_stream.posts[0]));

export default apiInitializer(api => {
  api.renderInOutlet("discovery-list-container-top", 
    <template>
      {{#each (theme-prefix "firstPostsData" window=true) as |post|}}
        <div class="first-post-preview">
          <h4>{{post.topic_title}}</h4>
          {{{post.cooked}}}
        </div>
      {{/each}}
    </template>
  );
});

```

Can someone tell me what I’m doing wrong?

the error in the console was:

Compile error: SyntaxError: /theme-4/discourse/api-initializers/theme-initializer.gjs:

this is what showed in the preview

 ![image](https://global.discourse-cdn.com/meta/original/4X/0/0/4/004681f1fb968aaed1341e931f094c9f02bc795d.png)

Thank you

---

<div class="post-metadata">

### Author: ![NateDhaliwal](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/natedhaliwal/32/313494_2.png) [@NateDhaliwal](https://meta.discourse.org/u/NateDhaliwal)
#### Post date: [January 25, 2026, 1:05am UTC](https://meta.discourse.org/t/render-a-post-above-the-discovery-list-container-top-outlet/394270/2 "2026-01-25T01:05:58Z")

</div>

I’ve tweaked it and this seems to work:

```gjs
import Component from "@glimmer/component";
import { tracked } from "@glimmer/tracking";
import { htmlSafe } from "@ember/template";
import { ajax } from "discourse/lib/ajax";
import { apiInitializer } from "discourse/lib/api";

class FirstPosts extends Component {
  @tracked posts = [];

  constructor() {
    super(...arguments);
    this.loadPosts();
  }

  async loadPosts() {
    let topicIds = [123, 1807]; // change to your topic IDs
    let posts = [];
    for (constid of topicIds) {
      const data = await ajax(`/t/${id}.json`);
      if (data.post_stream && data.post_stream.posts.length > 0) {
        posts.push(data.post_stream.posts[0]);
      }
    }
    this.posts = posts;
  }

  <template>
    {{#each this.posts as |post|}}
      <div class="first-post-preview">
        <h4>{{post.topic_title}}</h4>
        {{htmlSafe post.cooked}}
      </div>
    {{/each}}
  </template>;
}

export default apiInitializer((api) => {
  api.renderInOutlet("discovery-list-container-top", FirstPosts);
});

```

 ![image](https://global.discourse-cdn.com/meta/original/4X/b/f/d/bfd58833943a69f287ef67a2a1892607d06c2cff.jpeg)

EDIT: Now using `ajax()` and `htmlSafe` instead of triple curly braces.

---

<div class="post-metadata">

### Author: ![Andrew\_Rowe](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/andrew_rowe/32/445877_2.png) [@Andrew\_Rowe](https://meta.discourse.org/u/Andrew_Rowe)
#### Post date: [January 25, 2026, 1:25am UTC](https://meta.discourse.org/t/render-a-post-above-the-discovery-list-container-top-outlet/394270/3 "2026-01-25T01:25:17Z")

</div>

Thank you Nate! I’m trying to figure out what you changed

Your code seems to match my first version

You have replaced let with const in the for loop

is that correct?

ask discourse version throws error

```plaintext
for (let id of topicIds) {
      let res = await fetch(`/t/${id}.json`);
      let data = await res.json();
      if (data.post_stream && data.post_stream.posts.length > 0) {
        posts.push(data.post_stream.posts[0]);
      }
    }

```

Nate’s version runs

```plaintext
for (let id of topicIds) {
      const res = await fetch(`/t/${id}.json`);
      const data = await res.json();
      if (data.post_stream && data.post_stream.posts.length > 0) {
        posts.push(data.post_stream.posts[0]);
      }
    }

```

Can anyone explain what is wrong? Why Let wouldn’t work and const does?

Thanks again Nate

---

<div class="post-metadata">

### Author: ![NateDhaliwal](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/natedhaliwal/32/313494_2.png) [@NateDhaliwal](https://meta.discourse.org/u/NateDhaliwal)
#### Post date: [January 25, 2026, 1:30am UTC](https://meta.discourse.org/t/render-a-post-above-the-discovery-list-container-top-outlet/394270/4 "2026-01-25T01:30:28Z")

</div>

I tried `let` and the result was the same. It’s just that I’d normally use `const` when using `fetch()` or `ajax()`.

I believe the error comes from the `static template = ` line. With it, I get:

```plaintext
[THEME 10283 'Pokemon Theme'] Error: connector component has no associated template. Ensure the template is colocated or authored with gjs.
    at h (plugin-connectors.js:35:11)
    at eY.renderInOutlet (plugin-api.gjs:1116:5)
    at todo.gjs:43:7
    at eH (plugin-api.gjs:3363:10)
    at Object.initialize (api.js:21:14)
    at i.initialize (app.js:265:28)
    at index.js:379:19
    at e.each (index.js:183:7)
    at e.walk (index.js:112:10)
    at e.each (index.js:59:20)
    at e.topsort (index.js:65:10)
    at iL._runInitializer (index.js:392:11)
    at iL.runInstanceInitializers (index.js:377:10)
    at l._bootSync (instance.js:116:22)
    at iL.didBecomeReady (index.js:784:18)
    at invoke (index.js:262:14)
    at m.flush (index.js:180:11)
    at g.flush (index.js:334:19)
    at z._end (index.js:762:32)
    at _boundAutorunEnd (index.js:499:12)

```

And if I just use `<template>` directly, there’s no error. I don’t think using `static template` is valid here, so just using the template tag directly works.

---

<div class="post-metadata">

### Author: ![Andrew\_Rowe](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/andrew_rowe/32/445877_2.png) [@Andrew\_Rowe](https://meta.discourse.org/u/Andrew_Rowe)
#### Post date: [January 25, 2026, 4:10pm UTC](https://meta.discourse.org/t/render-a-post-above-the-discovery-list-container-top-outlet/394270/5 "2026-01-25T16:10:30Z")

</div>

I foolishly deleted the version I was testing and now I can’t get Nate’s most recent version to run

```plaintext
theme-initializer.gjs:18 Uncaught (in promise) ReferenceError: constid is not defined
    at n.loadPosts (theme-initializer.gjs:18:10)
    at new n (theme-initializer.gjs:12:10)
    at h.createComponent (index.js:259:12)
    at $.create (index.js:419:28)
    at Object.evaluate (index.js:985:23)
    at Object.evaluate (index.js:103:106)
    at tr.evaluateSyscall (index.js:2873:20)
    at tr.evaluateInner (index.js:2852:64)
    at tr.evaluateOuter (index.js:2849:10)
    at tH.next (index.js:4167:45)
    at tH._execute (index.js:4157:21)
    at tH.execute (index.js:4133:41)
    at tq.sync (index.js:4194:120)
    at tz.render (index-BCp6wOJU.js:4636:43)
    at index-BCp6wOJU.js:4934:16
    at eX (index.js:2414:7)
    at tG._renderRoots (index-BCp6wOJU.js:4914:7)
    at tG._renderRootsTransaction (index-BCp6wOJU.js:4962:12)
    at tG._renderRoot (index-BCp6wOJU.js:4904:10)
    at tG._appendDefinition (index-BCp6wOJU.js:4828:10)
    at tG.appendOutletView (index-BCp6wOJU.js:4818:10)
    at invoke (index.js:264:14)
    at m.flush (index.js:180:11)
    at g.flush (index.js:334:19)
    at z._end (index.js:762:32)
    at _boundAutorunEnd (index.js:499:12)

```

this very first version is the only one I can get to run

```plaintext
import { apiInitializer } from "discourse/lib/api";
import Component from "@glimmer/component";
import { tracked } from "@glimmer/tracking";

class FirstPosts extends Component {
  @tracked posts = [];

  constructor() {
    super(...arguments);
    this.loadPosts();
  }

  async loadPosts() {
    let topicIds = [98, 239]; // change to your topic IDs
    let posts = [];
    for (let id of topicIds) {
      const res = await fetch(`/t/${id}.json`);
      const data = await res.json();
      if (data.post_stream && data.post_stream.posts.length > 0) {
        posts.push(data.post_stream.posts[0]);
      }
    }
    this.posts = posts;
  }

  <template>
    {{#each this.posts as |post|}}
      <div class="first-post-preview">
        <h4>{{post.topic_title}}</h4>
        {{{post.cooked}}}
      </div>
    {{/each}}
  </template>;
}

export default apiInitializer((api) => {
  api.renderInOutlet("above-main-container", FirstPosts);
});

```

I am trying to use the theme JS tab to do this

maybe I should switch to a theme on gitthub, is that where my limitation is?

---

<div class="post-metadata">

### Author: ![merefield](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/merefield/32/176214_2.png) [@merefield](https://meta.discourse.org/u/merefield)
#### Post date: [January 25, 2026, 6:58pm UTC](https://meta.discourse.org/t/render-a-post-above-the-discovery-list-container-top-outlet/394270/6 "2026-01-25T18:58:14Z")

</div>

> [@NateDhaliwal](#):
>
> I tried `let` and the result was the same. It’s just that I’d normally use `const` when using `fetch()` or `ajax()`.

Yes, let and const are effectively identical here so that’s not the issue.

---

<div class="post-metadata">

### Author: ![merefield](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/merefield/32/176214_2.png) [@merefield](https://meta.discourse.org/u/merefield)
#### Post date: [January 25, 2026, 7:04pm UTC](https://meta.discourse.org/t/render-a-post-above-the-discovery-list-container-top-outlet/394270/7 "2026-01-25T19:04:01Z")

</div>

I believe (in theme components and plugins) you can only include templates with that syntax in a standalone .gjs file as that suffix flags the interpreter to pre-compile it. Not sure how that affects the inbuilt online theme system.

Moving to GitHub is in any case a very good idea.

---

<div class="post-metadata">

### Author: ![Andrew\_Rowe](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/andrew_rowe/32/445877_2.png) [@Andrew\_Rowe](https://meta.discourse.org/u/Andrew_Rowe)
#### Post date: [January 25, 2026, 7:11pm UTC](https://meta.discourse.org/t/render-a-post-above-the-discovery-list-container-top-outlet/394270/8 "2026-01-25T19:11:02Z")

</div>

> [@merefield](#):
>
> Moving to GitHub is in any case a very good idea.

Thank you for that advice, I am trying to do that now. Getting as far as I have has given me encouragement. Nate’s code above actually runs and puts the two topics on top. I will start a new topic with my theme idea and try to document what I learn. [ask.discourse.org](http://ask.discourse.org) is absolutely amazing!

---

<div class="post-metadata">

### Author: ![system](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/system/32/443519_2.png) [@system](https://meta.discourse.org/u/system)
#### Post date: [February 24, 2026, 7:11pm UTC](https://meta.discourse.org/t/render-a-post-above-the-discovery-list-container-top-outlet/394270/9 "2026-02-24T19:11:09Z")

</div>

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.
