Contribute to Open Source. Search issue labels to find the right project for you!

Change buttons that are nested in anchor tags


W3C states that:

The a element may be wrapped around entire paragraphs, lists, tables, and so forth, even entire sections, so long as there is no interactive content within (e.g. buttons or other links).

What is more, this causes double-focus problems (such as in #4894).

Several files make use of invalid HTML, with a button nested inside an a tag: * account-settings.handlebars * display-settings.handlebars * apps.html * compose.html * hello.html

I will be using an approach similar to this commit, replacing the anchor with a form element.

Updated 15/08/2017 20:13 2 Comments

emoji picker: Show name of emoji in emoji picker.


It would be great to have the name of the emoji appear somewhere (other than the title text) when you hover or move the selector box over it. Currently I find myself hovering over the emoji, waiting for the title text, and it also makes it feel less usable from the keyboard.

I’m not sure I quite like how Slack does it, but it has one example of what it could mean to show the name of the emoji on hover.

Updated 18/08/2017 00:57 6 Comments

onboarding: Make welcome-bot a real bot.


Currently, welcome bot sends you an onboarding message, that asks you to reply, so that users can test out the replying process. It would be great if welcome-bot could then reply back!

The first step is to write a welcome-bot that just replies with a fixed message, like :tada: I'm out for now, but enjoy the rest of your Zulip experience! the first time you send it a message, and then nothing forever after. It can store the “has replied to user” bit in the UserHotspot table, using a hotspot named something like “reply_to_welcome_bot”.

Updated 17/08/2017 17:02 4 Comments

dev tooling: Make streams and initial messages more like production.


The pseudo-code for setting up a realm in production is realm = do_create_realm(..) setup_initial_streams(realm) user = do_create_user(..) # the admin, e.g. Iago setup_initial_private_stream(user) send_initial_pms(user) send_initial_realm_messages(realm)

The task is basically to replace the creation of zulip_realm and possibly also mit_realm in with code like above.

It will also require some changes to how the admin user is created, and then changes later on down the file in terms of stream creation and other things. Though we also don’t need to keep any of the stream_list or zulip_stream_dict streams, if that simplifies things.

Updated 05/08/2017 06:47 1 Comments

dev tooling: Add "create new user" and "create new realm" buttons to /devlogin.


We’re about to make a lot of improvements to the onboarding process, and for testing (and user testing) it would be useful to have buttons on /devlogin that just create a new accounts/realms with random or semi-random data, and dump you into the start of the onboarding flow.

I might call the endpoints /register_realm and /register_user (they go in, and put the view code at the bottom of views/

Pseudocode for the register_realm view might be something like: ```

Only used in development environment

def register_development_realm: randomly generate an email prereg_user = create_preregistration_user(email, request, True) activation_url = create_confirmation_link(prereg_user, request.get_host(), Confirmation.USER_REGISTRATION) confirmation_key = activation_url.split(‘/’)[-1] create a request with the right stuff, and the form elements prefilled with random data return accounts_register(request) ```

The register_user user should be registered to the ‘zulip’ realm (and might need a email address).

The two links will also need to be added to /devtools.

Updated 04/08/2017 06:43 1 Comments

recent_sender: Also sort by stream or overall message recency as tiebreaks


Our recent_sender typeahead is good for mentioning people active in the current topic, but I think we could do a lot better with realms with many thousands of users by also applying weight to users who send a lot of messages in the stream or organization as further tiebreaks. I added a comment on this issue in e729814cfde23686bf7085ef463963a0820cf2b9 in the place where we’d want to do the check; presumably the data collection would go in the other function in the file.

@akhilmd @cory2067 you may be interested in working on this.

Updated 28/07/2017 18:04 1 Comments

org settings: Add realm setting to allow users to edit topics.


Discussion at quote I'm trying to think of what could help with the problem of "no topic discipline in the first few weeks of trying out the app -> bad experience with zulip". Allowing anyone to edit topics at the beginning would allow any one person who's rooting for zulip to save the whole org.

A potential name for the setting in the Realm object might be edit_topics_by_admins_only. The setting should be False by default, though all past orgs should be migrated in as True.

In the settings UI, I would put it under Organization Permissions, and call it “Users can edit the topic of any message”. It should be a sub-permission of “Users can edit their messages”, after the “Message edit limit in seconds” setting, and only be checkable if “Users can edit their messages” is true.

Much of the work should be similar to

Updated 14/08/2017 17:05 5 Comments

hotkeys: Add Alt+up and Alt+down for previous/next unread topic.


Alt+down should do the same thing as n (next unread topic), and Alt+up should go to the previous unread topic.

Full discussion at, but some highlights are: * Using Alt+down solves the problem of accidentally typing ‘n’ when you have an open compose box * Other messaging apps have an Alt+up and Alt+down, which makes these super discoverable * They nicely couple with Alt+left for going back (when you overshoot)

Updated 26/07/2017 01:53 3 Comments

registration: Store full_name in PreregistrationUser if we know it.


Currently all our confirmation links work reasonably similarly, with one odd pathway that tacks a query string onto the URL. This contributes to the convolution of the registration code down the line.

To fix this: * Add a field full_name (null=True) to PreregistrationUser * Change maybe_send_to_registration to put the full_name into the prereg_user that’s created * Change accounts_register to take the full_name from the prereg_user if it’s there, rather than from the post parameter

As followup, we can clean up the confirmation code: * in and confirmation/, change the do_confirm links to go straight to accounts_register instead of passing through confirmation.views.confirm. * delete, as well as confirm_preregistrationuser.html * Remove @require_post from accounts_register

Updated 29/07/2017 18:23 7 Comments

emails: Add log for outgoing emails.


zerver.lib.send_email.send_email should write an INFO log line for each email it attempts to send, and another ERROR line when mail.send() == 0.

The log file can be called email.log, and live next to server.log and friends. We can log the, the template_name = template_prefix.split('/')[-1], and the to_user_id if set.

Updated 17/08/2017 17:06 6 Comments

registration: Button on confirm_continue_registration should just register you.

  • Try to login with a github account that is not a part of the organization you are logging in to
  • Click “Continue to registration”

Currently, we just dump you on to /register. Instead, the button should be called “Register instead”, and we should just register you, using the credentials provided. The only way to get to this page is via google or github auth, I believe (maybe sso?)

This is a pretty high traffic pathway, since our login page looks like a registration page.

Updated 26/07/2017 23:07 7 Comments

settings: Reorganize organization settings.


We currently have “Organization settings” and “Organization permissions” in the settings tab. We should add a third, “Organization profile”.

This can build off of #5793.

The final settings should be: Organization profile: Has name, description, and avatar Organization settings: Has default language, notifications stream, and the bottom two sections of organization permissions (see #5793) Organization permissions: Has the top three sections of organization permissions (see #5793), along with waiting period for stream creation.

Feel free to ping me if this isn’t clear.

Updated 24/07/2017 17:43 2 Comments

emails: Missed message emails should wait 5 minutes.


Currently, we send missed message emails using something like the following algorithm: * Every time a notifiable message is sent to a user, add it to their missed messages queue * Every two minutes, group everything in the queue together and send it as a missed message email.

By “notifiable” I mean (received_pm or mentioned) and (idle or always_push_notify), where idle seems to be “zulip is not in focus for at least 140 seconds”. The relevant code is in process_message_event.

This has poor behavior if you are mostly online, but go offline every couple of minutes or so, since then you get lots of missed message emails. Instead, it would be better if: * We queue messages just as aggressively as we do now, if not more so (i.e. less than 140 seconds till idle) * We don’t send a missed message email until you have been offline for at least 5 minutes. * We remove messages from the queue if you stop being idle

This is a somewhat tricky change, so I would definitely post a strategy here or on before implementing. I could imagine using something like ScheduledEmail, or modifying the existing queue processor (MissedMessageWorker, which calls handle_missedmessage_emails).

Updated 17/07/2017 22:13 1 Comments

user docs: minimize references to the home view in /help/


Because the home view can be confusing to new users and excessive use of the home view early in one’s Zulip career can hurt the development of stream/topic discipline (leading to (no topic) messages and messages sent to the srong stream), we are trying to de-emphasize the home view to new users. We should make sure the user documentation does not encourage/imply that the home view is what people should use by default (and possibly document the home view as a “power user feature”).

For example, gives the following steps as its first suggestion:

  1. In your view, find a message sent to the stream.
  2. Click on the message’s stream to narrow your view to all messages sent to that particular stream.

(which basically only makes sense from the home view) rather than suggesting simply clicking on the stream name in the streams menu on the left-hand sidebar (which works from any narrow as well).

Updated 18/07/2017 16:16 2 Comments

registration: Initial narrow after registration should be to PMs with welcome bot.


Currently, we implement this by redirecting to this narrow after the tutorial. The tutorial is going away, so we need a different way of doing it.

Some ideas, not sure which is the best: * Put something in the session in accounts_register, that zerver.views.home.home_real can read and interpret. home_real already seems to have somewhat relevant code: narrow = [] # type: List[List[Text]] narrow_stream = None narrow_topic = request.GET.get("topic") if request.GET.get("stream"): [...] * Something else?

You can get welcome bot with get_system_bot(settings.WELCOME_BOT). + @hackerkid, if you have any ideas.

Updated 31/07/2017 15:45 9 Comments

right sidebar: Include non-displayed users in typeahead.


If someone is gone for three weeks, we remove them from the right sidebar. We should still include them at the bottom of the user search typeahead, though, since it feels like something is broken when you know someone is part of a realm and you can’t find them in user search.

Note that we include all such users in the compose box typeahead, so the list is already being sent to the frontend.

Updated 01/08/2017 00:29 4 Comments

Add rate limiting to the login and password change processes


Zulip historically has relied on strong password strength requirements (strong enough to protect against)

But it seems like a clear improvement to add (ideally) both target-user-based and IP-based rate limiting on attempts to check passwords in Zulip. We should look into whether Django has a good library for this, but I’d be tempted to roll our own thing unless a library makes it easy to handle all the cases below. In that case, we’d want to add a function that you pass the IP and target email to, probably in zerver/, for this check, and then use it in a few places: * web login * mobile login * password change flow * Any other re-authentication flow (the main one I can think of is the one we use to get your personal API key).

(Note that we already have rate-limiting implemented using redis for all logged-in views in zerver/lib/, which we may want to extend as part of this project)

@umairwaheed can you take care of this one?

Updated 03/08/2017 18:45 4 Comments

Eliminate use of `HTTP PUT` method when we don't mean it


We have a few places where we’re using a PUT HTTP method where the endpoint isn’t actually idempotent. This causes exceptions when things are automatically retransmitted by the browser incorrectly. The main ones are:

    url(r'^realm/icon$', rest_dispatch,                                                              
        {'PUT': 'zerver.views.realm_icon.upload_icon',                                               
    url(r'^realm/emoji/(?P<emoji_name>.*)$', rest_dispatch,                                          
        {'PUT': 'zerver.views.realm_emoji.upload_emoji',                                             
    url(r'^users/me/avatar$', rest_dispatch,                                                         
        {'PUT': 'zerver.views.user_settings.set_avatar_backend',                                     
    url(r'^users/me/alert_words$', rest_dispatch,                                                    
        {'GET': 'zerver.views.alert_words.list_alert_words',                                         
         'POST': 'zerver.views.alert_words.set_alert_words',                                         
         'PUT': 'zerver.views.alert_words.add_alert_words',                                          

¾ of these are because we’re uploading a file and we should just change to POST; the alert_words one is more interesting (but also hasn’t been a source of problems yet). Ideally we’d change them all.

The uploads part of this, at least, we should fix soon, since it’s easy to do and I don’t believe those APIs are in use in any apps (and we’d like to fix this before that changes).

Updated 06/08/2017 19:35 4 Comments

models: Remove reliance on short name in non-subdomains case.


We should remove our reliance on Realm.string_id in the non-subdomains case, so that you don’t have to create a string_id (or “Short name”) at the time of realm creation. At minimum, this means * Parts of the code that use Realm.string_id just to pass around a Realm object should either pass around a Realm or instead. * Management commands should take a --realm argument that can be either a number or a string (and then we can try matching that on either or the Realm.string_id). * Figuring out (e.g. via git grep string_id) where else we rely on string_id in the codebase * Checking that we don’t use string_id in the API.

This issue is probably best for someone with experience developing for Zulip.

Updated 01/07/2017 02:36 1 Comments

user docs: Write a good explanation for "your password is too weak".


A surprisingly common frustration while registering for Zulip is that our password checker, zxcvbn, will consider someone’s password (like d0nth4ckMe) too weak, and they won’t understand why. I think a good user doc here (that we could link to from the error message) would help a lot.

Suggested content: title: Why does Zulip think my password is too weak

Zulip uses the zxcvbn password checker, which makes a guess as to how long a modern password cracker will take to guess your password. If zxcvbn can crack your password in less than a certain amount of time (a couple of hours by default, but the server admin can change this), then we don’t allow the password. Explain that we only have false negatives; e.g. if zxcvbn thinks your password is weak, it has a proof that it is weak, but it doesn’t check for everything, so just because it thinks your password is strong doesn’t mean it is actually strong.

Some tips for making strong passwords: don’t use repeated letters, suggest things like 1password, maybe embed the xkcd comic. Also explain not reusing passwords.

Updated 30/06/2017 22:01 6 Comments

Add a reply button to the compose box.


When the compose box is closed, and when there is a selected message (i.e. most of the time), we should have a “Reply” button to the right of “New topic” and “New private message.” We should style it somewhat more prominently then the other buttons, which perhaps a blue border or something. It should have the same semantics as hitting “r” or “enter” to reply.

Updated 31/07/2017 18:37 4 Comments

Make vagrant proxy setup show warnings if necessary


If the user specified the HTTP_PROXY and HTTPS_PROXY variables in ~/.zulip-vagrant-config but didnt’t install vagrant-proxyconf plugin a warning should be shown when vagrant up is run by the user. I missed doing vagrant-proxyconf install in my new laptop and spend some time debugging the error (It’s kind of funny that I wrote this feature myself :smile: and still messed up the installation).

This would be a good issue for new contributors. The file that you would be changing for accomplishing this task would be mostly To know more about the proxy setup process see

Updated 08/06/2017 10:07 3 Comments

Improve abstractions for writing tests using the Zulip API


We now use **api_auth in 142 places in the codebase, and it’s kinda ugly. We should think about replacing the **api_auth mechanism we use for things like self.client_patch with something more like self.api_patch(user_profile, "/users/me/subscriptions") , where we aren’t specifying how to do auth in every single test.

We should get a few thoughts on the specific interface before changing this.

Updated 08/06/2017 05:16 4 Comments

Make the UI for setting a bot as an incoming webhook bot more fancy/self-explanatory


As part of #5082, we added a basic dropdown menu for making it possible to set a bot as an incoming webhook, with limited permissions to only send messages.

I think it’s probably worth doing a pass at making that look really nice, keeping in mind that we’ll eventually have at least 4 choices: * Incoming webook * Outgoing webhook (with sub-options for format) * Generic bot * Embedded bot (with sub-options for which one)

Updated 07/06/2017 04:26 1 Comments

Expand and reorganize "Using Travis" section from docs/


The new docs/ is a mix of developer docs and user docs, for users of Travis-for-Zulip.

It’d probably be worth concentrating the user docs together so that people can read them without going through the developer docs. E.g., the “sign up your personal repo” bit, and maybe a section like “Reading Travis CI output” that discusses the setup/run structure and the hiding of output.

From @gnprice’s

Updated 06/06/2017 20:30 1 Comments

Add limited ordered list support to our markdown


Markdown has this cool ordered list feature where you can do this: 1. first item 1. second 1. third

And it’ll auto-renumber them for you to ½/3.

We can’t use existing markdown ordered lists implementations, because they will also turn a solo 2. into a 1., which really sucks if you’re splitting a list across multiple messages. But I think we could do something where if you do several of the same number, it does turn it into an ordered list, counting from that number. is a helpful resource for anyone interested in working on this.

Updated 01/06/2017 21:06 1 Comments

Confluence Integration


It would be useful to have an integration with Confluence such that a Zulip message would be created each time a page in the Confluence Wiki is created / edited / deleted. This would make it obvious when documentation activity is occurring.

I tried to add the integrations label to this issue per the instructions on the integrations page but it appears you can only label issues if you are a contributor. If someone else could add the label, that would be great!

Updated 13/06/2017 13:36 3 Comments

Improve visual design of html emails.


Our current email templates are quite old, and look dated. It would be great to restyle them to look more modern and to fit the Zulip brand (underwater sea theme).

For this issue, don’t worry too much about the text; that can be improved independently.

All of our email templates are in templates/zerver/emails, and all our html email templates end in .html.

Updated 09/08/2017 08:34 15 Comments

Add setting(s) to control to what extent message deletion is allowed in an organization


Now that #135 is completed, we should add options to control to what extent deletion is allowed. I can imagine supporting at least these uses cases: * Not allowed at all (for organizations that want a strong audit history) * Allowed only for organization administrators (the current behavior) * Allowed only for organization administrators and deleting messages you sent yourself.

I think we can probably do this cleanly as just 2 bool settings: * Allow users to delete messages that they sent * Organization administrators can delete messages they can see

While we’re working on this, we should also probably edit the text of the modal for message deletion to make clear the risks involved with deleting messages.

Once this is done, we should make sure the options are documented clearly.

Updated 05/06/2017 20:18 2 Comments

Document log2zulip integration


We have this cool script for forwarding errors from tailing a given set of log files into Zulip, log2zulip, that just got moved to api/integrations/log2zulip (and thus now is distributed as part of our pip package). It’d be awesome to document it as one of our official integrations in /integrations, since it’s actually pretty useful.

There’s a sample simple configuration file here: $ cat puppet/zulip_ops/files/log2zulip.conf ["/var/log/nginx/error.log"]

Updated 26/05/2017 22:19 1 Comments

Add documentation for init.d starting nginx.


Write developer documentation for in developer docs for init.d and Linux in

The main purpose of this is just to make clean that Zulip uses the system nginx, not something run via supervisord, so when one changes a certificate, one needs to restart the system nginx.

For reference: Zulip chat

Updated 28/07/2017 00:40 2 Comments

Make Zulip give a better error for Google Compute Platform weird boto configuration


GCE has an /etc/boto.cfg, which GCP prepopulates in its image to include: [Plugin] plugin_directory = /usr/lib/python3/dist-packages/google_compute_engine/boto

The boto library reads this, an ends up being totally broken on import with Python 2. We should at least add code in our production installer to detect this situation and tell the user to fix it.

@jmandel FYI; did you end up opening an issue with Google about this?

Updated 17/08/2017 00:58 10 Comments

i18n: Add translation packages to stats page.


The stats page isn’t a part of the regular webapp, and our current build process for the page doesn’t include the packages that are needed to add translation tags.

To work on this issue, I’d start by grepping for 18 and stats.js in zproject/ to see how we add translation to the regular webapp, and what’s different about our build process for the stats page. may also be useful reading.

It would also be great to add translation tags as needed to stats.html and stats.js as a part of resolving this issue (they are fairly small files). is helpful reading for how to test the stats page in development.

Updated 03/08/2017 18:35 5 Comments

Strengthen check for name validity.


Currently zerver.lib.users.check_full_name is more lax than the RFC standard for the name part of name <email>. We’d like to be able to send emails to users using UserProfile.full_name for name.

This involves a few steps: * Figure out what the standard is, and if python already has a library that implements this check. Maybe in the email.header or email.utils modules? * Add this check to check_full_name. If you’re writing the check from scratch, feel free to err on the side of writing a more-restrictive-than-needed check if it is simpler to understand. * Write a migration that converts non-valid full names to valid full names (can be hackish, e.g. it can just remove some offending characters. I expect this to be a pretty rare occurance)

While you’re looking at this, it would also be great to * Make sure by the end of this process newlines, tabs, and other such control characters are also not allowed (either via adding them to UserProfile.NAME_INVALID_CHARS or via the other parts of check_full_name)

As a bonus, or as a followup, it would be great to apply a similar check to

Updated 16/06/2017 02:58 11 Comments

views: Apply human_users_only decorator to human-only views.


4516 introduces a human_users_only decorator that can be used to block bots from e.g. changing their display settings or doing other things that don’t make sense for bot users.

It would be great to add the decorator to all the functions in zerver/views/* that need it. For each such function, we need to add the decorator, remove any relevant if user_profile.is_bot: return json_error .. logic, and add the endpoint to test_human_only_endpoints in

I’d split this into a bunch of commits (e.g. one per file, or more fine-grained than that) to make this easy to review.

Updated 03/08/2017 18:36 13 Comments

stats: Extract messages sent over time legend from plotly.


Currently the messages sent over time legend has confusing styling; the squares should be checkboxes, and “Humans” and “Bots” should be grouped together separately from “Me”.

The first step to doing this is to replace the plotly legend with three regular checkboxes. The click handlers of the checkboxes should either call the appropriate plotly functions to retrace the graph, or if it’s easier, they can just redraw the graph (ideally keeping the same rangeslider position).

@italo-batista, this could be a great issue for you to look at. Adding @manjithd2 as well, in case you’d like to follow it!

Updated 08/06/2017 15:17 5 Comments

Clicking a link in the message feed defocuses the compose box


If you click a link in the message feed to another site, the compose box loses focus, which is slightly annoying if you’re consulting some linked-to resource as part of drafting a reply.

I suspect this is effectively a bug in how we fixed the earlier issue that clicking a link in the message feed would focus the link (causing enter to re-open the link).

Updated 15/08/2017 22:34 15 Comments

Change consider_bankruptcy to use UserPresence instead of pointer.


Currently, the following piece of code in static/js/unread_ui.js puts up the bankruptcy modal if you have more than 500 unread messages and your pointer is more than 2 days in the past:

    var now = new XDate(true).getTime() / 1000;
    if ((page_params.unread_count > 500) &&
        (now - page_params.furthest_read_time > 60 * 60 * 24 * 2)) { // 2 days.
        var unread_info = templates.render('bankruptcy_modal',
                                           {unread_count: page_params.unread_count});

It would be better to use the information in UserPresence to calculate this, since page_params.furthest_read_time can be very far back for those that use the left sidebar to read Zulip rather than the Home view.

It would also be better to change 2 days to 4 days, so that it doesn’t include just being gone for the weekend.

Updated 16/08/2017 21:47 25 Comments

Audit our webhook integrations for ping messages that should be handled


As a follow-up to #3994, it’d be super awesome to audit our other integrations for whether they have “ping” type messages that are being silently accepted and should instead send out a similar notice. Probably the best way to check is to read the webhook docs for the integration, but we could also check our code in most cases.

I’d sorta do this in a few stages that all feel fairly quick (and log findings in this issue). E.g. start by checking out the 5 other Git integrations and opening issues for any that need work, and going from there.

Updated 16/06/2017 02:58 8 Comments

Show a banner with link to a custom url when user joins for the first time


There are two parts for this project.

Part 1 - Banner

When a user joins an organization for the first time a banner would be shown with link to an external webpage. The banner would ask user to check out the link to know more details about the organization (Or something similar).

eg: In case of the link can point to

The administrator should be able to customize the link and enable/disable the banner.

Part 2 - Link in Gear menu

The external URL should be also linked from the gear menu as the banner is shown only when the user joins an organization. Perhaps the link can be called “Organization guidelines” or something, and only appear if an administrator has set that feature?

Discussion regarding this feature can be accessed here.

Check out the New feature tutorial to see how you should go on to implement a new feature in zulip.

Updated 16/08/2017 01:51 4 Comments

search: Add ability to search by huddle.


We’ll want to add a new search keyword, like huddle-with:<email>.

On the backend, the main change that needs to be made is in NarrowBuilder in zerver/views/

The frontend is a bit messier, but I would git grep for pm-with which should have a superset of the changes that are needed.

This is something that will also need a careful test suite.

This would be a great medium size project for someone who has done several smaller projects, and is looking for something bigger.

Updated 16/06/2017 02:58 11 Comments

analytics: Improve new realm experience on /stats.


One of the first things someone might do when trying out zulip is to click on the links in the gear menu, one of which is (or will soon be) a link to the /stats page. Currently this page is completely broken for new realms.

A good solution would be to just show fixture data until the realm has a bit of traffic.

Some steps: * Remove the min_length argument from get_chart_data and the functions it calls (git grep for min_length from the analytics/ directory), and also from the $.get calls in stats.js. * For the charts in stats.js, if data.end_times.length is small: * show some fixture data instead * make the opacity of the graph 40% or something * disable all the buttons * overlay a message on top, like “Not enough data; please check back in a couple of days.”

Notes: Also check that e.g. the weekly view on Messages Sent Over Time looks okay with < 1wk of data, and that the Number of Users graph looks okay with 1-2 days of data. If it doesn’t we can open further issues to fix it.

Some notes on the analytics frontend is available at

You can delete all the analytics data with ./ clear_analytics_tables --force, and you can modify e.g. DAYS_OF_DATA in (and then run ./ to mimic a young realm. You can also modify clear_analytics_tables (via do_drop_all_analytics_tables) to only delete things after a certain end_time, with UserCount.objects.filter(end_time__gt=myendtime).delete().

Updated 16/08/2017 04:26 19 Comments

Improve visual formatting of message edit history


Now, after a message has been edited, it’s possible to see the history versions of the message (see #268). The new UI is functional, but could look a lot nicer. The big structural things are these: * [x] We should optimize the timestamp display to not repeat the date every time, while still providing precise dates for each transition in the message’s content. * [ ] Only show who edited messages if it was someone other than the author (only relevant for topic edits). * [ ] We should start displaying topic edits (maybe just show the topic part of a recipient bar to show changes in the topic?) * [ ] Fix the funny alignment of notes about who edited things. * [x] Improve the colors. The current colors were chosen for a use case where the diff would be shown on every message, not only in this off-to-the-side edit history view. * [x] Potentially add some sort of (optional?) display of what was removed from the previous version. That is tracked in #1406, so it’s fine to close this issue even if that isn’t resolved.

This is a meta-issue for now; we may end up splitting it into several sub-issues once someone is actually working on it.

Updated 16/06/2017 03:04 7 Comments

Improve "Uploaded files" / attachment UI behavior


We merged, which means there’s now a UI for deleting attachments that you didn’t intend to upload. But it seems like we probably want to enhance that in a few ways:

(1) It doesn’t live-update to show attachments you’ve uploaded during the current browser session. (2) Since users are probably unlikely to update their attachments, it might make sense to not bother including the data in page_params; for a user who has sent thousands of screenshots in their time using Zulip, the page is probably pretty slow.

I think (1) + (2) probably have a joint solution of only fetching + rendering this particular settings page when a user actually clicks on the “Uploaded files” button.

(3) After an attachment is deleted, it’d be nice to somehow update how the relevant messages are rendered to display an “attachment deleted” image of some sort. I don’t have a great solution for how to do this that isn’t messy, but the approximate idea would be to (1) move the Attachment object into a “deleted” state rather than removing it and (2) if one tries to access a deleted Attachment image, return the URL to a fixed “File deleted” image rather than the (now nonexistent) original file’s URL.

(4) Finally, I think we should provide some clarity that deleting an attachment will (maybe just in the documentation paragraph).

Updated 27/06/2017 00:31 3 Comments

Add support for message shortcuts.



It would be a useful feature for Zulip to include a system for message shortcuts, that is, shortenings for longer phrases and established wordings.


  • Imagine a development help stream, where new users often ask redundant questions. Instead of typing answers over and over, one could simply type :<shortening-for-answer>. Zulip would then replace the shortening with the saved phrase for it.

  • #1684 proposed a similar feature for the quick composition of polite standard phrases. Instead of being lazy and typing “afk” when you’re not available, one could add the shortening :afk, which would then get replaced by I will be away for a bit.

Implementation proposals:

  • This feature could be implemented similar to @-mentions: After entering : in the compose box, a drop-down list of all possible shortening would pop up. The user could then continue typing to narrow down his search. After pressing enter/tab, the respective phrase would get inserted.

  • In the settings menu, we could add a list where users can enter new shortenings. A few standard shortening (for established wordings) would be already included.


Please share your thoughts on this in the comments or on in the Zulip discussion on this.

Updated 24/07/2017 11:07 5 Comments

Improve the find my team page.


The find my team page allows users to enter an email address (actually, up to 10 email addresses) and receive an email with a link to the login page of their organization. The basic functionality is there, but it could use a few improvements:

  • [ ] You shouldn’t be able to click “Find team” if you don’t have a valid list of email addresses. Slack does this really nicely:

  • [ ] We should send an email regardless of whether they are in a Zulip org or not.

  • [ ] The followup page should have links to resend the email or enter a different email address.

  • [ ] The URL of the followup page currently has the email as a URL parameter, which should be removed.

  • [x] Add the 'In the Zulip development environment, outgoing emails are printed to the console.' text (git grep for it to see how we do it elsewhere)

  • [x] On load, the cursor should go into the box where you enter your email address.

The find my team page is at http://<host>:9991/find-my-team/. In the dev environment, you’ll need to first change 'FIND_TEAM_LINK_DISABLED' to False in zproject/

Updated 26/06/2017 21:24 13 Comments

Allow users to check subdomain availability on registration page.


To get to the page: go to localhost:9991/create_realm, enter an email, click Create Organization, and then click on the confirmation email in your terminal.

It would be really nice to have a “Check” button to the right of this box: image that checked if your short name/subdomain is already taken or not.

Started a discussion at

Updated 26/06/2017 21:24 4 Comments

Allow searching by emoji


Currently searching for :octopus: doesn’t work. Some notes: * Possibly some care will be needed in parsing out the emoji/doing autocomplete on the search string, since there are :s at the end of things like sender:. Or possibly we can just reuse the code that does this in composebox_typeahead.js. * We search the rendered message, rather than the raw message (this is required to do highlighting correctly). So we’ll be searching for the relevant href tag for the emoji, rather than the unicode or any such thing. * Note that we allow custom realm emoji, though the href thing should just work for that as well.

This task is probably appropriate for a more experienced programmer.

Updated 29/07/2017 14:05 7 Comments

Integration guide could be more novice-friendly


I’m working through the Hello World example in the integration guide ( and there were some things I found confusing as a developer not well-versed in the world of web services. I’m opening this issue to capture my notes walking through the document. (Hi @christi3k! Also, I’m about half through as I start this.)

What is the expected audience for this document? Dev novices? Webapp novices? Someone who has already written a webhook for something else?

Topics I needed to read more about before I could understand parts of the document: - How does a webhook work? How is it different from calling a REST API? - What is a test fixture? - What is a decorator?

Questions I had about Zulip or the example: - Is the directory /zerver/lib/webhooks (seen on the filesystem) related to /zerver/test/webhooks or /zerver/view/webhooks? - There are many references to the API key, but no mention that replacing the placeholder api_key with your personal API key from the Zulip user’s settings is necessary for the examples to work. (The curl example fails with a less-than-helpful message “syntax error near unexpected token `newline'”) - Reference to running tests from the “/srv/zulip directory” is confusing without Vagrant. On my non-Vagrant system there is Zulip stuff in /srv, but nothing called “/srv/zulip” and that’s not where my installation is. (Also: the non-Vagrant install instructions don’t mention that the docs assume Vagrant defaults.)

A typo:

“We have several different ways that we integrate with 3rd part products”

Updated 03/08/2017 18:35 4 Comments

new accounts, if started at URL for a narrow, should be directed there after account creation


I open up a new browser window in which I am not logged into any Zulip realm.

I go to .

I create a new account.

I’m taken to the general realm tutorial, and when I skip it, I’m not taken directly to the particular stream & topic for that narrow. It would be great if I were.

Updated 26/06/2017 21:28 1 Comments

Improve testing of markdown.contains_backend_only_syntax()


Currently, echo.contains_bugdown does a pretty good job of checking what bugdown is supported, but there are a few gaps.

However, we have some more obscure markdown features (e.g. !modal_link()) that are not checked for in the file. We have some test data in zerver/fixtures/markdown_test_cases.json as well as tests in zerver/tests/ and frontend tests in frontend_tests/node_tests/echo.js. The test fixture data is preferred for new tests, since it is automated tested in both the test_bugdown and echo.js test suites.

We should do a few things: (1) Document the above notes on how we test bugdown in docs/ (2) Fill the gaps where markdown.contains_backend_only_syntax does not produce correct output, and add tests for this. The things I’m aware of include !modal_link and friends (see the issues below) (3) Add a blueslip.warn call to report to the server whenever the local echo support ends up discovering a mismatch between marked and bugdown, so that we can catch future mismatches and fix or test them.

Some related issues / open PRs that may make sense to work on as part of this include: - - -

@hackerkid is that enough info to get started on improving this area of Zulip?

Updated 29/07/2017 01:33 15 Comments

The tutorial causes multiple notification permission panels in Safari.


SUMMARY After a user walks through the tutorial, they will be presented with Safari’s Notification Center permission panel once for every step in the tutorial (currently five).

EXPECTED BEHAVIOR The user should only see the permission panel once.

REPRO For a server you have never logged in to before: - Login to a new account to enable the tutorial. - Click through the tutorial. - Safari will present the notifications permission panel once for each step of the demo.

If you have previously gone through the tutorial and answered the Safari notification permissions panel, you will need to first run these steps: - Open the Safari preferences (Safari menu -> Preferences). - Click on the Notifications tab. - Find the server you will log in to (usually “localhost” for the dev server). - Select it and click the Remove button in the lower left. - Create a new user with which to login and walk through the tutorial. - [WARNING] Alternatively, from the zulip directory, run ./tools/do-destroy-rebuild-database to destroy your database and start with the defaults. This will destroy all existing data in the database.

VERSIONS AFFECTED - Safari 9.1.1 (11601.6.17) - Safari Technology Preview 9.1.1 (11601.6.17, 11602.1.33)

NOTES - If you remove the Zulip server from Safari’s Notification Center preferences after clicking through any of the tutorial (for example, after the first four steps), Safari will still present notification permission panels for each step in the tutorial. - Firefox and Chrome, which use custom notification frameworks and not the native Notification Center, do not have this problem. - If you remove your server from the Safari’s notification preferences after the tutorial, reload the page, and click on the website, you will see one notification permission panel (the expected behavior). - Only the first answer matters. If the user selects Allow and then selects Deny on the subsequent panels, their preference will still be set to Allow. (This is a Safari bug.)

Updated 16/08/2017 06:32 8 Comments

Fork me on GitHub